Add deterministic Ask-to-Act handoff action - #3030
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@16Miku is attempting to deploy a commit to the esokullu's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
🟡 Changes recommended
Attachment-backed retries lose their files, and fallback parsing does not enforce the declared strict schema.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds a structured Ask-to-Act classifier and one-click Act-mode retry flow across both browser builds.
Changes:
- Adds handoff schema, prompt, parser, and post-response classification.
- Adds the localized handoff button, styling, and retry integration.
- Adds mirrored regression coverage and test isolation.
File summaries
| File | Description |
|---|---|
test/run.js |
Adds classifier and integration regression coverage. |
src/chrome/src/agent/agent.js |
Runs and emits Ask-mode handoff classification. |
src/chrome/src/agent/planner.js |
Defines the handoff schema, prompt, builder, and parser. |
src/chrome/src/ui/sidepanel.js |
Renders and binds the Act retry action. |
src/chrome/styles/sidepanel.css |
Styles the handoff button. |
src/chrome/src/ui/locales/en.js |
Adds English handoff strings. |
src/chrome/src/ui/locales/ar.js |
Adds Arabic locale keys. |
src/chrome/src/ui/locales/bn.js |
Adds Bengali locale keys. |
src/chrome/src/ui/locales/de.js |
Adds German locale keys. |
src/chrome/src/ui/locales/es.js |
Adds Spanish locale keys. |
src/chrome/src/ui/locales/fa.js |
Adds Persian locale keys. |
src/chrome/src/ui/locales/fr.js |
Adds French locale keys. |
src/chrome/src/ui/locales/he.js |
Adds Hebrew locale keys. |
src/chrome/src/ui/locales/hi.js |
Adds Hindi locale keys. |
src/chrome/src/ui/locales/id.js |
Adds Indonesian locale keys. |
src/chrome/src/ui/locales/ja.js |
Adds Japanese locale keys. |
src/chrome/src/ui/locales/ko.js |
Adds Korean locale keys. |
src/chrome/src/ui/locales/ms.js |
Adds Malay locale keys. |
src/chrome/src/ui/locales/nl.js |
Adds Dutch locale keys. |
src/chrome/src/ui/locales/pl.js |
Adds Polish locale keys. |
src/chrome/src/ui/locales/pt.js |
Adds Portuguese locale keys. |
src/chrome/src/ui/locales/ru.js |
Adds Russian locale keys. |
src/chrome/src/ui/locales/th.js |
Adds Thai locale keys. |
src/chrome/src/ui/locales/tl.js |
Adds Tagalog locale keys. |
src/chrome/src/ui/locales/tr.js |
Adds Turkish locale keys. |
src/chrome/src/ui/locales/uk.js |
Adds Ukrainian locale keys. |
src/chrome/src/ui/locales/vi.js |
Adds Vietnamese locale keys. |
src/chrome/src/ui/locales/zh.js |
Adds Chinese locale keys. |
src/firefox/src/agent/agent.js |
Mirrors handoff classification and emission. |
src/firefox/src/agent/planner.js |
Mirrors handoff schema and parsing. |
src/firefox/src/ui/sidepanel.js |
Mirrors the Act retry action. |
src/firefox/styles/sidepanel.css |
Mirrors handoff button styling. |
src/firefox/src/ui/locales/en.js |
Adds English handoff strings. |
src/firefox/src/ui/locales/ar.js |
Adds Arabic locale keys. |
src/firefox/src/ui/locales/bn.js |
Adds Bengali locale keys. |
src/firefox/src/ui/locales/de.js |
Adds German locale keys. |
src/firefox/src/ui/locales/es.js |
Adds Spanish locale keys. |
src/firefox/src/ui/locales/fa.js |
Adds Persian locale keys. |
src/firefox/src/ui/locales/fr.js |
Adds French locale keys. |
src/firefox/src/ui/locales/he.js |
Adds Hebrew locale keys. |
src/firefox/src/ui/locales/hi.js |
Adds Hindi locale keys. |
src/firefox/src/ui/locales/id.js |
Adds Indonesian locale keys. |
src/firefox/src/ui/locales/ja.js |
Adds Japanese locale keys. |
src/firefox/src/ui/locales/ko.js |
Adds Korean locale keys. |
src/firefox/src/ui/locales/ms.js |
Adds Malay locale keys. |
src/firefox/src/ui/locales/nl.js |
Adds Dutch locale keys. |
src/firefox/src/ui/locales/pl.js |
Adds Polish locale keys. |
src/firefox/src/ui/locales/pt.js |
Adds Portuguese locale keys. |
src/firefox/src/ui/locales/ru.js |
Adds Russian locale keys. |
src/firefox/src/ui/locales/th.js |
Adds Thai locale keys. |
src/firefox/src/ui/locales/tl.js |
Adds Tagalog locale keys. |
src/firefox/src/ui/locales/tr.js |
Adds Turkish locale keys. |
src/firefox/src/ui/locales/uk.js |
Adds Ukrainian locale keys. |
src/firefox/src/ui/locales/vi.js |
Adds Vietnamese locale keys. |
src/firefox/src/ui/locales/zh.js |
Adds Chinese locale keys. |
Review details
Files not reviewed (5)
- src/chrome/src/ui/locales/bn.js: Generated file
- src/chrome/src/ui/locales/hi.js: Generated file
- src/chrome/src/ui/locales/ru.js: Generated file
- src/chrome/src/ui/locales/th.js: Generated file
- src/chrome/src/ui/locales/uk.js: Generated file
- Files reviewed: 50/55 changed files
- Comments generated: 4
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Addressed the review findings in
Validation:
The Vercel check remains blocked by external deployment authorization, unchanged from the earlier PR run. |
There was a problem hiding this comment.
🟡 Changes recommended
The classifier can delay completed Ask turns, and attachment payloads are retained without a bounded lifetime.
Get a fresh assessment by requesting another Copilot review.
Review details
Files not reviewed (5)
- src/chrome/src/ui/locales/bn.js: Generated file
- src/chrome/src/ui/locales/hi.js: Generated file
- src/chrome/src/ui/locales/ru.js: Generated file
- src/chrome/src/ui/locales/th.js: Generated file
- src/chrome/src/ui/locales/uk.js: Generated file
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
src/chrome/src/agent/agent.js:19980
- The classifier call has no short, classifier-specific deadline, while both
processMessagepaths await this method before returning. A slow or unsupported provider can therefore keep the completed Ask turn in the processing state for the normal LLM request timeout (or longer while reading a response body), preventing the user from sending another message and delaying non-streamed results. Please either run this best-effort classification outside the original request's critical path or cap it with a small abortable timeout.
src/firefox/src/agent/agent.js:17764 - The classifier call has no short, classifier-specific deadline, while both
processMessagepaths await this method before returning. A slow or unsupported provider can therefore keep the completed Ask turn in the processing state for the normal LLM request timeout (or longer while reading a response body), preventing the user from sending another message and delaying non-streamed results. Please either run this best-effort classification outside the original request's critical path or cap it with a small abortable timeout.
- Files reviewed: 50/55 changed files
- Comments generated: 2
- Review effort level: Balanced
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Addressed the latest review findings in db5130e:\n\n- Added a dedicated 5-second abortable deadline for the best-effort Ask-to-Act classifier in both Chrome and Firefox, so a slow provider cannot hold the completed Ask turn for the normal request timeout.\n- Added a 30-second bounded lifetime for assistant fallback retry payloads, including attachment copies, while preserving the existing button retry cleanup.\n- Added mirrored regression coverage for the deadline, timeout fail-closed behavior, attachment retention, and payload expiry.\n\nValidation:\n- |
There was a problem hiding this comment.
🟡 Changes recommended
The handoff blocks completion, mishandles inherited selection scope, and bypasses Chrome streaming cost state.
Get a fresh assessment by requesting another Copilot review.
Review details
Files not reviewed (5)
- src/chrome/src/ui/locales/bn.js: Generated file
- src/chrome/src/ui/locales/hi.js: Generated file
- src/chrome/src/ui/locales/ru.js: Generated file
- src/chrome/src/ui/locales/th.js: Generated file
- src/chrome/src/ui/locales/uk.js: Generated file
Suppressed comments (5)
Previously missed (3) — in code that hasn't changed since the last review.
src/chrome/src/agent/agent.js:19969
- Inherited selection-grounding is missed here. Follow-up turns intentionally omit
runOptions.sourceGrounding;_selectionGroundedRunOptionsreconstructs it only inside the completed inner call, while the durable scope remains inselectionGroundingScopes. Such a follow-up can therefore render this Act handoff even thoughrejectSelectionScopedModewill refuse the button when clicked. Guard the durable scope as well.
src/firefox/src/agent/agent.js:17753 - Inherited selection-grounding is missed here. Follow-up turns intentionally omit
runOptions.sourceGrounding;_selectionGroundedRunOptionsreconstructs it only inside the completed inner call, while the durable scope remains inselectionGroundingScopes. Such a follow-up can therefore render this Act handoff even thoughrejectSelectionScopedModewill refuse the button when clicked. Guard the durable scope as well.
src/chrome/src/ui/locales/es.js:178 - These new strings remain English in every non-English locale in both browser trees, so localized users get an English CTA and accessible hint amid translated mode controls. The repository expects locale dictionaries to contain translated copy (see
test/run.js:41555-41574); provide translations for these keys across the mirrored locale files.
src/firefox/src/agent/agent.js:34658
- The streaming path also awaits the best-effort classifier before releasing the run and returning the answer, so classifier latency or the 5-second timeout keeps the completed Ask turn busy. This should be decoupled from foreground completion rather than making the optional handoff part of the critical response path.
src/chrome/src/agent/agent.js:41648 - The streaming path also awaits the best-effort classifier before releasing the run and returning the answer, so classifier latency or the 5-second timeout keeps the completed Ask turn busy. This should be decoupled from foreground completion rather than making the optional handoff part of the critical response path.
- Files reviewed: 50/55 changed files
- Comments generated: 3
- Review effort level: Balanced
Decouple best-effort handoff classification from completion, preserve cost accounting and selection-scope guards, and localize the new handoff strings across browser builds. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Implemented the latest review fixes in commit
Validation: |
There was a problem hiding this comment.
🟡 Changes recommended
Unescaped classifier boundaries permit prompt-structure injection, and valid short replies or off-screen actions can miss the handoff.
Get a fresh assessment by requesting another Copilot review.
Review details
Files not reviewed (5)
- src/chrome/src/ui/locales/bn.js: Generated file
- src/chrome/src/ui/locales/hi.js: Generated file
- src/chrome/src/ui/locales/ru.js: Generated file
- src/chrome/src/ui/locales/th.js: Generated file
- src/chrome/src/ui/locales/uk.js: Generated file
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
src/chrome/src/agent/planner.js:817
- These interpolated values can contain newlines and literal
<user_request>/<assistant_answer>tags, so an attacker-controlled page title or page-derived answer can break the classifier's data boundaries.sanitizeTextonly strips control characters and truncates; unlikesanitizePlannerPageFieldabove, it does not neutralize boundary markup. Encode the fields as structured JSON or strip/escape every reserved delimiter before building this classifier message.
src/firefox/src/agent/planner.js:817 - These interpolated values can contain newlines and literal
<user_request>/<assistant_answer>tags, so an attacker-controlled page title or page-derived answer can break the classifier's data boundaries.sanitizeTextonly strips control characters and truncates; unlikesanitizePlannerPageFieldabove, it does not neutralize boundary markup. Encode the fields as structured JSON or strip/escape every reserved delimiter before building this classifier message.
- Files reviewed: 50/55 changed files
- Comments generated: 4
- Review effort level: Balanced
| || typeof finalResponse !== 'string' | ||
| || finalResponse.trim().length < 8 |
| configureRetryButton(btn, retryPayload); | ||
| content.appendChild(btn); |
| || typeof finalResponse !== 'string' | ||
| || finalResponse.trim().length < 8 |
| configureRetryButton(btn, retryPayload); | ||
| content.appendChild(btn); |
Encode classifier inputs as untrusted JSON data, allow short non-empty answers, and keep asynchronously rendered handoff actions visible. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Implemented the latest review fixes in commit
Validation: |
|
Manual validation completed after the latest changes:
Automated validation remains green: |
|
Additional manual validation completed with the OpenRouter channel:
This confirms the Ask-to-Act handoff works end-to-end with an OpenRouter model as well as the previously documented WebBrain Compass flow. The local OpenAI-compatible Proxy/Kimi observation remains a provider-specific compatibility/timeout follow-up, not a regression in the core handoff flow. |
Summary
Fixes #3029 by adding a structured Ask-to-Act handoff signal and a deterministic one-click transition from Ask mode to Act mode.
What changed
mode_handoff(act/none) classifier schema, prompt, message builder, and parser.ask_mode_handoffupdate only for a validatedactresult.Switch to Act & retryaction that reuses the existing retry payload and mode-switching flow.Validation
node test/run.js— 2306 passed, 0 failednode --checkManual verification (WebBrain Compass)
Test page:
https://the-internet.herokuapp.com/loginRequest:
Observed:
Switch to Act & retrybutton appeared below the answer.requires_state_change: trueandrequires_submission: false.An earlier run with a local OpenAI-compatible proxy and
kimi-k2.6did not show the button; the main Ask response remained correct and the fail-closed fallback applied. The Compass end-to-end flow is verified; provider-specific structured-output compatibility may warrant follow-up.Scope
No changes were made to the main branch, no upstream branches were force-updated, and no submission action is introduced by the handoff button itself.