feat: ship inline chat to everyone - #1284
Conversation
|
Greptile (@greptileai) review |
|
Claude (@claude) review |
|
Claude finished Nikhil (@shadowfax92)'s task in 1m 37s —— View job Code Review
LGTM. This is a clean, minimal feature-ship change. Here's the breakdown: What changed
- const supportsInlineChat =
- supports(Feature.ALPHA_FEATURES_SUPPORT) &&
- supports(Feature.NEWTAB_CHAT_SUPPORT)
+ const supportsInlineChat = supports(Feature.NEWTAB_CHAT_SUPPORT)Why it's correct
One thing worth confirming (non-blocking)
|
✅ Tests passed — 1307/1311
|
Greptile SummaryThis PR ships the new-tab inline chat to all users by removing the
Confidence Score: 5/5Safe to merge — the change is a single boolean simplification with a clear, well-tested fallback path for unsupported BrowserOS versions. The only modification is dropping the alpha-flag requirement from a capability check. The capability system and routing helpers are unchanged, and the side-panel fallback for users below BrowserOS 0.40.0.0 continues to work exactly as before. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[AgentCommandHome mounts] --> B{capabilitiesLoading?}
B -- yes --> C[llmRoutingMode = 'wait']
B -- no --> D{supports NEWTAB_CHAT_SUPPORT?}
D -- yes --> E[llmRoutingMode = 'inline-chat']
D -- no --> F[llmRoutingMode = 'sidepanel']
E --> G[navigate to /home/chat]
F --> H[openSidePanelWithSearch]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[AgentCommandHome mounts] --> B{capabilitiesLoading?}
B -- yes --> C[llmRoutingMode = 'wait']
B -- no --> D{supports NEWTAB_CHAT_SUPPORT?}
D -- yes --> E[llmRoutingMode = 'inline-chat']
D -- no --> F[llmRoutingMode = 'sidepanel']
E --> G[navigate to /home/chat]
F --> H[openSidePanelWithSearch]
Reviews (2): Last reviewed commit: "feat: ship inline chat to everyone" | Re-trigger Greptile |
She was completely blocked and said so in the most reassuring words available: "all 26 candidates look already done". Almost every refusal was `boundary_taken` - "its files are owned by a live task" - and in four cases the live task owning them was the one she had opened for that same issue. A task whose dispatch fails stays `queued`, and nothing in the system ever looked at `queued`. `reapStalledWorkers` handles `running`; a task created and never started simply holds its file boundary. Its own issue can then never be chosen again. That is a deadlock, not idleness, and two of the four frozen issues were the start of the T27 migration. "Never dispatched" is read from the runner's record rather than the clock: a stream that opened leaves `streamOutcome` set and a completed turn leaves `completedTurns`, and either means the runner took it however long ago. Ten minutes of grace, which is two autonomy ticks - one tick could be a slot that was full, which is ordinary backpressure. Cancelled rather than failed. Nobody failed; the dispatch did not happen, and `cancelled` says that without accusing a worker that never ran. Driven in the release. The reaper fired four times - browseros-ai#1281 queued 279 minutes, browseros-ai#1283 237, browseros-ai#1285 190, browseros-ai#1284 184, none with a turn ever opened - and twenty seconds later she chose browseros-ai#1284 and started ring 01 herself. 904 e2e checks in 84 scenarios, up from 896.
…enty-six The line she printed when she could not choose: All 26 candidate(s) look already done — nothing to choose The truth, once the reasons were counted rather than assumed: Nothing to choose from 26 candidate(s): 16 held by another task, 7 already has a worker, 1 looks already done, 1 no boundary One case out of twenty-six, presented as all of them, in the most reassuring words available. It is the same sentence that hid the queued deadlock for hours, and fixing that deadlock did not fix the sentence. The boundary refusal is named too. "Its files are owned by a live task" is anonymous, and sixteen of those in a row read as a busy swarm - when five of the holders are tasks escalated to the operator hours ago, sitting in `awaitingReview` because their send-backs are exhausted and holding their paths while they wait. It now says which task, in which state, and for how long: Skipping browseros-ai#1284: its files are held by gHashTag/trios#1284 (queued, 2m) A block nobody can attribute is a block nobody clears. Nothing about the mechanism changed: those five tasks are correctly escalated and correctly still hold their boundaries - a person has to decide, and a bee editing the same files meanwhile would collide with work waiting to be accepted. What changed is that the block is now visible and has a name. 910 e2e checks.
…s mine The reaper I added earlier tonight cancels a task whose dispatch never happened, which unfroze four issues. It also created a cycle: the next tick chooses the same issue, dispatch refuses at the end of that tick because the provider key resolves empty, the task sits queued, ten minutes later the reaper cancels it again. browseros-ai#1284 and browseros-ai#1285 went round that way through branches r1, r2, r3, r4, cutting a fresh worktree each round while nothing could possibly start. A permanent deadlock and a permanent spin are both wrong, and the second was introduced by the fix for the first. Worth saying plainly rather than filing under "further improvement". The key is the condition that makes the whole round pointless, so it belongs before the choosing rather than after it. `autonomyBlockReason` now refuses the tick outright: Not picking up work: the provider key resolves empty, so nothing could be dispatched even if an issue were chosen Ordering is deliberate and tested. Consent and budget still outrank it - those are decisions, and a decision outranks a resource - but the key outranks capacity, because with a full swarm and no key the actionable fact is the key. The live transport is the only one gated, the same exemption the dispatch precheck already makes for the harness. What the diagnostics added an hour ago finally said out loud, and what makes this the right fix rather than a guess: fetchIssueBody.primary_failed | Keychain item not found for ai.browseros.trios fetchIssueBody | HTTP 403 worker.api_key_unavailable | API key for zai resolved empty Neither the GitHub token nor the provider key was reachable in that window. The authenticated fallback I added is only as good as the token, and there is still no working second source for either - `~/.trios/config.json` holds both keys with zero-length values. 915 e2e checks in 87 scenarios, up from 910.
Summary
NEWTAB_CHAT_SUPPORTas the BrowserOS compatibility boundary.Design
AgentCommandHomealready owns the support boolean that feedsresolveHomeLlmRoutingMode. This change narrows that boolean to the real compatibility capability, so supported BrowserOS versions use inline chat without requiring alpha opt-in.Test plan
bun test apps/agent/screens/agent-command/home-compose.helpers.test.tsbun run lintbun run typecheckbun run test:mainbun run checkbun run build:agent