Skip to content

feat: cache-aware foreground tool timeouts - #422

Merged
code-yeongyu merged 9 commits into
mainfrom
feat/cache-aware-tool-timeouts
Jul 28, 2026
Merged

feat: cache-aware foreground tool timeouts#422
code-yeongyu merged 9 commits into
mainfrom
feat/cache-aware-tool-timeouts

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

The bash tool (and, cross-repo, omo's task tool) now size how long they block in the foreground on the active model's prompt-cache lifetime instead of a fixed 600s ceiling. A 5-minute cache yields a ~270s safe ceiling (30s buffer); a still-running foreground command is handed to a background session alive at that deadline rather than blocking past cache expiry or being killed.

Blocking past the cache lifetime expires the cache and forces a full re-read on the next request. Sizing the ceiling by the TTL keeps the cache warm without losing the running work.

Plan: .omo/plans/cache-aware-tool-timeouts.md

What changed

Layer Change
packages/ai New browser-safe resolvePromptCacheTtlSeconds(model, env?). Mirrors each API's own resolveCacheRetention precedence verbatim (anthropic falls back to "long" and honors the bare process.env.PI_CACHE_RETENTION branch; openai/bedrock fall back to "short"; pi-messages returns undefined). Unknown-cache APIs (google, mistral, pi-messages) and retention "none"undefined.
packages/coding-agent core promptCache settings (cacheAwareTimeouts default true, safetyBufferSeconds default 30), prompt-cache-budget.ts, typed ExtensionContext.getPromptCacheSafeWaitSeconds(), advisory PI_PROMPT_CACHE_SAFE_WAIT_SECONDS env bridge refreshed on session start/reload/model select.
bash-timeout extension resolveEffectiveBashTimeouts() caps the recommended max at the budget; the policy prompt is rebuilt per before_agent_start and names the ceiling + the prompt-cache reason.
terminal extension The previously declared-but-unwired terminal.timeoutAction is now implemented and drives foreground auto-detach at deadment D.

The explicit timeout T is never shortened — it stays the native PTY kill deadline, and still applies after a detach.

Zero behavior change when no budget applies

TTL unknown (google), retention none, or cacheAwareTimeouts: false → the injected default and recommended max keep today's values and the policy prompt is byte-identical under strict === (pinned by test).

Detach linearization

Exit > abort > detach. When D fires: queue one microtask → check exit → check abort → install the settled-aware onExit gate → recheck → commit detach and remove the abort listener synchronously. An exit or abort at/before that point wins; an abort after commit is ignored (kill_bash becomes the stop surface). readDelta() is called exactly once at detach, so bash_output continues without duplication.

Verification

All green in single runs:

  • packages/ai: prompt-cache-ttl.test.ts 24/24 (RED 23/23 captured first)
  • packages/coding-agent: 8 suites (terminal-bash-auto-detach, terminal-extension, terminal-settings-notify, terminal-monitor, bash-timeout-extension, prompt-cache-budget, prompt-surface-stale-wait-idioms, 5943 regression) → 89/89
  • root npm run checkexit 0 (includes check:browser-smoke)

Real-surface QA (real PTY, D shrunk to 5s, timeoutAction: background):

bash({ command: "echo BEFORE_DETACH; sleep 8; echo AFTER_DETACH; sleep 60", timeout: 12 })
-> detached at exactly 5.0s
-> {"bash_id":"bash_1","background":true,"auto_detached":true,"status":"running"}
-> partial output: BEFORE_DETACH  (AFTER_DETACH correctly absent)
-> "(not killed; the original 12s timeout still applies)"
-> bash_output at ~10s: AFTER_DETACH, with BEFORE_DETACH NOT repeated (delta cursor advanced once)

senpi-qa channels: pty-drive 8/8 (native backend, no orphans), cli-smoke 8/8, mock-loop --with-tool --api anthropic-messages 4/4. The real ~/.senpi/agent/auth.json sha256 was asserted unchanged in every run.

Note on the browser boundary

The first implementation imported supportsPromptCaching directly from bedrock-converse-stream.ts, which dragged the AWS SDK into the browser-safe root and broke check:browser-smoke with 18 unresolved node:* errors. Fixed by moving the pure compat predicates into the browser-safe utility, with the API modules importing from it and re-exporting — one source of truth, no divergence risk.

Companion change

The omo side (packages/senpi-task bounded foreground wait + promoteToBackground) landed separately in the omo repo as 6846ef8c2, written against the frozen contract (feature-detected getter, then env, else unbounded) so it works with older senpi too.


Summary by cubic

Makes foreground tool waits cache‑aware. bash now caps foreground blocking to the active model’s prompt‑cache TTL (minus a buffer) and auto‑detaches before expiry so the cache stays warm and the work continues in the background. Defaults are safe; set promptCache.cacheAwareTimeouts: false to opt out and terminal.timeoutAction: "background" to enable auto‑detach.

  • New Features

    • packages/ai: Added browser‑safe resolvePromptCacheTtlSeconds(model, env?) with PROMPT_CACHE_TTL_SHORT_SECONDS/PROMPT_CACHE_TTL_LONG_SECONDS. Moved pure compat predicates into a shared utility and re‑exported from API modules.
    • packages/coding-agent: New promptCache settings (cacheAwareTimeouts default true, safetyBufferSeconds default 30). Exposed getPromptCacheSafeWaitSeconds() on the extension context and mirrored the budget in PI_PROMPT_CACHE_SAFE_WAIT_SECONDS (cleared when absent).
    • bash-timeout extension: Caps the recommended max timeout to the cache‑safe budget and updates the policy prompt to explain the cache reason. Explicit timeout values are unchanged.
    • terminal extension: Implemented terminal.timeoutAction. With background, foreground runs that exceed the budget auto‑detach at the deadline; the original native timeout still applies. No change when the budget is absent or timeoutAction is kill.
  • Bug Fixes

    • bash-timeout extension: Tolerates a missing extension context in timeout handlers to avoid crashes when the context isn’t provided.

Written for commit 4cada46. Summary will update on new commits.

Review in cubic

@code-yeongyu
code-yeongyu merged commit 2e26dee into main Jul 28, 2026
11 checks passed
@code-yeongyu
code-yeongyu deleted the feat/cache-aware-tool-timeouts branch July 28, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant