Skip to content

fix: keep tool tokens valid during active long-running jobs - #6323

Open
mvanhorn wants to merge 1 commit into
nexu-io:mainfrom
mvanhorn:fix/4910-refresh-active-run-tool-token
Open

fix: keep tool tokens valid during active long-running jobs#6323
mvanhorn wants to merge 1 commit into
nexu-io:mainfrom
mvanhorn:fix/4910-refresh-active-run-tool-token

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

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 noteAgentActivity path, 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_INVALID at 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

  • UI — new page / dialog / panel / menu item / setting / empty state in apps/web or apps/desktop (including Electron menu bar)
  • Keyboard shortcut — new or changed
  • CLI / env var — new od subcommand or flag, new tools-dev / tools-pack flag, or new OD_* env var
  • API / contract — new /api/* endpoint, new SSE event, or changed shape in packages/contracts
  • Extension point — new entry under skills/, design-systems/, design-templates/, or craft/, or change to the skills protocol
  • i18n keys — added new translation keys (see TRANSLATIONS.md for the locale workflow)
  • New top-level dependency — adding any new entry to the root package.json (dependencies or devDependencies); workspace-package package.json files are out of scope. Include a paragraph on what we get vs. what bytes we ship (see CONTRIBUTING.md → Code style)
  • Default behavior change — changes what existing users experience without opting in (default model, default setting, file/SQLite schema, auto-network on startup, auto-install)
  • None — internal refactor, docs, tests, or translation update only

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 in apps/web, apps/desktop, packages/contracts, or the root package.json is 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 under apps/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.ts drives 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.ts covers 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.

@lefarcen

lefarcen commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thanks @mvanhorn — refreshing the run-scoped tool token lease on real agent activity is a sensible fix for the TOOL_TOKEN_INVALID path in #4910. I'll follow up here on the PR metadata/details shortly.

💡 To drive this PR to merge hands-free, paste this to your AI coding agent (Claude Code / Codex / opencode / Cursor …):
Take over nexu-io/open-design#6323 until it merges — read https://raw.githubusercontent.com/nexu-io/looper/main/skills/pr-takeover/SKILL.md and follow it.

@lefarcen
lefarcen requested a review from mrcfps August 1, 2026 08:25
@lefarcen lefarcen added size/M PR changes 100-300 lines risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps type/bugfix Bug fix labels Aug 1, 2026
@lefarcen

lefarcen commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The Why + validation are already strong here, especially the way you separate the concrete TOOL_TOKEN_INVALID defect from the broader output-quality complaints in #4910. Could you add a short What users will see section from the user's point of view, and since the diff here is daemon/tests-only, either attach the screenshots required by the checked UI box or uncheck that box if the change is actually non-visual?

@lefarcen lefarcen added the needs-validation Runtime change detected; needs human or /explore agent validation. label Aug 1, 2026
@lefarcen

lefarcen commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🧪 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 mrcfps left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

@lefarcen
lefarcen requested a review from AmyShang-alt August 1, 2026 08:38
@lefarcen

lefarcen commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-validation Runtime change detected; needs human or /explore agent validation. risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps size/M PR changes 100-300 lines type/bugfix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Open Design's Output Quality Greatly Degraded....

3 participants