(MOT-4178) feat(console): Monaco code editor + injectable directory UI#579
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
skill-check — worker0 verified, 48 skipped (no docs/).
Four for four. Nicely done. |
📝 WalkthroughWalkthroughThe change adds shared Monaco and markdown UI components, introduces injectable directory editing with skill and prompt update functions, embeds worker UI assets, and adds workers-dev support for discovering, launching, monitoring, and toggling UI watch processes. ChangesShared console UI
Directory editing and injected UI
Workers-dev UI watcher
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant DirectoryPage
participant WorkerFunction
participant Filesystem
participant Console
DirectoryPage->>WorkerFunction: request or update raw markdown
WorkerFunction->>Filesystem: read or atomically write markdown
Filesystem-->>WorkerFunction: return content and metadata
WorkerFunction-->>DirectoryPage: return response
WorkerFunction->>Console: dispatch directory change trigger
Console-->>DirectoryPage: refresh or mark draft stale
sequenceDiagram
participant Developer
participant WorkersDev
participant Worker
participant UIWatcher
Developer->>WorkersDev: enable UI watch
WorkersDev->>Worker: set UI watch environment
WorkersDev->>UIWatcher: run pnpm watch
UIWatcher-->>WorkersDev: stream tagged build output
WorkersDev-->>Developer: show UI watch status
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (4)
workers-dev/src/orchestrator.rs (1)
421-482: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMinor: hardcoded
"[ui] "prefix duplicates theUI_LOG_TAGconstant.The announcement (line ~445) and failure (line ~474) log lines both hardcode the
"[ui] "prefix literally, whileread_stream_taggeduses theUI_LOG_TAGconstant defined just abovebuild_view. ReusingUI_LOG_TAGhere would avoid the two copies drifting if the tag ever changes.♻️ Proposed fix
push_log( rt, format!( - "[ui] watch: pnpm watch in {} · {}=1 (console tabs hot-reload on rebuild)", + "{UI_LOG_TAG}watch: pnpm watch in {} · {}=1 (console tabs hot-reload on rebuild)", ui_dir.display(), ui_watch_env(name) ), );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workers-dev/src/orchestrator.rs` around lines 421 - 482, Update the log messages in spawn_ui_watcher, including the successful watch announcement and spawn-failure message, to reuse the existing UI_LOG_TAG constant instead of hardcoding the "[ui] " prefix. Preserve the current message content and formatting while ensuring both paths derive their tag from UI_LOG_TAG.iii-directory/ui/styles.css (1)
395-402: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace deprecated
word-break: break-word.Stylelint flags this keyword as deprecated for
word-break. Useoverflow-wrapinstead.🎨 Suggested fix
[data-iii-ui="iii-directory"] .dir-ui-error { padding: 8px 12px; border-top: 1px solid var(--color-rule-2); font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; color: var(--color-alert); - word-break: break-word; + overflow-wrap: break-word; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@iii-directory/ui/styles.css` around lines 395 - 402, Update the .dir-ui-error rule’s deprecated word-break declaration to use overflow-wrap with equivalent long-word wrapping behavior, while preserving the existing error styling.Source: Linters/SAST tools
iii-directory/ui/src/configuration/index.tsx (1)
47-52: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
setNumberdoesn't enforce the non-negative constraint implied bymin={0}.Negative values for
download_timeout_ms/registry_cache_ttl_msparse successfully (Number("-5")isn'tNaN) and get committed, even though the field'smin={0}hint and the field semantics (durations) imply non-negative only.🔢 Suggested fix
const setNumber = (field: string, raw: string) => { const next = { ...value } - if (raw.trim() === '') delete next[field] - else if (!Number.isNaN(Number(raw))) next[field] = Number(raw) + if (raw.trim() === '') delete next[field] + else { + const n = Number(raw) + if (!Number.isNaN(n) && n >= 0) next[field] = n + } commit(next) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@iii-directory/ui/src/configuration/index.tsx` around lines 47 - 52, Update setNumber to commit numeric values only when they are non-negative, rejecting parsed values below 0 so duration fields such as download_timeout_ms and registry_cache_ttl_ms honor their min={0} constraint; preserve the existing empty-input deletion and valid-number behavior.iii-directory/ui/src/function-trigger/SkillsViews.tsx (1)
170-191: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
PromptsListViewre-implements theListShelllayout instead of reusing it.SkillsViews.tsxextracts the Card/MetaRow/StatusPill/PulseLine loading-and-count layout intoListShellfor reuse bySkillsListView, butPromptsViews.tsx'sPromptsListViewduplicates the same structure inline.
iii-directory/ui/src/function-trigger/SkillsViews.tsx#L170-L191: keepListShellas the shared component (no change needed here beyond exporting it if not already, and generalizing thenounpluralization forpromptsif reused).iii-directory/ui/src/function-trigger/PromptsViews.tsx#L28-L77: replace the inlineCard/MetaRow/StatusPill/PulseLinemarkup inPromptsListViewwithListShell, passingnoun="prompts"and the existing list JSX aschildren.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@iii-directory/ui/src/function-trigger/SkillsViews.tsx` around lines 170 - 191, The duplicated list layout should be replaced with the shared ListShell component. In iii-directory/ui/src/function-trigger/SkillsViews.tsx lines 170-191, export ListShell if needed and generalize noun pluralization so “prompts” renders correctly; in iii-directory/ui/src/function-trigger/PromptsViews.tsx lines 28-77, update PromptsListView to use ListShell with noun="prompts" and pass its existing list JSX as children, removing the inline Card/MetaRow/StatusPill/PulseLine structure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@console/SKILL.md`:
- Around line 58-66: Update the directory-tree fenced code block in the
documentation to use the text language tag (` ```text `), preserving its
contents so it satisfies MD040.
In `@console/web/src/components/ui/CodeEditor.tsx`:
- Around line 220-240: Update the CodeEditor component’s ready-state wrapper
around hostRef and the fallback textarea so the supplied id remains bound to a
stable DOM element after Monaco takes over. Move the id from the conditionally
rendered textarea to the persistent wrapper or API target, while preserving the
existing textarea value, event, accessibility, and focus behavior.
- Around line 184-201: Update the CodeEditor component’s Monaco readiness and
rendered root handling so disabled editors cannot receive focus: remove the
Monaco root from tab order when disabled, expose disabled semantics via the
root’s accessibility attributes or a compatible inert container, and blur
editorRef when disabled becomes true. Preserve the existing readOnly/domReadOnly
behavior for readOnly and disabled states.
In `@docs/sops/injectable-console-ui.md`:
- Around line 21-28: Update all three references in
docs/sops/injectable-console-ui.md (lines 21-28, 166-168, and 437) to point to
console/SKILL.md instead of workers/console/SKILL.md, preserving the surrounding
guidance.
In `@iii-directory/README.md`:
- Line 232: Update the directory::skills::download table cell in README.md to
escape the pipe between version? and tag? so the GFM parser treats it as literal
content and preserves the table’s column structure.
In `@iii-directory/ui/src/page/browser.tsx`:
- Around line 156-173: Prevent stale asynchronous results in the browser page:
move the existing selectedRef declaration above open, then guard open’s load
callbacks at iii-directory/ui/src/page/browser.tsx lines 156-173 with
selectedRef.current !== key before updating loaded content, draft, or load
errors. Apply the same captured-key staleness guard in save at
iii-directory/ui/src/page/browser.tsx lines 205-221 before updating loaded
state, selection, or save errors.
In `@workers-dev/src/tui/mod.rs`:
- Around line 1475-1478: Shorten the help-overlay legend added in the lines.push
call so it fits within the 58-character body width used by draw_dialog. Preserve
the essential UI and watch hot-reload guidance while removing redundant wording;
do not rely on clipping or wrapping.
---
Nitpick comments:
In `@iii-directory/ui/src/configuration/index.tsx`:
- Around line 47-52: Update setNumber to commit numeric values only when they
are non-negative, rejecting parsed values below 0 so duration fields such as
download_timeout_ms and registry_cache_ttl_ms honor their min={0} constraint;
preserve the existing empty-input deletion and valid-number behavior.
In `@iii-directory/ui/src/function-trigger/SkillsViews.tsx`:
- Around line 170-191: The duplicated list layout should be replaced with the
shared ListShell component. In
iii-directory/ui/src/function-trigger/SkillsViews.tsx lines 170-191, export
ListShell if needed and generalize noun pluralization so “prompts” renders
correctly; in iii-directory/ui/src/function-trigger/PromptsViews.tsx lines
28-77, update PromptsListView to use ListShell with noun="prompts" and pass its
existing list JSX as children, removing the inline
Card/MetaRow/StatusPill/PulseLine structure.
In `@iii-directory/ui/styles.css`:
- Around line 395-402: Update the .dir-ui-error rule’s deprecated word-break
declaration to use overflow-wrap with equivalent long-word wrapping behavior,
while preserving the existing error styling.
In `@workers-dev/src/orchestrator.rs`:
- Around line 421-482: Update the log messages in spawn_ui_watcher, including
the successful watch announcement and spawn-failure message, to reuse the
existing UI_LOG_TAG constant instead of hardcoding the "[ui] " prefix. Preserve
the current message content and formatting while ensuring both paths derive
their tag from UI_LOG_TAG.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 83b17268-2483-4b50-a728-7d62210993c4
⛔ Files ignored due to path filters (3)
approval-gate/Cargo.lockis excluded by!**/*.lockiii-directory/Cargo.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (56)
console/SKILL.mdconsole/web/package.jsonconsole/web/public/vendor/console-ui.jsconsole/web/src/components/chat/directory/__tests__/parsers.test.tsconsole/web/src/components/chat/directory/index.tsxconsole/web/src/components/chat/directory/shared.tsxconsole/web/src/components/function-trigger/FunctionTriggerCard.tsxconsole/web/src/components/function-trigger/renderer-registry.tsxconsole/web/src/components/ui/CodeEditor.tsxconsole/web/src/components/ui/MarkdownPreview.tsxconsole/web/src/lib/console-api.tsconsole/web/src/lib/console-ui-conformance.test.tsconsole/web/src/lib/monaco.tsconsole/web/src/lib/syntax.tsxconsole/web/src/pages/Memory/components/RulesPanel.tsxdocs/sops/injectable-console-ui.mdiii-directory/Cargo.tomliii-directory/README.mdiii-directory/build.rsiii-directory/src/fs_source.rsiii-directory/src/functions/mod.rsiii-directory/src/functions/prompts.rsiii-directory/src/functions/skills.rsiii-directory/src/functions/update.rsiii-directory/src/lib.rsiii-directory/src/main.rsiii-directory/src/ui.rsiii-directory/ui/build.mjsiii-directory/ui/package.jsoniii-directory/ui/page.tsxiii-directory/ui/src/configuration/index.tsxiii-directory/ui/src/function-trigger/DownloadView.tsxiii-directory/ui/src/function-trigger/PromptsViews.tsxiii-directory/ui/src/function-trigger/RegistryViews.tsxiii-directory/ui/src/function-trigger/SkillsViews.tsxiii-directory/ui/src/function-trigger/UpdateViews.tsxiii-directory/ui/src/function-trigger/index.tsxiii-directory/ui/src/function-trigger/parsers.tsiii-directory/ui/src/lib/envelope.tsiii-directory/ui/src/lib/format.tsiii-directory/ui/src/lib/widgets.tsxiii-directory/ui/src/page/browser.tsxiii-directory/ui/src/page/index.tsxiii-directory/ui/styles.cssiii-directory/ui/tsconfig.jsonpackages/console-ui/component-names.mjspackages/console-ui/index.d.tspnpm-workspace.yamlworkers-dev/README.mdworkers-dev/src/config.rsworkers-dev/src/discover.rsworkers-dev/src/main.rsworkers-dev/src/orchestrator.rsworkers-dev/src/runtime.rsworkers-dev/src/status.rsworkers-dev/src/tui/mod.rs
💤 Files with no reviewable changes (3)
- console/web/src/components/chat/directory/tests/parsers.test.ts
- console/web/src/components/chat/directory/index.tsx
- console/web/src/components/chat/directory/shared.tsx
| > **Companion skill — keep it in sync.** `workers/console/SKILL.md` is a | ||
| > standalone skill teaching this same workflow to authors *outside* this | ||
| > repo: it consumes `@iii-dev/console-ui` via `npm install` and the | ||
| > `iii-console-ui` crate via `cargo add`, instead of the workspace/path | ||
| > links this SOP uses. By design it references no repo files, so nothing | ||
| > keeps it honest automatically — any change to this SOP, the wire | ||
| > contract, the shared component surface, or either package MUST update | ||
| > the skill in the same change. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the standalone skill path. The PR adds console/SKILL.md, but these new references point authors to nonexistent workers/console/SKILL.md.
docs/sops/injectable-console-ui.md#L21-L28: change the companion-skill path toconsole/SKILL.md.docs/sops/injectable-console-ui.md#L166-L168: point out-of-repo authors toconsole/SKILL.md.docs/sops/injectable-console-ui.md#L437-L437: update the package-installation reference toconsole/SKILL.md.
📍 Affects 1 file
docs/sops/injectable-console-ui.md#L21-L28(this comment)docs/sops/injectable-console-ui.md#L166-L168docs/sops/injectable-console-ui.md#L437-L437
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/sops/injectable-console-ui.md` around lines 21 - 28, Update all three
references in docs/sops/injectable-console-ui.md (lines 21-28, 166-168, and 437)
to point to console/SKILL.md instead of workers/console/SKILL.md, preserving the
surrounding guidance.
| lines.push(Line::from(Span::styled( | ||
| " UI: ui = ships injectable console UI · watch = hot-reload on (w)", | ||
| styled_if(color, hint_style()), | ||
| ))); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspect draw_dialog to see if it wraps or truncates lines longer than `width`.
rg -n -A25 'fn draw_dialog' workers-dev/src/tui/mod.rsRepository: iii-hq/workers
Length of output: 1237
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== draw_dialog rest =="
sed -n '904,975p' workers-dev/src/tui/mod.rs
echo
echo "== help overlay callers around 1475 =="
sed -n '1420,1495p' workers-dev/src/tui/mod.rs
echo
echo "== all draw_dialog calls =="
rg -n 'draw_dialog\(' workers-dev/src/tui/mod.rs
echo
echo "== line lengths in help legend area =="
python3 - <<'PY'
from pathlib import Path
text = Path('workers-dev/src/tui/mod.rs').read_text().splitlines()
for i in range(1440, 1485):
line = text[i-1]
idx = line.find('"')
if idx != -1:
print(f"{i}: {line[idx-4:idx+120]} len={len(line[idx:line.rfind('\")}])}")
PYRepository: iii-hq/workers
Length of output: 5711
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== all draw_dialog calls =="
rg -n -B12 -A8 'draw_dialog\(' workers-dev/src/tui/mod.rs
echo
echo "== current help overlay body sizes =="
python3 - <<'PY'
from pathlib import Path
p = Path('workers-dev/src/tui/mod.rs')
text = p.read_text().splitlines()
start = text.index('fn draw_help_overlay(f: &mut Frame, area: Rect, color: bool) {')
end = next(i for i in range(start, len(text)) if text[i].startswith('fn draw_') or text[i].startswith('///'))
code = '\n'.join(text[start:end])
lines = code.split('\n')
print(f"draw_help_overlay starts at line {start + 1}, ends before line {end + 1}")
for i, line in enumerate(lines, 1):
if '"' in line:
first = line.index('"')
last = first + 1 + line[first+1:].index('"')
s = line[first:first+1+len(line[first+1:line.find('"', start=first+1))])
if 'status' in s or 'UI:' in s or 'external' in s or 'elsewhere' in s or 'keys' in s or '(none)' in s:
print(f"{start + i}: len={len(s)} {list(s[-20:].encode())[-5:]} {s}")
PY
echo
echo "== dependency overlay legend sizing =="
python3 - <<'PY'
from pathlib import Path
p = Path('workers-dev/src/tui/mod.rs')
text = p.read_text().splitlines()
start = text.index('fn draw_deps_overlay(f: &mut Frame, area: Rect, name: &str, deps: &[String], dependents: &[String], ctx: &UiCtx)')
end = min(next((i for i in range(start+1, len(text)) if text[i].startswith('fn draw_') or text[i].startswith('///')), len(text)), start+220)
for i in range(start, end):
line = text[i]
if '"' in line:
j = line.index('"')
k = j + 1 + line[j+1:].index('"')
s = line[j:k+1]
if any(x in s for x in ['external', 'elsewhere', 'connections', 'dependency', 'dependents', '(none)', 'draw_dialog']):
print(f"{i+1}: len={len(s)} {s}")
PYRepository: iii-hq/workers
Length of output: 3308
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== exact lengths of relevant help-overlay lines =="
python3 - <<'PY'
from pathlib import Path
p = Path('workers-dev/src/tui/mod.rs')
lines = p.read_text().splitlines()
for start, end, title in [
(1398, 1422, 'confirm restart'),
(1429, 1488, 'draw help overlay'),
]:
print(f'-- {title} --')
for i in range(start, end + 1):
line = lines[i - 1]
for j in range(1, len(line) - 1):
if line[j] == '"':
break
else:
j = len(line)
while line[j].isalnum() or line[j].isspace():
j += 1
print(f'{i:4}: width={j:2}', line[:j])
PY
echo
echo "== dependency-overlay legend relevant lines =="
python3 - <<'PY'
from pathlib import Path
p = Path('workers-dev/src/tui/mod.rs')
lines = p.read_text().splitlines()
for i in range(975, 987):
print(f'{i:4}: {lines[i-1]}')
PYRepository: iii-hq/workers
Length of output: 337
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('workers-dev/src/tui/mod.rs')
lines = p.read_text().splitlines()
for start, end, title in [(1398, 1422, 'confirm restart'), (1429, 1488, 'draw help overlay')]:
print(f'-- {title} --')
for i in range(start, end + 1):
line = lines[i - 1]
# find first double quote and matching closing quote only for content lines
if '"' in line:
first = line.index('"')
second = line.index('"', first + 1)
raw = line[first+1:second]
else:
raw = f'line[{i}]'
print(f'{i:4}: len={len(line):2}; content={len(raw):2}: {raw[:80]}')
PY
echo
echo "== exact line length with len =="
python3 - <<'PY'
s = ' UI: ui = ships injectable console UI · watch = hot-reload on (w)'
print(s)
print('len=', len(''.join(s.splitlines())), 'raw_len=', len(s))
print('width_58_excess=', len(s) - 58)
PYRepository: iii-hq/workers
Length of output: 3529
Shorten the overflowed help-overlay legend or widen the dialog.
This line adds 67 chars of help-overlay content while draw_dialog(..., 58, ...) renders a 58-char body at lines 1440-1457; the legend line will be clipped instead of word-wrapped. Move the UI/help legend to its own wider overlay, widen this dialog, or shorten the message.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@workers-dev/src/tui/mod.rs` around lines 1475 - 1478, Shorten the
help-overlay legend added in the lines.push call so it fits within the
58-character body width used by draw_dialog. Preserve the essential UI and watch
hot-reload guidance while removing redundant wording; do not rely on clipping or
wrapping.
…ble id, stale async guards - CodeEditor: `inert` + blur while disabled (Monaco's hidden textarea was still tabbable); `id` moves to the wrapper so anchors survive the fallback→Monaco swap - directory browser: guard open()/save() async results against a changed selection — a slow load can no longer overwrite another entry's draft, and a save no longer yanks the user back after navigating away - docs: fence language in SKILL.md, escaped pipe in README table Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e72b53d to
26e2c6c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@iii-directory/ui/styles.css`:
- Around line 395-401: Update the .dir-ui-error rule to replace deprecated
word-break: break-word with word-break: normal and add overflow-wrap: anywhere,
preserving the existing error styling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b5547481-278d-4a5d-9a39-af36f453e81e
⛔ Files ignored due to path filters (3)
approval-gate/Cargo.lockis excluded by!**/*.lockiii-directory/Cargo.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (56)
console/SKILL.mdconsole/web/package.jsonconsole/web/public/vendor/console-ui.jsconsole/web/src/components/chat/directory/__tests__/parsers.test.tsconsole/web/src/components/chat/directory/index.tsxconsole/web/src/components/chat/directory/shared.tsxconsole/web/src/components/function-trigger/FunctionTriggerCard.tsxconsole/web/src/components/function-trigger/renderer-registry.tsxconsole/web/src/components/ui/CodeEditor.tsxconsole/web/src/components/ui/MarkdownPreview.tsxconsole/web/src/lib/console-api.tsconsole/web/src/lib/console-ui-conformance.test.tsconsole/web/src/lib/monaco.tsconsole/web/src/lib/syntax.tsxconsole/web/src/pages/Memory/components/RulesPanel.tsxdocs/sops/injectable-console-ui.mdiii-directory/Cargo.tomliii-directory/README.mdiii-directory/build.rsiii-directory/src/fs_source.rsiii-directory/src/functions/mod.rsiii-directory/src/functions/prompts.rsiii-directory/src/functions/skills.rsiii-directory/src/functions/update.rsiii-directory/src/lib.rsiii-directory/src/main.rsiii-directory/src/ui.rsiii-directory/ui/build.mjsiii-directory/ui/package.jsoniii-directory/ui/page.tsxiii-directory/ui/src/configuration/index.tsxiii-directory/ui/src/function-trigger/DownloadView.tsxiii-directory/ui/src/function-trigger/PromptsViews.tsxiii-directory/ui/src/function-trigger/RegistryViews.tsxiii-directory/ui/src/function-trigger/SkillsViews.tsxiii-directory/ui/src/function-trigger/UpdateViews.tsxiii-directory/ui/src/function-trigger/index.tsxiii-directory/ui/src/function-trigger/parsers.tsiii-directory/ui/src/lib/envelope.tsiii-directory/ui/src/lib/format.tsiii-directory/ui/src/lib/widgets.tsxiii-directory/ui/src/page/browser.tsxiii-directory/ui/src/page/index.tsxiii-directory/ui/styles.cssiii-directory/ui/tsconfig.jsonpackages/console-ui/component-names.mjspackages/console-ui/index.d.tspnpm-workspace.yamlworkers-dev/README.mdworkers-dev/src/config.rsworkers-dev/src/discover.rsworkers-dev/src/main.rsworkers-dev/src/orchestrator.rsworkers-dev/src/runtime.rsworkers-dev/src/status.rsworkers-dev/src/tui/mod.rs
💤 Files with no reviewable changes (3)
- console/web/src/components/chat/directory/index.tsx
- console/web/src/components/chat/directory/tests/parsers.test.ts
- console/web/src/components/chat/directory/shared.tsx
🚧 Files skipped from review as they are similar to previous changes (47)
- packages/console-ui/component-names.mjs
- iii-directory/ui/package.json
- iii-directory/ui/page.tsx
- iii-directory/ui/tsconfig.json
- iii-directory/Cargo.toml
- console/web/src/lib/console-api.ts
- iii-directory/ui/src/lib/envelope.ts
- iii-directory/ui/build.mjs
- console/web/package.json
- console/web/src/pages/Memory/components/RulesPanel.tsx
- console/web/src/lib/monaco.ts
- iii-directory/ui/src/function-trigger/index.tsx
- iii-directory/src/lib.rs
- pnpm-workspace.yaml
- console/web/src/components/function-trigger/FunctionTriggerCard.tsx
- iii-directory/ui/src/lib/format.ts
- iii-directory/src/ui.rs
- iii-directory/README.md
- console/web/src/components/ui/MarkdownPreview.tsx
- workers-dev/src/config.rs
- workers-dev/README.md
- iii-directory/src/main.rs
- iii-directory/ui/src/lib/widgets.tsx
- console/web/src/lib/syntax.tsx
- console/web/src/components/function-trigger/renderer-registry.tsx
- iii-directory/src/fs_source.rs
- workers-dev/src/runtime.rs
- iii-directory/src/functions/mod.rs
- iii-directory/build.rs
- iii-directory/ui/src/page/browser.tsx
- workers-dev/src/status.rs
- iii-directory/ui/src/configuration/index.tsx
- packages/console-ui/index.d.ts
- console/web/src/lib/console-ui-conformance.test.ts
- iii-directory/src/functions/prompts.rs
- iii-directory/ui/src/function-trigger/UpdateViews.tsx
- workers-dev/src/tui/mod.rs
- iii-directory/ui/src/page/index.tsx
- workers-dev/src/discover.rs
- console/web/src/components/ui/CodeEditor.tsx
- iii-directory/src/functions/update.rs
- iii-directory/ui/src/function-trigger/PromptsViews.tsx
- iii-directory/ui/src/function-trigger/parsers.ts
- iii-directory/ui/src/function-trigger/SkillsViews.tsx
- iii-directory/ui/src/function-trigger/RegistryViews.tsx
- iii-directory/src/functions/skills.rs
- workers-dev/src/orchestrator.rs
| [data-iii-ui="iii-directory"] .dir-ui-error { | ||
| padding: 8px 12px; | ||
| border-top: 1px solid var(--color-rule-2); | ||
| font-family: var(--font-mono, ui-monospace, monospace); | ||
| font-size: 12px; | ||
| color: var(--color-alert); | ||
| word-break: break-word; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
if rg -nP 'word-break\s*:\s*break-word' iii-directory/ui/styles.css; then
echo "Deprecated word-break value remains."
exit 1
fiRepository: iii-hq/workers
Length of output: 219
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate config files =="
git ls-files | rg '(^|/)(\.([cp]stylelintrc(.*))|stylelint\.config\.(cjs|mjs|js|ts|yaml|yml)|package\.json)$' || true
echo "== stylelint-related config snippets =="
for f in $(git ls-files | rg '(^|/)(\.([cp]stylelintrc(.*))|stylelint\.config\.(cjs|mjs|js|ts|yaml|yml)|package\.json)$' || true); do
echo "--- $f"
case "$f" in
*package.json) rg -n '"stylelint"|"stylelint-|word-break|break-word' "$f" || true ;;
*) rg -n 'word-break|break-word|deprecated|css-word-break|config' "$f" || true ;;
esac
done
echo "== package dependencies =="
if [ -f package.json ]; then
node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json','utf8'));
for (const k of ['dependencies','devDependencies','peerDependencies']) {
if (p[k]) console.log(k, p[k]);
}
JS
fi
echo "== stylelint config files =="
git ls-files | rg '(^|/)\.?stylelintrc.*$|stylelint\.config\.(cjs|mjs|js|ts|yaml|yml)$' || trueRepository: iii-hq/workers
Length of output: 1897
🌐 Web query:
MDN CSS word-break break-word deprecated overflow-wrap anywhere
💡 Result:
The CSS value word-break: break-word is deprecated [1][2]. It is maintained in specifications primarily for backward compatibility with legacy content [3][4]. Authors are advised against using it in new style sheets [5][6]. For managing text overflow, the modern and recommended approach is to use the overflow-wrap property [6]. The following comparison clarifies the relationship between these properties: 1. Recommended Alternative: The functionality previously associated with word-break: break-word is now effectively covered by overflow-wrap: anywhere [7][8]. This value allows otherwise unbreakable strings (such as long words or URLs) to be broken at any point to prevent overflow, and it considers these break opportunities when calculating min-content intrinsic sizes [9][8]. 2. Legacy Behavior: When specified, word-break: break-word behaves as a combination of word-break: normal and overflow-wrap: anywhere [1][2]. Because of this, it can cause different layout results compared to overflow-wrap: break-word, as the latter does not consider soft wrap opportunities when calculating min-content intrinsic sizes [9][7][8]. In summary, you should avoid word-break: break-word [5]. Use overflow-wrap: anywhere (or overflow-wrap: break-word depending on your specific requirements regarding intrinsic sizing) to handle text wrapping and prevent container overflow [9][8][6].
Citations:
- 1: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/word-break
- 2: https://github.com/mdn/content/blob/main/files/en-us/web/css/reference/properties/word-break/index.md
- 3: https://drafts.csswg.org/css-text/
- 4: [css-text-3] Implement or unship word-break:break-word w3c/csswg-drafts#2390
- 5: [css-text-3] Normatively disallow break-word w3c/csswg-drafts#4087
- 6: https://web-platform-dx.github.io/web-features-explorer/features/word-break-break-word/
- 7: https://stackoverflow.com/questions/66724509/overflow-wrap-break-word-vs-word-break-break-word
- 8: https://stackoverflow.com/questions/56618668/do-overflow-wrap-break-word-and-word-break-break-word-ever-behave-differen
- 9: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/overflow-wrap
Replace deprecated word-break: break-word.
Use word-break: normal plus overflow-wrap: anywhere for long error values instead.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 401-401: Deprecated keyword "break-word" for property "word-break" (declaration-property-value-keyword-no-deprecated)
(declaration-property-value-keyword-no-deprecated)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@iii-directory/ui/styles.css` around lines 395 - 401, Update the .dir-ui-error
rule to replace deprecated word-break: break-word with word-break: normal and
add overflow-wrap: anywhere, preserving the existing error styling.
Source: Linters/SAST tools
What
CodeEditorcomponent (@iii-dev/console-ui) was reimplemented on Monaco: lazy-loaded in its own chunk, workers bundled by Vite (fully offline), and a theme derived at runtime from the design tokens so it followshtml[data-theme]in both themes. Every editing surface uses it — injected worker UIs pick it up at runtime for zero bundle bytes, and the Memory rules editor drops its raw textarea for it.console:script/console:styleassets), joined by a skills & prompts browser/editor page (#/ext/directory) with split edit/preview, backed by newdirectory::skills::update/directory::prompts::updatefunctions.--ui-watch(or the TUIwkey) spawnspnpm watchin a worker'sui/and armsIII_<WORKER>_UI_WATCH, so open console tabs hot-swap worker UI on every rebuild.CodeEditor; never bundle an editor into a worker asset) and a new standaloneconsole/SKILL.mdteaches the whole workflow to out-of-repo authors (npm install @iii-dev/console-ui,cargo add iii-console-ui). The SOP requires keeping the skill in sync.Why
The Prism-overlay textarea was fine for small edits but wrong for real markdown/JSON authoring, and per-worker editors would each ship megabytes to duplicate it. Backing the single shared
CodeEditorwith Monaco upgrades the console and every worker UI at once while keeping "the console owns the editor" as contract. Moving directory rendering into the worker is the injectable-UI design eating its own dogfood: the directory can now evolve its UI without a console release.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Style