@code-yeongyu/senpi 2026.8.26 → 2026.8.28
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 +76 -0
- package/README.md +3 -3
- package/dist/cli/args.d.ts +3 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +14 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +10 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +67 -29
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/credential-accounts.d.ts +31 -0
- package/dist/core/credential-accounts.d.ts.map +1 -0
- package/dist/core/credential-accounts.js +125 -0
- package/dist/core/credential-accounts.js.map +1 -0
- package/dist/core/credential-pool/classify.d.ts +42 -0
- package/dist/core/credential-pool/classify.d.ts.map +1 -0
- package/dist/core/credential-pool/classify.js +75 -0
- package/dist/core/credential-pool/classify.js.map +1 -0
- package/dist/core/credential-pool/env-slots.d.ts +22 -0
- package/dist/core/credential-pool/env-slots.d.ts.map +1 -0
- package/dist/core/credential-pool/env-slots.js +37 -0
- package/dist/core/credential-pool/env-slots.js.map +1 -0
- package/dist/core/credential-pool/failover.d.ts +54 -0
- package/dist/core/credential-pool/failover.d.ts.map +1 -0
- package/dist/core/credential-pool/failover.js +106 -0
- package/dist/core/credential-pool/failover.js.map +1 -0
- package/dist/core/credential-pool/rotation-stream.d.ts +43 -0
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -0
- package/dist/core/credential-pool/rotation-stream.js +96 -0
- package/dist/core/credential-pool/rotation-stream.js.map +1 -0
- package/dist/core/credential-pool/state-store.d.ts +89 -0
- package/dist/core/credential-pool/state-store.d.ts.map +1 -0
- package/dist/core/credential-pool/state-store.js +166 -0
- package/dist/core/credential-pool/state-store.js.map +1 -0
- package/dist/core/extensions/builtin/account/index.d.ts +9 -0
- package/dist/core/extensions/builtin/account/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/account/index.js +69 -0
- package/dist/core/extensions/builtin/account/index.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +67 -0
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +1 -0
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.js +14 -22
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation-recovery.js +2 -0
- package/dist/core/extensions/builtin/goal/continuation-recovery.js.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation.d.ts +8 -1
- package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation.js +15 -0
- package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js +2 -2
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js.map +1 -1
- package/dist/core/extensions/builtin/goal/format.d.ts +6 -1
- package/dist/core/extensions/builtin/goal/format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/format.js +6 -0
- package/dist/core/extensions/builtin/goal/format.js.map +1 -1
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +5 -2
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +31 -7
- package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/persistence.js +2 -0
- package/dist/core/extensions/builtin/goal/persistence.js.map +1 -1
- package/dist/core/extensions/builtin/goal/renderers.d.ts +14 -0
- package/dist/core/extensions/builtin/goal/renderers.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/renderers.js +153 -0
- package/dist/core/extensions/builtin/goal/renderers.js.map +1 -0
- package/dist/core/extensions/builtin/goal/store.d.ts +6 -2
- package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/store.js +8 -2
- package/dist/core/extensions/builtin/goal/store.js.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.js +16 -6
- package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
- package/dist/core/extensions/builtin/goal/types.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/types.js.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.js +10 -3
- package/dist/core/extensions/builtin/imagegen/index.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +4 -0
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.js +1 -1
- package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.js +1 -1
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.js.map +1 -1
- package/dist/core/hidden-stdout-log.d.ts +10 -0
- package/dist/core/hidden-stdout-log.d.ts.map +1 -1
- package/dist/core/hidden-stdout-log.js +36 -5
- package/dist/core/hidden-stdout-log.js.map +1 -1
- package/dist/core/model-config-schema.d.ts +85 -12
- package/dist/core/model-config-schema.d.ts.map +1 -1
- package/dist/core/model-config-schema.js +25 -0
- package/dist/core/model-config-schema.js.map +1 -1
- package/dist/core/model-runtime.d.ts +34 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +98 -5
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +2 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +32 -7
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +38 -3
- package/dist/main.js.map +1 -1
- package/dist/modes/app-server/server/account.d.ts.map +1 -1
- package/dist/modes/app-server/server/account.js +5 -5
- package/dist/modes/app-server/server/account.js.map +1 -1
- package/dist/modes/index.d.ts +1 -0
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -0
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +11 -3
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +31 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution-fallback.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution-fallback.js +82 -1
- package/dist/modes/interactive/components/tool-execution-fallback.js.map +1 -1
- package/dist/modes/interactive/grok/chrome.d.ts +4 -4
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
- package/dist/modes/interactive/grok/chrome.js.map +1 -1
- package/dist/modes/interactive/grok/footer.d.ts +3 -3
- package/dist/modes/interactive/grok/footer.d.ts.map +1 -1
- package/dist/modes/interactive/grok/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +44 -0
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-host-runtime.js +271 -0
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +65 -21
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +19 -6
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts +41 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -0
- package/dist/modes/rpc/host-ensure.js +245 -0
- package/dist/modes/rpc/host-ensure.js.map +1 -0
- package/dist/modes/rpc/host-lifecycle.d.ts +57 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -0
- package/dist/modes/rpc/host-lifecycle.js +491 -0
- package/dist/modes/rpc/host-lifecycle.js.map +1 -0
- package/dist/modes/rpc/host-watchdog.d.ts +33 -0
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -0
- package/dist/modes/rpc/host-watchdog.js +142 -0
- package/dist/modes/rpc/host-watchdog.js.map +1 -0
- package/dist/modes/rpc/multi-session-host.d.ts +7 -1
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +206 -32
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +41 -3
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +125 -14
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +6 -2
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +24 -6
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +13 -2
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +65 -25
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +9 -0
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +31 -3
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/docs/providers.md +48 -0
- package/docs/rpc.md +59 -5
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +44 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +13 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/inline-worker.ts +15 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +711 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +14 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +10 -10
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-eval-result.ts +9 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +6 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js +20 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts +21 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js +27 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts +24 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js +7 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.js +46 -14
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-pairs.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +11 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +30 -16
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.d.ts +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.js +75 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/classify.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts +45 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js +81 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.d.ts +31 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.js +65 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/select.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +12 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +37 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +32 -6
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +6 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +75 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +75 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.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/alibaba-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/mistral.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.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/qwen-token-plan-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.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/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +5 -5
- 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/dist/terminal.d.ts +5 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +90 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -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 } 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;\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 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};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason: \"not-eligible\" | \"single-flight\" | \"cap\" | \"stale\" | \"repetition\" | \"length-exhausted\";\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\" || !isContinuableStopReason(lastAssistant.stopReason)) 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\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\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 (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 input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason);\n\t}\n\treturn input.isIdle;\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 } 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 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};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason: \"not-eligible\" | \"single-flight\" | \"cap\" | \"stale\" | \"repetition\" | \"length-exhausted\" | \"unattended\";\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\" || !isContinuableStopReason(lastAssistant.stopReason)) 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\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\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 input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason);\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"]}
|
|
@@ -38,7 +38,7 @@ export class GoalDirectInputLifecycle {
|
|
|
38
38
|
if (currentGoal?.id !== candidate.goalId)
|
|
39
39
|
return;
|
|
40
40
|
if (currentGoal.status === "blocked" && isMechanicalContinuationBlock(currentGoal.blockedReason)) {
|
|
41
|
-
await resetContinuationStreak(ref);
|
|
41
|
+
await resetContinuationStreak(ref, { unattended: true });
|
|
42
42
|
const reactivated = await updateGoal(ref, { status: "active" }, "user");
|
|
43
43
|
this.#dependencies.beginAgentGoalAccounting(reactivated);
|
|
44
44
|
this.#dependencies.refreshGoalUi(ctx, reactivated);
|
|
@@ -46,7 +46,7 @@ export class GoalDirectInputLifecycle {
|
|
|
46
46
|
}
|
|
47
47
|
if (currentGoal.status !== "active")
|
|
48
48
|
return;
|
|
49
|
-
const reset = await resetContinuationStreak(ref);
|
|
49
|
+
const reset = await resetContinuationStreak(ref, { unattended: true });
|
|
50
50
|
if (reset !== null)
|
|
51
51
|
this.#dependencies.refreshGoalUi(ctx, reset);
|
|
52
52
|
if (this.#suppressedLoadResumeArmed) {
|
|
@@ -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;AAoB3E,gFAAgF;AAChF,MAAM,OAAO,wBAAwB;IAC3B,aAAa,CAAmC;IAChD,WAAW,GAAG,IAAI,GAAG,EAAgC,CAAC;IAC/D,0BAA0B,GAAG,KAAK,CAAC;IAEnC,YAAY,YAA8C;QACzD,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACnC,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,0BAA0B,GAAG,KAAK,CAAC;IACzC,CAAC;IAED,iFAAiF;IACjF,uBAAuB;QACtB,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAiB,EAAE,GAAqB;QACrD,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO;QAEzC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAA4B,EAAE,GAAqB;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO;QACpC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC;QACnF,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,IAAI;YAAE,OAAO;QAEnD,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,WAAW,EAAE,EAAE,KAAK,SAAS,CAAC,MAAM;YAAE,OAAO;QAEjD,IAAI,WAAW,CAAC,MAAM,KAAK,SAAS,IAAI,6BAA6B,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;YAClG,MAAM,uBAAuB,CAAC,GAAG,CAAC,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};\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 || 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,8 +1,13 @@
|
|
|
1
|
-
import type { Goal, GoalStatus, GoalToolResponse } from "./types.ts";
|
|
1
|
+
import type { Goal, GoalStatus, GoalToolResponse, GoalToolSnapshot } from "./types.ts";
|
|
2
2
|
export declare function formatGoalElapsedSeconds(value: number): string;
|
|
3
3
|
export declare function formatTokensCompact(value: number): string;
|
|
4
4
|
export declare function goalStatusLabel(status: GoalStatus): string;
|
|
5
5
|
export declare function formatGoalForTool(goal: Goal | null): string;
|
|
6
|
+
export type GoalToolRenderDetails = {
|
|
7
|
+
goal: GoalToolSnapshot | null;
|
|
8
|
+
notice?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function goalToolRenderDetails(goal: Goal | null, notice?: string): GoalToolRenderDetails;
|
|
6
11
|
export declare function goalToolResponse(goal: Goal | null): GoalToolResponse;
|
|
7
12
|
export declare function formatGoalToolResponse(goal: Goal | null, notice?: string): string;
|
|
8
13
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB9D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAW1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAW3D;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB,CAK/F;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,gBAAgB,CAEpE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAGjF"}
|
|
@@ -51,6 +51,12 @@ export function formatGoalForTool(goal) {
|
|
|
51
51
|
lines.push(`Completed at: ${new Date(goal.completedAt * 1000).toISOString()}`);
|
|
52
52
|
return lines.join("\n");
|
|
53
53
|
}
|
|
54
|
+
export function goalToolRenderDetails(goal, notice) {
|
|
55
|
+
return {
|
|
56
|
+
goal: goal === null ? null : goalToolSnapshot(goal),
|
|
57
|
+
...(notice === undefined ? {} : { notice }),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
54
60
|
export function goalToolResponse(goal) {
|
|
55
61
|
return { goal: goal === null ? null : goalToolSnapshot(goal) };
|
|
56
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Goal, GoalStatus, GoalToolResponse, GoalToolSnapshot } from \"./types.ts\";\n\nexport function formatGoalElapsedSeconds(value: number): string {\n\tconst seconds = Math.max(0, Math.trunc(value));\n\tif (seconds < 60) return `${seconds}s`;\n\n\tconst minutes = Math.trunc(seconds / 60);\n\tif (minutes < 60) return `${minutes}m`;\n\n\tconst hours = Math.trunc(minutes / 60);\n\tconst remainingMinutes = minutes % 60;\n\tif (hours >= 24) {\n\t\tconst days = Math.trunc(hours / 24);\n\t\tconst remainingHours = hours % 24;\n\t\treturn `${days}d ${remainingHours}h ${remainingMinutes}m`;\n\t}\n\n\tif (remainingMinutes === 0) return `${hours}h`;\n\treturn `${hours}h ${remainingMinutes}m`;\n}\n\nexport function formatTokensCompact(value: number): string {\n\tconst abs = Math.abs(value);\n\tif (abs >= 1_000_000) return `${formatOneDecimal(value / 1_000_000)}M`;\n\tif (abs >= 1_000) return `${formatOneDecimal(value / 1_000)}K`;\n\treturn `${Math.trunc(value)}`;\n}\n\nexport function goalStatusLabel(status: GoalStatus): string {\n\tswitch (status) {\n\t\tcase \"active\":\n\t\t\treturn \"active\";\n\t\tcase \"paused\":\n\t\t\treturn \"paused\";\n\t\tcase \"blocked\":\n\t\t\treturn \"blocked\";\n\t\tcase \"complete\":\n\t\t\treturn \"complete\";\n\t}\n}\n\nexport function formatGoalForTool(goal: Goal | null): string {\n\tif (!goal) return \"No active goal is set.\";\n\tconst lines = [\n\t\t`Objective: ${goal.objective}`,\n\t\t`Status: ${goalStatusLabel(goal.status)}`,\n\t\t`Time used: ${formatGoalElapsedSeconds(goal.timeUsedSeconds)}`,\n\t\t`Tokens used: ${formatTokensCompact(goal.tokensUsed)}`,\n\t];\n\tif (goal.blockedReason) lines.push(`Blocked reason: ${goal.blockedReason}`);\n\tif (goal.completedAt) lines.push(`Completed at: ${new Date(goal.completedAt * 1000).toISOString()}`);\n\treturn lines.join(\"\\n\");\n}\n\nexport function goalToolResponse(goal: Goal | null): GoalToolResponse {\n\treturn { goal: goal === null ? null : goalToolSnapshot(goal) };\n}\n\nexport function formatGoalToolResponse(goal: Goal | null, notice?: string): string {\n\tconst response = JSON.stringify(goalToolResponse(goal), null, 2);\n\treturn notice === undefined ? response : `${response}\\n${notice}`;\n}\n\nfunction goalToolSnapshot(goal: Goal): GoalToolSnapshot {\n\treturn {\n\t\tthreadId: goal.threadId,\n\t\tobjective: goal.objective,\n\t\tstatus: goal.status,\n\t\ttokensUsed: goal.tokensUsed,\n\t\ttimeUsedSeconds: goal.timeUsedSeconds,\n\t\tcreatedAt: goal.createdAt,\n\t\tupdatedAt: goal.updatedAt,\n\t\t...(goal.blockedReason === undefined ? {} : { blockedReason: goal.blockedReason }),\n\t\t...(goal.blockedAt === undefined ? {} : { blockedAt: goal.blockedAt }),\n\t};\n}\n\nfunction formatOneDecimal(value: number): string {\n\tconst rounded = value.toFixed(1);\n\treturn rounded.endsWith(\".0\") ? rounded.slice(0, -2) : rounded;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/format.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Goal, GoalStatus, GoalToolResponse, GoalToolSnapshot } from \"./types.ts\";\n\nexport function formatGoalElapsedSeconds(value: number): string {\n\tconst seconds = Math.max(0, Math.trunc(value));\n\tif (seconds < 60) return `${seconds}s`;\n\n\tconst minutes = Math.trunc(seconds / 60);\n\tif (minutes < 60) return `${minutes}m`;\n\n\tconst hours = Math.trunc(minutes / 60);\n\tconst remainingMinutes = minutes % 60;\n\tif (hours >= 24) {\n\t\tconst days = Math.trunc(hours / 24);\n\t\tconst remainingHours = hours % 24;\n\t\treturn `${days}d ${remainingHours}h ${remainingMinutes}m`;\n\t}\n\n\tif (remainingMinutes === 0) return `${hours}h`;\n\treturn `${hours}h ${remainingMinutes}m`;\n}\n\nexport function formatTokensCompact(value: number): string {\n\tconst abs = Math.abs(value);\n\tif (abs >= 1_000_000) return `${formatOneDecimal(value / 1_000_000)}M`;\n\tif (abs >= 1_000) return `${formatOneDecimal(value / 1_000)}K`;\n\treturn `${Math.trunc(value)}`;\n}\n\nexport function goalStatusLabel(status: GoalStatus): string {\n\tswitch (status) {\n\t\tcase \"active\":\n\t\t\treturn \"active\";\n\t\tcase \"paused\":\n\t\t\treturn \"paused\";\n\t\tcase \"blocked\":\n\t\t\treturn \"blocked\";\n\t\tcase \"complete\":\n\t\t\treturn \"complete\";\n\t}\n}\n\nexport function formatGoalForTool(goal: Goal | null): string {\n\tif (!goal) return \"No active goal is set.\";\n\tconst lines = [\n\t\t`Objective: ${goal.objective}`,\n\t\t`Status: ${goalStatusLabel(goal.status)}`,\n\t\t`Time used: ${formatGoalElapsedSeconds(goal.timeUsedSeconds)}`,\n\t\t`Tokens used: ${formatTokensCompact(goal.tokensUsed)}`,\n\t];\n\tif (goal.blockedReason) lines.push(`Blocked reason: ${goal.blockedReason}`);\n\tif (goal.completedAt) lines.push(`Completed at: ${new Date(goal.completedAt * 1000).toISOString()}`);\n\treturn lines.join(\"\\n\");\n}\n\nexport type GoalToolRenderDetails = {\n\tgoal: GoalToolSnapshot | null;\n\tnotice?: string;\n};\n\nexport function goalToolRenderDetails(goal: Goal | null, notice?: string): GoalToolRenderDetails {\n\treturn {\n\t\tgoal: goal === null ? null : goalToolSnapshot(goal),\n\t\t...(notice === undefined ? {} : { notice }),\n\t};\n}\n\nexport function goalToolResponse(goal: Goal | null): GoalToolResponse {\n\treturn { goal: goal === null ? null : goalToolSnapshot(goal) };\n}\n\nexport function formatGoalToolResponse(goal: Goal | null, notice?: string): string {\n\tconst response = JSON.stringify(goalToolResponse(goal), null, 2);\n\treturn notice === undefined ? response : `${response}\\n${notice}`;\n}\n\nfunction goalToolSnapshot(goal: Goal): GoalToolSnapshot {\n\treturn {\n\t\tthreadId: goal.threadId,\n\t\tobjective: goal.objective,\n\t\tstatus: goal.status,\n\t\ttokensUsed: goal.tokensUsed,\n\t\ttimeUsedSeconds: goal.timeUsedSeconds,\n\t\tcreatedAt: goal.createdAt,\n\t\tupdatedAt: goal.updatedAt,\n\t\t...(goal.blockedReason === undefined ? {} : { blockedReason: goal.blockedReason }),\n\t\t...(goal.blockedAt === undefined ? {} : { blockedAt: goal.blockedAt }),\n\t};\n}\n\nfunction formatOneDecimal(value: number): string {\n\tconst rounded = value.toFixed(1);\n\treturn rounded.endsWith(\".0\") ? rounded.slice(0, -2) : rounded;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErE,OAAO,EAGN,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAE5B,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"lifecycle-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErE,OAAO,EAGN,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAE5B,MAAM,mBAAmB,CAAC;AAY3B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,iCAAiC,GAAG,OAAO,CAAC,uBAAuB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAEhG,KAAK,+BAA+B,GAAG;IACtC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iCAAiC,KAAK,MAAM,CAAC;IACzE,QAAQ,CAAC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC7C,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CAC7C,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACpC,GAAG,EAAE,gBAAgB,EACrB,kBAAkB,EAAE,MAAM,EAC1B,IAAI,EAAE,IAAI,GAAG,IAAI,GACf,IAAI,IAAI,IAAI,CASd;AAED,sFAAsF;AACtF,wBAAsB,6BAA6B,CAClD,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACtC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAiBtB;AAED,mHAAmH;AACnH,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACtC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAuBtB;AAED,wBAAgB,qCAAqC,CACpD,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,IAAI,EACV,iBAAiB,EAAE,MAAM,GACvB,MAAM,CAKR;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAM3E;AA6DD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK7E"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GOAL_CONTINUATION_MESSAGE_TYPE } from "../../../messages.js";
|
|
2
2
|
import { getLatestPhasesFromBranchEntries } from "../todotools/state.js";
|
|
3
3
|
import { buildGoalContinuationSignature, evaluateGoalContinuation, hashAssistantText, } from "./continuation.js";
|
|
4
|
-
import { CONTINUATION_CAP_BLOCKED_REASON, continuationCapRecoveryHint, LENGTH_EXHAUSTED_BLOCKED_REASON, REPETITION_BLOCKED_REASON, } from "./continuation-recovery.js";
|
|
4
|
+
import { CONTINUATION_CAP_BLOCKED_REASON, continuationCapRecoveryHint, LENGTH_EXHAUSTED_BLOCKED_REASON, REPETITION_BLOCKED_REASON, UNATTENDED_CONTINUATION_BLOCKED_REASON, } from "./continuation-recovery.js";
|
|
5
5
|
import { buildContinuationPrompt } from "./prompt.js";
|
|
6
6
|
import { recordContinuationDelivered, updateGoal } from "./store.js";
|
|
7
7
|
import { goalStoreRef } from "./store-ref.js";
|
|
@@ -33,7 +33,7 @@ export async function admitAndQueueGoalContinuation(pi, ctx, goal, options) {
|
|
|
33
33
|
if (options.input.currentSignature === undefined) {
|
|
34
34
|
throw new Error("Cannot queue a goal continuation without a progress signature");
|
|
35
35
|
}
|
|
36
|
-
const recordedGoal = await recordContinuationDelivered(goalStoreRef(ctx.sessionManager, ctx.cwd), options.input.currentSignature, goal.id);
|
|
36
|
+
const recordedGoal = await recordContinuationDelivered(goalStoreRef(ctx.sessionManager, ctx.cwd), options.input.currentSignature, goal.id, { countUnattended: options.input.path !== "monitorDelayed" });
|
|
37
37
|
if (recordedGoal === null)
|
|
38
38
|
return null;
|
|
39
39
|
options.markContinuationPending();
|
|
@@ -100,6 +100,7 @@ async function handleDeniedContinuation(pi, ctx, goal, input, reason) {
|
|
|
100
100
|
goalId: goal.id,
|
|
101
101
|
reason,
|
|
102
102
|
count: input.consecutiveContinuations,
|
|
103
|
+
unattendedContinuations: goal.unattendedContinuations ?? 0,
|
|
103
104
|
});
|
|
104
105
|
return blocked;
|
|
105
106
|
}
|
|
@@ -107,6 +108,8 @@ function blockedReasonForContinuationGuard(reason) {
|
|
|
107
108
|
switch (reason) {
|
|
108
109
|
case "cap":
|
|
109
110
|
return CONTINUATION_CAP_BLOCKED_REASON;
|
|
111
|
+
case "unattended":
|
|
112
|
+
return UNATTENDED_CONTINUATION_BLOCKED_REASON;
|
|
110
113
|
case "repetition":
|
|
111
114
|
return REPETITION_BLOCKED_REASON;
|
|
112
115
|
case "length-exhausted":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle-helpers.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { getLatestPhasesFromBranchEntries } from \"../todotools/state.ts\";\nimport {\n\tbuildGoalContinuationSignature,\n\tevaluateGoalContinuation,\n\ttype GoalContinuationInput,\n\ttype GoalContinuationVerdict,\n\thashAssistantText,\n} from \"./continuation.ts\";\nimport {\n\tCONTINUATION_CAP_BLOCKED_REASON,\n\tcontinuationCapRecoveryHint,\n\tLENGTH_EXHAUSTED_BLOCKED_REASON,\n\tREPETITION_BLOCKED_REASON,\n} from \"./continuation-recovery.ts\";\nimport { buildContinuationPrompt } from \"./prompt.ts\";\nimport { recordContinuationDelivered, updateGoal } from \"./store.ts\";\nimport { goalStoreRef } from \"./store-ref.ts\";\nimport { openTodoTaskContents } from \"./todo-gate.ts\";\nimport type { Goal } from \"./types.ts\";\n\ntype ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict, { kind: \"continue\" }>;\n\ntype GoalContinuationDeliveryOptions = {\n\treadonly input: Omit<GoalContinuationInput, \"goal\">;\n\treadonly content: (verdict: ContinuingGoalContinuationVerdict) => string;\n\treadonly markContinuationPending: () => void;\n};\n\nexport type SessionStartContinuationOptions = {\n\treadonly continuationPending: boolean;\n\treadonly markContinuationPending: () => void;\n};\n\n/**\n * Statuses that leave a goal stopped without finishing it. A restart is the only\n * moment the user can act on them, so both earn the resume prompt.\n */\nconst STOPPED_UNFINISHED_GOAL_STATUSES: readonly Goal[\"status\"][] = [\"paused\", \"blocked\"];\n\n/**\n * Mirrors codex `maybe_prompt_resume_paused_goal_after_resume`\n * (codex-rs/tui/src/app/thread_goal_actions.rs), which prompts on resume for every\n * stopped-but-unfinished status. senpi is budget-free, so codex's `UsageLimited`\n * has no counterpart here and the stopped set is `paused | blocked`.\n */\nexport function isResumeOfStoppedGoal(\n\tctx: ExtensionContext,\n\tsessionStartReason: string,\n\tgoal: Goal | null,\n): goal is Goal {\n\treturn (\n\t\tsessionStartReason === \"resume\" &&\n\t\tgoal !== null &&\n\t\tSTOPPED_UNFINISHED_GOAL_STATUSES.includes(goal.status) &&\n\t\tctx.hasUI &&\n\t\tctx.isIdle() &&\n\t\t!ctx.hasPendingMessages()\n\t);\n}\n\n/** Evaluates and delivers a continuation only after all guardrail checks admit it. */\nexport async function admitAndQueueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: GoalContinuationDeliveryOptions,\n): Promise<Goal | null> {\n\tconst verdict = evaluateGoalContinuation({ goal, ...options.input });\n\tif (verdict.kind === \"deny\") return handleDeniedContinuation(pi, ctx, goal, options.input, verdict.reason);\n\n\tif (options.input.currentSignature === undefined) {\n\t\tthrow new Error(\"Cannot queue a goal continuation without a progress signature\");\n\t}\n\tconst recordedGoal = await recordContinuationDelivered(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\toptions.input.currentSignature,\n\t\tgoal.id,\n\t);\n\tif (recordedGoal === null) return null;\n\toptions.markContinuationPending();\n\tqueueHiddenGoalPrompt(pi, options.content(verdict));\n\treturn recordedGoal;\n}\n\n/** Routes startup and resume continuations through the same verdict and delivery accounting as agent-end paths. */\nexport async function queueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: SessionStartContinuationOptions,\n): Promise<Goal | null> {\n\tconst signature = buildCurrentGoalContinuationSignature(\n\t\tctx,\n\t\tgoal,\n\t\tlastAssistantTextFromEntries(ctx.sessionManager.getBranch()),\n\t);\n\treturn admitAndQueueGoalContinuation(pi, ctx, goal, {\n\t\tinput: {\n\t\t\tisIdle: ctx.isIdle(),\n\t\t\thasPendingMessages: ctx.hasPendingMessages(),\n\t\t\tpath: \"sessionStart\",\n\t\t\tlastStopReason: undefined,\n\t\t\tconsecutiveContinuations: goal.consecutiveContinuations ?? 0,\n\t\t\tlastContinuationSignature: goal.lastContinuationSignature,\n\t\t\tcurrentSignature: signature,\n\t\t\tconsecutiveLengthRecoveries: 0,\n\t\t\trecentNormalizedOutputHashes: [],\n\t\t\ttoollessContinuationStreak: 0,\n\t\t\tcontinuationPending: options.continuationPending,\n\t\t},\n\t\tcontent: () => buildContinuationPrompt(goal),\n\t\tmarkContinuationPending: options.markContinuationPending,\n\t});\n}\n\nexport function buildCurrentGoalContinuationSignature(\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tlastAssistantText: string,\n): string {\n\tconst entries = ctx.sessionManager.getBranch();\n\tconst openTodos = openTodoTaskContents(entries).length;\n\tconst totalTodos = getLatestPhasesFromBranchEntries(entries).reduce((count, phase) => count + phase.tasks.length, 0);\n\treturn buildGoalContinuationSignature(goal, openTodos, totalTodos, hashAssistantText(lastAssistantText));\n}\n\nexport function lastAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") return textContent(message);\n\t}\n\treturn \"\";\n}\n\nfunction lastAssistantTextFromEntries(entries: readonly SessionEntry[]): string {\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 === \"assistant\") return textContent(entry.message);\n\t}\n\treturn \"\";\n}\n\nfunction textContent(message: Extract<AgentMessage, { role: \"assistant\" }>): string {\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\nasync function handleDeniedContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tinput: Omit<GoalContinuationInput, \"goal\">,\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): Promise<Goal> {\n\tconst blockedReason = blockedReasonForContinuationGuard(reason);\n\tif (blockedReason === undefined) return goal;\n\n\tconst blocked = await updateGoal(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\t{ status: \"blocked\", reason: blockedReason },\n\t\t\"model\",\n\t);\n\tif (ctx.hasUI) ctx.ui.notify(continuationCapRecoveryHint(blockedReason), \"warning\");\n\tpi.events?.emit(\"goal_continuation_guard_tripped\", {\n\t\tgoalId: goal.id,\n\t\treason,\n\t\tcount: input.consecutiveContinuations,\n\t});\n\treturn blocked;\n}\n\nfunction blockedReasonForContinuationGuard(\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): string | undefined {\n\tswitch (reason) {\n\t\tcase \"cap\":\n\t\t\treturn CONTINUATION_CAP_BLOCKED_REASON;\n\t\tcase \"repetition\":\n\t\t\treturn REPETITION_BLOCKED_REASON;\n\t\tcase \"length-exhausted\":\n\t\t\treturn LENGTH_EXHAUSTED_BLOCKED_REASON;\n\t\tcase \"not-eligible\":\n\t\tcase \"single-flight\":\n\t\tcase \"stale\":\n\t\t\treturn undefined;\n\t}\n}\n\nexport function queueHiddenGoalPrompt(pi: ExtensionAPI, content: string): void {\n\tpi.sendMessage(\n\t\t{ customType: GOAL_CONTINUATION_MESSAGE_TYPE, content, display: false },\n\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"lifecycle-helpers.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/lifecycle-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { getLatestPhasesFromBranchEntries } from \"../todotools/state.ts\";\nimport {\n\tbuildGoalContinuationSignature,\n\tevaluateGoalContinuation,\n\ttype GoalContinuationInput,\n\ttype GoalContinuationVerdict,\n\thashAssistantText,\n} from \"./continuation.ts\";\nimport {\n\tCONTINUATION_CAP_BLOCKED_REASON,\n\tcontinuationCapRecoveryHint,\n\tLENGTH_EXHAUSTED_BLOCKED_REASON,\n\tREPETITION_BLOCKED_REASON,\n\tUNATTENDED_CONTINUATION_BLOCKED_REASON,\n} from \"./continuation-recovery.ts\";\nimport { buildContinuationPrompt } from \"./prompt.ts\";\nimport { recordContinuationDelivered, updateGoal } from \"./store.ts\";\nimport { goalStoreRef } from \"./store-ref.ts\";\nimport { openTodoTaskContents } from \"./todo-gate.ts\";\nimport type { Goal } from \"./types.ts\";\n\ntype ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict, { kind: \"continue\" }>;\n\ntype GoalContinuationDeliveryOptions = {\n\treadonly input: Omit<GoalContinuationInput, \"goal\">;\n\treadonly content: (verdict: ContinuingGoalContinuationVerdict) => string;\n\treadonly markContinuationPending: () => void;\n};\n\nexport type SessionStartContinuationOptions = {\n\treadonly continuationPending: boolean;\n\treadonly markContinuationPending: () => void;\n};\n\n/**\n * Statuses that leave a goal stopped without finishing it. A restart is the only\n * moment the user can act on them, so both earn the resume prompt.\n */\nconst STOPPED_UNFINISHED_GOAL_STATUSES: readonly Goal[\"status\"][] = [\"paused\", \"blocked\"];\n\n/**\n * Mirrors codex `maybe_prompt_resume_paused_goal_after_resume`\n * (codex-rs/tui/src/app/thread_goal_actions.rs), which prompts on resume for every\n * stopped-but-unfinished status. senpi is budget-free, so codex's `UsageLimited`\n * has no counterpart here and the stopped set is `paused | blocked`.\n */\nexport function isResumeOfStoppedGoal(\n\tctx: ExtensionContext,\n\tsessionStartReason: string,\n\tgoal: Goal | null,\n): goal is Goal {\n\treturn (\n\t\tsessionStartReason === \"resume\" &&\n\t\tgoal !== null &&\n\t\tSTOPPED_UNFINISHED_GOAL_STATUSES.includes(goal.status) &&\n\t\tctx.hasUI &&\n\t\tctx.isIdle() &&\n\t\t!ctx.hasPendingMessages()\n\t);\n}\n\n/** Evaluates and delivers a continuation only after all guardrail checks admit it. */\nexport async function admitAndQueueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: GoalContinuationDeliveryOptions,\n): Promise<Goal | null> {\n\tconst verdict = evaluateGoalContinuation({ goal, ...options.input });\n\tif (verdict.kind === \"deny\") return handleDeniedContinuation(pi, ctx, goal, options.input, verdict.reason);\n\n\tif (options.input.currentSignature === undefined) {\n\t\tthrow new Error(\"Cannot queue a goal continuation without a progress signature\");\n\t}\n\tconst recordedGoal = await recordContinuationDelivered(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\toptions.input.currentSignature,\n\t\tgoal.id,\n\t\t{ countUnattended: options.input.path !== \"monitorDelayed\" },\n\t);\n\tif (recordedGoal === null) return null;\n\toptions.markContinuationPending();\n\tqueueHiddenGoalPrompt(pi, options.content(verdict));\n\treturn recordedGoal;\n}\n\n/** Routes startup and resume continuations through the same verdict and delivery accounting as agent-end paths. */\nexport async function queueGoalContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\toptions: SessionStartContinuationOptions,\n): Promise<Goal | null> {\n\tconst signature = buildCurrentGoalContinuationSignature(\n\t\tctx,\n\t\tgoal,\n\t\tlastAssistantTextFromEntries(ctx.sessionManager.getBranch()),\n\t);\n\treturn admitAndQueueGoalContinuation(pi, ctx, goal, {\n\t\tinput: {\n\t\t\tisIdle: ctx.isIdle(),\n\t\t\thasPendingMessages: ctx.hasPendingMessages(),\n\t\t\tpath: \"sessionStart\",\n\t\t\tlastStopReason: undefined,\n\t\t\tconsecutiveContinuations: goal.consecutiveContinuations ?? 0,\n\t\t\tlastContinuationSignature: goal.lastContinuationSignature,\n\t\t\tcurrentSignature: signature,\n\t\t\tconsecutiveLengthRecoveries: 0,\n\t\t\trecentNormalizedOutputHashes: [],\n\t\t\ttoollessContinuationStreak: 0,\n\t\t\tcontinuationPending: options.continuationPending,\n\t\t},\n\t\tcontent: () => buildContinuationPrompt(goal),\n\t\tmarkContinuationPending: options.markContinuationPending,\n\t});\n}\n\nexport function buildCurrentGoalContinuationSignature(\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tlastAssistantText: string,\n): string {\n\tconst entries = ctx.sessionManager.getBranch();\n\tconst openTodos = openTodoTaskContents(entries).length;\n\tconst totalTodos = getLatestPhasesFromBranchEntries(entries).reduce((count, phase) => count + phase.tasks.length, 0);\n\treturn buildGoalContinuationSignature(goal, openTodos, totalTodos, hashAssistantText(lastAssistantText));\n}\n\nexport function lastAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") return textContent(message);\n\t}\n\treturn \"\";\n}\n\nfunction lastAssistantTextFromEntries(entries: readonly SessionEntry[]): string {\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 === \"assistant\") return textContent(entry.message);\n\t}\n\treturn \"\";\n}\n\nfunction textContent(message: Extract<AgentMessage, { role: \"assistant\" }>): string {\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\nasync function handleDeniedContinuation(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tgoal: Goal,\n\tinput: Omit<GoalContinuationInput, \"goal\">,\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): Promise<Goal> {\n\tconst blockedReason = blockedReasonForContinuationGuard(reason);\n\tif (blockedReason === undefined) return goal;\n\n\tconst blocked = await updateGoal(\n\t\tgoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\t{ status: \"blocked\", reason: blockedReason },\n\t\t\"model\",\n\t);\n\tif (ctx.hasUI) ctx.ui.notify(continuationCapRecoveryHint(blockedReason), \"warning\");\n\tpi.events?.emit(\"goal_continuation_guard_tripped\", {\n\t\tgoalId: goal.id,\n\t\treason,\n\t\tcount: input.consecutiveContinuations,\n\t\tunattendedContinuations: goal.unattendedContinuations ?? 0,\n\t});\n\treturn blocked;\n}\n\nfunction blockedReasonForContinuationGuard(\n\treason: Extract<GoalContinuationVerdict, { kind: \"deny\" }>[\"reason\"],\n): string | undefined {\n\tswitch (reason) {\n\t\tcase \"cap\":\n\t\t\treturn CONTINUATION_CAP_BLOCKED_REASON;\n\t\tcase \"unattended\":\n\t\t\treturn UNATTENDED_CONTINUATION_BLOCKED_REASON;\n\t\tcase \"repetition\":\n\t\t\treturn REPETITION_BLOCKED_REASON;\n\t\tcase \"length-exhausted\":\n\t\t\treturn LENGTH_EXHAUSTED_BLOCKED_REASON;\n\t\tcase \"not-eligible\":\n\t\tcase \"single-flight\":\n\t\tcase \"stale\":\n\t\t\treturn undefined;\n\t}\n}\n\nexport function queueHiddenGoalPrompt(pi: ExtensionAPI, content: string): void {\n\tpi.sendMessage(\n\t\t{ customType: GOAL_CONTINUATION_MESSAGE_TYPE, content, display: false },\n\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAarE,OAAO,EAAE,2CAA2C,EAAE,MAAM,iBAAiB,CAAC;AAkB9E,OAAO,KAAK,EACX,eAAe,EAIf,uBAAuB,EAEvB,kBAAkB,EAClB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"monitor-continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAarE,OAAO,EAAE,2CAA2C,EAAE,MAAM,iBAAiB,CAAC;AAkB9E,OAAO,KAAK,EACX,eAAe,EAIf,uBAAuB,EAEvB,kBAAkB,EAClB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,KAAK,EAAE,IAAI,EAAsB,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,eAAO,MAAM,iCAAiC,gCAAgC,CAAC;AAC/E,eAAO,MAAM,+BAA+B,8BAA8B,CAAC;AAC3E,eAAO,MAAM,mCAAmC,kCAAkC,CAAC;AACnF,eAAO,MAAM,wBAAwB,oCAAoC,CAAC;AAE1E,qBAAa,4BAA4B;;gBAiCvC,EAAE,EAAE,YAAY,EAChB,qBAAqB,GAAE,MAAM,OAAqB,EAClD,uBAAuB,GAAE,MAAM,IAAe,EAC9C,UAAU,CAAC,EAAE,cAAc;IAS5B,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAW5B,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IA0D7D,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAoBnE,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAgB5E,iBAAiB,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IA2B3D,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IASjC,sGAAsG;IACtG,oBAAoB,IAAI,OAAO;IAI/B;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAMtC,mGAAmG;IACnG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAwBtC,6FAA6F;IAC7F,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAc5D,sEAAsE;IACtE,cAAc,IAAI,IAAI;IAOtB,mGAAmG;IACnG,uBAAuB,IAAI,IAAI;IAI/B,OAAO,IAAI,IAAI;CAkWf"}
|
|
@@ -5,6 +5,7 @@ import { continuationTurnUsedTools, evaluateGoalContinuation, GOAL_USER_GRACE_DE
|
|
|
5
5
|
import { lastAssistantMessage } from "./last-assistant-message.js";
|
|
6
6
|
import { admitAndQueueGoalContinuation, buildCurrentGoalContinuationSignature, lastAssistantText, } from "./lifecycle-helpers.js";
|
|
7
7
|
import { buildContinuationPrompt, buildGoalStallNotice, buildTruncationRecoveryPrompt } from "./prompt.js";
|
|
8
|
+
import { isStaleExtensionContextError } from "./stale-context.js";
|
|
8
9
|
import { resetContinuationStreak } from "./store.js";
|
|
9
10
|
import { goalStoreRef } from "./store-ref.js";
|
|
10
11
|
import { collectAssistantUsage } from "./turn-usage.js";
|
|
@@ -100,7 +101,8 @@ export class MonitorAwareGoalContinuation {
|
|
|
100
101
|
return goal;
|
|
101
102
|
case "cap":
|
|
102
103
|
case "repetition":
|
|
103
|
-
case "length-exhausted":
|
|
104
|
+
case "length-exhausted":
|
|
105
|
+
case "unattended": {
|
|
104
106
|
const admission = await this.#admitAndQueue(options.ctx, goal, "immediate", options.messages);
|
|
105
107
|
return admission.goal;
|
|
106
108
|
}
|
|
@@ -300,10 +302,28 @@ export class MonitorAwareGoalContinuation {
|
|
|
300
302
|
}
|
|
301
303
|
this.#armTimer(kind, delayMs, delayMs);
|
|
302
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* `hasUI` is an `assertActive()`-guarded getter, so a ctx retired by session
|
|
307
|
+
* replacement or reload THROWS instead of reporting false. Optional chaining
|
|
308
|
+
* only guards an undefined ctx (what `dispose()` leaves behind), never a stale
|
|
309
|
+
* object left by a replacement that never disposed this monitor. Callers reach
|
|
310
|
+
* this from timer and event callbacks where a throw is fatal, so a retired ctx
|
|
311
|
+
* reports "no UI" and any other failure keeps its current behavior.
|
|
312
|
+
*/
|
|
313
|
+
#ctxHasUI(ctx = this.#ctx) {
|
|
314
|
+
try {
|
|
315
|
+
return ctx?.hasUI === true;
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
if (isStaleExtensionContextError(error))
|
|
319
|
+
return false;
|
|
320
|
+
throw error;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
303
323
|
#armTimer(kind, delayMs, totalMs, drainFire = false) {
|
|
304
324
|
this.#scheduledDueAtMs = Date.now() + delayMs;
|
|
305
325
|
const ctx = this.#ctx;
|
|
306
|
-
if (ctx
|
|
326
|
+
if (ctx !== undefined && this.#ctxHasUI(ctx)) {
|
|
307
327
|
this.#waitTicker?.sync(ctx, {
|
|
308
328
|
kind,
|
|
309
329
|
remainingMs: delayMs,
|
|
@@ -313,10 +333,14 @@ export class MonitorAwareGoalContinuation {
|
|
|
313
333
|
}
|
|
314
334
|
this.#timer = setTimeout(() => {
|
|
315
335
|
void this.#continueIfEligible(kind, drainFire).catch((error) => {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
336
|
+
// Runs from a bare setTimeout: anything thrown here escapes as an
|
|
337
|
+
// uncaughtException and kills the session. A retired ctx cannot be
|
|
338
|
+
// notified, and its own staleness is the expected cause of this
|
|
339
|
+
// rejection after a session replacement, so drop it quietly.
|
|
340
|
+
if (isStaleExtensionContextError(error) || !this.#ctxHasUI())
|
|
341
|
+
return;
|
|
342
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
343
|
+
this.#ctx?.ui.notify(`Goal continuation delivery failed: ${message}`, "error");
|
|
320
344
|
});
|
|
321
345
|
}, delayMs);
|
|
322
346
|
}
|
|
@@ -420,7 +444,7 @@ export class MonitorAwareGoalContinuation {
|
|
|
420
444
|
consecutiveContinuations: this.#toollessContinuationStreak,
|
|
421
445
|
toolless: true,
|
|
422
446
|
});
|
|
423
|
-
if (ctx
|
|
447
|
+
if (this.#ctxHasUI(ctx)) {
|
|
424
448
|
const context = liveSources.length > 0 ? `while ${liveSources.join(", ")} channels stayed active` : "without tool use";
|
|
425
449
|
ctx.ui.notify(`Goal continuation repeated ${this.#toollessContinuationStreak} toolless turns ${context} - injected a stall check.`, "info");
|
|
426
450
|
}
|