Repository navigation
feat: onboarding feedback — Chromium setup step, pinned response language, ports, and no polling - #1329
Conversation
…uage, ports, and no polling
Findings from a first-run test of the harness template (TypeSafe Judge,
Claude Sonnet 5.5, "Create an app or tool") and their fixes:
- browser: one Chromium resolver for sessions, doctor and scraping
(configured, $CHROME, system, managed download, Playwright, Puppeteer
caches); browser::chromium::status and browser::chromium::install (Chrome
for Testing into ~/.cache/iii/browser, progress events); a
`chromium_missing:` error that says what to do.
- ade: a Browser step in the setup wizard when Chromium is missing (one-click
download with progress, or manual install), a palette command and an inline
"Install Chromium" action; recommended providers stay unchecked after a
connection; new chats start on the provider's default, then the router's
first model; http_host from the stored configuration; manifest default
0.0.0.0; no idle wake-ups in the compose watch.
- harness: the response language is detected from the user's first message,
pinned for the session and named in the session context and in
agent_trigger's schema; invalid tool-call JSON is reported as such, with
the text around the error; binding expiry, orphaned-turn recovery and
discovery are event-driven; a duplicate fire of a spent binding no longer
writes a second outcome.
- llm-router: degraded tool arguments carry `_invalid` {error, offset,
context} for text that is not JSON.
- session-manager: collapsed agent_trigger calls keep function and
description, so labels survive a reload.
- http: http::status (host, port, local URL); manifest default 0.0.0.0.
- queue: wake-ups on enqueue and due times instead of a 100 ms poll;
engine events instead of 1 s re-checks.
- ide, ADE Workers page, judge UI, browser UI, console-ui: triggers instead
of timers (git and turn-log watches, compose-operation events).
- iii-directory prompts: the session's response language, not the latest
message's.
- eval: SendOptions.reasoning; regenerated schema goldens.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedToo many files! This PR contains 198 files, which is 98 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configuration
⛔ Files ignored due to path filters (3)
📒 Files selected for processing (198)
You can disable this status message by setting the
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 |
skill-check — worker0 verified, 82 skipped (no docs/).
Four for four. Nicely done. |
…kills-changed notices
The harness now names the session's response language in the system prompt
("Response language: English (from the user's first message) …") once it can
tell it from the first message. The integration runner's expected prompt
lacked that line, so the scripted router's hash check rejected the first
request: INT-011/019/020/023 and the Console Playwright specs failed or timed
out. The expected prompt now carries a `__RESPONSE_LANGUAGE__` marker that
expand.rs fills with the harness's own detector on the actual send message.
iii-directory downloads registry skills shortly after boot; the resulting
"available skills have changed" notice could land inside a scenario depending
on network timing. The scripted router ignores the skills-changed and
skills-removed notices when matching, like the registry-changed notice, and
evidence no longer counts that notice as a user message.
…ate instead of the tour
- Models, Browser, Judge and Ready say what happens in plain words: no sign-in
file paths, CLI paths or versions, worker versions, function ids, key
references, configuration entries or install folders. What stays explicit
is every worker a step adds ("Adds a new worker: provider-claude-code"),
with one line on iii being composable: each worker adds behavior and lives
in worker-compose.yaml. Failure messages keep the error and its hint.
- Ready drops "Start the tour" (and the tour code that only served it) for a
Finish button and the project's example prompts. They come from
onboarding.yaml in the project folder, read on each call by the new
console::onboarding::prompts (invalid entries skipped, a missing or broken
file shows none). Each prompt names its agent profile and a priority list
of { provider, model, effort? }. Clicking one opens a new chat with the
prompt in the message box (not sent), that profile selected, and the first
listed model the router serves here at that effort.
- Registry providers without a recipe say "Set it up after it is added."
instead of their registry description.
- ADE README: the Browser step, the example prompts and onboarding.yaml.
…e's unit tests The integration crate now links the harness for its response-language detector, so `cargo test -p harness-integration` builds the harness, whose build script wants pnpm to bundle the UI. The validate job has no Node; it now creates a stub ui/dist and sets SKIP_UI_BUILD=1, as ci.yml already does for iii-directory. These tests never serve the harness UI.
…OT-3619) main drifted after #1329 (harness gained whatlang/regex; console-ui moved to iii-sdk 0.23.0). Adds whatlang 0.18.0 + allocator-api2 0.2.21 and dependency edges only; no existing crate version changes. Unblocks approval-gate rust lint + test and interface boot smoke.
…#1353) * chore(ci): drop stale "harness enables iii-stream" comment (MOT-3619) * chore(fp): note that the stream:: pipe block covers deprecated iii-stream (MOT-3619) * chore(mcp): document stream:: hidden prefix as deprecated iii-stream (MOT-3619) * chore(lsp): tag iii-stream trigger types deprecated in completions and hover (MOT-3619) * chore(permissions): mark the stream::set deny as deprecated iii-stream (MOT-3619) * chore(docs): stop suggesting iii-stream in guidelines and worker-yaml docs (MOT-3619) * chore(image-resize): drop unused iii-stream from the example engine config (MOT-3619) * chore(openwiki): point the multi-instance note at an owned trigger type (MOT-3619) * chore(console-ui): use a state trigger in the useWorkerLive config example (MOT-3619) * chore(harness): drop unused iii-stream from test stacks and mark stream triggers deprecated in docs (MOT-3619) * chore(approval-gate): drop unused iii-pubsub from the testkit engine config (MOT-3619) * chore(approval-gate): refresh stale Cargo.lock for --locked builds (MOT-3619) main drifted after #1329 (harness gained whatlang/regex; console-ui moved to iii-sdk 0.23.0). Adds whatlang 0.18.0 + allocator-api2 0.2.21 and dependency edges only; no existing crate version changes. Unblocks approval-gate rust lint + test and interface boot smoke.
Summary
We ran a first-run test of the harness template, recorded end to end, with the published workers:
iii project init -t harness, moved to its own ports;That run surfaced a set of problems. This PR fixes them:
http's manifests declared127.0.0.1while their code binds0.0.0.0.The same test then ran against workers built from this branch. Every one of those problems is gone (see Evidence).
The harness template follows in iii-hq/templates#106: README sections for ports, network access, Judge and Chromium, and the builder profile reading the public URL from
http::status.Improvements
Chromium for the
browserworker (new)browser/src/chromium/), used by sessions,browser::doctorand the scraping tiers alike. It checks, in order:executable;$CHROME;chromium_missing:and says what to do.browser::chromium::status {}(read-only, allowed for agents) reports:browser::chromium::install { force? }returns immediately and downloads Chrome for Testing (Stable, about 200 MB) into~/.cache/iii/browser. The base folder can be changed withIII_BROWSER_CACHE_DIR.dittoon macOS.--versionbefore it is used.browser::chromium-install-progress: phases plus downloaded and total bytes.--no-sandbox, as Playwright does. Status reportssandboxed: false.chromium_source, and the worker logs a warning at startup when no Chromium is found.ADE setup wizard
browser::*call whose error containschromium_missing.compose-operationevents;engine::workers-available;Setup wizard: plain words, and example prompts instead of the tour
secret://…) and configuration entries;worker-compose.yaml. Failure messages keep the error and its hint.onboardingworker, along with the tour code that only served it. Instead there is a Finish button and the project's example prompts.onboarding.yamlin the project folder, read on each call by the newconsole::onboarding::prompts. Invalid entries are skipped, and a missing or broken file shows none.{ provider, model, effort? }.Starting model
Response language (harness, iii-directory, session-manager, ADE)
agent_trigger's schema said "in the user's language", without ever naming it.whatlang, after stripping code, mentions, quotes, URLs and paths), with a confidence of at least 0.8;agent_trigger'sdescriptionschema.harnessandiii-directoryuse "the response language named in your session context" instead of the latest message.session::messages-tailnow keepsfunctionanddescriptionof collapsedagent_triggercalls, so the ADE keeps the label after a reload instead of showing the bare function id.Malformed tool calls (llm-router, harness, providers)
coder::update-filewas not truncated. The model wrote invalid JSON (a stray]). Witheager_input_streaming, the API no longer validates tool input, and the harness told the model its call had been cut off.degraded_argumentsadds_invalid{error, offset, context}for text that is not JSON.max_output_tokens;incomplete_json;invalid_json, showing the parser message and the text near the error.eager_input_streamingcomments in both providers are corrected.data:line it has to drop.Ports and network access
http::status(new, read-only, allowed for agents) returns{ host, port, url, last_reload_error }. Agents and the builder profile use it instead of assuminghttp://127.0.0.1:3111.httpandademanifests declaredhost/http_host: 127.0.0.1, while the binaries bind0.0.0.0. With aconfig_override, Compose builds the value from the manifest defaults, so the bind address changed depending on whether an override existed. Both now declare0.0.0.0.http_hostin the ADE is now read from the stored configuration at startup, soconfig_overridecan set it;--http-hoststill wins.No polling
shell::exec(git) on every focus change, throttled to 3 s, so every click in the ADE produced tracesshell::git-changedtrigger (new: HEAD, index, refs and worktrees watched with 200 ms batching); a non-repository folder is not re-read until.gitappearsshell::turns::listevery 1.5 s while a turn runsshell::turns::changedtrigger (new)compose::operationevery 0.7 to 3 scompose-operationevents, subscribed before the operation startsstate::listsweep every 30 sexpires_at; a full pass at boot and on worker connect/disconnectstate::list_keysevery 120 sengine::workers-availableevents and failed enqueuesengine::workers::listevery 1 s per call in flightpoll_interval_msis deprecated and ignoredengine::functions::infoengine::functions-available/engine::workers-availableRuntime.addBinding)browser::sessions::listevery 15 ssession-updatedloadeventuseWorkerLive(console-ui)Other fixes
harness::on-engine-change,harness::on-compose-operationandqueue::on-engine-changeare denied to agents;http::statusandbrowser::chromium::statusare allowed.poll_interval_mskey is no longer sent byharness,evalandsentinel.evalcompiles again:SendOptions.reasoning(from feat: providers declare default models and thinking levels; harness and ADE start on them #1306), with its schema goldens regenerated.Evidence
Before, with the published workers (ade 1.9.52, harness 1.8.44, browser 0.2.25):
httpstops withAddress in useon 3111, and:3111/todo-appanswers another project's 404.Recording (MP4, 4 min)
After, with workers built from this branch and the same prompt:
httpruns on 3137 throughconfig_override. The agent reads it fromhttp::status, openshttp://127.0.0.1:3137/todo-appin the downloaded Chromium, and verifies it.Recording (MP4, 2 min 24 s)
Plainer wizard and example prompts (second commit): Codex is left out, Chromium downloads, then the Judge, Ready with the template's prompts, and Build a TODO app. The chat opens on Create an app or tool with Claude Sonnet 5.5 Medium and the prompt ready to send.
Recording (MP4, 54 s)
Test plan
Rust,
cargo testfor each changed worker:harness-integration --lib116CI checks run locally:
cargo fmt --all -- --checkandcargo clippy --locked --all-targets -- -D warnings(plus--all-featureswhere the CI uses it) are clean;validate_worker.pypasses for every changed worker;.github/scriptspytest: 321 passed.Frontends:
pnpm build(tsc -b && vite build) passes;End to end: a project generated from the template, with these workers and Chromium hidden, went through:
It shows English labels,
http::status→:3137, the page verified in the downloaded Chromium, and a single "Trigger fired" card for the compose wake.CI:
harness-integrationruns locally against iii 0.24.5-rc.2, with all 35 scenarios passing and Console Playwright 16/16. The integration runner now expects the response-language line, and ignores the boot-time "skills changed" notice that could land inside a scenario. The validate job stubs the harness UI bundle (SKIP_UI_BUILD=1), since the integration crate now links the harness. Reproduced without pnpm on PATH: 118 unit tests pass, 41 fixtures are valid, andactionlintis clean.Plainer wizard and example prompts:
pnpm buildpasses;cargo test: 165 passed, with clippy and fmt clean;smoke-init.shpasses.End to end, a project generated from docs(harness): ports, network access, Judge and Chromium; the builder reads the http port templates#106 shows the four prompts. Clicking one prefills the composer and selects the profile and Claude Sonnet 5.5 Medium.
Language detection: English and Portuguese prompts are detected (confidence 1.0 and 0.93). Prompts too short to tell ("Create a todo app with a notes field") stay unset instead of guessing.
Notes
origin/main:icon-size-conformance(DeviceSignIn) andMermaidDiagram;ProviderConfigurationPanelis flaky only under the full suite;bddsuites of iii-directory (32 registry/network scenarios) and session-manager (10 live-engine scenarios);e2e_rabbitmqneeds Docker.engine::functions-availableis itself a 5 s hash comparison. It should fire on register/unregister and cover schema changes.harness::sweep-pendingcron.waitFor(selector)and the scrapling challenge loops.compose::logslong-poll (Compose has no log stream).