@code-yeongyu/senpi 2026.9.24-2 → 2026.9.24-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/bundle/chunks/{anthropic-messages-UPLQFNTT.js → anthropic-messages-UYDVRFAS.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-UHPJ2C4D.js → app-server-command-OTRHYRIB.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-XAR2E66I.js → azure-openai-responses-DODWR4W6.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
- package/dist/bundle/chunks/{chunk-WISJJQ4K.js → chunk-6Q6DGME2.js} +1 -1
- package/dist/bundle/chunks/{chunk-YWO3OBYK.js → chunk-77ACEMYL.js} +1 -1
- package/dist/bundle/chunks/chunk-ELFCNCBY.js +11 -0
- package/dist/bundle/chunks/{chunk-WTSAB6AE.js → chunk-FD34HSJJ.js} +2 -2
- package/dist/bundle/chunks/{chunk-2PLPSKHD.js → chunk-HZAKOVHN.js} +1 -1
- package/dist/bundle/chunks/chunk-JBOV6VNK.js +8 -0
- package/dist/bundle/chunks/{chunk-YBC274GY.js → chunk-KMJXSXRX.js} +3 -3
- package/dist/bundle/chunks/{chunk-JRQSHZPP.js → chunk-OZCB6BP3.js} +4 -3
- package/dist/bundle/chunks/{chunk-NQAVM5XL.js → chunk-SFYHCFRO.js} +1 -1
- package/dist/bundle/chunks/{chunk-ONR57UMO.js → chunk-TTY5BHCG.js} +1 -1
- package/dist/bundle/chunks/{chunk-YKU45B65.js → chunk-UM43CBL4.js} +156 -98
- package/dist/bundle/chunks/{chunk-NGHOUIPR.js → chunk-WM5FVFAP.js} +2 -2
- package/dist/bundle/chunks/{chunk-NKVUDCGZ.js → chunk-ZKZAATFM.js} +1 -1
- package/dist/bundle/chunks/{cli-main-O5Y3TBID.js → cli-main-TX6I4X4F.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-B5QMFONL.js → google-generative-ai-VIEFECKJ.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-O2TGMVWF.js → google-vertex-Q64CKFID.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-Y33OIZBU.js → help-fast-path-ZGKPSDFO.js} +1 -1
- package/dist/bundle/chunks/{host-command-WJOL27Q7.js → host-command-BMHJ4YUD.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-YBFXYFZP.js → host-lifecycle-2GZAGSGW.js} +1 -1
- package/dist/bundle/chunks/{interactive-host-runtime-XVTF3NUD.js → interactive-host-runtime-YI75GFD5.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-OO3NGM4G.js → interactive-mode-UI5Q6FGY.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-6MKBBOKF.js → multi-session-host-D6HMI3RQ.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-CK7T4WNM.js → openai-codex-responses-YSGZZDD5.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-OPQKN7FH.js → openai-completions-4CLXDDHJ.js} +3 -3
- package/dist/bundle/chunks/openai-responses-IBFGBAJP.js +2 -0
- package/dist/bundle/chunks/{package-manager-cli-BMEWLAI2.js → package-manager-cli-3UWH3ZZS.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-ZFA6ELXJ.js → rotation-stream-NATO6IMN.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-5653CV65.js → rpc-mode-LXIZHJSJ.js} +1 -1
- package/dist/bundle/chunks/{session-picker-PPYK56TA.js → session-picker-BP7THCWF.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +190 -131
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +3 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +42 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/build.js +3 -0
- package/dist/core/dynamic-prompt/build.js.map +1 -1
- package/dist/core/dynamic-prompt/handoff.d.ts +16 -0
- package/dist/core/dynamic-prompt/handoff.d.ts.map +1 -0
- package/dist/core/dynamic-prompt/handoff.js +16 -0
- package/dist/core/dynamic-prompt/handoff.js.map +1 -0
- package/dist/core/dynamic-prompt/index.d.ts +1 -0
- package/dist/core/dynamic-prompt/index.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/index.js +1 -0
- package/dist/core/dynamic-prompt/index.js.map +1 -1
- package/dist/core/dynamic-prompt/policies.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/policies.js +2 -1
- package/dist/core/dynamic-prompt/policies.js.map +1 -1
- package/dist/core/dynamic-prompt/style.js +2 -2
- package/dist/core/dynamic-prompt/style.js.map +1 -1
- package/dist/core/environment-context.d.ts +13 -0
- package/dist/core/environment-context.d.ts.map +1 -1
- package/dist/core/environment-context.js +31 -0
- package/dist/core/environment-context.js.map +1 -1
- package/dist/core/extensions/builtin/anthropic-bash/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/anthropic-bash/index.js +1 -1
- package/dist/core/extensions/builtin/anthropic-bash/index.js.map +1 -1
- package/dist/core/extensions/builtin/anthropic-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/anthropic-web-search/index.js +1 -1
- package/dist/core/extensions/builtin/anthropic-web-search/index.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.js +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.js.map +1 -1
- package/dist/core/extensions/builtin/cache-keepalive/index.d.ts +1 -0
- package/dist/core/extensions/builtin/cache-keepalive/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cache-keepalive/index.js +4 -0
- package/dist/core/extensions/builtin/cache-keepalive/index.js.map +1 -1
- package/dist/core/extensions/builtin/cache-keepalive/prewarm-entry.d.ts +21 -0
- package/dist/core/extensions/builtin/cache-keepalive/prewarm-entry.d.ts.map +1 -0
- package/dist/core/extensions/builtin/cache-keepalive/prewarm-entry.js +23 -0
- package/dist/core/extensions/builtin/cache-keepalive/prewarm-entry.js.map +1 -0
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.d.ts +25 -0
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.d.ts.map +1 -0
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.js +86 -0
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +6 -2
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +3 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.js +6 -3
- package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation.js +1 -1
- package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.d.ts +2 -0
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js +2 -0
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +14 -0
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/todo-owed-backstop.d.ts +47 -0
- package/dist/core/extensions/builtin/goal/todo-owed-backstop.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/todo-owed-backstop.js +155 -0
- package/dist/core/extensions/builtin/goal/todo-owed-backstop.js.map +1 -0
- package/dist/core/extensions/builtin/hooks/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/hooks/index.js +6 -2
- package/dist/core/extensions/builtin/hooks/index.js.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.js +1 -1
- package/dist/core/extensions/builtin/imagegen/index.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.js +15 -6
- package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
- package/dist/core/extensions/builtin/openai-image-gen/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/openai-image-gen/index.js +13 -3
- package/dist/core/extensions/builtin/openai-image-gen/index.js.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +12 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +13 -2
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5-5.js +13 -2
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +14 -3
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +15 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +17 -5
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +6 -2
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +11 -2
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +10 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.6.js +12 -4
- package/dist/core/extensions/builtin/prompt-preset/grok-4.6.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js +45 -31
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/index.js +3 -2
- package/dist/core/extensions/builtin/prompt-preset/index.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-code.js +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-code.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +13 -2
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-url-widget.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-url-widget.js +4 -3
- package/dist/core/extensions/builtin/prompt-url-widget.js.map +1 -1
- package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rules/index.js +15 -8
- package/dist/core/extensions/builtin/rules/index.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/commands.d.ts +2 -1
- package/dist/core/extensions/builtin/todotools/commands.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/commands.js +6 -3
- package/dist/core/extensions/builtin/todotools/commands.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/first-turn.d.ts +38 -0
- package/dist/core/extensions/builtin/todotools/first-turn.d.ts.map +1 -0
- package/dist/core/extensions/builtin/todotools/first-turn.js +83 -0
- package/dist/core/extensions/builtin/todotools/first-turn.js.map +1 -0
- package/dist/core/extensions/builtin/todotools/index.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.js +69 -14
- package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -2
- package/dist/core/extensions/builtin/todotools/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/prompt.js +2 -3
- package/dist/core/extensions/builtin/todotools/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts +4 -3
- package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.js +4 -3
- package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/todo-ask.d.ts +13 -0
- package/dist/core/extensions/builtin/todotools/todo-ask.d.ts.map +1 -0
- package/dist/core/extensions/builtin/todotools/todo-ask.js +61 -0
- package/dist/core/extensions/builtin/todotools/todo-ask.js.map +1 -0
- package/dist/core/extensions/builtin/todotools/todo-format.d.ts +30 -2
- package/dist/core/extensions/builtin/todotools/todo-format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/todo-format.js +58 -1
- package/dist/core/extensions/builtin/todotools/todo-format.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/todo-storage.d.ts +5 -2
- package/dist/core/extensions/builtin/todotools/todo-storage.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/todo-storage.js +23 -12
- package/dist/core/extensions/builtin/todotools/todo-storage.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/todo-types.d.ts +14 -0
- package/dist/core/extensions/builtin/todotools/todo-types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/todo-types.js +2 -0
- package/dist/core/extensions/builtin/todotools/todo-types.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.d.ts +3 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.js +23 -8
- package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +5 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +7 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +27 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +53 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +10 -2
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-runtime.d.ts +11 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +13 -0
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/prompt-cache-prefix-request.d.ts +45 -0
- package/dist/core/prompt-cache-prefix-request.d.ts.map +1 -0
- package/dist/core/prompt-cache-prefix-request.js +134 -0
- package/dist/core/prompt-cache-prefix-request.js.map +1 -0
- package/dist/core/settings-manager.d.ts +4 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-shapes.d.ts +5 -0
- package/dist/core/settings-shapes.d.ts.map +1 -1
- package/dist/core/settings-shapes.js.map +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +6 -0
- package/dist/core/usage-totals.js.map +1 -1
- package/docs/extensions.md +22 -0
- package/docs/settings.md +7 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +16 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.js +24 -17
- package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +57 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-prompt-cache.d.ts +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-prompt-cache.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-prompt-cache.js +62 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-prompt-cache.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +12 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +11 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +63 -9
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.lazy.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.lazy.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.lazy.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/prompt-cache-warmers.d.ts +13 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/prompt-cache-warmers.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/prompt-cache-warmers.js +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/prompt-cache-warmers.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/warm-prompt-cache.d.ts +4 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/warm-prompt-cache.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/warm-prompt-cache.js +22 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/warm-prompt-cache.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/google-vertex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +13 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.js +7 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-J7IUURQ6.js +0 -8
- package/dist/bundle/chunks/chunk-MO2U7YRX.js +0 -11
- package/dist/bundle/chunks/openai-responses-QHWM3KPO.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AgentMessage, EMPTY_TOOL_USE_DEMOTION_DIAGNOSTIC } from \"@earendil-works/pi-agent-core\";\nimport type { Goal } from \"./types.ts\";\n\ntype AssistantAgentMessage = Extract<AgentMessage, { role: \"assistant\" }>;\ntype ToolResultAgentMessage = Extract<AgentMessage, { role: \"toolResult\" }>;\n\nexport const GOAL_CONTINUATION_CAP = 8;\nexport const GOAL_STALL_TOOLLESS_THRESHOLD = 3;\nexport const GOAL_REPETITION_HASH_STREAK = 3;\nexport const GOAL_LENGTH_RECOVERY_LIMIT = 1;\n/**\n * Hard budget of automatic continuations without accepted direct user input (#1139).\n * Progress and tool use never refill it: only direct input does. Stays above the\n * #447 distinct-progress pin (50) and an 8-hour monitor-backstop cadence\n * (~120 deliveries at 240s), below the observed 289-continuation incident run.\n */\nexport const GOAL_UNATTENDED_CONTINUATION_LIMIT = 150;\nexport const GOAL_USER_GRACE_DELAY_MS = 10_000;\n\nexport type GoalContinuationPath =\n\t| \"immediate\"\n\t| \"monitorDelayed\"\n\t| \"userGrace\"\n\t| \"sessionStart\"\n\t| \"systemRecovery\"\n\t| \"providerRecovery\";\n\nexport type GoalContinuationInput = {\n\treadonly goal: Goal | null;\n\treadonly isIdle: boolean;\n\treadonly hasPendingMessages: boolean;\n\treadonly path: GoalContinuationPath;\n\treadonly lastStopReason: AssistantAgentMessage[\"stopReason\"] | undefined;\n\treadonly lastTurnWasMalformedToolUse: boolean;\n\treadonly consecutiveContinuations: number;\n\treadonly lastContinuationSignature: string | undefined;\n\treadonly currentSignature: string | undefined;\n\treadonly consecutiveLengthRecoveries: number;\n\treadonly recentNormalizedOutputHashes: readonly string[];\n\treadonly toollessContinuationStreak: number;\n\treadonly continuationPending: boolean;\n\t/** The last turn was rejected (or silently starved) by context size and recovery did not shrink it. */\n\treadonly lastTurnStuckOnContextOverflow: boolean;\n};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason:\n\t\t\t\t| \"not-eligible\"\n\t\t\t\t| \"single-flight\"\n\t\t\t\t| \"cap\"\n\t\t\t\t| \"stale\"\n\t\t\t\t| \"repetition\"\n\t\t\t\t| \"length-exhausted\"\n\t\t\t\t| \"unattended\"\n\t\t\t\t| \"context-overflow\";\n\t };\n\nexport function shouldQueueGoalContinuationWhenIdle(\n\tgoal: Goal | null,\n\tisIdle: boolean,\n\thasPendingMessages: boolean,\n): goal is Goal {\n\treturn goal?.status === \"active\" && isIdle && !hasPendingMessages;\n}\n\nexport function shouldQueueGoalContinuationAfterAgentEnd(\n\tgoal: Goal | null,\n\thasPendingMessages: boolean,\n\tmessages: readonly AgentMessage[],\n): goal is Goal {\n\treturn goal?.status === \"active\" && !hasPendingMessages && didAgentEndCleanly(messages);\n}\n\nfunction didAgentEndCleanly(messages: readonly AgentMessage[]): boolean {\n\tconst lastAssistantIndex = findLastAssistantMessageIndex(messages);\n\tif (lastAssistantIndex === undefined) return false;\n\n\tconst lastAssistant = messages[lastAssistantIndex];\n\tif (lastAssistant?.role !== \"assistant\") return false;\n\tif (!isContinuableStopReason(lastAssistant.stopReason) && !isMalformedToolUseTurn(lastAssistant)) return false;\n\n\tfor (let index = lastAssistantIndex + 1; index < messages.length; index++) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"toolResult\" && isAbortedToolResult(message)) return false;\n\t}\n\treturn true;\n}\n\nfunction findLastAssistantMessageIndex(messages: readonly AgentMessage[]): number | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") {\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isContinuableStopReason(stopReason: AssistantAgentMessage[\"stopReason\"]): boolean {\n\treturn stopReason === \"stop\" || stopReason === \"length\";\n}\n\n// The agent loop demotes a tool-call-less `toolUse` stop to `stop` before `agent_end`, so the\n// original stop reason is gone by the time a goal sees the turn. Accept either shape: the raw\n// message (extensions observing it pre-demotion) or the demotion diagnostic the loop leaves behind.\nexport function isMalformedToolUseTurn(message: AssistantAgentMessage): boolean {\n\tif (message.content.some((content) => content.type === \"toolCall\")) return false;\n\tif (message.stopReason === \"toolUse\") return true;\n\treturn (\n\t\tmessage.stopReason === \"stop\" &&\n\t\t(message.diagnostics ?? []).some((diagnostic) => diagnostic.type === EMPTY_TOOL_USE_DEMOTION_DIAGNOSTIC)\n\t);\n}\n\nfunction isAbortedToolResult(message: ToolResultAgentMessage): boolean {\n\tif (!message.isError) return false;\n\treturn message.content.some((content) => content.type === \"text\" && /\\babort(?:ed)?\\b/i.test(content.text));\n}\n\nexport function evaluateGoalContinuation(input: GoalContinuationInput): GoalContinuationVerdict {\n\t// Re-sending an overflowed context fails identically on every path (#1422).\n\tif (input.goal?.status === \"active\" && input.lastTurnStuckOnContextOverflow) {\n\t\treturn { kind: \"deny\", reason: \"context-overflow\" };\n\t}\n\tif (!isEligibleForGoalContinuation(input)) return { kind: \"deny\", reason: \"not-eligible\" };\n\tif (input.continuationPending) return { kind: \"deny\", reason: \"single-flight\" };\n\tif (hasRepeatedNormalizedOutputHash(input.recentNormalizedOutputHashes))\n\t\treturn { kind: \"deny\", reason: \"repetition\" };\n\tif (isUnattendedBudgetExhausted(input)) return { kind: \"deny\", reason: \"unattended\" };\n\tif (input.consecutiveContinuations >= GOAL_CONTINUATION_CAP) {\n\t\treturn { kind: \"deny\", reason: \"cap\" };\n\t}\n\tif (\n\t\t(input.path === \"immediate\" || input.path === \"userGrace\") &&\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.lastContinuationSignature === input.currentSignature\n\t) {\n\t\treturn { kind: \"deny\", reason: \"stale\" };\n\t}\n\tif (input.lastStopReason === \"length\") {\n\t\tif (input.consecutiveLengthRecoveries >= GOAL_LENGTH_RECOVERY_LIMIT) {\n\t\t\treturn { kind: \"deny\", reason: \"length-exhausted\" };\n\t\t}\n\t\treturn { kind: \"continue\", prompt: \"minimal\", stallNotice: shouldShowStallNotice(input) };\n\t}\n\treturn { kind: \"continue\", prompt: \"full\", stallNotice: shouldShowStallNotice(input) };\n}\n\n/** Produces a stable, whitespace-insensitive representation for repetition detection. */\nexport function normalizeAssistantText(text: string): string {\n\treturn text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\n/** Hashes normalized assistant text with the deterministic 32-bit FNV-1a algorithm. */\nexport function hashAssistantText(text: string): string {\n\tconst normalized = normalizeAssistantText(text);\n\tlet hash = 0x811c9dc5;\n\tfor (let index = 0; index < normalized.length; index++) {\n\t\thash ^= normalized.charCodeAt(index);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Identifies the observable goal progress for stale-continuation admission.\n * Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.\n */\nexport function buildGoalContinuationSignature(\n\tgoal: Pick<Goal, \"id\">,\n\topenTodos: number,\n\ttotalTodos: number,\n\tlastAssistantTextHash: string,\n): string {\n\treturn `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;\n}\n\nexport function hasGoalContinuationProgress(\n\tinput: Pick<GoalContinuationInput, \"lastContinuationSignature\" | \"currentSignature\">,\n): boolean {\n\treturn (\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.currentSignature !== undefined &&\n\t\tinput.lastContinuationSignature !== input.currentSignature\n\t);\n}\n\nexport function continuationTurnUsedTools(messages: readonly AgentMessage[]): boolean {\n\treturn messages.some((message) => {\n\t\tif (message?.role === \"toolResult\") return true;\n\t\treturn message?.role === \"assistant\" && message.content.some((content) => content.type === \"toolCall\");\n\t});\n}\n\nfunction isEligibleForGoalContinuation(input: GoalContinuationInput): boolean {\n\tif (input.goal?.status !== \"active\" || input.hasPendingMessages) return false;\n\tif (input.path === \"systemRecovery\" || input.path === \"providerRecovery\") return true;\n\tif (input.path === \"immediate\") {\n\t\treturn (\n\t\t\tinput.lastTurnWasMalformedToolUse ||\n\t\t\t(input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason))\n\t\t);\n\t}\n\treturn input.isIdle;\n}\n\n/** Monitor-delayed deliveries are exempt: armed-wake waiting is by-design and rate-limited by the cache-aware timer. */\nfunction isUnattendedBudgetExhausted(input: GoalContinuationInput): boolean {\n\tif (input.path === \"monitorDelayed\") return false;\n\treturn (input.goal?.unattendedContinuations ?? 0) >= GOAL_UNATTENDED_CONTINUATION_LIMIT;\n}\n\nfunction hasRepeatedNormalizedOutputHash(hashes: readonly string[]): boolean {\n\tconst latestHash = hashes.at(-1);\n\tif (latestHash === undefined) return false;\n\n\tlet streak = 0;\n\tfor (let index = hashes.length - 1; index >= 0 && hashes[index] === latestHash; index--) {\n\t\tstreak += 1;\n\t}\n\treturn streak >= GOAL_REPETITION_HASH_STREAK;\n}\n\nfunction shouldShowStallNotice(input: GoalContinuationInput): boolean {\n\treturn input.toollessContinuationStreak >= GOAL_STALL_TOOLLESS_THRESHOLD;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AgentMessage, EMPTY_TOOL_USE_DEMOTION_DIAGNOSTIC } from \"@earendil-works/pi-agent-core\";\nimport type { Goal } from \"./types.ts\";\n\ntype AssistantAgentMessage = Extract<AgentMessage, { role: \"assistant\" }>;\ntype ToolResultAgentMessage = Extract<AgentMessage, { role: \"toolResult\" }>;\n\nexport const GOAL_CONTINUATION_CAP = 8;\nexport const GOAL_STALL_TOOLLESS_THRESHOLD = 3;\nexport const GOAL_REPETITION_HASH_STREAK = 3;\nexport const GOAL_LENGTH_RECOVERY_LIMIT = 1;\n/**\n * Hard budget of automatic continuations without accepted direct user input (#1139).\n * Progress and tool use never refill it: only direct input does. Stays above the\n * #447 distinct-progress pin (50) and an 8-hour monitor-backstop cadence\n * (~120 deliveries at 240s), below the observed 289-continuation incident run.\n */\nexport const GOAL_UNATTENDED_CONTINUATION_LIMIT = 150;\nexport const GOAL_USER_GRACE_DELAY_MS = 10_000;\n\nexport type GoalContinuationPath =\n\t| \"immediate\"\n\t| \"monitorDelayed\"\n\t| \"userGrace\"\n\t| \"sessionStart\"\n\t| \"systemRecovery\"\n\t| \"providerRecovery\";\n\nexport type GoalContinuationInput = {\n\treadonly goal: Goal | null;\n\treadonly isIdle: boolean;\n\treadonly hasPendingMessages: boolean;\n\treadonly path: GoalContinuationPath;\n\treadonly lastStopReason: AssistantAgentMessage[\"stopReason\"] | undefined;\n\treadonly lastTurnWasMalformedToolUse: boolean;\n\treadonly consecutiveContinuations: number;\n\treadonly lastContinuationSignature: string | undefined;\n\treadonly currentSignature: string | undefined;\n\treadonly consecutiveLengthRecoveries: number;\n\treadonly recentNormalizedOutputHashes: readonly string[];\n\treadonly toollessContinuationStreak: number;\n\treadonly continuationPending: boolean;\n\t/** The last turn was rejected (or silently starved) by context size and recovery did not shrink it. */\n\treadonly lastTurnStuckOnContextOverflow: boolean;\n};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason:\n\t\t\t\t| \"not-eligible\"\n\t\t\t\t| \"single-flight\"\n\t\t\t\t| \"cap\"\n\t\t\t\t| \"stale\"\n\t\t\t\t| \"repetition\"\n\t\t\t\t| \"length-exhausted\"\n\t\t\t\t| \"unattended\"\n\t\t\t\t| \"context-overflow\";\n\t };\n\nexport function shouldQueueGoalContinuationWhenIdle(\n\tgoal: Goal | null,\n\tisIdle: boolean,\n\thasPendingMessages: boolean,\n): goal is Goal {\n\treturn goal?.status === \"active\" && isIdle && !hasPendingMessages;\n}\n\nexport function shouldQueueGoalContinuationAfterAgentEnd(\n\tgoal: Goal | null,\n\thasPendingMessages: boolean,\n\tmessages: readonly AgentMessage[],\n): goal is Goal {\n\treturn goal?.status === \"active\" && !hasPendingMessages && didAgentEndCleanly(messages);\n}\n\nexport function didAgentEndCleanly(messages: readonly AgentMessage[]): boolean {\n\tconst lastAssistantIndex = findLastAssistantMessageIndex(messages);\n\tif (lastAssistantIndex === undefined) return false;\n\n\tconst lastAssistant = messages[lastAssistantIndex];\n\tif (lastAssistant?.role !== \"assistant\") return false;\n\tif (!isContinuableStopReason(lastAssistant.stopReason) && !isMalformedToolUseTurn(lastAssistant)) return false;\n\n\tfor (let index = lastAssistantIndex + 1; index < messages.length; index++) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"toolResult\" && isAbortedToolResult(message)) return false;\n\t}\n\treturn true;\n}\n\nfunction findLastAssistantMessageIndex(messages: readonly AgentMessage[]): number | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") {\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isContinuableStopReason(stopReason: AssistantAgentMessage[\"stopReason\"]): boolean {\n\treturn stopReason === \"stop\" || stopReason === \"length\";\n}\n\n// The agent loop demotes a tool-call-less `toolUse` stop to `stop` before `agent_end`, so the\n// original stop reason is gone by the time a goal sees the turn. Accept either shape: the raw\n// message (extensions observing it pre-demotion) or the demotion diagnostic the loop leaves behind.\nexport function isMalformedToolUseTurn(message: AssistantAgentMessage): boolean {\n\tif (message.content.some((content) => content.type === \"toolCall\")) return false;\n\tif (message.stopReason === \"toolUse\") return true;\n\treturn (\n\t\tmessage.stopReason === \"stop\" &&\n\t\t(message.diagnostics ?? []).some((diagnostic) => diagnostic.type === EMPTY_TOOL_USE_DEMOTION_DIAGNOSTIC)\n\t);\n}\n\nfunction isAbortedToolResult(message: ToolResultAgentMessage): boolean {\n\tif (!message.isError) return false;\n\treturn message.content.some((content) => content.type === \"text\" && /\\babort(?:ed)?\\b/i.test(content.text));\n}\n\nexport function evaluateGoalContinuation(input: GoalContinuationInput): GoalContinuationVerdict {\n\t// Re-sending an overflowed context fails identically on every path (#1422).\n\tif (input.goal?.status === \"active\" && input.lastTurnStuckOnContextOverflow) {\n\t\treturn { kind: \"deny\", reason: \"context-overflow\" };\n\t}\n\tif (!isEligibleForGoalContinuation(input)) return { kind: \"deny\", reason: \"not-eligible\" };\n\tif (input.continuationPending) return { kind: \"deny\", reason: \"single-flight\" };\n\tif (hasRepeatedNormalizedOutputHash(input.recentNormalizedOutputHashes))\n\t\treturn { kind: \"deny\", reason: \"repetition\" };\n\tif (isUnattendedBudgetExhausted(input)) return { kind: \"deny\", reason: \"unattended\" };\n\tif (input.consecutiveContinuations >= GOAL_CONTINUATION_CAP) {\n\t\treturn { kind: \"deny\", reason: \"cap\" };\n\t}\n\tif (\n\t\t(input.path === \"immediate\" || input.path === \"userGrace\") &&\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.lastContinuationSignature === input.currentSignature\n\t) {\n\t\treturn { kind: \"deny\", reason: \"stale\" };\n\t}\n\tif (input.lastStopReason === \"length\") {\n\t\tif (input.consecutiveLengthRecoveries >= GOAL_LENGTH_RECOVERY_LIMIT) {\n\t\t\treturn { kind: \"deny\", reason: \"length-exhausted\" };\n\t\t}\n\t\treturn { kind: \"continue\", prompt: \"minimal\", stallNotice: shouldShowStallNotice(input) };\n\t}\n\treturn { kind: \"continue\", prompt: \"full\", stallNotice: shouldShowStallNotice(input) };\n}\n\n/** Produces a stable, whitespace-insensitive representation for repetition detection. */\nexport function normalizeAssistantText(text: string): string {\n\treturn text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\n/** Hashes normalized assistant text with the deterministic 32-bit FNV-1a algorithm. */\nexport function hashAssistantText(text: string): string {\n\tconst normalized = normalizeAssistantText(text);\n\tlet hash = 0x811c9dc5;\n\tfor (let index = 0; index < normalized.length; index++) {\n\t\thash ^= normalized.charCodeAt(index);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Identifies the observable goal progress for stale-continuation admission.\n * Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.\n */\nexport function buildGoalContinuationSignature(\n\tgoal: Pick<Goal, \"id\">,\n\topenTodos: number,\n\ttotalTodos: number,\n\tlastAssistantTextHash: string,\n): string {\n\treturn `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;\n}\n\nexport function hasGoalContinuationProgress(\n\tinput: Pick<GoalContinuationInput, \"lastContinuationSignature\" | \"currentSignature\">,\n): boolean {\n\treturn (\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.currentSignature !== undefined &&\n\t\tinput.lastContinuationSignature !== input.currentSignature\n\t);\n}\n\nexport function continuationTurnUsedTools(messages: readonly AgentMessage[]): boolean {\n\treturn messages.some((message) => {\n\t\tif (message?.role === \"toolResult\") return true;\n\t\treturn message?.role === \"assistant\" && message.content.some((content) => content.type === \"toolCall\");\n\t});\n}\n\nfunction isEligibleForGoalContinuation(input: GoalContinuationInput): boolean {\n\tif (input.goal?.status !== \"active\" || input.hasPendingMessages) return false;\n\tif (input.path === \"systemRecovery\" || input.path === \"providerRecovery\") return true;\n\tif (input.path === \"immediate\") {\n\t\treturn (\n\t\t\tinput.lastTurnWasMalformedToolUse ||\n\t\t\t(input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason))\n\t\t);\n\t}\n\treturn input.isIdle;\n}\n\n/** Monitor-delayed deliveries are exempt: armed-wake waiting is by-design and rate-limited by the cache-aware timer. */\nfunction isUnattendedBudgetExhausted(input: GoalContinuationInput): boolean {\n\tif (input.path === \"monitorDelayed\") return false;\n\treturn (input.goal?.unattendedContinuations ?? 0) >= GOAL_UNATTENDED_CONTINUATION_LIMIT;\n}\n\nfunction hasRepeatedNormalizedOutputHash(hashes: readonly string[]): boolean {\n\tconst latestHash = hashes.at(-1);\n\tif (latestHash === undefined) return false;\n\n\tlet streak = 0;\n\tfor (let index = hashes.length - 1; index >= 0 && hashes[index] === latestHash; index--) {\n\t\tstreak += 1;\n\t}\n\treturn streak >= GOAL_REPETITION_HASH_STREAK;\n}\n\nfunction shouldShowStallNotice(input: GoalContinuationInput): boolean {\n\treturn input.toollessContinuationStreak >= GOAL_STALL_TOOLLESS_THRESHOLD;\n}\n"]}
|
|
@@ -12,6 +12,8 @@ type DirectInputLifecycleDependencies = {
|
|
|
12
12
|
* to "send a message to resume"; this callback is what keeps that promise.
|
|
13
13
|
*/
|
|
14
14
|
readonly resumeAfterSuppressedLoad?: (ctx: ExtensionContext, goal: Goal) => Promise<void>;
|
|
15
|
+
/** Fired for every accepted direct (non-extension) input, goal or not. */
|
|
16
|
+
readonly onAcceptedDirectInput?: () => void;
|
|
15
17
|
};
|
|
16
18
|
/** Correlates raw input with admission before changing persisted Goal state. */
|
|
17
19
|
export declare class GoalDirectInputLifecycle {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-input-lifecycle.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/direct-input-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAMrD,KAAK,gCAAgC,GAAG;IACvC,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,YAAY,CAAC;IAC/D,QAAQ,CAAC,wBAAwB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACpE;;;;OAIG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"direct-input-lifecycle.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/direct-input-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAMrD,KAAK,gCAAgC,GAAG;IACvC,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,YAAY,CAAC;IAC/D,QAAQ,CAAC,wBAAwB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACpE;;;;OAIG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,0EAA0E;IAC1E,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5C,CAAC;AAEF,gFAAgF;AAChF,qBAAa,wBAAwB;;IAKpC,YAAY,YAAY,EAAE,gCAAgC,EAEzD;IAED,KAAK,IAAI,IAAI,CAGZ;IAED,iFAAiF;IACjF,uBAAuB,IAAI,IAAI,CAE9B;IAEK,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrE;IAEK,aAAa,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BtF;CACD"}
|
|
@@ -31,6 +31,8 @@ export class GoalDirectInputLifecycle {
|
|
|
31
31
|
this.#candidates.delete(event.inputId);
|
|
32
32
|
const accepted = event.disposition === "started" || event.disposition === "queued";
|
|
33
33
|
this.#dependencies.monitor.resolveDirectInput(event.inputId, accepted);
|
|
34
|
+
if (accepted)
|
|
35
|
+
this.#dependencies.onAcceptedDirectInput?.();
|
|
34
36
|
if (!accepted || candidate.goalId === null)
|
|
35
37
|
return;
|
|
36
38
|
const ref = this.#dependencies.goalStoreRef(ctx);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-input-lifecycle.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/direct-input-lifecycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAE3E,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"direct-input-lifecycle.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/direct-input-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionContext, InputDispositionEvent, InputEvent } from \"../../types.ts\";\nimport { isMechanicalContinuationBlock } from \"./continuation-recovery.ts\";\nimport type { MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { readGoal, resetContinuationStreak, updateGoal } from \"./store.ts\";\nimport type { Goal, GoalStoreRef } from \"./types.ts\";\n\ntype DirectInputCandidate = {\n\treadonly goalId: string | null;\n};\n\ntype DirectInputLifecycleDependencies = {\n\treadonly monitor: MonitorAwareGoalContinuation;\n\treadonly goalStoreRef: (ctx: ExtensionContext) => GoalStoreRef;\n\treadonly beginAgentGoalAccounting: (goal: Goal) => void;\n\treadonly refreshGoalUi: (ctx: ExtensionContext, goal: Goal) => void;\n\t/**\n\t * One-shot resume fired when the first user message after a suppressed\n\t * flooded load is accepted. The load-time suppression notice tells the user\n\t * to \"send a message to resume\"; this callback is what keeps that promise.\n\t */\n\treadonly resumeAfterSuppressedLoad?: (ctx: ExtensionContext, goal: Goal) => Promise<void>;\n\t/** Fired for every accepted direct (non-extension) input, goal or not. */\n\treadonly onAcceptedDirectInput?: () => void;\n};\n\n/** Correlates raw input with admission before changing persisted Goal state. */\nexport class GoalDirectInputLifecycle {\n\treadonly #dependencies: DirectInputLifecycleDependencies;\n\treadonly #candidates = new Map<string, DirectInputCandidate>();\n\t#suppressedLoadResumeArmed = false;\n\n\tconstructor(dependencies: DirectInputLifecycleDependencies) {\n\t\tthis.#dependencies = dependencies;\n\t}\n\n\treset(): void {\n\t\tthis.#candidates.clear();\n\t\tthis.#suppressedLoadResumeArmed = false;\n\t}\n\n\t/** Arms the one-shot resume for a goal parked by load-time flood suppression. */\n\tarmSuppressedLoadResume(): void {\n\t\tthis.#suppressedLoadResumeArmed = true;\n\t}\n\n\tasync onInput(event: InputEvent, ctx: ExtensionContext): Promise<void> {\n\t\tif (event.source === \"extension\") return;\n\n\t\tthis.#dependencies.monitor.holdDirectInput(event.inputId);\n\t\tthis.#candidates.set(event.inputId, { goalId: null });\n\t\tconst goal = await readGoal(this.#dependencies.goalStoreRef(ctx));\n\t\tthis.#candidates.set(event.inputId, { goalId: goal?.id ?? null });\n\t}\n\n\tasync onDisposition(event: InputDispositionEvent, ctx: ExtensionContext): Promise<void> {\n\t\tconst candidate = this.#candidates.get(event.inputId);\n\t\tif (candidate === undefined) return;\n\t\tthis.#candidates.delete(event.inputId);\n\t\tconst accepted = event.disposition === \"started\" || event.disposition === \"queued\";\n\t\tthis.#dependencies.monitor.resolveDirectInput(event.inputId, accepted);\n\t\tif (accepted) this.#dependencies.onAcceptedDirectInput?.();\n\t\tif (!accepted || candidate.goalId === null) return;\n\n\t\tconst ref = this.#dependencies.goalStoreRef(ctx);\n\t\tconst currentGoal = await readGoal(ref);\n\t\tif (currentGoal?.id !== candidate.goalId) return;\n\n\t\tif (currentGoal.status === \"blocked\" && isMechanicalContinuationBlock(currentGoal.blockedReason)) {\n\t\t\tawait resetContinuationStreak(ref, { unattended: true });\n\t\t\tconst reactivated = await updateGoal(ref, { status: \"active\" }, \"user\");\n\t\t\tthis.#dependencies.beginAgentGoalAccounting(reactivated);\n\t\t\tthis.#dependencies.refreshGoalUi(ctx, reactivated);\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentGoal.status !== \"active\") return;\n\t\tconst reset = await resetContinuationStreak(ref, { unattended: true });\n\t\tif (reset !== null) this.#dependencies.refreshGoalUi(ctx, reset);\n\t\tif (this.#suppressedLoadResumeArmed) {\n\t\t\tthis.#suppressedLoadResumeArmed = false;\n\t\t\tawait this.#dependencies.resumeAfterSuppressedLoad?.(ctx, reset ?? currentGoal);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAiCrE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAsZ5D"}
|
|
@@ -17,6 +17,7 @@ import { accountGoalUsage, readGoal, updateGoal } from "./store.js";
|
|
|
17
17
|
import { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from "./store-changed-event.js";
|
|
18
18
|
import { goalStoreRef as buildGoalStoreRef } from "./store-ref.js";
|
|
19
19
|
import { staleGoalTodoReminder, todoResultAddsOpenTasks } from "./todo-gate.js";
|
|
20
|
+
import { TodoOwedBackstop } from "./todo-owed-backstop.js";
|
|
20
21
|
import { registerGoalTools } from "./tool-registration.js";
|
|
21
22
|
import { TurnUsageTracker } from "./turn-usage.js";
|
|
22
23
|
import { updateGoalUi } from "./ui.js";
|
|
@@ -41,12 +42,14 @@ export default function goalExtension(pi) {
|
|
|
41
42
|
const monitorContinuation = new MonitorAwareGoalContinuation(pi, () => continuationPending, () => {
|
|
42
43
|
continuationPending = true;
|
|
43
44
|
}, goalWaitTicker);
|
|
45
|
+
const todoOwedBackstop = new TodoOwedBackstop(pi);
|
|
44
46
|
const directInputLifecycle = new GoalDirectInputLifecycle({
|
|
45
47
|
monitor: monitorContinuation,
|
|
46
48
|
goalStoreRef,
|
|
47
49
|
beginAgentGoalAccounting,
|
|
48
50
|
refreshGoalUi: refreshGoalUiBestEffort,
|
|
49
51
|
resumeAfterSuppressedLoad: (resumeCtx, goal) => queueGoalContinuationForCurrentSession(pi, resumeCtx, goal),
|
|
52
|
+
onAcceptedDirectInput: () => todoOwedBackstop.resetChain(),
|
|
50
53
|
});
|
|
51
54
|
const goalTicker = new GoalElapsedTicker({
|
|
52
55
|
render: (renderCtx, renderGoal, live) => updateGoalUi(renderCtx, renderGoal, live),
|
|
@@ -105,6 +108,7 @@ export default function goalExtension(pi) {
|
|
|
105
108
|
activeContext = ctx;
|
|
106
109
|
monitorContinuation.start(ctx);
|
|
107
110
|
directInputLifecycle.reset();
|
|
111
|
+
todoOwedBackstop.resetChain();
|
|
108
112
|
const ref = goalStoreRef(ctx);
|
|
109
113
|
await migrateLegacyGoalFile(ref);
|
|
110
114
|
const goal = await readGoal(goalStoreRef(ctx));
|
|
@@ -149,6 +153,9 @@ export default function goalExtension(pi) {
|
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
});
|
|
156
|
+
pi.on("session_tree", async () => {
|
|
157
|
+
todoOwedBackstop.resetChain();
|
|
158
|
+
});
|
|
152
159
|
pi.on("input", async (event, ctx) => {
|
|
153
160
|
await directInputLifecycle.onInput(event, ctx);
|
|
154
161
|
});
|
|
@@ -226,6 +233,13 @@ export default function goalExtension(pi) {
|
|
|
226
233
|
goal = continuationGoal;
|
|
227
234
|
syncContinuationGoal(ctx, goal);
|
|
228
235
|
}
|
|
236
|
+
todoOwedBackstop.afterAgentEnd({
|
|
237
|
+
ctx,
|
|
238
|
+
event,
|
|
239
|
+
goal,
|
|
240
|
+
continuationPending,
|
|
241
|
+
hasActiveWakeSources: monitorContinuation.hasActiveWakeSources(),
|
|
242
|
+
});
|
|
229
243
|
});
|
|
230
244
|
pi.on("agent_settled", async (_event, ctx) => {
|
|
231
245
|
const goal = await monitorContinuation.afterAgentSettled();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { MANUAL_CONTINUE_CUSTOM_TYPE } from \"../../../manual-continue.ts\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { continueGoalAfterAgentEnd } from \"./agent-end-continuation.ts\";\nimport { GOAL_CACHE_WARMUP_ENTRY_TYPE } from \"./cache-warm.ts\";\nimport { isSameGoalCacheWarmCard, renderGoalCacheWarmupEntry } from \"./cache-warm-renderer.ts\";\nimport { registerGoalCommand } from \"./command-registration.ts\";\nimport { GOAL_CONTINUATION_CAP } from \"./continuation.ts\";\nimport { GoalDirectInputLifecycle } from \"./direct-input-lifecycle.ts\";\nimport { GoalElapsedTicker } from \"./elapsed-ticker.ts\";\nimport { formatGoalForTool, goalStatusLabel } from \"./format.ts\";\nimport { isResumeOfStoppedGoal, queueGoalContinuation } from \"./lifecycle-helpers.ts\";\nimport { GOAL_CONTINUATION_SCHEDULED_EVENT, MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { migrateLegacyGoalFile } from \"./persistence.ts\";\nimport { reengageGoalAfterReload } from \"./reload-reengagement.ts\";\nimport { isStaleExtensionContextError } from \"./stale-context.ts\";\nimport { accountGoalUsage, readGoal, updateGoal } from \"./store.ts\";\nimport { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from \"./store-changed-event.ts\";\nimport { goalStoreRef as buildGoalStoreRef } from \"./store-ref.ts\";\nimport { staleGoalTodoReminder, todoResultAddsOpenTasks } from \"./todo-gate.ts\";\nimport { registerGoalTools } from \"./tool-registration.ts\";\nimport { TurnUsageTracker } from \"./turn-usage.ts\";\nimport type { Goal, GoalAccountingMode, GoalStoreRef } from \"./types.ts\";\nimport { updateGoalUi } from \"./ui.ts\";\nimport { GOAL_WAIT_STATUS_KEY, GoalWaitTicker } from \"./wait-ticker.ts\";\n\nconst RESUME_GOAL_CHOICE = \"Resume goal\";\nconst LEAVE_GOAL_STOPPED_CHOICE = \"Leave stopped\";\n\ntype AgentGoalAccounting = {\n\tgoalId: string;\n\tmeasuredFromMilliseconds: number;\n};\n\nexport default function goalExtension(pi: ExtensionAPI): void {\n\tlet agentTurnInProgress = false;\n\tlet staleGoalReminderSentThisTurn = false;\n\tlet agentGoalAccounting: AgentGoalAccounting | null = null;\n\tlet blockedThisTurnGoalId: string | null = null;\n\tlet completedThisTurnGoalId: string | null = null;\n\tlet continuationPending = false;\n\tlet activeContext: ExtensionContext | undefined;\n\tconst turnUsage = new TurnUsageTracker();\n\t// No stale-ctx swallow here: GoalWaitTicker retires itself on a stale render\n\t// (a ticker that keeps ticking against a retired ctx freezes the footer\n\t// countdown forever); non-stale render errors still propagate.\n\tconst goalWaitTicker = new GoalWaitTicker({\n\t\trender: (renderCtx, status) => renderCtx.ui.setStatus(GOAL_WAIT_STATUS_KEY, status),\n\t});\n\tconst monitorContinuation = new MonitorAwareGoalContinuation(\n\t\tpi,\n\t\t() => continuationPending,\n\t\t() => {\n\t\t\tcontinuationPending = true;\n\t\t},\n\t\tgoalWaitTicker,\n\t);\n\tconst directInputLifecycle = new GoalDirectInputLifecycle({\n\t\tmonitor: monitorContinuation,\n\t\tgoalStoreRef,\n\t\tbeginAgentGoalAccounting,\n\t\trefreshGoalUi: refreshGoalUiBestEffort,\n\t\tresumeAfterSuppressedLoad: (resumeCtx, goal) => queueGoalContinuationForCurrentSession(pi, resumeCtx, goal),\n\t});\n\n\tconst goalTicker = new GoalElapsedTicker({\n\t\trender: (renderCtx, renderGoal, live) => updateGoalUi(renderCtx, renderGoal, live),\n\t});\n\n\tpi.registerEntryRenderer(GOAL_CACHE_WARMUP_ENTRY_TYPE, renderGoalCacheWarmupEntry, {\n\t\treplaces: isSameGoalCacheWarmCard,\n\t});\n\tregisterGoalTools(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting: (goal) => {\n\t\t\tmonitorContinuation.noteContinuationStarted();\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t},\n\t\tmarkGoalBlockedThisTurn,\n\t\tmarkGoalCompletedThisTurn,\n\t\trefreshGoalUi,\n\t});\n\tregisterGoalCommand(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting,\n\t\tstopAgentGoalAccounting,\n\t\tclearAgentGoalAccounting,\n\t\tqueueGoalContinuation: (extensionApi, commandCtx, goal) => {\n\t\t\tvoid queueGoalContinuationForCurrentSession(extensionApi, commandCtx, goal);\n\t\t},\n\t\trefreshGoalUi,\n\t});\n\n\tconst unsubscribeGoalStoreChanged =\n\t\tpi.events?.on(GOAL_STORE_CHANGED_EVENT, async (data) => {\n\t\t\tif (!isGoalStoreChangedEvent(data)) return;\n\t\t\tconst ctx = data.ctx ?? activeContext;\n\t\t\tif (\n\t\t\t\tctx === undefined ||\n\t\t\t\tctx.sessionManager.getSessionId() !== data.threadId ||\n\t\t\t\t!ctx.isIdle() ||\n\t\t\t\tctx.hasPendingMessages()\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\t\tif (goal?.status !== \"active\") return;\n\t\t\tmonitorContinuation.syncGoal(goal);\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\t\tpi.events?.emit(GOAL_CONTINUATION_SCHEDULED_EVENT, {\n\t\t\t\tgoalId: goal.id,\n\t\t\t\tdelayMs: 0,\n\t\t\t\tactiveMonitorCount: 0,\n\t\t\t\twakeSources: {},\n\t\t\t\treason: GOAL_STORE_CHANGED_EVENT,\n\t\t\t});\n\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t}) ?? (() => {});\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tactiveContext = ctx;\n\t\tmonitorContinuation.start(ctx);\n\t\tdirectInputLifecycle.reset();\n\t\tconst ref = goalStoreRef(ctx);\n\t\tawait migrateLegacyGoalFile(ref);\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUi(ctx, goal);\n\t\tif (await maybePromptResumeStoppedGoal(pi, ctx, event.reason, goal)) {\n\t\t\treturn;\n\t\t}\n\t\tif (goal && event.reason === \"reload\") {\n\t\t\t// A reload retires the extension generation and every armed continuation\n\t\t\t// timer with it. Re-engage through the reload path: stopped goals stay\n\t\t\t// stopped, active goals resume the wait the reload tore down.\n\t\t\tawait reengageGoalAfterReload({\n\t\t\t\tctx,\n\t\t\t\tgoal,\n\t\t\t\tmonitor: monitorContinuation,\n\t\t\t\tcountTrailingContinuations: () => countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch()),\n\t\t\t\tqueueContinuation: () => queueGoalContinuationForCurrentSession(pi, ctx, goal),\n\t\t\t});\n\t\t} else if (goal) {\n\t\t\t// Migration-lite admission: a resumed session carrying a trailing flood of\n\t\t\t// historical continuations must not reignite on load. Skip the auto-queue,\n\t\t\t// leave the goal active (no status rewrite), and tell the user how to resume.\n\t\t\tconst trailingContinuations = countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch());\n\t\t\tif (trailingContinuations >= GOAL_CONTINUATION_CAP) {\n\t\t\t\t// The load-time flood suppression parks the goal without rewriting its\n\t\t\t\t// status, so the only resume signal left is the user's next message.\n\t\t\t\t// Arm the one-shot latch the direct-input lifecycle fires when that\n\t\t\t\t// message is accepted; without it the promise in the notice is a lie\n\t\t\t\t// and the resumed session sits idle until the goal is recreated.\n\t\t\t\tdirectInputLifecycle.armSuppressedLoadResume();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Goal auto-continuation suppressed for this resumed session (${trailingContinuations} historical continuations). Send a message to resume.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t\t}\n\t\t}\n\t});\n\n\tpi.on(\"input\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onInput(event, ctx);\n\t});\n\n\tpi.on(\"input_disposition\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onDisposition(event, ctx);\n\t});\n\n\tpi.on(\"turn_start\", async () => {\n\t\tstaleGoalReminderSentThisTurn = false;\n\t});\n\n\t// When the model starts tracking new open todo work while the thread has no\n\t// goal (or only a stale, already-complete one), append a system reminder to\n\t// the todo result so the model registers the goal when the work warrants it.\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tif (event.toolName !== \"todo\" || event.isError || staleGoalReminderSentThisTurn) return undefined;\n\t\tif (!todoResultAddsOpenTasks(event.details)) return undefined;\n\t\tconst reminder = staleGoalTodoReminder(await readGoal(goalStoreRef(ctx)));\n\t\tif (reminder === undefined) return undefined;\n\t\tstaleGoalReminderSentThisTurn = true;\n\t\treturn { content: [...event.content, { type: \"text\" as const, text: reminder }] };\n\t});\n\n\tpi.on(\"agent_start\", async (_event, ctx) => {\n\t\tconst continuationStarted = continuationPending;\n\t\tcontinuationPending = false;\n\t\tif (continuationStarted) monitorContinuation.noteContinuationStarted();\n\t\tagentTurnInProgress = true;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tturnUsage.reset();\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t});\n\n\tpi.on(\"message_start\", async (event, ctx) => {\n\t\tif (event.message.role !== \"custom\" || event.message.customType !== MANUAL_CONTINUE_CUSTOM_TYPE) return;\n\t\tconst ref = goalStoreRef(ctx);\n\t\tconst goal = await readGoal(ref);\n\t\tif (goal?.status !== \"blocked\") return;\n\t\tsyncContinuationGoal(ctx, await updateGoal(ref, { status: \"active\" }, \"user\"));\n\t});\n\n\tpi.on(\"message_end\", async (event) => {\n\t\tturnUsage.noteMessageEnd(event.message);\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\tconst mode: GoalAccountingMode =\n\t\t\tblockedThisTurnGoalId !== null\n\t\t\t\t? \"activeOrBlocked\"\n\t\t\t\t: completedThisTurnGoalId === null\n\t\t\t\t\t? \"active\"\n\t\t\t\t\t: \"activeOrComplete\";\n\t\tlet goal = await accountCurrentAgentTurn(ctx, mode, event.messages);\n\t\tagentTurnInProgress = false;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tif (event.aborted === true && event.abortSource === \"user\" && goal?.status === \"active\") {\n\t\t\tgoal = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t}\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\tconst continuationGoal = await continueGoalAfterAgentEnd(monitorContinuation, { ctx, event, goal });\n\t\tif (continuationGoal !== goal) {\n\t\t\tgoal = continuationGoal;\n\t\t\tsyncContinuationGoal(ctx, goal);\n\t\t}\n\t});\n\n\tpi.on(\"agent_settled\", async (_event, ctx) => {\n\t\tconst goal = await monitorContinuation.afterAgentSettled();\n\t\tif (goal !== undefined) syncContinuationGoal(ctx, goal);\n\t});\n\n\tpi.on(\"session_abort\", async (_event, ctx) => {\n\t\tcontinuationPending = false;\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status !== \"active\") return;\n\t\tconst accounted = await accountCurrentAgentTurn(ctx, \"active\");\n\t\tif (accounted?.status === \"active\") {\n\t\t\tconst blocked = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, blocked);\n\t\t}\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tactiveContext = undefined;\n\t\tunsubscribeGoalStoreChanged();\n\t\tif (agentGoalAccounting !== null) {\n\t\t\tawait accountCurrentAgentTurn(ctx, \"active\");\n\t\t}\n\t\tclearAgentGoalAccounting();\n\t\tgoalTicker.stop();\n\t\tmonitorContinuation.dispose();\n\t});\n\n\tasync function maybePromptResumeStoppedGoal(\n\t\tpi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tsessionStartReason: string,\n\t\tgoal: Goal | null,\n\t): Promise<boolean> {\n\t\tif (!isResumeOfStoppedGoal(ctx, sessionStartReason, goal)) {\n\t\t\treturn false;\n\t\t}\n\t\t// RPC switch_session cannot service a nested interactive UI request until the\n\t\t// switch response completes. Keep the goal stopped and let the user resume it\n\t\t// explicitly after the new session finishes binding.\n\t\tif (ctx.mode === \"rpc\") {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Goal remains ${goal.status} after session resume. Resume it explicitly after the session finishes loading.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst choice = await ctx.ui.select(`Resume ${goal.status} goal?\\nGoal: ${goal.objective}`, [\n\t\t\tRESUME_GOAL_CHOICE,\n\t\t\tLEAVE_GOAL_STOPPED_CHOICE,\n\t\t]);\n\t\tif (choice !== RESUME_GOAL_CHOICE) return true;\n\n\t\tconst resumed = await updateGoal(goalStoreRef(ctx), { status: \"active\" }, \"user\");\n\t\tbeginAgentGoalAccounting(resumed);\n\t\trefreshGoalUi(ctx, resumed);\n\t\tctx.ui.notify(`Goal ${goalStatusLabel(resumed.status)}\\n${formatGoalForTool(resumed)}`, \"info\");\n\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, resumed);\n\t\treturn true;\n\t}\n\n\tasync function queueGoalContinuationForCurrentSession(\n\t\textensionApi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tgoal: Goal,\n\t): Promise<void> {\n\t\tconst continuedGoal = await queueGoalContinuation(extensionApi, ctx, goal, {\n\t\t\tcontinuationPending,\n\t\t\tmarkContinuationPending: () => {\n\t\t\t\tcontinuationPending = true;\n\t\t\t},\n\t\t});\n\t\tif (continuedGoal === null) {\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, null);\n\t\t\treturn;\n\t\t}\n\t\tif (continuedGoal.status === goal.status) return;\n\t\tif (continuedGoal.status === \"active\") beginAgentGoalAccounting(continuedGoal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, continuedGoal);\n\t}\n\n\tfunction beginAgentGoalAccounting(goal: Goal): void {\n\t\tif (goal.status !== \"active\") return;\n\t\tif (agentGoalAccounting?.goalId === goal.id) return;\n\t\tturnUsage.discardPending();\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction markGoalBlockedThisTurn(goal: Goal): void {\n\t\tif (agentTurnInProgress) blockedThisTurnGoalId = goal.id;\n\t}\n\n\tfunction markGoalCompletedThisTurn(goal: Goal): void {\n\t\tif (!agentTurnInProgress) return;\n\t\tcompletedThisTurnGoalId = goal.id;\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction stopAgentGoalAccounting(goalId: string): void {\n\t\tif (agentGoalAccounting?.goalId === goalId) {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t\tif (blockedThisTurnGoalId === goalId) {\n\t\t\tblockedThisTurnGoalId = null;\n\t\t}\n\t\tif (completedThisTurnGoalId === goalId) {\n\t\t\tcompletedThisTurnGoalId = null;\n\t\t}\n\t}\n\n\tfunction clearAgentGoalAccounting(): void {\n\t\tagentGoalAccounting = null;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t}\n\n\tfunction syncContinuationGoal(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tif (goal?.status === \"active\") beginAgentGoalAccounting(goal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t}\n\n\tfunction refreshGoalUi(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tmonitorContinuation.syncGoal(goal);\n\t\tconst accounting = agentGoalAccounting;\n\t\tif (ctx.hasUI && goal?.status === \"active\" && accounting?.goalId === goal.id) {\n\t\t\tgoalTicker.sync(ctx, goal, accounting.measuredFromMilliseconds);\n\t\t\treturn;\n\t\t}\n\t\tgoalTicker.stop();\n\t\tupdateGoalUi(ctx, goal);\n\t}\n\n\tfunction refreshGoalUiBestEffort(ctx: ExtensionContext, goal: Goal | null): void {\n\t\ttry {\n\t\t\trefreshGoalUi(ctx, goal);\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function accountCurrentAgentTurn(\n\t\tctx: ExtensionContext,\n\t\tmode: GoalAccountingMode,\n\t\tagentRunMessages?: unknown[],\n\t): Promise<Goal | null> {\n\t\tconst accounting = agentGoalAccounting;\n\t\tconst ref = goalStoreRef(ctx);\n\t\tif (accounting === null) return readGoal(ref);\n\n\t\tconst usage =\n\t\t\tagentRunMessages === undefined ? turnUsage.takePending() : turnUsage.takeRemaining(agentRunMessages);\n\t\tconst now = Date.now();\n\t\tconst elapsedSeconds = Math.max(0, Math.round((now - accounting.measuredFromMilliseconds) / 1000));\n\t\tconst goal = await accountGoalUsage(ref, usage, elapsedSeconds, mode, accounting.goalId);\n\t\tif (goal?.id === accounting.goalId) {\n\t\t\tagentGoalAccounting = { goalId: accounting.goalId, measuredFromMilliseconds: now };\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\treturn goal;\n\t}\n}\n\n/**\n * Counts goal-continuation entries queued since the most recent real user message\n * in the current branch (mirrors the todo-gate / todo-bridge backward branch read).\n * A real user message is the only reset: the assistant turns in between are exactly\n * the unattended loop this admission guard exists to stop.\n */\nfunction countTrailingGoalContinuationEntries(entries: readonly SessionEntry[]): number {\n\tlet count = 0;\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"message\" && entry.message.role === \"user\") break;\n\t\tif (entry?.type === \"custom_message\" && entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE) count += 1;\n\t}\n\treturn count;\n}\n\nfunction goalStoreRef(ctx: ExtensionContext): GoalStoreRef {\n\treturn buildGoalStoreRef(ctx.sessionManager, ctx.cwd);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { MANUAL_CONTINUE_CUSTOM_TYPE } from \"../../../manual-continue.ts\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { continueGoalAfterAgentEnd } from \"./agent-end-continuation.ts\";\nimport { GOAL_CACHE_WARMUP_ENTRY_TYPE } from \"./cache-warm.ts\";\nimport { isSameGoalCacheWarmCard, renderGoalCacheWarmupEntry } from \"./cache-warm-renderer.ts\";\nimport { registerGoalCommand } from \"./command-registration.ts\";\nimport { GOAL_CONTINUATION_CAP } from \"./continuation.ts\";\nimport { GoalDirectInputLifecycle } from \"./direct-input-lifecycle.ts\";\nimport { GoalElapsedTicker } from \"./elapsed-ticker.ts\";\nimport { formatGoalForTool, goalStatusLabel } from \"./format.ts\";\nimport { isResumeOfStoppedGoal, queueGoalContinuation } from \"./lifecycle-helpers.ts\";\nimport { GOAL_CONTINUATION_SCHEDULED_EVENT, MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { migrateLegacyGoalFile } from \"./persistence.ts\";\nimport { reengageGoalAfterReload } from \"./reload-reengagement.ts\";\nimport { isStaleExtensionContextError } from \"./stale-context.ts\";\nimport { accountGoalUsage, readGoal, updateGoal } from \"./store.ts\";\nimport { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from \"./store-changed-event.ts\";\nimport { goalStoreRef as buildGoalStoreRef } from \"./store-ref.ts\";\nimport { staleGoalTodoReminder, todoResultAddsOpenTasks } from \"./todo-gate.ts\";\nimport { TodoOwedBackstop } from \"./todo-owed-backstop.ts\";\nimport { registerGoalTools } from \"./tool-registration.ts\";\nimport { TurnUsageTracker } from \"./turn-usage.ts\";\nimport type { Goal, GoalAccountingMode, GoalStoreRef } from \"./types.ts\";\nimport { updateGoalUi } from \"./ui.ts\";\nimport { GOAL_WAIT_STATUS_KEY, GoalWaitTicker } from \"./wait-ticker.ts\";\n\nconst RESUME_GOAL_CHOICE = \"Resume goal\";\nconst LEAVE_GOAL_STOPPED_CHOICE = \"Leave stopped\";\n\ntype AgentGoalAccounting = {\n\tgoalId: string;\n\tmeasuredFromMilliseconds: number;\n};\n\nexport default function goalExtension(pi: ExtensionAPI): void {\n\tlet agentTurnInProgress = false;\n\tlet staleGoalReminderSentThisTurn = false;\n\tlet agentGoalAccounting: AgentGoalAccounting | null = null;\n\tlet blockedThisTurnGoalId: string | null = null;\n\tlet completedThisTurnGoalId: string | null = null;\n\tlet continuationPending = false;\n\tlet activeContext: ExtensionContext | undefined;\n\tconst turnUsage = new TurnUsageTracker();\n\t// No stale-ctx swallow here: GoalWaitTicker retires itself on a stale render\n\t// (a ticker that keeps ticking against a retired ctx freezes the footer\n\t// countdown forever); non-stale render errors still propagate.\n\tconst goalWaitTicker = new GoalWaitTicker({\n\t\trender: (renderCtx, status) => renderCtx.ui.setStatus(GOAL_WAIT_STATUS_KEY, status),\n\t});\n\tconst monitorContinuation = new MonitorAwareGoalContinuation(\n\t\tpi,\n\t\t() => continuationPending,\n\t\t() => {\n\t\t\tcontinuationPending = true;\n\t\t},\n\t\tgoalWaitTicker,\n\t);\n\tconst todoOwedBackstop = new TodoOwedBackstop(pi);\n\tconst directInputLifecycle = new GoalDirectInputLifecycle({\n\t\tmonitor: monitorContinuation,\n\t\tgoalStoreRef,\n\t\tbeginAgentGoalAccounting,\n\t\trefreshGoalUi: refreshGoalUiBestEffort,\n\t\tresumeAfterSuppressedLoad: (resumeCtx, goal) => queueGoalContinuationForCurrentSession(pi, resumeCtx, goal),\n\t\tonAcceptedDirectInput: () => todoOwedBackstop.resetChain(),\n\t});\n\n\tconst goalTicker = new GoalElapsedTicker({\n\t\trender: (renderCtx, renderGoal, live) => updateGoalUi(renderCtx, renderGoal, live),\n\t});\n\n\tpi.registerEntryRenderer(GOAL_CACHE_WARMUP_ENTRY_TYPE, renderGoalCacheWarmupEntry, {\n\t\treplaces: isSameGoalCacheWarmCard,\n\t});\n\tregisterGoalTools(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting: (goal) => {\n\t\t\tmonitorContinuation.noteContinuationStarted();\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t},\n\t\tmarkGoalBlockedThisTurn,\n\t\tmarkGoalCompletedThisTurn,\n\t\trefreshGoalUi,\n\t});\n\tregisterGoalCommand(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting,\n\t\tstopAgentGoalAccounting,\n\t\tclearAgentGoalAccounting,\n\t\tqueueGoalContinuation: (extensionApi, commandCtx, goal) => {\n\t\t\tvoid queueGoalContinuationForCurrentSession(extensionApi, commandCtx, goal);\n\t\t},\n\t\trefreshGoalUi,\n\t});\n\n\tconst unsubscribeGoalStoreChanged =\n\t\tpi.events?.on(GOAL_STORE_CHANGED_EVENT, async (data) => {\n\t\t\tif (!isGoalStoreChangedEvent(data)) return;\n\t\t\tconst ctx = data.ctx ?? activeContext;\n\t\t\tif (\n\t\t\t\tctx === undefined ||\n\t\t\t\tctx.sessionManager.getSessionId() !== data.threadId ||\n\t\t\t\t!ctx.isIdle() ||\n\t\t\t\tctx.hasPendingMessages()\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\t\tif (goal?.status !== \"active\") return;\n\t\t\tmonitorContinuation.syncGoal(goal);\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\t\tpi.events?.emit(GOAL_CONTINUATION_SCHEDULED_EVENT, {\n\t\t\t\tgoalId: goal.id,\n\t\t\t\tdelayMs: 0,\n\t\t\t\tactiveMonitorCount: 0,\n\t\t\t\twakeSources: {},\n\t\t\t\treason: GOAL_STORE_CHANGED_EVENT,\n\t\t\t});\n\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t}) ?? (() => {});\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tactiveContext = ctx;\n\t\tmonitorContinuation.start(ctx);\n\t\tdirectInputLifecycle.reset();\n\t\ttodoOwedBackstop.resetChain();\n\t\tconst ref = goalStoreRef(ctx);\n\t\tawait migrateLegacyGoalFile(ref);\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUi(ctx, goal);\n\t\tif (await maybePromptResumeStoppedGoal(pi, ctx, event.reason, goal)) {\n\t\t\treturn;\n\t\t}\n\t\tif (goal && event.reason === \"reload\") {\n\t\t\t// A reload retires the extension generation and every armed continuation\n\t\t\t// timer with it. Re-engage through the reload path: stopped goals stay\n\t\t\t// stopped, active goals resume the wait the reload tore down.\n\t\t\tawait reengageGoalAfterReload({\n\t\t\t\tctx,\n\t\t\t\tgoal,\n\t\t\t\tmonitor: monitorContinuation,\n\t\t\t\tcountTrailingContinuations: () => countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch()),\n\t\t\t\tqueueContinuation: () => queueGoalContinuationForCurrentSession(pi, ctx, goal),\n\t\t\t});\n\t\t} else if (goal) {\n\t\t\t// Migration-lite admission: a resumed session carrying a trailing flood of\n\t\t\t// historical continuations must not reignite on load. Skip the auto-queue,\n\t\t\t// leave the goal active (no status rewrite), and tell the user how to resume.\n\t\t\tconst trailingContinuations = countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch());\n\t\t\tif (trailingContinuations >= GOAL_CONTINUATION_CAP) {\n\t\t\t\t// The load-time flood suppression parks the goal without rewriting its\n\t\t\t\t// status, so the only resume signal left is the user's next message.\n\t\t\t\t// Arm the one-shot latch the direct-input lifecycle fires when that\n\t\t\t\t// message is accepted; without it the promise in the notice is a lie\n\t\t\t\t// and the resumed session sits idle until the goal is recreated.\n\t\t\t\tdirectInputLifecycle.armSuppressedLoadResume();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Goal auto-continuation suppressed for this resumed session (${trailingContinuations} historical continuations). Send a message to resume.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t\t}\n\t\t}\n\t});\n\n\tpi.on(\"session_tree\", async () => {\n\t\ttodoOwedBackstop.resetChain();\n\t});\n\n\tpi.on(\"input\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onInput(event, ctx);\n\t});\n\n\tpi.on(\"input_disposition\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onDisposition(event, ctx);\n\t});\n\n\tpi.on(\"turn_start\", async () => {\n\t\tstaleGoalReminderSentThisTurn = false;\n\t});\n\n\t// When the model starts tracking new open todo work while the thread has no\n\t// goal (or only a stale, already-complete one), append a system reminder to\n\t// the todo result so the model registers the goal when the work warrants it.\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tif (event.toolName !== \"todo\" || event.isError || staleGoalReminderSentThisTurn) return undefined;\n\t\tif (!todoResultAddsOpenTasks(event.details)) return undefined;\n\t\tconst reminder = staleGoalTodoReminder(await readGoal(goalStoreRef(ctx)));\n\t\tif (reminder === undefined) return undefined;\n\t\tstaleGoalReminderSentThisTurn = true;\n\t\treturn { content: [...event.content, { type: \"text\" as const, text: reminder }] };\n\t});\n\n\tpi.on(\"agent_start\", async (_event, ctx) => {\n\t\tconst continuationStarted = continuationPending;\n\t\tcontinuationPending = false;\n\t\tif (continuationStarted) monitorContinuation.noteContinuationStarted();\n\t\tagentTurnInProgress = true;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tturnUsage.reset();\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t});\n\n\tpi.on(\"message_start\", async (event, ctx) => {\n\t\tif (event.message.role !== \"custom\" || event.message.customType !== MANUAL_CONTINUE_CUSTOM_TYPE) return;\n\t\tconst ref = goalStoreRef(ctx);\n\t\tconst goal = await readGoal(ref);\n\t\tif (goal?.status !== \"blocked\") return;\n\t\tsyncContinuationGoal(ctx, await updateGoal(ref, { status: \"active\" }, \"user\"));\n\t});\n\n\tpi.on(\"message_end\", async (event) => {\n\t\tturnUsage.noteMessageEnd(event.message);\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\tconst mode: GoalAccountingMode =\n\t\t\tblockedThisTurnGoalId !== null\n\t\t\t\t? \"activeOrBlocked\"\n\t\t\t\t: completedThisTurnGoalId === null\n\t\t\t\t\t? \"active\"\n\t\t\t\t\t: \"activeOrComplete\";\n\t\tlet goal = await accountCurrentAgentTurn(ctx, mode, event.messages);\n\t\tagentTurnInProgress = false;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tif (event.aborted === true && event.abortSource === \"user\" && goal?.status === \"active\") {\n\t\t\tgoal = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t}\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\tconst continuationGoal = await continueGoalAfterAgentEnd(monitorContinuation, { ctx, event, goal });\n\t\tif (continuationGoal !== goal) {\n\t\t\tgoal = continuationGoal;\n\t\t\tsyncContinuationGoal(ctx, goal);\n\t\t}\n\t\ttodoOwedBackstop.afterAgentEnd({\n\t\t\tctx,\n\t\t\tevent,\n\t\t\tgoal,\n\t\t\tcontinuationPending,\n\t\t\thasActiveWakeSources: monitorContinuation.hasActiveWakeSources(),\n\t\t});\n\t});\n\n\tpi.on(\"agent_settled\", async (_event, ctx) => {\n\t\tconst goal = await monitorContinuation.afterAgentSettled();\n\t\tif (goal !== undefined) syncContinuationGoal(ctx, goal);\n\t});\n\n\tpi.on(\"session_abort\", async (_event, ctx) => {\n\t\tcontinuationPending = false;\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status !== \"active\") return;\n\t\tconst accounted = await accountCurrentAgentTurn(ctx, \"active\");\n\t\tif (accounted?.status === \"active\") {\n\t\t\tconst blocked = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, blocked);\n\t\t}\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tactiveContext = undefined;\n\t\tunsubscribeGoalStoreChanged();\n\t\tif (agentGoalAccounting !== null) {\n\t\t\tawait accountCurrentAgentTurn(ctx, \"active\");\n\t\t}\n\t\tclearAgentGoalAccounting();\n\t\tgoalTicker.stop();\n\t\tmonitorContinuation.dispose();\n\t});\n\n\tasync function maybePromptResumeStoppedGoal(\n\t\tpi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tsessionStartReason: string,\n\t\tgoal: Goal | null,\n\t): Promise<boolean> {\n\t\tif (!isResumeOfStoppedGoal(ctx, sessionStartReason, goal)) {\n\t\t\treturn false;\n\t\t}\n\t\t// RPC switch_session cannot service a nested interactive UI request until the\n\t\t// switch response completes. Keep the goal stopped and let the user resume it\n\t\t// explicitly after the new session finishes binding.\n\t\tif (ctx.mode === \"rpc\") {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Goal remains ${goal.status} after session resume. Resume it explicitly after the session finishes loading.`,\n\t\t\t\t\"info\",\n\t\t\t);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst choice = await ctx.ui.select(`Resume ${goal.status} goal?\\nGoal: ${goal.objective}`, [\n\t\t\tRESUME_GOAL_CHOICE,\n\t\t\tLEAVE_GOAL_STOPPED_CHOICE,\n\t\t]);\n\t\tif (choice !== RESUME_GOAL_CHOICE) return true;\n\n\t\tconst resumed = await updateGoal(goalStoreRef(ctx), { status: \"active\" }, \"user\");\n\t\tbeginAgentGoalAccounting(resumed);\n\t\trefreshGoalUi(ctx, resumed);\n\t\tctx.ui.notify(`Goal ${goalStatusLabel(resumed.status)}\\n${formatGoalForTool(resumed)}`, \"info\");\n\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, resumed);\n\t\treturn true;\n\t}\n\n\tasync function queueGoalContinuationForCurrentSession(\n\t\textensionApi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tgoal: Goal,\n\t): Promise<void> {\n\t\tconst continuedGoal = await queueGoalContinuation(extensionApi, ctx, goal, {\n\t\t\tcontinuationPending,\n\t\t\tmarkContinuationPending: () => {\n\t\t\t\tcontinuationPending = true;\n\t\t\t},\n\t\t});\n\t\tif (continuedGoal === null) {\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, null);\n\t\t\treturn;\n\t\t}\n\t\tif (continuedGoal.status === goal.status) return;\n\t\tif (continuedGoal.status === \"active\") beginAgentGoalAccounting(continuedGoal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, continuedGoal);\n\t}\n\n\tfunction beginAgentGoalAccounting(goal: Goal): void {\n\t\tif (goal.status !== \"active\") return;\n\t\tif (agentGoalAccounting?.goalId === goal.id) return;\n\t\tturnUsage.discardPending();\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction markGoalBlockedThisTurn(goal: Goal): void {\n\t\tif (agentTurnInProgress) blockedThisTurnGoalId = goal.id;\n\t}\n\n\tfunction markGoalCompletedThisTurn(goal: Goal): void {\n\t\tif (!agentTurnInProgress) return;\n\t\tcompletedThisTurnGoalId = goal.id;\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction stopAgentGoalAccounting(goalId: string): void {\n\t\tif (agentGoalAccounting?.goalId === goalId) {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t\tif (blockedThisTurnGoalId === goalId) {\n\t\t\tblockedThisTurnGoalId = null;\n\t\t}\n\t\tif (completedThisTurnGoalId === goalId) {\n\t\t\tcompletedThisTurnGoalId = null;\n\t\t}\n\t}\n\n\tfunction clearAgentGoalAccounting(): void {\n\t\tagentGoalAccounting = null;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t}\n\n\tfunction syncContinuationGoal(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tif (goal?.status === \"active\") beginAgentGoalAccounting(goal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t}\n\n\tfunction refreshGoalUi(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tmonitorContinuation.syncGoal(goal);\n\t\tconst accounting = agentGoalAccounting;\n\t\tif (ctx.hasUI && goal?.status === \"active\" && accounting?.goalId === goal.id) {\n\t\t\tgoalTicker.sync(ctx, goal, accounting.measuredFromMilliseconds);\n\t\t\treturn;\n\t\t}\n\t\tgoalTicker.stop();\n\t\tupdateGoalUi(ctx, goal);\n\t}\n\n\tfunction refreshGoalUiBestEffort(ctx: ExtensionContext, goal: Goal | null): void {\n\t\ttry {\n\t\t\trefreshGoalUi(ctx, goal);\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function accountCurrentAgentTurn(\n\t\tctx: ExtensionContext,\n\t\tmode: GoalAccountingMode,\n\t\tagentRunMessages?: unknown[],\n\t): Promise<Goal | null> {\n\t\tconst accounting = agentGoalAccounting;\n\t\tconst ref = goalStoreRef(ctx);\n\t\tif (accounting === null) return readGoal(ref);\n\n\t\tconst usage =\n\t\t\tagentRunMessages === undefined ? turnUsage.takePending() : turnUsage.takeRemaining(agentRunMessages);\n\t\tconst now = Date.now();\n\t\tconst elapsedSeconds = Math.max(0, Math.round((now - accounting.measuredFromMilliseconds) / 1000));\n\t\tconst goal = await accountGoalUsage(ref, usage, elapsedSeconds, mode, accounting.goalId);\n\t\tif (goal?.id === accounting.goalId) {\n\t\t\tagentGoalAccounting = { goalId: accounting.goalId, measuredFromMilliseconds: now };\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\treturn goal;\n\t}\n}\n\n/**\n * Counts goal-continuation entries queued since the most recent real user message\n * in the current branch (mirrors the todo-gate / todo-bridge backward branch read).\n * A real user message is the only reset: the assistant turns in between are exactly\n * the unattended loop this admission guard exists to stop.\n */\nfunction countTrailingGoalContinuationEntries(entries: readonly SessionEntry[]): number {\n\tlet count = 0;\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"message\" && entry.message.role === \"user\") break;\n\t\tif (entry?.type === \"custom_message\" && entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE) count += 1;\n\t}\n\treturn count;\n}\n\nfunction goalStoreRef(ctx: ExtensionContext): GoalStoreRef {\n\treturn buildGoalStoreRef(ctx.sessionManager, ctx.cwd);\n}\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AgentEndEvent, ExtensionAPI, ExtensionContext } from "../../types.ts";
|
|
2
|
+
import type { Goal } from "./types.ts";
|
|
3
|
+
export declare const TODO_OWED_CUSTOM_TYPE = "senpi.todo-owed";
|
|
4
|
+
export declare const TODO_OWED_REMINDER_EVENT = "todo_owed_reminder";
|
|
5
|
+
export declare const TODO_OWED_CHAIN_LIMIT = 2;
|
|
6
|
+
export declare const TODO_OWED_SECOND_PREFIX = "Second and final reminder. ";
|
|
7
|
+
export type TodoOwedSuppression = "disabled" | "subagent" | "non-interactive" | "not-clean" | "length" | "pending-messages" | "active-goal" | "continuation-pending" | "no-open-tasks" | "wake-source" | "ask-user-call" | "question" | "cap";
|
|
8
|
+
export type TodoOwedReminderEvent = {
|
|
9
|
+
sessionId: string;
|
|
10
|
+
chainCount: number;
|
|
11
|
+
openTasks: number;
|
|
12
|
+
now: string;
|
|
13
|
+
next: string;
|
|
14
|
+
reason: "delivered" | "capped";
|
|
15
|
+
};
|
|
16
|
+
export type TodoOwedInput = {
|
|
17
|
+
readonly ctx: ExtensionContext;
|
|
18
|
+
readonly event: AgentEndEvent;
|
|
19
|
+
readonly goal: Goal | null;
|
|
20
|
+
readonly continuationPending: boolean;
|
|
21
|
+
readonly hasActiveWakeSources: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare function buildTodoOwedReminder(anchors: {
|
|
24
|
+
ask: string;
|
|
25
|
+
now: string;
|
|
26
|
+
next: string;
|
|
27
|
+
}, final: boolean): string;
|
|
28
|
+
/** True when the last non-empty paragraph of the text ends any sentence with `?`. */
|
|
29
|
+
export declare function endsWithQuestion(text: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The first clause that makes the ended turn NOT owe a nudge, or undefined when every
|
|
32
|
+
* clause holds except the per-chain cap. Child sessions are untagged today (their header
|
|
33
|
+
* carries no `parentSession`), so they pass the main-session clause and are treated as main.
|
|
34
|
+
*/
|
|
35
|
+
export declare function firstTodoOwedSuppression(input: TodoOwedInput): Exclude<TodoOwedSuppression, "cap"> | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Per-session chain state. The chain counts nudges since the last accepted direct user
|
|
38
|
+
* input (or `session_start` / `session_tree`); after two deliveries the third owed turn
|
|
39
|
+
* notifies the user once and every later one stays silent until the chain resets.
|
|
40
|
+
*/
|
|
41
|
+
export declare class TodoOwedBackstop {
|
|
42
|
+
#private;
|
|
43
|
+
constructor(pi: ExtensionAPI);
|
|
44
|
+
resetChain(): void;
|
|
45
|
+
afterAgentEnd(input: TodoOwedInput): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=todo-owed-backstop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo-owed-backstop.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/todo-owed-backstop.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAiB,MAAM,gBAAgB,CAAC;AAMnG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AACvD,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAQrE,MAAM,MAAM,mBAAmB,GAC5B,UAAU,GACV,UAAU,GACV,iBAAiB,GACjB,WAAW,GACX,QAAQ,GACR,kBAAkB,GAClB,aAAa,GACb,sBAAsB,GACtB,eAAe,GACf,aAAa,GACb,eAAe,GACf,UAAU,GACV,KAAK,CAAC;AAET,MAAM,MAAM,qBAAqB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACvC,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAKjH;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtD;AAwBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,mBAAmB,EAAE,KAAK,CAAC,GAAG,SAAS,CAkB9G;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;;IAM5B,YAAY,EAAE,EAAE,YAAY,EAE3B;IAED,UAAU,IAAI,IAAI,CAGjB;IAED,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CA6CxC;CAUD"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Turn-end backstop for main sessions without an active goal: a text-only end of turn
|
|
2
|
+
// while the todo list still has open tasks gets one hidden nudge (two per chain at most).
|
|
3
|
+
// Anthropic's Opus 5.5 guide, "Unattended agentic runs": "If a turn ends with items still
|
|
4
|
+
// open and no blocker stated, send a short user message naming them" and "stop after two
|
|
5
|
+
// or three automatic continuations on the same task rather than repeating them indefinitely".
|
|
6
|
+
import { createSessionLogger } from "../../../session-log.js";
|
|
7
|
+
import { SettingsManager } from "../../../settings-manager.js";
|
|
8
|
+
import { TOOL_NAMES as ASK_USER_TOOL_NAMES } from "../ask-user/family.js";
|
|
9
|
+
import { describeAskNowNext, getLatestTodoStateFromBranchEntries } from "../todotools/state.js";
|
|
10
|
+
import { didAgentEndCleanly } from "./continuation.js";
|
|
11
|
+
import { lastAssistantMessage } from "./last-assistant-message.js";
|
|
12
|
+
import { openTodoTaskContents } from "./todo-gate.js";
|
|
13
|
+
export const TODO_OWED_CUSTOM_TYPE = "senpi.todo-owed";
|
|
14
|
+
export const TODO_OWED_REMINDER_EVENT = "todo_owed_reminder";
|
|
15
|
+
export const TODO_OWED_CHAIN_LIMIT = 2;
|
|
16
|
+
export const TODO_OWED_SECOND_PREFIX = "Second and final reminder. ";
|
|
17
|
+
/** One-shot, non-interactive runs; the same set `terminal/notify.ts` never wakes. */
|
|
18
|
+
const NON_INTERACTIVE_MODES = new Set(["print", "json"]);
|
|
19
|
+
const ASK_USER_TOOLS = new Set(Object.values(ASK_USER_TOOL_NAMES));
|
|
20
|
+
// A `?` that ends a sentence: followed by optional closing quotes/brackets/emphasis, then whitespace or the end.
|
|
21
|
+
const QUESTION_SENTENCE_END = /[?\uFF1F]["'`*_)\]}\u2019\u201D]*(?:\s|$)/u;
|
|
22
|
+
export function buildTodoOwedReminder(anchors, final) {
|
|
23
|
+
const prefix = final ? TODO_OWED_SECOND_PREFIX : "";
|
|
24
|
+
return `<system-reminder>
|
|
25
|
+
${prefix}The turn ended with open todo work and no question to the user. Ask: ${anchors.ask}. Now: ${anchors.now}. Next: ${anchors.next}. Either continue the next open task now with real tool calls, or mark it done/dropped via the todo tool and tell the user in one sentence why you stopped. Do not restate the plan.
|
|
26
|
+
</system-reminder>`;
|
|
27
|
+
}
|
|
28
|
+
/** True when the last non-empty paragraph of the text ends any sentence with `?`. */
|
|
29
|
+
export function endsWithQuestion(text) {
|
|
30
|
+
const paragraphs = text
|
|
31
|
+
.split(/\n\s*\n/)
|
|
32
|
+
.map((paragraph) => paragraph.trim())
|
|
33
|
+
.filter((paragraph) => paragraph !== "");
|
|
34
|
+
const last = paragraphs.at(-1);
|
|
35
|
+
return last !== undefined && QUESTION_SENTENCE_END.test(last);
|
|
36
|
+
}
|
|
37
|
+
function assistantText(message) {
|
|
38
|
+
if (message === undefined)
|
|
39
|
+
return "";
|
|
40
|
+
return message.content
|
|
41
|
+
.filter((content) => content.type === "text")
|
|
42
|
+
.map((content) => content.text)
|
|
43
|
+
.join("\n");
|
|
44
|
+
}
|
|
45
|
+
function calledAskUser(messages) {
|
|
46
|
+
return messages.some((message) => message.role === "assistant" &&
|
|
47
|
+
message.content.some((content) => content.type === "toolCall" && ASK_USER_TOOLS.has(content.name)));
|
|
48
|
+
}
|
|
49
|
+
function readTurnEndBackstopSetting(ctx) {
|
|
50
|
+
return SettingsManager.create(ctx.cwd, ctx.agentDir, {
|
|
51
|
+
projectTrusted: ctx.isProjectTrusted(),
|
|
52
|
+
}).getTodoTurnEndBackstop();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The first clause that makes the ended turn NOT owe a nudge, or undefined when every
|
|
56
|
+
* clause holds except the per-chain cap. Child sessions are untagged today (their header
|
|
57
|
+
* carries no `parentSession`), so they pass the main-session clause and are treated as main.
|
|
58
|
+
*/
|
|
59
|
+
export function firstTodoOwedSuppression(input) {
|
|
60
|
+
const { ctx, event, goal } = input;
|
|
61
|
+
// Optional call: session managers that predate `getHeader` (and the goal test
|
|
62
|
+
// harness fakes) expose no parent tag, which reads as "main session" - the same
|
|
63
|
+
// treatment untagged child sessions get today.
|
|
64
|
+
if (ctx.sessionManager.getHeader?.()?.parentSession !== undefined)
|
|
65
|
+
return "subagent";
|
|
66
|
+
if (NON_INTERACTIVE_MODES.has(ctx.mode))
|
|
67
|
+
return "non-interactive";
|
|
68
|
+
if (event.aborted === true || !didAgentEndCleanly(event.messages))
|
|
69
|
+
return "not-clean";
|
|
70
|
+
if (lastAssistantMessage(event.messages)?.stopReason === "length")
|
|
71
|
+
return "length";
|
|
72
|
+
if (ctx.hasPendingMessages())
|
|
73
|
+
return "pending-messages";
|
|
74
|
+
if (goal?.status === "active")
|
|
75
|
+
return "active-goal";
|
|
76
|
+
if (input.continuationPending)
|
|
77
|
+
return "continuation-pending";
|
|
78
|
+
if (openTodoTaskContents(ctx.sessionManager.getBranch()).length === 0)
|
|
79
|
+
return "no-open-tasks";
|
|
80
|
+
if (input.hasActiveWakeSources)
|
|
81
|
+
return "wake-source";
|
|
82
|
+
if (calledAskUser(event.messages))
|
|
83
|
+
return "ask-user-call";
|
|
84
|
+
if (endsWithQuestion(assistantText(lastAssistantMessage(event.messages))))
|
|
85
|
+
return "question";
|
|
86
|
+
if (!readTurnEndBackstopSetting(ctx))
|
|
87
|
+
return "disabled";
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Per-session chain state. The chain counts nudges since the last accepted direct user
|
|
92
|
+
* input (or `session_start` / `session_tree`); after two deliveries the third owed turn
|
|
93
|
+
* notifies the user once and every later one stays silent until the chain resets.
|
|
94
|
+
*/
|
|
95
|
+
export class TodoOwedBackstop {
|
|
96
|
+
#pi;
|
|
97
|
+
#remindersThisChain = 0;
|
|
98
|
+
#notifiedThisChain = false;
|
|
99
|
+
#logger;
|
|
100
|
+
constructor(pi) {
|
|
101
|
+
this.#pi = pi;
|
|
102
|
+
}
|
|
103
|
+
resetChain() {
|
|
104
|
+
this.#remindersThisChain = 0;
|
|
105
|
+
this.#notifiedThisChain = false;
|
|
106
|
+
}
|
|
107
|
+
afterAgentEnd(input) {
|
|
108
|
+
const suppression = firstTodoOwedSuppression(input);
|
|
109
|
+
if (suppression !== undefined) {
|
|
110
|
+
this.#logSuppression(input.ctx, suppression);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const { ctx } = input;
|
|
114
|
+
const branch = ctx.sessionManager.getBranch();
|
|
115
|
+
const openTasks = openTodoTaskContents(branch).length;
|
|
116
|
+
const anchors = describeAskNowNext(getLatestTodoStateFromBranchEntries(branch));
|
|
117
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
118
|
+
if (this.#remindersThisChain >= TODO_OWED_CHAIN_LIMIT) {
|
|
119
|
+
if (this.#notifiedThisChain) {
|
|
120
|
+
this.#logSuppression(ctx, "cap");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.#notifiedThisChain = true;
|
|
124
|
+
ctx.ui.notify(`Agent stopped with ${openTasks} open todo tasks (Now: ${anchors.now}). Send a message to continue.`, "warning");
|
|
125
|
+
this.#emit({
|
|
126
|
+
sessionId,
|
|
127
|
+
chainCount: this.#remindersThisChain,
|
|
128
|
+
openTasks,
|
|
129
|
+
now: anchors.now,
|
|
130
|
+
next: anchors.next,
|
|
131
|
+
reason: "capped",
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.#remindersThisChain += 1;
|
|
136
|
+
const content = buildTodoOwedReminder(anchors, this.#remindersThisChain === TODO_OWED_CHAIN_LIMIT);
|
|
137
|
+
this.#pi.sendMessage({ customType: TODO_OWED_CUSTOM_TYPE, content, display: false }, { triggerTurn: true, deliverAs: "followUp" });
|
|
138
|
+
this.#emit({
|
|
139
|
+
sessionId,
|
|
140
|
+
chainCount: this.#remindersThisChain,
|
|
141
|
+
openTasks,
|
|
142
|
+
now: anchors.now,
|
|
143
|
+
next: anchors.next,
|
|
144
|
+
reason: "delivered",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
#emit(event) {
|
|
148
|
+
this.#pi.events.emit(TODO_OWED_REMINDER_EVENT, event);
|
|
149
|
+
}
|
|
150
|
+
#logSuppression(ctx, reason) {
|
|
151
|
+
this.#logger ??= createSessionLogger(ctx.agentDir);
|
|
152
|
+
this.#logger.debug("todo_owed_backstop_suppressed", { reason });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=todo-owed-backstop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo-owed-backstop.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/todo-owed-backstop.ts"],"names":[],"mappings":"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","sourcesContent":["// Turn-end backstop for main sessions without an active goal: a text-only end of turn\n// while the todo list still has open tasks gets one hidden nudge (two per chain at most).\n// Anthropic's Opus 5.5 guide, \"Unattended agentic runs\": \"If a turn ends with items still\n// open and no blocker stated, send a short user message naming them\" and \"stop after two\n// or three automatic continuations on the same task rather than repeating them indefinitely\".\n\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { createSessionLogger, type SessionLogger } from \"../../../session-log.ts\";\nimport { SettingsManager } from \"../../../settings-manager.ts\";\nimport type { AgentEndEvent, ExtensionAPI, ExtensionContext, ExtensionMode } from \"../../types.ts\";\nimport { TOOL_NAMES as ASK_USER_TOOL_NAMES } from \"../ask-user/family.ts\";\nimport { describeAskNowNext, getLatestTodoStateFromBranchEntries } from \"../todotools/state.ts\";\nimport { didAgentEndCleanly } from \"./continuation.ts\";\nimport { lastAssistantMessage } from \"./last-assistant-message.ts\";\nimport { openTodoTaskContents } from \"./todo-gate.ts\";\nimport type { Goal } from \"./types.ts\";\n\nexport const TODO_OWED_CUSTOM_TYPE = \"senpi.todo-owed\";\nexport const TODO_OWED_REMINDER_EVENT = \"todo_owed_reminder\";\nexport const TODO_OWED_CHAIN_LIMIT = 2;\nexport const TODO_OWED_SECOND_PREFIX = \"Second and final reminder. \";\n\n/** One-shot, non-interactive runs; the same set `terminal/notify.ts` never wakes. */\nconst NON_INTERACTIVE_MODES: ReadonlySet<ExtensionMode> = new Set([\"print\", \"json\"]);\nconst ASK_USER_TOOLS: ReadonlySet<string> = new Set(Object.values(ASK_USER_TOOL_NAMES));\n// A `?` that ends a sentence: followed by optional closing quotes/brackets/emphasis, then whitespace or the end.\nconst QUESTION_SENTENCE_END = /[?\\uFF1F][\"'`*_)\\]}\\u2019\\u201D]*(?:\\s|$)/u;\n\nexport type TodoOwedSuppression =\n\t| \"disabled\"\n\t| \"subagent\"\n\t| \"non-interactive\"\n\t| \"not-clean\"\n\t| \"length\"\n\t| \"pending-messages\"\n\t| \"active-goal\"\n\t| \"continuation-pending\"\n\t| \"no-open-tasks\"\n\t| \"wake-source\"\n\t| \"ask-user-call\"\n\t| \"question\"\n\t| \"cap\";\n\nexport type TodoOwedReminderEvent = {\n\tsessionId: string;\n\tchainCount: number;\n\topenTasks: number;\n\tnow: string;\n\tnext: string;\n\treason: \"delivered\" | \"capped\";\n};\n\nexport type TodoOwedInput = {\n\treadonly ctx: ExtensionContext;\n\treadonly event: AgentEndEvent;\n\treadonly goal: Goal | null;\n\treadonly continuationPending: boolean;\n\treadonly hasActiveWakeSources: boolean;\n};\n\nexport function buildTodoOwedReminder(anchors: { ask: string; now: string; next: string }, final: boolean): string {\n\tconst prefix = final ? TODO_OWED_SECOND_PREFIX : \"\";\n\treturn `<system-reminder>\n${prefix}The turn ended with open todo work and no question to the user. Ask: ${anchors.ask}. Now: ${anchors.now}. Next: ${anchors.next}. Either continue the next open task now with real tool calls, or mark it done/dropped via the todo tool and tell the user in one sentence why you stopped. Do not restate the plan.\n</system-reminder>`;\n}\n\n/** True when the last non-empty paragraph of the text ends any sentence with `?`. */\nexport function endsWithQuestion(text: string): boolean {\n\tconst paragraphs = text\n\t\t.split(/\\n\\s*\\n/)\n\t\t.map((paragraph) => paragraph.trim())\n\t\t.filter((paragraph) => paragraph !== \"\");\n\tconst last = paragraphs.at(-1);\n\treturn last !== undefined && QUESTION_SENTENCE_END.test(last);\n}\n\nfunction assistantText(message: Extract<AgentMessage, { role: \"assistant\" }> | undefined): string {\n\tif (message === undefined) return \"\";\n\treturn message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\");\n}\n\nfunction calledAskUser(messages: readonly AgentMessage[]): boolean {\n\treturn messages.some(\n\t\t(message) =>\n\t\t\tmessage.role === \"assistant\" &&\n\t\t\tmessage.content.some((content) => content.type === \"toolCall\" && ASK_USER_TOOLS.has(content.name)),\n\t);\n}\n\nfunction readTurnEndBackstopSetting(ctx: ExtensionContext): boolean {\n\treturn SettingsManager.create(ctx.cwd, ctx.agentDir, {\n\t\tprojectTrusted: ctx.isProjectTrusted(),\n\t}).getTodoTurnEndBackstop();\n}\n\n/**\n * The first clause that makes the ended turn NOT owe a nudge, or undefined when every\n * clause holds except the per-chain cap. Child sessions are untagged today (their header\n * carries no `parentSession`), so they pass the main-session clause and are treated as main.\n */\nexport function firstTodoOwedSuppression(input: TodoOwedInput): Exclude<TodoOwedSuppression, \"cap\"> | undefined {\n\tconst { ctx, event, goal } = input;\n\t// Optional call: session managers that predate `getHeader` (and the goal test\n\t// harness fakes) expose no parent tag, which reads as \"main session\" - the same\n\t// treatment untagged child sessions get today.\n\tif (ctx.sessionManager.getHeader?.()?.parentSession !== undefined) return \"subagent\";\n\tif (NON_INTERACTIVE_MODES.has(ctx.mode)) return \"non-interactive\";\n\tif (event.aborted === true || !didAgentEndCleanly(event.messages)) return \"not-clean\";\n\tif (lastAssistantMessage(event.messages)?.stopReason === \"length\") return \"length\";\n\tif (ctx.hasPendingMessages()) return \"pending-messages\";\n\tif (goal?.status === \"active\") return \"active-goal\";\n\tif (input.continuationPending) return \"continuation-pending\";\n\tif (openTodoTaskContents(ctx.sessionManager.getBranch()).length === 0) return \"no-open-tasks\";\n\tif (input.hasActiveWakeSources) return \"wake-source\";\n\tif (calledAskUser(event.messages)) return \"ask-user-call\";\n\tif (endsWithQuestion(assistantText(lastAssistantMessage(event.messages)))) return \"question\";\n\tif (!readTurnEndBackstopSetting(ctx)) return \"disabled\";\n\treturn undefined;\n}\n\n/**\n * Per-session chain state. The chain counts nudges since the last accepted direct user\n * input (or `session_start` / `session_tree`); after two deliveries the third owed turn\n * notifies the user once and every later one stays silent until the chain resets.\n */\nexport class TodoOwedBackstop {\n\treadonly #pi: ExtensionAPI;\n\t#remindersThisChain = 0;\n\t#notifiedThisChain = false;\n\t#logger: SessionLogger | undefined;\n\n\tconstructor(pi: ExtensionAPI) {\n\t\tthis.#pi = pi;\n\t}\n\n\tresetChain(): void {\n\t\tthis.#remindersThisChain = 0;\n\t\tthis.#notifiedThisChain = false;\n\t}\n\n\tafterAgentEnd(input: TodoOwedInput): void {\n\t\tconst suppression = firstTodoOwedSuppression(input);\n\t\tif (suppression !== undefined) {\n\t\t\tthis.#logSuppression(input.ctx, suppression);\n\t\t\treturn;\n\t\t}\n\t\tconst { ctx } = input;\n\t\tconst branch = ctx.sessionManager.getBranch();\n\t\tconst openTasks = openTodoTaskContents(branch).length;\n\t\tconst anchors = describeAskNowNext(getLatestTodoStateFromBranchEntries(branch));\n\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\tif (this.#remindersThisChain >= TODO_OWED_CHAIN_LIMIT) {\n\t\t\tif (this.#notifiedThisChain) {\n\t\t\t\tthis.#logSuppression(ctx, \"cap\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.#notifiedThisChain = true;\n\t\t\tctx.ui.notify(\n\t\t\t\t`Agent stopped with ${openTasks} open todo tasks (Now: ${anchors.now}). Send a message to continue.`,\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t\tthis.#emit({\n\t\t\t\tsessionId,\n\t\t\t\tchainCount: this.#remindersThisChain,\n\t\t\t\topenTasks,\n\t\t\t\tnow: anchors.now,\n\t\t\t\tnext: anchors.next,\n\t\t\t\treason: \"capped\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.#remindersThisChain += 1;\n\t\tconst content = buildTodoOwedReminder(anchors, this.#remindersThisChain === TODO_OWED_CHAIN_LIMIT);\n\t\tthis.#pi.sendMessage(\n\t\t\t{ customType: TODO_OWED_CUSTOM_TYPE, content, display: false },\n\t\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t\t);\n\t\tthis.#emit({\n\t\t\tsessionId,\n\t\t\tchainCount: this.#remindersThisChain,\n\t\t\topenTasks,\n\t\t\tnow: anchors.now,\n\t\t\tnext: anchors.next,\n\t\t\treason: \"delivered\",\n\t\t});\n\t}\n\n\t#emit(event: TodoOwedReminderEvent): void {\n\t\tthis.#pi.events.emit(TODO_OWED_REMINDER_EVENT, event);\n\t}\n\n\t#logSuppression(ctx: ExtensionContext, reason: TodoOwedSuppression): void {\n\t\tthis.#logger ??= createSessionLogger(ctx.agentDir);\n\t\tthis.#logger.debug(\"todo_owed_backstop_suppressed\", { reason });\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,YAAY,EAIZ,MAAM,gBAAgB,CAAC;AA+CxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EACX,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,GACzB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA2P7D;AAmBD,OAAO,EACN,qBAAqB,EACrB,yBAAyB,EACzB,6BAA6B,GAC7B,MAAM,YAAY,CAAC"}
|