fix: keep tool tokens valid during active long-running jobs - #6323
fix: keep tool tokens valid during active long-running jobs#6323mvanhorn wants to merge 1 commit into
Conversation
|
Thanks @mvanhorn — refreshing the run-scoped tool token lease on real agent activity is a sensible fix for the
|
|
The |
|
🧪 Queued for QA validation — this PR has changes that need a manual QA pass before it's merged. Nothing needed from you; we'll update here once it's validated. Thanks for the contribution! 🙏 |
mrcfps
left a comment
There was a problem hiding this comment.
@mvanhorn I reviewed the complete daemon token-lifecycle diff. The sliding lease refreshes only live tokens for the active run, preserves the original token and authorization scope, expires again after inactivity, and remains covered by the existing child-exit/finalization revocation paths. I also verified the focused unit and daemon integration coverage (9 tests), daemon and full-workspace typechecks, and the repository guard; all passed. Thanks for the careful, narrowly scoped fix and the strong regression coverage — this should make long-running media workflows much more reliable. 🙏
🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.|
One last PR-body detail before this moves forward: could you also fill in Bug fix verification, and either attach the screenshots implied by the checked UI box or uncheck that box if the change is daemon-only? That, together with a short What users will see note, should bring the description in line with the current template. |
Why
Treat the existing 15-minute token TTL as an inactivity lease instead of an absolute limit: add a registry operation that refreshes every live token for a run by updating its expiry metadata and replacing its expiry timer. Invoke that operation from the chat run's existing
noteAgentActivitypath, before its disabled-watchdog early return, so genuine agent events keep the same injected token usable without introducing token replacement or exposing new credentials. Preserve all current security boundaries: endpoint and operation allowlists do not change, unknown or already-revoked tokens cannot be revived, an inactive lease still expires, and run finalization or child exit still revokes immediately.Issue #4910 reports multi-hour agent-driven video runs that produced poor HyperFrames outputs, while the same general request eventually produced a usable result with Ollama. The pasted run transcript provides one concrete daemon failure: after the agent repaired and rendered several compositions, a final media rerender was rejected with
TOOL_TOKEN_INVALID. The daemon currently mints a run-scoped tool token with a fixed 15-minute TTL, so an otherwise active run can lose media access long before a multi-step video workflow finishes. This plan covers that reproducible token-lifecycle defect only; it does not claim to resolve the broader provider-dependent quality and token-usage complaints.Closes #4910
What users will see
Nothing visible in the UI. A long-running agent session that keeps emitting activity no longer fails partway through with
TOOL_TOKEN_INVALIDat the 15-minute mark, so multi-step workflows that previously died mid-run now finish. An idle run still loses its token on the same 15-minute window as before.Surface area
apps/weborapps/desktop(including Electron menu bar)odsubcommand or flag, newtools-dev/tools-packflag, or newOD_*env var/api/*endpoint, new SSE event, or changed shape inpackages/contractsskills/,design-systems/,design-templates/, orcraft/, or change to the skills protocolTRANSLATIONS.mdfor the locale workflow)package.json(dependenciesordevDependencies); workspace-packagepackage.jsonfiles are out of scope. Include a paragraph on what we get vs. what bytes we ship (seeCONTRIBUTING.md→ Code style)The 15-minute tool-token TTL becomes an inactivity lease for every run, with no opt-in. That is the point of the fix, but it does change how long a token can live for existing users, so it belongs under this box rather than under "None". The change is confined to
apps/daemon; nothing inapps/web,apps/desktop,packages/contracts, or the rootpackage.jsonis touched.Screenshots
None — the change is daemon-only. The four changed files are
apps/daemon/src/server.ts,apps/daemon/src/tool-tokens.ts, and two test files underapps/daemon/tests/.Bug fix verification
Reproduced against the failure in #4910: the daemon mints a run-scoped tool token with a fixed 15-minute TTL, so a run that is still actively emitting agent events loses media access at the 15-minute mark and the next media call is rejected with
TOOL_TOKEN_INVALID.Verified by two new test files:
apps/daemon/tests/tool-token-active-run-lease.test.tsdrives a run past the original 15-minute deadline while emitting agent activity, and asserts the same token still validates afterwards with unchanged run, project, endpoint, and operation scope. It also asserts a run whose inactivity watchdog is disabled still refreshes the lease, since activity bookkeeping runs before the watchdog early return.apps/daemon/tests/tool-tokens.test.tscovers the boundaries: a refreshed token still expires once the renewed inactivity window elapses; an unknown, expired, or manually revoked token is never recreated by a refresh; activity on one run refreshes only that run's token and leaves a concurrent run's expiry independent; and child exit or terminal finalization still leaves no active token for the run.Both suites are new in this PR and are the regression coverage for the defect; neither existed before, so the behaviour above was previously untested.
Validation
An active run refreshes its token before the original 15-minute deadline, and the same token validates after that original deadline with unchanged run, project, endpoint, and operation scope.
A refreshed token expires once the renewed inactivity window elapses, while an unknown, expired, or manually revoked token is never recreated by a run refresh.
Activity from one concurrent run refreshes only that run's token; another run under the same project retains its independent expiry.
A daemon integration run whose fake agent emits activity causes the run's token lease to refresh, and child exit or terminal finalization still leaves no active token for that run.
Runs with the inactivity watchdog disabled still refresh the token lease when agent activity arrives, matching the existing requirement that activity bookkeeping occurs before the watchdog early return.
AI was used for assistance.