odysseus/routes
RaresKeY 981652358e
fix(agent): allow remaining actions for an approved task (#6113)
* fix(agent): allow remaining actions for an approved task

* fix(agent): make approval continuation control-only

* fix(ci): preserve approval taint and cache-buster contract

* fix(ui): keep tool approvals in current chat

* fix(ui): route tool approvals through chat submit

* test(ui): pin approval submit routing

* fix(agent): complete approval denial flow

* fix(ui): avoid duplicate ask-user close icon

* fix(agent): retain approved tool in continuation set

* revert(ui): keep PR 6113 scoped to approval continuation

* fix(agent): add task and chat approval scopes

* fix(ui): prevent duplicate ask-user close icon

* feat(ui): add ask-user option shortcuts

* fix(compare): route ask-user choices per pane

* fix(agent): keep skill-test approvals to a single action

The chat card now reuses the wire value `approve` to mean chat-session
scope, and `consume()` returned `allow_remaining_actions=True` for it
unconditionally. The skill-test approval route was never updated: it still
sends `approve` meaning "once", and its button still reads "Allow once",
but the grant it got back set `approval_gate_bypassed` for the rest of the
resumed run. That surface wraps the skill body and every transcript byte
as untrusted context, so it is the last place where one click should
ungate everything that follows.

Give `consume()` an explicit `allow_continuation` flag. Callers that own a
resumable chat keep the scope the user picked; callers that do not — the
skill tester, unattended audits — get SINGLE_ACTION and the gate re-arms
behind the sealed action, which is what their label promises.

* fix(ui): cache-bust every module the approval click depends on

chatStream.js, compare/index.js and compare/stream.js all changed
behaviour but kept their old `?v=`, while chat.js and chatRenderer.js were
bumped. A returning browser therefore serves the new chat.js — which now
deliberately leaves the composer empty and clicks the send button — next to
the cached chatStream.js that has no interceptor. With an empty composer
that button sits at `data-mode="newchat"`, so the click opens a new chat
and the approval is dropped.

Bump the three, and version compare/stream.js's chatRenderer import to
match everyone else's so the ask_user keydown listener binds to one module
instance instead of two.

* fix(ui): keep the digit shortcuts off tool approval cards

With an approval card on screen and focus anywhere outside an input, a bare
`1` fired `approve_task` — the widest of the three grants — with no
modifier and no confirmation. That card is the one control whose entire
purpose is deliberate consent after untrusted context influenced the run,
and Deny sits at 3.

Label the card with its kind and skip the shortcut for approvals. Ordinary
ask_user questions keep 1-3.

* fix(compare): restore a pane's ask_user card instead of dropping the choice

renderAskUserCard removes the card as soon as onSubmit accepts, but the
resume loop gave up silently after 10s if the originating stream still owned
the pane. The user saw the click land, the card vanish, and nothing happen,
with no way to get it back.

Re-render the card on that deadline and say why. The reroll case still
returns without sending — that choice belongs to a stream that no longer
exists.

* refactor(chat): drop the unreachable deny branch

`if decision != "deny"` is always true — the deny path returns a
StreamingResponse a few lines above. It reads as if deny still falls
through to the toggle restore.

---------

Co-authored-by: Léo <leograndcontact@gmail.com>
2026-08-19 08:01:34 -06:00
..
admin_wipe refactor(routes): move admin_wipe domain into routes/admin_wipe/ subpackage (#5659) 2026-07-21 12:39:27 +02:00
cleanup refactor(routes): move cleanup domain into routes/cleanup/ subpackage (#5658) 2026-07-21 12:38:32 +02:00
compare refactor(routes): move compare domain into routes/compare/ subpackage (#5660) 2026-07-21 12:40:09 +02:00
contacts Merge remote-tracking branch 'origin/dev' 2026-07-07 00:51:34 +00:00
document refactor(routes): move document domain into routes/document/ subpackage (#5885) 2026-08-04 03:54:55 -06:00
gallery fix(gallery): handle MPS float64 mask inputs (#5903) 2026-08-12 01:23:43 +01:00
history fix(history): defer full transcript hydration to model sends (#5929) 2026-08-10 19:39:21 +01:00
mcp fix(mcp): stop assuming http://localhost:7000 for the OAuth callback (#6032) 2026-08-15 23:09:01 -06:00
memory fix(memory): don't let an unreadable store get overwritten with an empty one (#5831) 2026-08-06 02:33:50 -06:00
note fix(reminders): support OAuth SMTP accounts (#5649) 2026-07-22 16:03:35 +02:00
research feat(auth): define Default/Local owner contract (#5795) 2026-08-15 20:27:26 +01:00
search refactor(routes): move search domain into routes/search/ subpackage (#5779) 2026-07-28 22:26:29 +02:00
task refactor(routes): move task domain into routes/task/ subpackage 2026-08-17 10:07:17 +08:00
vault refactor(routes): move vault domain into routes/vault/ subpackage (#5780) 2026-08-03 20:44:00 +02:00
webhook refactor(routes): move webhook domain into routes/webhook/ subpackage (#5781) 2026-08-03 20:44:31 +02:00
__init__.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
_validators.py fix(hwfit): validate remote SSH detection targets (#3718) 2026-06-11 00:43:49 +02:00
admin_wipe_routes.py refactor(routes): move admin_wipe domain into routes/admin_wipe/ subpackage (#5659) 2026-07-21 12:39:27 +02:00
api_token_routes.py fix(api): normalize non-object JSON bodies to empty dict in token PATCH (#3976) 2026-06-15 18:05:15 +01:00
assistant_routes.py feat(auth): define Default/Local owner contract (#5795) 2026-08-15 20:27:26 +01:00
auth_routes.py fix(auth): derive the session cookie Secure flag from the request scheme (#6048) 2026-08-16 22:56:36 +01:00
backup_routes.py fix(memory): don't let an unreadable store get overwritten with an empty one (#5831) 2026-08-06 02:33:50 -06:00
calendar_routes.py fix(calendar): keep default creation transactional (#5806) 2026-08-12 04:51:52 +01:00
chat_helpers.py fix(agent): allow remaining actions for an approved task (#6113) 2026-08-19 08:01:34 -06:00
chat_routes.py fix(agent): allow remaining actions for an approved task (#6113) 2026-08-19 08:01:34 -06:00
chatgpt_subscription_routes.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
cleanup_routes.py refactor(routes): move cleanup domain into routes/cleanup/ subpackage (#5658) 2026-07-21 12:38:32 +02:00
codex_routes.py fix: improve uploaded document retrieval and deep research reuse (#4784) 2026-06-27 19:24:17 +01:00
compare_routes.py refactor(routes): move compare domain into routes/compare/ subpackage (#5660) 2026-07-21 12:40:09 +02:00
contacts_routes.py Merge remote-tracking branch 'origin/dev' 2026-07-07 00:51:34 +00:00
cookbook_helpers.py fix(cookbook): activate local Windows venv in bash runner (#5734) 2026-08-18 16:19:33 +02:00
cookbook_output.py fix(cookbook): report dead finished downloads as completed instead of stopped (#4025) 2026-06-15 15:26:55 +09:00
cookbook_routes.py fix(cookbook): activate local Windows venv in bash runner (#5734) 2026-08-18 16:19:33 +02:00
copilot_routes.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
device_flow.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
diagnostics_routes.py feat(ui): add real-time diagnostic logs console (#974) 2026-06-15 10:32:51 +02:00
document_helpers.py refactor(routes): move document domain into routes/document/ subpackage (#5885) 2026-08-04 03:54:55 -06:00
document_routes.py refactor(routes): move document domain into routes/document/ subpackage (#5885) 2026-08-04 03:54:55 -06:00
editor_draft_routes.py Ignore invalid editor draft payloads (#1533) 2026-06-03 14:07:03 +09:00
email_helpers.py fix(email): route summaries through shared LLM adapter (#5841) 2026-08-08 23:06:41 +02:00
email_pollers.py fix(email): route summaries through shared LLM adapter (#5841) 2026-08-08 23:06:41 +02:00
email_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
embedding_routes.py feat(paths): abstract runtime path logic for frozen distribution packages (#969) 2026-06-15 17:44:10 +01:00
emoji_routes.py refactor(constants): single source of truth for data dir (#3368) 2026-06-08 09:58:52 +02:00
font_routes.py Keep compact font family names together (#1263) 2026-06-03 14:24:30 +09:00
gallery_helpers.py Merge dev into main for testing 2026-06-28 14:07:23 +00:00
gallery_routes.py Merge dev into main for testing 2026-06-28 14:07:23 +00:00
history_routes.py refactor(routes): move history domain into routes/history/ subpackage (#5090) 2026-07-04 13:36:35 +02:00
hwfit_routes.py Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
mcp_routes.py refactor(routes): move mcp domain into routes/mcp/ subpackage (#5899) 2026-08-11 02:24:55 -06:00
memory_routes.py refactor(routes): move memory domain into routes/memory/ subpackage (#5007) 2026-06-30 17:52:14 +02:00
model_routes.py fix(models): show API models by default (#6089) 2026-08-17 13:41:04 +02:00
note_routes.py refactor(routes): move note domain into routes/note/ subpackage (#5236) 2026-07-20 13:52:30 +02:00
personal_routes.py fix(personal): run directory indexing off the event loop (#5634) 2026-08-15 10:12:47 +01:00
prefs_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
preset_routes.py fix(ai): offload model resolution from async paths 2026-06-28 00:48:35 +01:00
research_routes.py refactor(routes): move research domain into routes/research/ subpackage 2026-06-28 14:34:11 +01:00
search_routes.py refactor(routes): move search domain into routes/search/ subpackage (#5779) 2026-07-28 22:26:29 +02:00
session_routes.py fix(history): defer full transcript hydration to model sends (#5929) 2026-08-10 19:39:21 +01:00
shell_routes.py Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
signature_routes.py Constrain signature uploads to PNG data (#2844) 2026-06-05 13:17:43 +02:00
skills_routes.py fix(agent): allow remaining actions for an approved task (#6113) 2026-08-19 08:01:34 -06:00
stt_routes.py refactor(uploads): centralize upload byte-limits in upload_limits.py (#3364) (#3518) 2026-06-09 01:24:30 +02:00
task_routes.py refactor(routes): move task domain into routes/task/ subpackage 2026-08-17 10:07:17 +08:00
tts_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
upload_routes.py fix(stabilization): harden attachment lifecycle and agent guard signals (#5420) 2026-07-11 15:14:14 +01:00
vault_routes.py refactor(routes): move vault domain into routes/vault/ subpackage (#5780) 2026-08-03 20:44:00 +02:00
webhook_routes.py refactor(routes): move webhook domain into routes/webhook/ subpackage (#5781) 2026-08-03 20:44:31 +02:00
workspace_routes.py feat(agent): confine agent file/shell tools to a selectable workspace (#3665) 2026-06-11 18:17:54 +02:00