visionclaw 0.1.219-beta.0 → 0.1.219-dev.codex-issue-2805-worker-runtime.2
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/dist/agent/api-proxy.d.ts +0 -16
- package/dist/agent/api-proxy.d.ts.map +1 -1
- package/dist/agent/api-proxy.js +9 -8
- package/dist/agent/api-proxy.js.map +1 -1
- package/dist/agent/browser-launcher.d.ts +3 -0
- package/dist/agent/browser-launcher.d.ts.map +1 -1
- package/dist/agent/browser-launcher.js +101 -43
- package/dist/agent/browser-launcher.js.map +1 -1
- package/dist/agent/coding-conventions.d.ts +8 -0
- package/dist/agent/coding-conventions.d.ts.map +1 -0
- package/dist/agent/coding-conventions.js +19 -0
- package/dist/agent/coding-conventions.js.map +1 -0
- package/dist/agent/command-handlers.d.ts.map +1 -1
- package/dist/agent/command-handlers.js +4 -16
- package/dist/agent/command-handlers.js.map +1 -1
- package/dist/agent/context-action-restart-fallback.d.ts.map +1 -1
- package/dist/agent/context-action-restart-fallback.js +9 -3
- package/dist/agent/context-action-restart-fallback.js.map +1 -1
- package/dist/agent/context-refresh.d.ts.map +1 -1
- package/dist/agent/context-refresh.js +0 -7
- package/dist/agent/context-refresh.js.map +1 -1
- package/dist/agent/context.d.ts +2 -4
- package/dist/agent/context.d.ts.map +1 -1
- package/dist/agent/context.js +12 -21
- package/dist/agent/context.js.map +1 -1
- package/dist/agent/engine-fallback.d.ts +0 -35
- package/dist/agent/engine-fallback.d.ts.map +1 -1
- package/dist/agent/engine-fallback.js +4 -3
- package/dist/agent/engine-fallback.js.map +1 -1
- package/dist/agent/engine-switch.d.ts +19 -38
- package/dist/agent/engine-switch.d.ts.map +1 -1
- package/dist/agent/engine-switch.js +46 -111
- package/dist/agent/engine-switch.js.map +1 -1
- package/dist/agent/engines/browser-tool-policy.d.ts +12 -1
- package/dist/agent/engines/browser-tool-policy.d.ts.map +1 -1
- package/dist/agent/engines/browser-tool-policy.js +17 -2
- package/dist/agent/engines/browser-tool-policy.js.map +1 -1
- package/dist/agent/engines/claude/executor-shell-groups.d.ts +11 -0
- package/dist/agent/engines/claude/executor-shell-groups.d.ts.map +1 -0
- package/dist/agent/engines/claude/executor-shell-groups.js +22 -0
- package/dist/agent/engines/claude/executor-shell-groups.js.map +1 -0
- package/dist/agent/engines/claude/session.d.ts +13 -4
- package/dist/agent/engines/claude/session.d.ts.map +1 -1
- package/dist/agent/engines/claude/session.js +165 -84
- package/dist/agent/engines/claude/session.js.map +1 -1
- package/dist/agent/engines/pi/shared/usage.d.ts +6 -8
- package/dist/agent/engines/pi/shared/usage.d.ts.map +1 -1
- package/dist/agent/engines/pi/shared/usage.js +24 -7
- package/dist/agent/engines/pi/shared/usage.js.map +1 -1
- package/dist/agent/engines/pi/tools.d.ts +3 -10
- package/dist/agent/engines/pi/tools.d.ts.map +1 -1
- package/dist/agent/engines/pi/tools.js +6 -20
- package/dist/agent/engines/pi/tools.js.map +1 -1
- package/dist/agent/engines/pi-coding/executor-shell.d.ts +4 -0
- package/dist/agent/engines/pi-coding/executor-shell.d.ts.map +1 -0
- package/dist/agent/engines/pi-coding/executor-shell.js +175 -0
- package/dist/agent/engines/pi-coding/executor-shell.js.map +1 -0
- package/dist/agent/engines/pi-coding/session.d.ts +4 -4
- package/dist/agent/engines/pi-coding/session.d.ts.map +1 -1
- package/dist/agent/engines/pi-coding/session.js +118 -66
- package/dist/agent/engines/pi-coding/session.js.map +1 -1
- package/dist/agent/engines/pi-coding/tools.d.ts +2 -5
- package/dist/agent/engines/pi-coding/tools.d.ts.map +1 -1
- package/dist/agent/engines/pi-coding/tools.js +7 -5
- package/dist/agent/engines/pi-coding/tools.js.map +1 -1
- package/dist/agent/engines/session-types.d.ts +8 -8
- package/dist/agent/engines/session-types.d.ts.map +1 -1
- package/dist/agent/external-context/interrupt.d.ts +0 -2
- package/dist/agent/external-context/interrupt.d.ts.map +1 -1
- package/dist/agent/external-context/interrupt.js +0 -1
- package/dist/agent/external-context/interrupt.js.map +1 -1
- package/dist/agent/external-context/registry.d.ts +0 -2
- package/dist/agent/external-context/registry.d.ts.map +1 -1
- package/dist/agent/external-context/registry.js +2 -4
- package/dist/agent/external-context/registry.js.map +1 -1
- package/dist/agent/external-context/runtime.d.ts.map +1 -1
- package/dist/agent/external-context/runtime.js +15 -14
- package/dist/agent/external-context/runtime.js.map +1 -1
- package/dist/agent/external-context/types.d.ts +0 -2
- package/dist/agent/external-context/types.d.ts.map +1 -1
- package/dist/agent/fast-responder.d.ts +4 -20
- package/dist/agent/fast-responder.d.ts.map +1 -1
- package/dist/agent/fast-responder.js +28 -42
- package/dist/agent/fast-responder.js.map +1 -1
- package/dist/agent/interrupt-handler.d.ts +4 -18
- package/dist/agent/interrupt-handler.d.ts.map +1 -1
- package/dist/agent/interrupt-handler.js +52 -283
- package/dist/agent/interrupt-handler.js.map +1 -1
- package/dist/agent/lab-run-system-prompt.d.ts.map +1 -1
- package/dist/agent/lab-run-system-prompt.js +4 -1
- package/dist/agent/lab-run-system-prompt.js.map +1 -1
- package/dist/agent/lifecycle-trace.d.ts.map +1 -1
- package/dist/agent/lifecycle-trace.js +6 -5
- package/dist/agent/lifecycle-trace.js.map +1 -1
- package/dist/agent/loop.d.ts +9 -3
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +288 -157
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/memory-protocol.d.ts +2 -2
- package/dist/agent/memory-protocol.d.ts.map +1 -1
- package/dist/agent/memory-protocol.js +3 -15
- package/dist/agent/memory-protocol.js.map +1 -1
- package/dist/agent/memory-store.d.ts +58 -0
- package/dist/agent/memory-store.d.ts.map +1 -0
- package/dist/agent/memory-store.js +152 -0
- package/dist/agent/memory-store.js.map +1 -0
- package/dist/agent/model-provider.d.ts +18 -5
- package/dist/agent/model-provider.d.ts.map +1 -1
- package/dist/agent/model-provider.js +58 -18
- package/dist/agent/model-provider.js.map +1 -1
- package/dist/agent/nightly-maintenance/dreaming-batch.d.ts +184 -0
- package/dist/agent/nightly-maintenance/dreaming-batch.d.ts.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-batch.js +192 -0
- package/dist/agent/nightly-maintenance/dreaming-batch.js.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-files.d.ts +48 -0
- package/dist/agent/nightly-maintenance/dreaming-files.d.ts.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-files.js +109 -0
- package/dist/agent/nightly-maintenance/dreaming-files.js.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-ledger.d.ts +62 -0
- package/dist/agent/nightly-maintenance/dreaming-ledger.d.ts.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-ledger.js +146 -0
- package/dist/agent/nightly-maintenance/dreaming-ledger.js.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-planner.d.ts +86 -0
- package/dist/agent/nightly-maintenance/dreaming-planner.d.ts.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-planner.js +304 -0
- package/dist/agent/nightly-maintenance/dreaming-planner.js.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-runner.d.ts +93 -0
- package/dist/agent/nightly-maintenance/dreaming-runner.d.ts.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-runner.js +156 -0
- package/dist/agent/nightly-maintenance/dreaming-runner.js.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-sources.d.ts +115 -0
- package/dist/agent/nightly-maintenance/dreaming-sources.d.ts.map +1 -0
- package/dist/agent/nightly-maintenance/dreaming-sources.js +270 -0
- package/dist/agent/nightly-maintenance/dreaming-sources.js.map +1 -0
- package/dist/agent/nightly-maintenance/index.d.ts +28 -8
- package/dist/agent/nightly-maintenance/index.d.ts.map +1 -1
- package/dist/agent/nightly-maintenance/index.js +42 -15
- package/dist/agent/nightly-maintenance/index.js.map +1 -1
- package/dist/agent/nightly-maintenance/skill-learning-gate.js +1 -1
- package/dist/agent/nightly-maintenance/skill-learning-gate.js.map +1 -1
- package/dist/agent/nightly-maintenance/vocabulary-processor.d.ts +1 -1
- package/dist/agent/nightly-maintenance/vocabulary-processor.d.ts.map +1 -1
- package/dist/agent/product-identity.d.ts +5 -4
- package/dist/agent/product-identity.d.ts.map +1 -1
- package/dist/agent/product-identity.js +7 -6
- package/dist/agent/product-identity.js.map +1 -1
- package/dist/agent/public-activity.js +1 -1
- package/dist/agent/public-activity.js.map +1 -1
- package/dist/agent/reply-watchdog.d.ts +5 -3
- package/dist/agent/reply-watchdog.d.ts.map +1 -1
- package/dist/agent/reply-watchdog.js +6 -4
- package/dist/agent/reply-watchdog.js.map +1 -1
- package/dist/agent/runtime-context.d.ts +27 -0
- package/dist/agent/runtime-context.d.ts.map +1 -0
- package/dist/agent/runtime-context.js +60 -0
- package/dist/agent/runtime-context.js.map +1 -0
- package/dist/agent/runtime-disclosure-policy.d.ts +6 -0
- package/dist/agent/runtime-disclosure-policy.d.ts.map +1 -0
- package/dist/agent/runtime-disclosure-policy.js +16 -0
- package/dist/agent/runtime-disclosure-policy.js.map +1 -0
- package/dist/agent/runtime-surface.d.ts +15 -4
- package/dist/agent/runtime-surface.d.ts.map +1 -1
- package/dist/agent/runtime-surface.js +0 -1
- package/dist/agent/runtime-surface.js.map +1 -1
- package/dist/agent/session-manager.d.ts +30 -126
- package/dist/agent/session-manager.d.ts.map +1 -1
- package/dist/agent/session-manager.js +60 -484
- package/dist/agent/session-manager.js.map +1 -1
- package/dist/agent/state.d.ts +42 -2
- package/dist/agent/state.d.ts.map +1 -1
- package/dist/agent/state.js +21 -11
- package/dist/agent/state.js.map +1 -1
- package/dist/agent/stream-handler.d.ts +6 -13
- package/dist/agent/stream-handler.d.ts.map +1 -1
- package/dist/agent/stream-handler.js +8 -62
- package/dist/agent/stream-handler.js.map +1 -1
- package/dist/agent/system-prompt.d.ts +2 -0
- package/dist/agent/system-prompt.d.ts.map +1 -1
- package/dist/agent/system-prompt.js +21 -20
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/agent/tool-usage.d.ts.map +1 -1
- package/dist/agent/tool-usage.js +0 -1
- package/dist/agent/tool-usage.js.map +1 -1
- package/dist/agent/transcript/transcript-backfill.js +3 -3
- package/dist/agent/transcript/transcript-backfill.js.map +1 -1
- package/dist/agent/transcript/transcript-indexer.d.ts +3 -31
- package/dist/agent/transcript/transcript-indexer.d.ts.map +1 -1
- package/dist/agent/transcript/transcript-indexer.js +58 -57
- package/dist/agent/transcript/transcript-indexer.js.map +1 -1
- package/dist/agent/transcript-parsers/trivial-tools.d.ts.map +1 -1
- package/dist/agent/transcript-parsers/trivial-tools.js +0 -2
- package/dist/agent/transcript-parsers/trivial-tools.js.map +1 -1
- package/dist/agent/transcript-parsers/types.d.ts +1 -1
- package/dist/agent/transcript-summarizer.d.ts +14 -0
- package/dist/agent/transcript-summarizer.d.ts.map +1 -1
- package/dist/agent/transcript-summarizer.js +69 -45
- package/dist/agent/transcript-summarizer.js.map +1 -1
- package/dist/agent/usage/usage-report-queue.d.ts.map +1 -1
- package/dist/agent/usage/usage-report-queue.js +53 -52
- package/dist/agent/usage/usage-report-queue.js.map +1 -1
- package/dist/agent/usage/usage-report-types.d.ts +1 -1
- package/dist/agent/usage/usage-report-types.d.ts.map +1 -1
- package/dist/agent/vocabulary-glossary.d.ts +3 -3
- package/dist/agent/wake-cycle-runner.d.ts +14 -17
- package/dist/agent/wake-cycle-runner.d.ts.map +1 -1
- package/dist/agent/wake-cycle-runner.js +121 -290
- package/dist/agent/wake-cycle-runner.js.map +1 -1
- package/dist/builtin-skills/owner-manual/SKILL.md +2 -2
- package/dist/calendar/occurrence-ownership.d.ts.map +1 -1
- package/dist/calendar/occurrence-ownership.js +6 -5
- package/dist/calendar/occurrence-ownership.js.map +1 -1
- package/dist/calendar/scheduler.d.ts.map +1 -1
- package/dist/calendar/scheduler.js +4 -3
- package/dist/calendar/scheduler.js.map +1 -1
- package/dist/channels/interface.d.ts +8 -2
- package/dist/channels/interface.d.ts.map +1 -1
- package/dist/channels/interface.js +8 -1
- package/dist/channels/interface.js.map +1 -1
- package/dist/channels/manager.d.ts.map +1 -1
- package/dist/channels/manager.js +5 -1
- package/dist/channels/manager.js.map +1 -1
- package/dist/channels/queue.d.ts.map +1 -1
- package/dist/channels/queue.js +8 -0
- package/dist/channels/queue.js.map +1 -1
- package/dist/channels/tui.d.ts +14 -1
- package/dist/channels/tui.d.ts.map +1 -1
- package/dist/channels/tui.js +64 -2
- package/dist/channels/tui.js.map +1 -1
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +22 -53
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +13 -7
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +51 -64
- package/dist/config/index.js.map +1 -1
- package/dist/config/types.d.ts +28 -7
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +22 -20
- package/dist/config/types.js.map +1 -1
- package/dist/conversations/lazy-runtime.d.ts +5 -0
- package/dist/conversations/lazy-runtime.d.ts.map +1 -0
- package/dist/conversations/lazy-runtime.js +12 -0
- package/dist/conversations/lazy-runtime.js.map +1 -0
- package/dist/conversations/runtime.d.ts +17 -0
- package/dist/conversations/runtime.d.ts.map +1 -0
- package/dist/conversations/runtime.js +92 -0
- package/dist/conversations/runtime.js.map +1 -0
- package/dist/conversations/scheduler.d.ts +57 -0
- package/dist/conversations/scheduler.d.ts.map +1 -0
- package/dist/conversations/scheduler.js +175 -0
- package/dist/conversations/scheduler.js.map +1 -0
- package/dist/data-processing/pipeline.d.ts +0 -2
- package/dist/data-processing/pipeline.d.ts.map +1 -1
- package/dist/data-processing/pipeline.js +19 -24
- package/dist/data-processing/pipeline.js.map +1 -1
- package/dist/data-processing/restructure.d.ts +0 -2
- package/dist/data-processing/restructure.d.ts.map +1 -1
- package/dist/data-processing/restructure.js +6 -9
- package/dist/data-processing/restructure.js.map +1 -1
- package/dist/data-processing/types.d.ts +2 -9
- package/dist/data-processing/types.d.ts.map +1 -1
- package/dist/data-processing/types.js +2 -13
- package/dist/data-processing/types.js.map +1 -1
- package/dist/email/email-route-store.d.ts.map +1 -1
- package/dist/email/email-route-store.js +6 -5
- package/dist/email/email-route-store.js.map +1 -1
- package/dist/i18n/messages.d.ts +26 -2
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/i18n/messages.js +30 -5
- package/dist/i18n/messages.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +11 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +49 -1
- package/dist/logger.js.map +1 -1
- package/dist/obs/mini-app/status.d.ts.map +1 -1
- package/dist/obs/mini-app/status.js +0 -1
- package/dist/obs/mini-app/status.js.map +1 -1
- package/dist/onboarding/onboarding-service-client.d.ts +1 -0
- package/dist/onboarding/onboarding-service-client.d.ts.map +1 -1
- package/dist/onboarding/onboarding-service-client.js.map +1 -1
- package/dist/onboarding/remote-set-owner.d.ts.map +1 -1
- package/dist/onboarding/remote-set-owner.js +0 -1
- package/dist/onboarding/remote-set-owner.js.map +1 -1
- package/dist/onboarding/set-owner.d.ts +1 -1
- package/dist/onboarding/set-owner.d.ts.map +1 -1
- package/dist/onboarding/set-owner.js +3 -6
- package/dist/onboarding/set-owner.js.map +1 -1
- package/dist/reconfigure.d.ts.map +1 -1
- package/dist/reconfigure.js +1 -32
- package/dist/reconfigure.js.map +1 -1
- package/dist/reset.d.ts.map +1 -1
- package/dist/reset.js +3 -1
- package/dist/reset.js.map +1 -1
- package/dist/threads/active-threads-store.d.ts.map +1 -1
- package/dist/threads/active-threads-store.js +8 -27
- package/dist/threads/active-threads-store.js.map +1 -1
- package/dist/threads/dreaming-execution.d.ts +10 -0
- package/dist/threads/dreaming-execution.d.ts.map +1 -0
- package/dist/threads/dreaming-execution.js +78 -0
- package/dist/threads/dreaming-execution.js.map +1 -0
- package/dist/threads/execution-authority.d.ts +43 -0
- package/dist/threads/execution-authority.d.ts.map +1 -0
- package/dist/threads/execution-authority.js +75 -0
- package/dist/threads/execution-authority.js.map +1 -0
- package/dist/threads/execution-budget.d.ts +107 -0
- package/dist/threads/execution-budget.d.ts.map +1 -0
- package/dist/threads/execution-budget.js +257 -0
- package/dist/threads/execution-budget.js.map +1 -0
- package/dist/threads/execution-host.d.ts +17 -0
- package/dist/threads/execution-host.d.ts.map +1 -0
- package/dist/threads/execution-host.js +66 -0
- package/dist/threads/execution-host.js.map +1 -0
- package/dist/threads/execution-scheduler.d.ts +162 -0
- package/dist/threads/execution-scheduler.d.ts.map +1 -0
- package/dist/threads/execution-scheduler.js +413 -0
- package/dist/threads/execution-scheduler.js.map +1 -0
- package/dist/threads/execution-snapshot.d.ts +91 -0
- package/dist/threads/execution-snapshot.d.ts.map +1 -0
- package/dist/threads/execution-snapshot.js +146 -0
- package/dist/threads/execution-snapshot.js.map +1 -0
- package/dist/threads/execution-store.d.ts +374 -0
- package/dist/threads/execution-store.d.ts.map +1 -0
- package/dist/threads/execution-store.js +910 -0
- package/dist/threads/execution-store.js.map +1 -0
- package/dist/threads/execution-thread-error.d.ts +9 -0
- package/dist/threads/execution-thread-error.d.ts.map +1 -0
- package/dist/threads/execution-thread-error.js +12 -0
- package/dist/threads/execution-thread-error.js.map +1 -0
- package/dist/threads/executor-exit.d.ts +18 -0
- package/dist/threads/executor-exit.d.ts.map +1 -0
- package/dist/threads/executor-exit.js +21 -0
- package/dist/threads/executor-exit.js.map +1 -0
- package/dist/threads/foreground-task.d.ts +91 -0
- package/dist/threads/foreground-task.d.ts.map +1 -0
- package/dist/threads/foreground-task.js +191 -0
- package/dist/threads/foreground-task.js.map +1 -0
- package/dist/threads/foreman-business.d.ts +9 -0
- package/dist/threads/foreman-business.d.ts.map +1 -0
- package/dist/threads/foreman-business.js +117 -0
- package/dist/threads/foreman-business.js.map +1 -0
- package/dist/threads/foreman-client.d.ts +18 -0
- package/dist/threads/foreman-client.d.ts.map +1 -0
- package/dist/threads/foreman-client.js +51 -0
- package/dist/threads/foreman-client.js.map +1 -0
- package/dist/threads/foreman-delivery.d.ts +5 -0
- package/dist/threads/foreman-delivery.d.ts.map +1 -0
- package/dist/threads/foreman-delivery.js +21 -0
- package/dist/threads/foreman-delivery.js.map +1 -0
- package/dist/threads/foreman-execution.d.ts +32 -0
- package/dist/threads/foreman-execution.d.ts.map +1 -0
- package/dist/threads/foreman-execution.js +90 -0
- package/dist/threads/foreman-execution.js.map +1 -0
- package/dist/threads/foreman-host.d.ts +77 -0
- package/dist/threads/foreman-host.d.ts.map +1 -0
- package/dist/threads/foreman-host.js +891 -0
- package/dist/threads/foreman-host.js.map +1 -0
- package/dist/threads/foreman-protocol.d.ts +242 -0
- package/dist/threads/foreman-protocol.d.ts.map +1 -0
- package/dist/threads/foreman-protocol.js +116 -0
- package/dist/threads/foreman-protocol.js.map +1 -0
- package/dist/threads/foreman-store.d.ts +151 -0
- package/dist/threads/foreman-store.d.ts.map +1 -0
- package/dist/threads/foreman-store.js +299 -0
- package/dist/threads/foreman-store.js.map +1 -0
- package/dist/threads/generic-execution.d.ts +25 -0
- package/dist/threads/generic-execution.d.ts.map +1 -0
- package/dist/threads/generic-execution.js +86 -0
- package/dist/threads/generic-execution.js.map +1 -0
- package/dist/threads/init-thread-dir.d.ts +2 -2
- package/dist/threads/init-thread-dir.d.ts.map +1 -1
- package/dist/threads/init-thread-dir.js +6 -6
- package/dist/threads/init-thread-dir.js.map +1 -1
- package/dist/threads/ipc.d.ts +108 -2
- package/dist/threads/ipc.d.ts.map +1 -1
- package/dist/threads/ipc.js +14 -2
- package/dist/threads/ipc.js.map +1 -1
- package/dist/threads/lab-run-thread.d.ts +3 -5
- package/dist/threads/lab-run-thread.d.ts.map +1 -1
- package/dist/threads/lab-run-thread.js +3 -5
- package/dist/threads/lab-run-thread.js.map +1 -1
- package/dist/threads/lab-runtime-policy.d.ts +26 -21
- package/dist/threads/lab-runtime-policy.d.ts.map +1 -1
- package/dist/threads/lab-runtime-policy.js +31 -126
- package/dist/threads/lab-runtime-policy.js.map +1 -1
- package/dist/threads/process-group.d.ts +41 -0
- package/dist/threads/process-group.d.ts.map +1 -0
- package/dist/threads/process-group.js +161 -0
- package/dist/threads/process-group.js.map +1 -0
- package/dist/threads/relay-adapter.d.ts +8 -0
- package/dist/threads/relay-adapter.d.ts.map +1 -1
- package/dist/threads/relay-adapter.js +26 -1
- package/dist/threads/relay-adapter.js.map +1 -1
- package/dist/threads/supervisor.d.ts +191 -57
- package/dist/threads/supervisor.d.ts.map +1 -1
- package/dist/threads/supervisor.js +766 -427
- package/dist/threads/supervisor.js.map +1 -1
- package/dist/threads/task-workspace.d.ts +8 -0
- package/dist/threads/task-workspace.d.ts.map +1 -0
- package/dist/threads/task-workspace.js +52 -0
- package/dist/threads/task-workspace.js.map +1 -0
- package/dist/threads/worker-entry.d.ts.map +1 -1
- package/dist/threads/worker-entry.js +314 -34
- package/dist/threads/worker-entry.js.map +1 -1
- package/dist/threads/worker-execution-runtime.d.ts +75 -0
- package/dist/threads/worker-execution-runtime.d.ts.map +1 -0
- package/dist/threads/worker-execution-runtime.js +142 -0
- package/dist/threads/worker-execution-runtime.js.map +1 -0
- package/dist/threads/worker-execution.d.ts +35 -0
- package/dist/threads/worker-execution.d.ts.map +1 -0
- package/dist/threads/worker-execution.js +2 -0
- package/dist/threads/worker-execution.js.map +1 -0
- package/dist/threads/worker-runtime-policy.d.ts +42 -0
- package/dist/threads/worker-runtime-policy.d.ts.map +1 -0
- package/dist/threads/worker-runtime-policy.js +98 -0
- package/dist/threads/worker-runtime-policy.js.map +1 -0
- package/dist/tools/adapter-tool.d.ts +12 -0
- package/dist/tools/adapter-tool.d.ts.map +1 -0
- package/dist/tools/adapter-tool.js +2 -0
- package/dist/tools/adapter-tool.js.map +1 -0
- package/dist/tools/data-service.d.ts +2 -2
- package/dist/tools/delegation.d.ts +121 -0
- package/dist/tools/delegation.d.ts.map +1 -0
- package/dist/tools/delegation.js +106 -0
- package/dist/tools/delegation.js.map +1 -0
- package/dist/tools/dream-memory.d.ts +122 -0
- package/dist/tools/dream-memory.d.ts.map +1 -0
- package/dist/tools/dream-memory.js +513 -0
- package/dist/tools/dream-memory.js.map +1 -0
- package/dist/tools/email.d.ts +1 -1
- package/dist/tools/execution-control.d.ts +31 -0
- package/dist/tools/execution-control.d.ts.map +1 -0
- package/dist/tools/execution-control.js +71 -0
- package/dist/tools/execution-control.js.map +1 -0
- package/dist/tools/index.d.ts +5 -7
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -13
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp-manager.d.ts +1 -1
- package/dist/tools/memory.d.ts +1 -1
- package/dist/tools/memory.d.ts.map +1 -1
- package/dist/tools/memory.js +69 -45
- package/dist/tools/memory.js.map +1 -1
- package/dist/tools/notify.d.ts +5 -0
- package/dist/tools/notify.d.ts.map +1 -1
- package/dist/tools/notify.js +45 -10
- package/dist/tools/notify.js.map +1 -1
- package/dist/tools/skill.d.ts +1 -1
- package/dist/tools/totp.d.ts +1 -1
- package/dist/tui/client.d.ts +1 -16
- package/dist/tui/client.d.ts.map +1 -1
- package/dist/tui/client.js +0 -4
- package/dist/tui/client.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +0 -41
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/protocol.d.ts +2 -1
- package/dist/tui/protocol.d.ts.map +1 -1
- package/dist/tui/protocol.js +2 -1
- package/dist/tui/protocol.js.map +1 -1
- package/dist/tui/renderer.d.ts.map +1 -1
- package/dist/tui/renderer.js +0 -5
- package/dist/tui/renderer.js.map +1 -1
- package/dist/tui/request-store.d.ts +1 -1
- package/dist/tui/request-store.d.ts.map +1 -1
- package/dist/tui/request-store.js +2 -2
- package/dist/tui/request-store.js.map +1 -1
- package/dist/tui/server.d.ts.map +1 -1
- package/dist/tui/server.js +137 -25
- package/dist/tui/server.js.map +1 -1
- package/dist/utils/claude-transcripts.d.ts +6 -0
- package/dist/utils/claude-transcripts.d.ts.map +1 -1
- package/dist/utils/claude-transcripts.js +8 -2
- package/dist/utils/claude-transcripts.js.map +1 -1
- package/dist/utils/restart.d.ts.map +1 -1
- package/dist/utils/restart.js +6 -0
- package/dist/utils/restart.js.map +1 -1
- package/dist-agent/bundle.cjs +2 -2
- package/package.json +1 -1
- package/dist/agent/mailbox.d.ts +0 -50
- package/dist/agent/mailbox.d.ts.map +0 -1
- package/dist/agent/mailbox.js +0 -124
- package/dist/agent/mailbox.js.map +0 -1
- package/dist/agent/nightly-maintenance/memory-dreaming-sweep.d.ts +0 -77
- package/dist/agent/nightly-maintenance/memory-dreaming-sweep.d.ts.map +0 -1
- package/dist/agent/nightly-maintenance/memory-dreaming-sweep.js +0 -158
- package/dist/agent/nightly-maintenance/memory-dreaming-sweep.js.map +0 -1
- package/dist/agent/nightly-maintenance/memory-dreaming.d.ts +0 -116
- package/dist/agent/nightly-maintenance/memory-dreaming.d.ts.map +0 -1
- package/dist/agent/nightly-maintenance/memory-dreaming.js +0 -458
- package/dist/agent/nightly-maintenance/memory-dreaming.js.map +0 -1
- package/dist/threads/task-contracts.d.ts +0 -194
- package/dist/threads/task-contracts.d.ts.map +0 -1
- package/dist/threads/task-contracts.js +0 -82
- package/dist/threads/task-contracts.js.map +0 -1
- package/dist/threads/task-sidecar.d.ts +0 -145
- package/dist/threads/task-sidecar.d.ts.map +0 -1
- package/dist/threads/task-sidecar.js +0 -311
- package/dist/threads/task-sidecar.js.map +0 -1
- package/dist/threads/task-store.d.ts +0 -172
- package/dist/threads/task-store.d.ts.map +0 -1
- package/dist/threads/task-store.js +0 -599
- package/dist/threads/task-store.js.map +0 -1
- package/dist/threads/thread-task-context.d.ts +0 -40
- package/dist/threads/thread-task-context.d.ts.map +0 -1
- package/dist/threads/thread-task-context.js +0 -160
- package/dist/threads/thread-task-context.js.map +0 -1
- package/dist/threads/thread-task-controller.d.ts +0 -122
- package/dist/threads/thread-task-controller.d.ts.map +0 -1
- package/dist/threads/thread-task-controller.js +0 -276
- package/dist/threads/thread-task-controller.js.map +0 -1
- package/dist/threads/thread-task-runtime.d.ts +0 -354
- package/dist/threads/thread-task-runtime.d.ts.map +0 -1
- package/dist/threads/thread-task-runtime.js +0 -917
- package/dist/threads/thread-task-runtime.js.map +0 -1
- package/dist/tools/switch-session.d.ts +0 -15
- package/dist/tools/switch-session.d.ts.map +0 -1
- package/dist/tools/switch-session.js +0 -88
- package/dist/tools/switch-session.js.map +0 -1
- package/dist/tools/thread-tasks.d.ts +0 -23
- package/dist/tools/thread-tasks.d.ts.map +0 -1
- package/dist/tools/thread-tasks.js +0 -122
- package/dist/tools/thread-tasks.js.map +0 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WakeCycleRunner — encapsulates the
|
|
2
|
+
* WakeCycleRunner — encapsulates the wake loop, Claude
|
|
3
3
|
* stream processing, error classification / retry logic, transcript
|
|
4
4
|
* sanitization, and post-cycle transcript memory indexing.
|
|
5
5
|
*
|
|
6
6
|
* Extracted from loop.ts so the main loop is a thin orchestrator.
|
|
7
7
|
*/
|
|
8
|
-
import { isEmailChannel,
|
|
8
|
+
import { isEmailChannel, presentsAssistantText } from "../channels/interface.js";
|
|
9
9
|
import { isCalendarInterruptMessage } from "./owner-initiated-eligibility.js";
|
|
10
10
|
import { emailAddressesMatch } from "../utils/email.js";
|
|
11
|
+
import { EXTERNAL_WAKE_KIND } from "../channels/queue.js";
|
|
11
12
|
import { nextRecoveryPhase } from "./lifecycle-transitions.js";
|
|
12
13
|
import { COMPACTION_FAILURE_CONTINUATION, CompactionFailureError } from "./compaction-failure.js";
|
|
13
14
|
import { ToolOutputRepairError } from "./transcript-output-repair.js";
|
|
@@ -32,36 +33,7 @@ import path from "path";
|
|
|
32
33
|
import { randomUUID } from "node:crypto";
|
|
33
34
|
import { runContextRefresh } from "./context-refresh.js";
|
|
34
35
|
import { loadToolAbortRecoveryChain, saveToolAbortRecoveryChain } from "./recovery-chain.js";
|
|
35
|
-
import {
|
|
36
|
-
import { isThreadTaskContextBlock } from "../threads/thread-task-context.js";
|
|
37
|
-
/**
|
|
38
|
-
* Session memos are internal working text (handoff instructions, worktree
|
|
39
|
-
* paths, "do not notify" constraints). They must never be sent as owner chat.
|
|
40
|
-
*
|
|
41
|
-
* Last-resort ping when a coding completion was armed and this wake never
|
|
42
|
-
* successfully notified (PR #839: do not silently drop the result). The
|
|
43
|
-
* body is a fixed human line — never the memo, never a paraphrase of it.
|
|
44
|
-
*/
|
|
45
|
-
async function deliverCodingCompletionFallbackPing(ownerConfig) {
|
|
46
|
-
const message = t("coding.completion_unnotified", resolveLocale(ownerConfig.language));
|
|
47
|
-
try {
|
|
48
|
-
const result = await sendUserNotification({ message, purpose: "completion" });
|
|
49
|
-
if (result.isError) {
|
|
50
|
-
const text = result.content
|
|
51
|
-
.map((c) => "text" in c ? c.text : "")
|
|
52
|
-
.filter((s) => s.length > 0)
|
|
53
|
-
.join(" ");
|
|
54
|
-
logger.warn(`Coding completion notification failed: ${text || "unknown error"}`);
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
logger.system("Delivered coding completion fallback ping (generic; not the session memo)");
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
logger.warn(`Coding completion notification threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
36
|
+
import { getWorkerExecutionRuntime } from "../threads/worker-execution-runtime.js";
|
|
65
37
|
const AUTH_PATTERNS = /\b(401|402|403|authentication|billing|unauthorized|forbidden|api.?key)\b/i;
|
|
66
38
|
// Fatal environment/installation problems that won't fix themselves on retry.
|
|
67
39
|
// In particular: the Claude Agent SDK immediately exits with code 1 when its
|
|
@@ -304,15 +276,15 @@ export function isSharedCredentialFailure(err) {
|
|
|
304
276
|
}
|
|
305
277
|
return classifyError(err) === "provider_failed" && !isEngineScopedFailure(err);
|
|
306
278
|
}
|
|
307
|
-
function formatOwnerErrorNotice(category, consecutiveErrors,
|
|
279
|
+
function formatOwnerErrorNotice(category, consecutiveErrors, errMsg) {
|
|
308
280
|
if (category === "fatal") {
|
|
309
|
-
return
|
|
281
|
+
return "Agent encountered an internal runtime error. This wake has stopped; the next message or heartbeat will retry.";
|
|
310
282
|
}
|
|
311
283
|
if (category === "local") {
|
|
312
284
|
// Name the cause. The old text blamed the model provider for an error the
|
|
313
285
|
// provider never saw, which is what made the original alert storm
|
|
314
286
|
// impossible to diagnose from the notification alone.
|
|
315
|
-
return `Agent hit a local session-coordination error (not a provider failure): ${errMsg ?? "unknown cause"}.
|
|
287
|
+
return `Agent hit a local session-coordination error (not a provider failure): ${errMsg ?? "unknown cause"}. This wake has stopped; the next message or heartbeat will retry.`;
|
|
316
288
|
}
|
|
317
289
|
if (category === "request_invalid") {
|
|
318
290
|
return `Agent stopped this wake because the provider rejected a malformed request (${errMsg ?? "unknown cause"}).`;
|
|
@@ -323,7 +295,7 @@ function formatOwnerErrorNotice(category, consecutiveErrors, sleepMin, errMsg) {
|
|
|
323
295
|
if (category === "empty_turn") {
|
|
324
296
|
return "The assistant returned another empty turn without confirming completion. The task may be incomplete. I stopped automatic continuation to avoid repeating work; existing results should be checked before continuing.";
|
|
325
297
|
}
|
|
326
|
-
return `Agent encountered an internal model/provider error ${consecutiveErrors} times in a row.
|
|
298
|
+
return `Agent encountered an internal model/provider error ${consecutiveErrors} times in a row. This wake has stopped; the next message or heartbeat will retry.`;
|
|
327
299
|
}
|
|
328
300
|
function isPromptTooLong(err) {
|
|
329
301
|
const terminalReason = getTerminalReason(err);
|
|
@@ -391,7 +363,6 @@ export const MAX_EMPTY_TURN_RETRIES = 1;
|
|
|
391
363
|
const ERROR_RETRY_COMPACT_USED_PCT = 0.7;
|
|
392
364
|
const BASE_DELAY_MS = 5_000;
|
|
393
365
|
const MAX_DELAY_MS = 5 * 60_000;
|
|
394
|
-
const FATAL_SLEEP_MS = 5 * 60_000;
|
|
395
366
|
/** Max times to retry the LLM call on stream silence timeout before aborting. */
|
|
396
367
|
export const MAX_SILENCE_RETRIES = 3;
|
|
397
368
|
/** Bounded retries for transient stream/network disconnects in any wake cycle. */
|
|
@@ -405,26 +376,7 @@ export const MAX_OUTPUT_RECOVERY_ATTEMPTS = 2;
|
|
|
405
376
|
/** Escalating silence timeouts (ms) per attempt: 5min, 10min, 15min. */
|
|
406
377
|
const SILENCE_TIMEOUT_SCHEDULE_MS = [300_000, 600_000, 900_000];
|
|
407
378
|
/** Decreasing effort levels per attempt to reduce thinking overhead on retries. */
|
|
408
|
-
const EFFORT_SCHEDULE =
|
|
409
|
-
coding: ["xhigh", "high", "medium"],
|
|
410
|
-
general: ["xhigh", "high", "medium"],
|
|
411
|
-
};
|
|
412
|
-
/**
|
|
413
|
-
* A wake retried on a reset session re-sends its first message, whose thread
|
|
414
|
-
* task block (#1996) was built before the reset's reconcile. Swap it for a
|
|
415
|
-
* fresh one so the new session sees exactly one, current copy. Without a
|
|
416
|
-
* task runtime this returns the blocks unchanged.
|
|
417
|
-
*/
|
|
418
|
-
export function withFreshThreadTaskBlock(blocks) {
|
|
419
|
-
const fresh = buildThreadTaskContext();
|
|
420
|
-
const index = blocks.findIndex((block) => block.type === "text" && isThreadTaskContextBlock(block.text));
|
|
421
|
-
if (index === -1)
|
|
422
|
-
return fresh ? [...blocks, { type: "text", text: fresh }] : blocks;
|
|
423
|
-
const rest = blocks.filter((_, i) => i !== index);
|
|
424
|
-
if (fresh)
|
|
425
|
-
rest.splice(index, 0, { type: "text", text: fresh });
|
|
426
|
-
return rest;
|
|
427
|
-
}
|
|
379
|
+
const EFFORT_SCHEDULE = ["xhigh", "high", "medium"];
|
|
428
380
|
export class WakeCycleRunner {
|
|
429
381
|
externalContextRegistry;
|
|
430
382
|
deps;
|
|
@@ -448,9 +400,8 @@ export class WakeCycleRunner {
|
|
|
448
400
|
* Watchdog recoveries span multiple queue-driven wakes, so this state lives
|
|
449
401
|
* on the resident runner rather than inside a single run() invocation.
|
|
450
402
|
* Attempt count is retained across clean wakes that lack finish/stop so a
|
|
451
|
-
* recovery chain can actually reach MAX_TOOL_ABORT_RECOVERIES.
|
|
452
|
-
*
|
|
453
|
-
* switch_session(complete) clear it.
|
|
403
|
+
* recovery chain can actually reach MAX_TOOL_ABORT_RECOVERIES. Only finish
|
|
404
|
+
* or stop clear it.
|
|
454
405
|
*
|
|
455
406
|
* Ordinary threads also persist the chain, so a restart cannot refill the
|
|
456
407
|
* budget. LabRun queues are process-local and stay in memory.
|
|
@@ -530,30 +481,30 @@ export class WakeCycleRunner {
|
|
|
530
481
|
}
|
|
531
482
|
}
|
|
532
483
|
/**
|
|
533
|
-
* Execute one full wake cycle: the
|
|
534
|
-
*
|
|
484
|
+
* Execute one full wake cycle: the wake loop, stream processing, error
|
|
485
|
+
* recovery, and post-cycle transcript indexing.
|
|
535
486
|
*
|
|
536
487
|
* @param contentBlocks The multimodal user-message blocks for this cycle.
|
|
537
488
|
* @param trigger Whether this wake was from a message or heartbeat.
|
|
538
489
|
* @param messages Inbound messages (empty for heartbeat).
|
|
539
|
-
* @param calendarSummary Calendar summary string for session-switch context.
|
|
540
490
|
* @param consecutiveErrors Current error counter from previous cycles.
|
|
541
491
|
* @returns Updated consecutive error count.
|
|
542
492
|
*/
|
|
543
|
-
async run(contentBlocks, trigger, messages,
|
|
493
|
+
async run(contentBlocks, trigger, messages, consecutiveErrors) {
|
|
544
494
|
const { config, ownerConfig, session, activityTracker, interruptHandler, messageQueue } = this.deps;
|
|
545
495
|
this.malformedRequestRefreshAttempted = false;
|
|
546
496
|
this.emptyTurnRetries = 0;
|
|
547
497
|
this.silenceRecoveryExhausted = false;
|
|
548
498
|
this.recoveryPhase = "Running";
|
|
549
499
|
// --- Capture transcript start lines for post-cycle indexing ---
|
|
550
|
-
//
|
|
551
|
-
// of using a single start line captured
|
|
552
|
-
//
|
|
500
|
+
// Recovery can rotate the session to a new transcript, so anchor by
|
|
501
|
+
// transcript path instead of using a single start line captured at cycle
|
|
502
|
+
// entry.
|
|
553
503
|
const wakeCycleId = generateWakeCycleId();
|
|
554
504
|
/** Numbers model turns within this wake for their task-event keys. */
|
|
555
|
-
let responseSeq = 0;
|
|
556
505
|
let awaitingUser = false;
|
|
506
|
+
/** The model ended the wake with an accepted finish (not a timeout or exhausted recovery). */
|
|
507
|
+
let wakeFinished = false;
|
|
557
508
|
let terminalError = false;
|
|
558
509
|
const wakeCycleTimestampStart = new Date().toISOString();
|
|
559
510
|
const transcriptAnchors = new Map();
|
|
@@ -563,17 +514,6 @@ export class WakeCycleRunner {
|
|
|
563
514
|
transcriptAnchors.set(activeTranscript.path, await countFileLines(activeTranscript.path));
|
|
564
515
|
};
|
|
565
516
|
await ensureTranscriptAnchor(resolveIndexableTranscript(session.activeSession.getTranscriptInfo(), session.activeSession.getTranscriptPath()));
|
|
566
|
-
// Session switch loop: if the agent calls switch_session, we close the
|
|
567
|
-
// current stream, switch sessions, and re-enter with a new stream.
|
|
568
|
-
let didSwitch = false;
|
|
569
|
-
let switchForwardMessage = "";
|
|
570
|
-
let pendingMemoAck = true;
|
|
571
|
-
// Armed on a coding→general completion handoff when the coding session
|
|
572
|
-
// did not notify the owner itself. The re-entered general session is
|
|
573
|
-
// expected to humanize the memo via notify_user. If this wake never
|
|
574
|
-
// successfully notifies, runtime last-resorts a fixed human ping (PR #839)
|
|
575
|
-
// — never the memo body.
|
|
576
|
-
let pendingCompletionFallback = null;
|
|
577
517
|
// Survives premature-end continuations: a later turn that repeats the
|
|
578
518
|
// answer as prose must not re-deliver after notify_user already landed.
|
|
579
519
|
let notifyUserDeliveredThisWake = false;
|
|
@@ -584,7 +524,6 @@ export class WakeCycleRunner {
|
|
|
584
524
|
let silenceCompactionDone = false;
|
|
585
525
|
const externalContext = await this.externalContextRegistry.collect({
|
|
586
526
|
trigger,
|
|
587
|
-
sessionMode: session.activeMode,
|
|
588
527
|
messages,
|
|
589
528
|
});
|
|
590
529
|
setCurrentExternalContext(externalContext.section, externalContext.digest, externalContext.providerBlocks);
|
|
@@ -600,62 +539,18 @@ export class WakeCycleRunner {
|
|
|
600
539
|
// failover. If the session cannot be rotated, stay on the current engine
|
|
601
540
|
// and try again next wake rather than replaying its history elsewhere.
|
|
602
541
|
if (recovered) {
|
|
603
|
-
if (await this.rotateSessionForEngineSwitch(session, String(activeBefore), recovered.recovered, "recovery")) {
|
|
604
|
-
contentBlocks = withFreshThreadTaskBlock(contentBlocks);
|
|
605
|
-
}
|
|
606
|
-
else {
|
|
542
|
+
if (!await this.rotateSessionForEngineSwitch(session, String(activeBefore), recovered.recovered, "recovery")) {
|
|
607
543
|
setFallbackEngine(fallbackBefore);
|
|
608
544
|
}
|
|
609
545
|
}
|
|
610
546
|
}
|
|
611
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- intentional
|
|
547
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- intentional: recovery paths re-enter via continue
|
|
612
548
|
wakeLoop: while (true) {
|
|
613
549
|
const activeSession = session.activeSession;
|
|
614
550
|
try {
|
|
615
551
|
await activeSession.warmUp();
|
|
616
552
|
await ensureTranscriptAnchor(resolveIndexableTranscript(activeSession.getTranscriptInfo(), activeSession.getTranscriptPath()));
|
|
617
|
-
let messageContent;
|
|
618
|
-
if (didSwitch) {
|
|
619
|
-
// Handoff boundary (#1996): fold what the previous session did into
|
|
620
|
-
// the task checkpoints before the other session reads them. Bounded.
|
|
621
|
-
await reconcileThreadTasks("handoff", RECONCILE_WAIT_MS.handoff);
|
|
622
|
-
const switchMemos = session.consumeMemosForActive();
|
|
623
|
-
const switchParts = [];
|
|
624
|
-
switchParts.push(`[Session Switch] time=${new Date().toLocaleString()} active_session=${session.activeMode}`);
|
|
625
|
-
if (switchMemos) {
|
|
626
|
-
switchParts.push("");
|
|
627
|
-
switchParts.push(switchMemos);
|
|
628
|
-
}
|
|
629
|
-
const codingStatus = session.getCodingSessionStatus();
|
|
630
|
-
if (codingStatus && session.activeMode === "general") {
|
|
631
|
-
switchParts.push("");
|
|
632
|
-
switchParts.push(`## Active Coding Task`);
|
|
633
|
-
switchParts.push(codingStatus);
|
|
634
|
-
}
|
|
635
|
-
if (calendarSummary) {
|
|
636
|
-
switchParts.push("");
|
|
637
|
-
switchParts.push("## Upcoming Calendar Events");
|
|
638
|
-
switchParts.push(calendarSummary);
|
|
639
|
-
}
|
|
640
|
-
if (switchForwardMessage) {
|
|
641
|
-
switchParts.push("");
|
|
642
|
-
switchParts.push(switchForwardMessage);
|
|
643
|
-
}
|
|
644
|
-
// The destination session has its own context: give it the
|
|
645
|
-
// thread's tasks as they are now.
|
|
646
|
-
const threadTaskBlock = buildThreadTaskContext();
|
|
647
|
-
messageContent = [
|
|
648
|
-
{ type: "text", text: switchParts.join("\n") },
|
|
649
|
-
...(threadTaskBlock ? [{ type: "text", text: threadTaskBlock }] : []),
|
|
650
|
-
];
|
|
651
|
-
didSwitch = false;
|
|
652
|
-
switchForwardMessage = "";
|
|
653
|
-
pendingMemoAck = true;
|
|
654
|
-
}
|
|
655
|
-
else {
|
|
656
|
-
messageContent =
|
|
657
|
-
contentBlocks;
|
|
658
|
-
}
|
|
553
|
+
let messageContent = contentBlocks;
|
|
659
554
|
let streamResult = {
|
|
660
555
|
toolTimeout: null,
|
|
661
556
|
finishCalled: false,
|
|
@@ -665,6 +560,10 @@ export class WakeCycleRunner {
|
|
|
665
560
|
notifyUserDelivered: false,
|
|
666
561
|
awaitingUser: false,
|
|
667
562
|
};
|
|
563
|
+
// A lifecycle-only continuation may call finish without repeating the
|
|
564
|
+
// answer from the previous turn. Keep that answer through this wake.
|
|
565
|
+
let lastReplyText = "";
|
|
566
|
+
let lastReplyPresented = false;
|
|
668
567
|
let subagentContinuations = 0;
|
|
669
568
|
let prematureEndContinuations = 0;
|
|
670
569
|
// turnLoop: each iteration drains one streamed turn (including all
|
|
@@ -687,23 +586,20 @@ export class WakeCycleRunner {
|
|
|
687
586
|
if (silenceAttempt > 1) {
|
|
688
587
|
activityTracker.notePublicPhase("Still working");
|
|
689
588
|
}
|
|
690
|
-
const effortSchedule = EFFORT_SCHEDULE
|
|
691
|
-
const tierEffort = getLlmEffort(config,
|
|
589
|
+
const effortSchedule = EFFORT_SCHEDULE;
|
|
590
|
+
const tierEffort = getLlmEffort(config, "main_general");
|
|
692
591
|
const effort = tierEffort && silenceAttempt > 1
|
|
693
592
|
? getLlmRetryEffort(tierEffort, silenceAttempt - 1)
|
|
694
593
|
: tierEffort ?? effortSchedule[silenceAttempt - 1];
|
|
695
594
|
const queryStream = activeSession.sendAndStream(messageContent, { effort, externalContextDigest: externalContext.digest });
|
|
696
|
-
if (pendingMemoAck) {
|
|
697
|
-
session.ackMemosForActive();
|
|
698
|
-
pendingMemoAck = false;
|
|
699
|
-
}
|
|
700
595
|
try {
|
|
701
|
-
streamResult = await processAgentStream(queryStream, activeSession, activityTracker,
|
|
596
|
+
streamResult = await processAgentStream(queryStream, activeSession, activityTracker, config, silenceTimeoutMs);
|
|
702
597
|
if (streamResult.notifyUserDelivered)
|
|
703
598
|
notifyUserDeliveredThisWake = true;
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
599
|
+
if (streamResult.lastAssistantText) {
|
|
600
|
+
lastReplyText = streamResult.lastAssistantText;
|
|
601
|
+
lastReplyPresented = streamResult.lastAssistantTextPresented === true;
|
|
602
|
+
}
|
|
707
603
|
// A successful SDK envelope can still contain a legitimate empty
|
|
708
604
|
// model turn. Apply the same task-state policy as SDK diagnostics.
|
|
709
605
|
if (!this.deps.singleShot && streamResult.emptyTurn && !streamResult.finishCalled && !streamResult.toolTimeout) {
|
|
@@ -791,7 +687,6 @@ export class WakeCycleRunner {
|
|
|
791
687
|
const degraded = await this.degradeActiveEngine(engineFallback, "silence_exhausted", session);
|
|
792
688
|
if (degraded === "hot") {
|
|
793
689
|
consecutiveErrors = 0;
|
|
794
|
-
contentBlocks = withFreshThreadTaskBlock(contentBlocks);
|
|
795
690
|
continue wakeLoop;
|
|
796
691
|
}
|
|
797
692
|
if (degraded === "restarting") {
|
|
@@ -810,9 +705,6 @@ export class WakeCycleRunner {
|
|
|
810
705
|
try {
|
|
811
706
|
await activeSession.requestCompaction();
|
|
812
707
|
consecutiveErrors = 0;
|
|
813
|
-
// The compacted session must see the tasks as the compaction
|
|
814
|
-
// reconcile just left them, not the wake-start block (#1996).
|
|
815
|
-
contentBlocks = withFreshThreadTaskBlock(contentBlocks);
|
|
816
708
|
continue wakeLoop;
|
|
817
709
|
}
|
|
818
710
|
catch (compactErr) {
|
|
@@ -837,7 +729,18 @@ export class WakeCycleRunner {
|
|
|
837
729
|
}
|
|
838
730
|
catch (streamErr) {
|
|
839
731
|
// TODO: guard retry against simultaneous stop requests and settle the failed input generator before retrying; both are rare stream/stop races.
|
|
840
|
-
|
|
732
|
+
// transientStreamRetries counts the disconnects already retried in
|
|
733
|
+
// this turn. Another one is Recovering; the ceiling throws, and
|
|
734
|
+
// the outer handler records it instead of retrying this turn.
|
|
735
|
+
const networkPhase = isTransientStreamFailure(streamErr)
|
|
736
|
+
? nextRecoveryPhase({
|
|
737
|
+
from: this.recoveryPhase,
|
|
738
|
+
bucket: "network",
|
|
739
|
+
spent: transientStreamRetries,
|
|
740
|
+
})
|
|
741
|
+
: null;
|
|
742
|
+
if (networkPhase === "Recovering") {
|
|
743
|
+
this.recoveryPhase = "Recovering";
|
|
841
744
|
transientStreamRetries++;
|
|
842
745
|
logger.system(`Transient stream failure (retry ${transientStreamRetries}/${MAX_TRANSIENT_STREAM_RETRIES}) — retrying the current business turn...`);
|
|
843
746
|
continue;
|
|
@@ -845,30 +748,10 @@ export class WakeCycleRunner {
|
|
|
845
748
|
throw streamErr;
|
|
846
749
|
}
|
|
847
750
|
}
|
|
848
|
-
// An owner-facing notification was DELIVERED this turn — any armed
|
|
849
|
-
// coding completion fallback has been superseded by the model's own
|
|
850
|
-
// summary. A notify_user call whose tool result errored (channel
|
|
851
|
-
// outage, bad explicit target) must not disarm the fallback, or the
|
|
852
|
-
// completion is silently lost.
|
|
853
|
-
if (streamResult.notifyUserDelivered) {
|
|
854
|
-
pendingCompletionFallback = null;
|
|
855
|
-
}
|
|
856
751
|
if (streamResult.finishCalled && streamResult.awaitingUser)
|
|
857
752
|
awaitingUser = true;
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
// and can be used after a successful completion notification. In
|
|
861
|
-
// that case finish only closes the wake at the stream layer; finalize
|
|
862
|
-
// the task here when the receipt is for this exact active task so a
|
|
863
|
-
// later general heartbeat cannot resurrect it.
|
|
864
|
-
const completionReceiptMatchesActiveCodingTask = session.activeMode === "coding" &&
|
|
865
|
-
!session.pendingSwitch &&
|
|
866
|
-
!streamResult.awaitingUser &&
|
|
867
|
-
Boolean(this.deps.agentState.codingCompletionTaskStartedAt &&
|
|
868
|
-
this.deps.agentState.codingCompletionTaskStartedAt === session.getActiveCodingTaskStartedAt());
|
|
869
|
-
if (streamResult.finishCalled && completionReceiptMatchesActiveCodingTask) {
|
|
870
|
-
session.finalizeCodingCompletionAfterFinish();
|
|
871
|
-
}
|
|
753
|
+
if (streamResult.finishCalled)
|
|
754
|
+
wakeFinished = true;
|
|
872
755
|
// A watchdog abort is scoped to the active tool. Preserve the result
|
|
873
756
|
// for the next queue-driven wake rather than resuming the same provider
|
|
874
757
|
// turn, which keeps lifecycle handling identical for Claude and Pi.
|
|
@@ -926,7 +809,7 @@ export class WakeCycleRunner {
|
|
|
926
809
|
}
|
|
927
810
|
// A successful SDK result only means the stream ended; it does not
|
|
928
811
|
// prove the task ended intentionally. Keep the original wake context
|
|
929
|
-
// alive until the model calls finish
|
|
812
|
+
// alive until the model calls finish.
|
|
930
813
|
// Gated on "no subagents currently active" (not on whether a subagent
|
|
931
814
|
// continuation ever fired): while subagents run, the subagent-wait
|
|
932
815
|
// mechanism above owns the turn; once they are done, the explicit
|
|
@@ -934,22 +817,30 @@ export class WakeCycleRunner {
|
|
|
934
817
|
// subagent continuation earlier.
|
|
935
818
|
if (!this.deps.singleShot &&
|
|
936
819
|
endedWithoutLifecycleAction &&
|
|
937
|
-
!session.pendingSwitch &&
|
|
938
820
|
runningSubagents.length === 0) {
|
|
939
|
-
|
|
821
|
+
// prematureEndContinuations counts the continuations already sent in
|
|
822
|
+
// this wake. One more is Recovering; the ceiling is Stopping, and
|
|
823
|
+
// this wake ends instead of starting another continuation.
|
|
824
|
+
const prematurePhase = nextRecoveryPhase({
|
|
825
|
+
from: this.recoveryPhase,
|
|
826
|
+
bucket: "premature_result",
|
|
827
|
+
spent: prematureEndContinuations,
|
|
828
|
+
});
|
|
829
|
+
if (prematurePhase === "Recovering") {
|
|
830
|
+
this.recoveryPhase = "Recovering";
|
|
940
831
|
prematureEndContinuations++;
|
|
941
|
-
logger.warn(`Turn ended without finish
|
|
832
|
+
logger.warn(`Turn ended without finish — continuing (${prematureEndContinuations}/${MAX_PREMATURE_END_CONTINUATIONS})`);
|
|
942
833
|
messageContent = [{
|
|
943
834
|
type: "text",
|
|
944
835
|
text: [
|
|
945
|
-
"Your previous turn ended without an explicit finish
|
|
836
|
+
"Your previous turn ended without an explicit finish call, so this wake cycle is still active.",
|
|
946
837
|
"Inspect the transcript and existing tool results before acting. Do not repeat successful notifications, emails, uploads, or other mutations/side effects.",
|
|
947
|
-
"If the requested work is already complete, only call finish now. Otherwise complete the remaining work, notify the user if needed, then call finish
|
|
838
|
+
"If the requested work is already complete, only call finish now. Otherwise complete the remaining work, notify the user if needed, then call finish.",
|
|
948
839
|
].join("\n"),
|
|
949
840
|
}];
|
|
950
841
|
continue turnLoop;
|
|
951
842
|
}
|
|
952
|
-
const errorMessage = `Wake cycle ended without finish
|
|
843
|
+
const errorMessage = `Wake cycle ended without finish after ${MAX_PREMATURE_END_CONTINUATIONS} continuations`;
|
|
953
844
|
logger.err(errorMessage);
|
|
954
845
|
// The alert is only actionable when the owner is actually waiting on
|
|
955
846
|
// something, and it fires at most once per wake cycle — so a long run
|
|
@@ -970,7 +861,7 @@ export class WakeCycleRunner {
|
|
|
970
861
|
const alreadyNotifiedOwner = this.deps.agentState.notifiedUserThisWake === true;
|
|
971
862
|
const recoveryAlertEligible = trigger === "message" && !alreadyNotifiedOwner;
|
|
972
863
|
if (recoveryAlertEligible) {
|
|
973
|
-
void notifyOwner(`Agent wake recovery stopped after ${MAX_PREMATURE_END_CONTINUATIONS} attempts
|
|
864
|
+
void notifyOwner(`Agent wake recovery stopped after ${MAX_PREMATURE_END_CONTINUATIONS} attempts. The task may be incomplete; please ask me to resume it.`, config).catch((notifyErr) => {
|
|
974
865
|
logger.warn(`Failed to notify owner about exhausted wake recovery: ${notifyErr instanceof Error ? notifyErr.message : String(notifyErr)}`);
|
|
975
866
|
});
|
|
976
867
|
}
|
|
@@ -1003,9 +894,18 @@ export class WakeCycleRunner {
|
|
|
1003
894
|
}
|
|
1004
895
|
}
|
|
1005
896
|
else {
|
|
897
|
+
// The persisted count is this chain's own budget. It survives
|
|
898
|
+
// wakes and restarts, so a new wake must not refill it.
|
|
899
|
+
const toolAbortPhase = nextRecoveryPhase({
|
|
900
|
+
from: this.recoveryPhase,
|
|
901
|
+
bucket: "tool_abort",
|
|
902
|
+
spent: this.toolAbortRecoveries,
|
|
903
|
+
});
|
|
1006
904
|
this.toolAbortRecoveryChainId ??= randomUUID();
|
|
1007
905
|
this.toolAbortRecoveries += 1;
|
|
1008
|
-
const retryable =
|
|
906
|
+
const retryable = toolAbortPhase === "Recovering";
|
|
907
|
+
if (retryable)
|
|
908
|
+
this.recoveryPhase = "Recovering";
|
|
1009
909
|
if (!retryable)
|
|
1010
910
|
this.toolAbortRecoveryExhausted = true;
|
|
1011
911
|
this.persistToolAbortRecoveryChain();
|
|
@@ -1047,12 +947,7 @@ export class WakeCycleRunner {
|
|
|
1047
947
|
this.clearToolAbortRecoveryBudget();
|
|
1048
948
|
}
|
|
1049
949
|
else if (streamResult.finishCalled) {
|
|
1050
|
-
|
|
1051
|
-
// handoffs must retain the budget; only a real finish tool clears
|
|
1052
|
-
// here. switch_session(complete) clears below via reason.
|
|
1053
|
-
if (streamResult.lifecycleTool !== "switch_session") {
|
|
1054
|
-
this.clearToolAbortRecoveryBudget();
|
|
1055
|
-
}
|
|
950
|
+
this.clearToolAbortRecoveryBudget();
|
|
1056
951
|
}
|
|
1057
952
|
// --- Direct assistant text delivery ---
|
|
1058
953
|
// When the model writes the answer as prose, calls finish, and never
|
|
@@ -1060,44 +955,34 @@ export class WakeCycleRunner {
|
|
|
1060
955
|
// adapters drop `assistant_text`). Send the LAST text block as a
|
|
1061
956
|
// normal notify so the originating channel actually delivers it.
|
|
1062
957
|
// Concatenated earlier blocks, thinking, and tool narration stay out.
|
|
1063
|
-
// Heartbeat,
|
|
958
|
+
// Heartbeat, singleShot, and toolTimeout stay silent.
|
|
1064
959
|
// Fin-App matches Telegram: live assistant_text is dropped, so this
|
|
1065
960
|
// last-block notify is the courtesy delivery when finish has no
|
|
1066
961
|
// notify_user. TUI still presents assistant_text in-thread.
|
|
1067
|
-
const fallbackText =
|
|
1068
|
-
// An accepted switch_session always leaves a pending request here --
|
|
1069
|
-
// `executePendingSwitch` only runs later in this wake -- so
|
|
1070
|
-
// `pendingSwitch` already covers that exit on its own. Requiring an
|
|
1071
|
-
// accepted `finish` below excludes it a second time.
|
|
1072
|
-
const skipBecauseSwitch = Boolean(session.pendingSwitch);
|
|
962
|
+
const fallbackText = lastReplyText;
|
|
1073
963
|
const skipBecauseNotified = notifyUserDeliveredThisWake || streamResult.notifyUserDelivered;
|
|
1074
964
|
const finishAccepted = streamResult.lifecycleTool === "finish";
|
|
1075
965
|
// Only replies to messages in the initial wake batch are eligible.
|
|
1076
966
|
// Resumes, external wakes and calendars may carry a delivery target
|
|
1077
967
|
// without requesting a reply. Mid-turn work uses explicit notify_user
|
|
1078
968
|
// for its result; a quick acknowledgment does not enable this fallback.
|
|
1079
|
-
const replyMessages = messages.filter((message) =>
|
|
969
|
+
const replyMessages = messages.filter((message) => message.channel !== "system" && message.meta?.kind !== EXTERNAL_WAKE_KIND && !isCalendarInterruptMessage(message));
|
|
1080
970
|
const fallbackEligible = !this.deps.singleShot &&
|
|
1081
971
|
!streamResult.toolTimeout &&
|
|
1082
972
|
!skipBecauseNotified &&
|
|
1083
973
|
fallbackText.length > 0 &&
|
|
1084
974
|
trigger === "message" &&
|
|
1085
975
|
finishAccepted &&
|
|
1086
|
-
!skipBecauseSwitch &&
|
|
1087
976
|
replyMessages.length > 0;
|
|
1088
977
|
if (replyMessages.length === 0 && fallbackText.length > 0 && finishAccepted && !skipBecauseNotified) {
|
|
1089
978
|
logger.info("Skipped finish-without-notify fallback: no reply message in the initial wake batch");
|
|
1090
979
|
}
|
|
1091
|
-
if (skipBecauseSwitch && fallbackText.length > 0 && trigger === "message") {
|
|
1092
|
-
logger.warn(`Skipped assistant_text delivery: the turn took switch_session without notify_user, so this text was NOT delivered to the owner: ${fallbackText.slice(0, 2000)}`);
|
|
1093
|
-
}
|
|
1094
980
|
// Premature-end recovery re-prompts, so unfinished prose is deliberately
|
|
1095
981
|
// not delivered (a rejected `finish` lands here too: it sets neither
|
|
1096
982
|
// `finishCalled` nor `lifecycleTool`). The owner still gets the generic
|
|
1097
983
|
// exhausted-recovery alert, but the text itself would vanish without a
|
|
1098
984
|
// trace -- record it so the drop is diagnosable.
|
|
1099
985
|
if (!finishAccepted &&
|
|
1100
|
-
!skipBecauseSwitch &&
|
|
1101
986
|
!skipBecauseNotified &&
|
|
1102
987
|
!streamResult.toolTimeout &&
|
|
1103
988
|
fallbackText.length > 0 &&
|
|
@@ -1107,16 +992,10 @@ export class WakeCycleRunner {
|
|
|
1107
992
|
if (fallbackEligible) {
|
|
1108
993
|
const fallbackTarget = resolveDirectAssistantFallbackTarget(replyMessages, ownerConfig.ownerEmail);
|
|
1109
994
|
const livePresentedOnChat = Boolean(fallbackTarget && presentsAssistantText(fallbackTarget.channel)) &&
|
|
1110
|
-
|
|
995
|
+
lastReplyPresented;
|
|
1111
996
|
if (livePresentedOnChat) {
|
|
1112
997
|
// Last live block actually landed in chat. Do not splice a
|
|
1113
998
|
// second last-block notify into the same thread.
|
|
1114
|
-
pendingCompletionFallback = null;
|
|
1115
|
-
}
|
|
1116
|
-
else if (fallbackTarget &&
|
|
1117
|
-
normalizeChannelName(fallbackTarget.channel) === "finapp" &&
|
|
1118
|
-
session.activeMode === "coding") {
|
|
1119
|
-
// Coding narration never becomes a Fin-App chat bubble. TUI still last-block notifies.
|
|
1120
999
|
}
|
|
1121
1000
|
else if (fallbackTarget) {
|
|
1122
1001
|
// Best-effort courtesy delivery: never let a fallback failure
|
|
@@ -1138,7 +1017,6 @@ export class WakeCycleRunner {
|
|
|
1138
1017
|
}
|
|
1139
1018
|
else {
|
|
1140
1019
|
logger.warn(`Delivered finish-without-notify fallback via ${fallbackTarget.channel} to ${fallbackTarget.to}`);
|
|
1141
|
-
pendingCompletionFallback = null;
|
|
1142
1020
|
}
|
|
1143
1021
|
}
|
|
1144
1022
|
catch (err) {
|
|
@@ -1207,46 +1085,6 @@ export class WakeCycleRunner {
|
|
|
1207
1085
|
logger.warn(`Post-query compaction failed: ${compactErr instanceof Error ? compactErr.message : String(compactErr)}`);
|
|
1208
1086
|
}
|
|
1209
1087
|
}
|
|
1210
|
-
const switchResult = session.executePendingSwitch();
|
|
1211
|
-
if (switchResult) {
|
|
1212
|
-
// switch_session sets finishCalled, so the finishCalled branch above
|
|
1213
|
-
// skips clearing when lifecycleTool is switch_session. Only complete
|
|
1214
|
-
// clears here; temporary handoff retains the budget.
|
|
1215
|
-
if (switchResult.reason === "complete") {
|
|
1216
|
-
this.clearToolAbortRecoveryBudget();
|
|
1217
|
-
}
|
|
1218
|
-
didSwitch = true;
|
|
1219
|
-
switchForwardMessage = [switchResult.workspaceNotice, switchResult.forwardMessage]
|
|
1220
|
-
.filter(Boolean)
|
|
1221
|
-
.join("\n\n");
|
|
1222
|
-
// Completion handoffs are user-visible outcomes. The re-entered
|
|
1223
|
-
// general session is expected to humanize the memo via notify_user.
|
|
1224
|
-
// Do not dump the memo as chat (internal working text). Arm a marker:
|
|
1225
|
-
// a later notify_user / last-block send disarms it; if the cycle
|
|
1226
|
-
// ends with no successful owner ping, last-resort a fixed human line
|
|
1227
|
-
// (PR #839: do not silently drop the result). Newest memo wins.
|
|
1228
|
-
if (switchResult.target === "general" &&
|
|
1229
|
-
switchResult.ownerNotificationRequired &&
|
|
1230
|
-
switchResult.completionMemo) {
|
|
1231
|
-
pendingCompletionFallback = switchResult.completionMemo;
|
|
1232
|
-
}
|
|
1233
|
-
// Coding already sent this task's final result. No memo was created,
|
|
1234
|
-
// so end the wake instead of invoking general for a duplicate summary.
|
|
1235
|
-
if (switchResult.target === "general" &&
|
|
1236
|
-
switchResult.ownerNotificationRequired === false &&
|
|
1237
|
-
switchResult.completionMemo) {
|
|
1238
|
-
// reason="complete" already cleared the recovery budget above.
|
|
1239
|
-
logger.system("Coding completion already delivered — ending wake without re-entering general");
|
|
1240
|
-
this.deps.engineFallback.noteEngineSuccess();
|
|
1241
|
-
this.invalidJsonBodyRecoveryCount = 0;
|
|
1242
|
-
this.localCoordinationErrors = 0;
|
|
1243
|
-
this.emptyTurnRetries = 0;
|
|
1244
|
-
consecutiveErrors = 0;
|
|
1245
|
-
break;
|
|
1246
|
-
}
|
|
1247
|
-
logger.system(`Re-entering wake cycle for ${switchResult.target} session`);
|
|
1248
|
-
continue;
|
|
1249
|
-
}
|
|
1250
1088
|
this.deps.engineFallback.noteEngineSuccess();
|
|
1251
1089
|
this.invalidJsonBodyRecoveryCount = 0;
|
|
1252
1090
|
this.localCoordinationErrors = 0;
|
|
@@ -1272,23 +1110,14 @@ export class WakeCycleRunner {
|
|
|
1272
1110
|
if (errorResult.kind === "continue_with_message") {
|
|
1273
1111
|
consecutiveErrors = errorResult.consecutiveErrors;
|
|
1274
1112
|
contentBlocks = [{ type: "text", text: errorResult.message }];
|
|
1275
|
-
// A rebuilt session starts without the thread's tasks (#1996).
|
|
1276
|
-
if (errorResult.newSession)
|
|
1277
|
-
contentBlocks = withFreshThreadTaskBlock(contentBlocks);
|
|
1278
|
-
didSwitch = false;
|
|
1279
|
-
switchForwardMessage = "";
|
|
1280
1113
|
continue;
|
|
1281
1114
|
}
|
|
1282
1115
|
if (errorResult.kind === "continue_with_reset") {
|
|
1283
1116
|
consecutiveErrors = 0;
|
|
1284
|
-
contentBlocks = withFreshThreadTaskBlock(contentBlocks);
|
|
1285
1117
|
continue;
|
|
1286
1118
|
}
|
|
1287
1119
|
if (errorResult.kind === "continue_preserve_count") {
|
|
1288
1120
|
consecutiveErrors = errorResult.consecutiveErrors;
|
|
1289
|
-
// Invalid-json recovery may have compacted (#1996): resend the
|
|
1290
|
-
// current task block. A no-op when nothing changed.
|
|
1291
|
-
contentBlocks = withFreshThreadTaskBlock(contentBlocks);
|
|
1292
1121
|
continue;
|
|
1293
1122
|
}
|
|
1294
1123
|
consecutiveErrors = errorResult.consecutiveErrors;
|
|
@@ -1296,17 +1125,7 @@ export class WakeCycleRunner {
|
|
|
1296
1125
|
}
|
|
1297
1126
|
}
|
|
1298
1127
|
break;
|
|
1299
|
-
} // end
|
|
1300
|
-
// --- Coding completion last-resort ping (PR #839) ---
|
|
1301
|
-
// The wake cycle is over and no owner notification superseded the armed
|
|
1302
|
-
// completion (general silent, errored, or stopped). Send a fixed human
|
|
1303
|
-
// line so the result is not silently lost. Never send the session memo
|
|
1304
|
-
// (handoff instructions, paths, do-not-notify constraints).
|
|
1305
|
-
if (pendingCompletionFallback) {
|
|
1306
|
-
logger.warn("Wake cycle ended without an owner notification for a coding completion — sending a generic ping, not the session memo");
|
|
1307
|
-
await deliverCodingCompletionFallbackPing(ownerConfig);
|
|
1308
|
-
pendingCompletionFallback = null;
|
|
1309
|
-
}
|
|
1128
|
+
} // end wake loop
|
|
1310
1129
|
// --- Post-wake-cycle transcript indexing (best-effort) ---
|
|
1311
1130
|
// Usage reports are no longer enqueued immediately here. Instead,
|
|
1312
1131
|
// indexWakeCycle extracts and stores tool call facts, and the background
|
|
@@ -1320,9 +1139,7 @@ export class WakeCycleRunner {
|
|
|
1320
1139
|
const wakeCycleOutcome = session.isStopRequested()
|
|
1321
1140
|
? "stopped"
|
|
1322
1141
|
: !terminalError && consecutiveErrors === 0
|
|
1323
|
-
?
|
|
1324
|
-
? "switched"
|
|
1325
|
-
: "completed"
|
|
1142
|
+
? "completed"
|
|
1326
1143
|
: "error";
|
|
1327
1144
|
// Always index wake cycles — including stopped/error cycles — so that
|
|
1328
1145
|
// usage metering is consistent for all cycles. The outcome field records
|
|
@@ -1331,7 +1148,7 @@ export class WakeCycleRunner {
|
|
|
1331
1148
|
const wakeCycleEndLine = await countFileLines(postCycleTranscript.path);
|
|
1332
1149
|
void indexWakeCycle({
|
|
1333
1150
|
wakeCycleId,
|
|
1334
|
-
sessionType:
|
|
1151
|
+
sessionType: "general",
|
|
1335
1152
|
sourceFile: postCycleTranscript.path,
|
|
1336
1153
|
sourceFormat: postCycleTranscript.format,
|
|
1337
1154
|
startLine: postCycleStartLine,
|
|
@@ -1357,10 +1174,11 @@ export class WakeCycleRunner {
|
|
|
1357
1174
|
: awaitingUser
|
|
1358
1175
|
? "waiting_user"
|
|
1359
1176
|
: "completed",
|
|
1177
|
+
finished: wakeFinished,
|
|
1360
1178
|
};
|
|
1361
1179
|
}
|
|
1362
1180
|
/**
|
|
1363
|
-
* Handle an error from the
|
|
1181
|
+
* Handle an error from the wake loop. Returns:
|
|
1364
1182
|
* - `continue_with_reset` for recovery paths that should retry immediately
|
|
1365
1183
|
* with a clean error counter (compaction/sanitization succeeded)
|
|
1366
1184
|
* - `continue_preserve_count` for normal retryable failures that should
|
|
@@ -1402,6 +1220,8 @@ export class WakeCycleRunner {
|
|
|
1402
1220
|
// terminal facts for this run, not a reason to start conversational
|
|
1403
1221
|
// recovery, notify the owner directly, sleep, or enqueue another wake.
|
|
1404
1222
|
if (this.deps.singleShot) {
|
|
1223
|
+
// Kept for the failure report, so the caller sees the cause.
|
|
1224
|
+
getWorkerExecutionRuntime()?.noteError(errMsg);
|
|
1405
1225
|
return { kind: "done", consecutiveErrors };
|
|
1406
1226
|
}
|
|
1407
1227
|
if (err instanceof CompactionFailureError ||
|
|
@@ -1463,7 +1283,6 @@ export class WakeCycleRunner {
|
|
|
1463
1283
|
message: `${config.agentName}: invalid Pi session could not be reset`,
|
|
1464
1284
|
details: {
|
|
1465
1285
|
code: "INVALID_PI_SESSION_RECOVERY_FAILED",
|
|
1466
|
-
activeSession: session.activeMode,
|
|
1467
1286
|
sessionId: invalidSessionId ?? "unknown",
|
|
1468
1287
|
provider: config.provider,
|
|
1469
1288
|
model: reportedModel(config),
|
|
@@ -1526,7 +1345,6 @@ export class WakeCycleRunner {
|
|
|
1526
1345
|
message: `${config.agentName}: stale session could not be reset`,
|
|
1527
1346
|
details: {
|
|
1528
1347
|
code: "SESSION_NOT_FOUND_RECOVERY_FAILED",
|
|
1529
|
-
activeSession: session.activeMode,
|
|
1530
1348
|
sessionId: deadSessionId ?? "unknown",
|
|
1531
1349
|
provider: config.provider,
|
|
1532
1350
|
model: reportedModel(config),
|
|
@@ -1613,7 +1431,7 @@ export class WakeCycleRunner {
|
|
|
1613
1431
|
}
|
|
1614
1432
|
if (recoveryCount === 2) {
|
|
1615
1433
|
const oldSessionId = session.activeSession.getSessionId();
|
|
1616
|
-
logger.warn(
|
|
1434
|
+
logger.warn("Invalid JSON body repeated after compaction; resetting session before retry");
|
|
1617
1435
|
session.activeSession.resetForNewSession("Previous session was reset automatically after repeated provider `400 Invalid JSON body` errors. " +
|
|
1618
1436
|
"This usually means the provider rejected the context/payload even after compaction. Continue from memory and the current user request; avoid reloading large prior tool outputs unless needed.");
|
|
1619
1437
|
logger.system(`Invalid-json-body recovery reset session: old=${oldSessionId ?? "unknown"} new=${session.activeSession.getSessionId() ?? "pending"}`);
|
|
@@ -1628,7 +1446,6 @@ export class WakeCycleRunner {
|
|
|
1628
1446
|
code: "INVALID_JSON_BODY_RECOVERY_FAILED",
|
|
1629
1447
|
consecutiveInvalidJsonBodyErrors: recoveryCount,
|
|
1630
1448
|
actionsAttempted: ["compaction", "session_reset", "controlled_restart"],
|
|
1631
|
-
activeSession: session.activeSession.mode,
|
|
1632
1449
|
provider: config.provider,
|
|
1633
1450
|
model: reportedModel(config),
|
|
1634
1451
|
},
|
|
@@ -1653,16 +1470,15 @@ export class WakeCycleRunner {
|
|
|
1653
1470
|
return { kind: "continue_preserve_count", consecutiveErrors };
|
|
1654
1471
|
}
|
|
1655
1472
|
// Retries exhausted: tell the owner what actually broke, naming the
|
|
1656
|
-
// local cause instead of blaming the model provider.
|
|
1657
|
-
|
|
1473
|
+
// local cause instead of blaming the model provider. The wake ends here.
|
|
1474
|
+
// Sleeping would keep the foreground slot busy until the timer fired.
|
|
1658
1475
|
logger.warn(`Notifying owner about persistent local coordination error: ${errMsg}`);
|
|
1659
1476
|
try {
|
|
1660
|
-
await notifyOwner(formatOwnerErrorNotice(category, consecutiveErrors,
|
|
1477
|
+
await notifyOwner(formatOwnerErrorNotice(category, consecutiveErrors, errMsg), config);
|
|
1661
1478
|
}
|
|
1662
1479
|
catch (notifyErr) {
|
|
1663
1480
|
logger.warn(`Failed to send error notification to owner: ${notifyErr instanceof Error ? notifyErr.message : String(notifyErr)}`);
|
|
1664
1481
|
}
|
|
1665
|
-
await new Promise((r) => setTimeout(r, FATAL_SLEEP_MS));
|
|
1666
1482
|
return { kind: "done", consecutiveErrors };
|
|
1667
1483
|
}
|
|
1668
1484
|
// --- Known malformed Responses replay ---
|
|
@@ -1701,7 +1517,7 @@ export class WakeCycleRunner {
|
|
|
1701
1517
|
}
|
|
1702
1518
|
logger.err(`Malformed Responses replay recovery failed — ending wake: ${errMsg}`);
|
|
1703
1519
|
try {
|
|
1704
|
-
await notifyOwner(formatOwnerErrorNotice(category, consecutiveErrors,
|
|
1520
|
+
await notifyOwner(formatOwnerErrorNotice(category, consecutiveErrors, errMsg), config);
|
|
1705
1521
|
}
|
|
1706
1522
|
catch (notifyErr) {
|
|
1707
1523
|
logger.warn(`Failed to send error notification to owner: ${notifyErr instanceof Error ? notifyErr.message : String(notifyErr)}`);
|
|
@@ -1713,10 +1529,7 @@ export class WakeCycleRunner {
|
|
|
1713
1529
|
// whether this wake has work that still needs an explicit resolution.
|
|
1714
1530
|
if (category === "empty_turn") {
|
|
1715
1531
|
const { activityTracker, interruptHandler } = this.deps;
|
|
1716
|
-
const hasPendingWork = activityTracker.getTodos().some((todo) => todo.status === "pending" || todo.status === "in_progress") || activityTracker.getActiveSubagents().length > 0
|
|
1717
|
-
// Paused tasks persist across wakes; they do not make an otherwise
|
|
1718
|
-
// idle heartbeat responsible for resuming coding work.
|
|
1719
|
-
|| session.getCodingSessionState() === "in_progress";
|
|
1532
|
+
const hasPendingWork = activityTracker.getTodos().some((todo) => todo.status === "pending" || todo.status === "in_progress") || activityTracker.getActiveSubagents().length > 0;
|
|
1720
1533
|
const idleHeartbeat = wake.trigger === "heartbeat"
|
|
1721
1534
|
&& wake.messages.length === 0
|
|
1722
1535
|
&& !interruptHandler.hasAcceptedWorkThisCycle()
|
|
@@ -1733,7 +1546,7 @@ export class WakeCycleRunner {
|
|
|
1733
1546
|
if (phase === "Stopping") {
|
|
1734
1547
|
logger.warn(`Empty-turn continuation did not confirm task completion: ${errMsg}`);
|
|
1735
1548
|
try {
|
|
1736
|
-
await notifyOwner(formatOwnerErrorNotice(category, this.emptyTurnRetries,
|
|
1549
|
+
await notifyOwner(formatOwnerErrorNotice(category, this.emptyTurnRetries, errMsg), config);
|
|
1737
1550
|
}
|
|
1738
1551
|
catch (notifyErr) {
|
|
1739
1552
|
logger.warn(`Failed to send empty-turn notification to owner: ${notifyErr instanceof Error ? notifyErr.message : String(notifyErr)}`);
|
|
@@ -1745,7 +1558,7 @@ export class WakeCycleRunner {
|
|
|
1745
1558
|
const message = [
|
|
1746
1559
|
"Your previous turn ended with no additional content. This alone does not indicate whether the task is complete.",
|
|
1747
1560
|
"Review the current request, task state, and existing tool results before acting. Do not repeat successful notifications, emails, uploads, or other side effects.",
|
|
1748
|
-
"If no work remains, only call finish
|
|
1561
|
+
"If no work remains, only call finish. Otherwise continue only the unfinished work, wait for running subagents as needed, then finish.",
|
|
1749
1562
|
"If completion cannot be verified or user input is needed, explain what remains uncertain to the user and call finish(awaiting_user=true).",
|
|
1750
1563
|
].join("\n");
|
|
1751
1564
|
logger.system("Empty assistant turn with unresolved work — sending one explicit continuation");
|
|
@@ -1802,10 +1615,22 @@ export class WakeCycleRunner {
|
|
|
1802
1615
|
logger.system("No alternate engine available for transient network failures; keeping consecutiveErrors and the cooldown");
|
|
1803
1616
|
}
|
|
1804
1617
|
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1618
|
+
// consecutiveErrors counts the failures already seen in this wake. The
|
|
1619
|
+
// notify threshold is the unknown bucket, not the network disconnect
|
|
1620
|
+
// ceiling. Reaching it is Stopping: notify, then end the wake. The next
|
|
1621
|
+
// attempt waits for a queued message or the proactive timer, not a sleep
|
|
1622
|
+
// that holds this slot.
|
|
1623
|
+
const unknownPhase = category === "fatal"
|
|
1624
|
+
? "Stopping"
|
|
1625
|
+
: nextRecoveryPhase({
|
|
1626
|
+
from: this.recoveryPhase,
|
|
1627
|
+
bucket: "unknown",
|
|
1628
|
+
spent: consecutiveErrors,
|
|
1629
|
+
});
|
|
1630
|
+
if (unknownPhase === "Recovering")
|
|
1631
|
+
this.recoveryPhase = "Recovering";
|
|
1632
|
+
if (unknownPhase === "Stopping") {
|
|
1633
|
+
const notice = formatOwnerErrorNotice(category, consecutiveErrors);
|
|
1809
1634
|
logger.warn(`Notifying owner about repeated agent error: ${errMsg}`);
|
|
1810
1635
|
try {
|
|
1811
1636
|
await notifyOwner(notice, config);
|
|
@@ -1814,7 +1639,6 @@ export class WakeCycleRunner {
|
|
|
1814
1639
|
logger.warn(`Failed to send error notification to owner: ${notifyErr instanceof Error ? notifyErr.message : String(notifyErr)}`);
|
|
1815
1640
|
}
|
|
1816
1641
|
consecutiveErrors = 0;
|
|
1817
|
-
await new Promise((r) => setTimeout(r, FATAL_SLEEP_MS));
|
|
1818
1642
|
}
|
|
1819
1643
|
else {
|
|
1820
1644
|
try {
|
|
@@ -1854,8 +1678,8 @@ export class WakeCycleRunner {
|
|
|
1854
1678
|
return;
|
|
1855
1679
|
}
|
|
1856
1680
|
// Between the failed `/compact` and the end of the cycle the session may
|
|
1857
|
-
// have been
|
|
1858
|
-
//
|
|
1681
|
+
// have already been rotated by the error path. Only rotate the session
|
|
1682
|
+
// that actually failed to compact.
|
|
1859
1683
|
if (pending.sessionId === null || session.activeSession.getSessionId() !== pending.sessionId) {
|
|
1860
1684
|
logger.system(`Post-query compaction failed terminally (${err.errorCode}) but the active session changed before the cycle ended; leaving rotation to the next check`);
|
|
1861
1685
|
return;
|
|
@@ -1893,8 +1717,15 @@ export class WakeCycleRunner {
|
|
|
1893
1717
|
// Two recovery turns total: repair, then one refresh. The second branch is
|
|
1894
1718
|
// gated by the ceiling, so raising MAX_OUTPUT_RECOVERY_ATTEMPTS is what
|
|
1895
1719
|
// allows another turn. Advancing before I/O keeps a failed repair from
|
|
1896
|
-
// resetting the allowance.
|
|
1897
|
-
|
|
1720
|
+
// resetting the allowance. The two kinds keep separate counts.
|
|
1721
|
+
const outputPhase = nextRecoveryPhase({
|
|
1722
|
+
from: this.recoveryPhase,
|
|
1723
|
+
bucket: recoveryKind === "policy_refused" ? "policy_refusal" : "oversized",
|
|
1724
|
+
spent: attempts[recoveryKind],
|
|
1725
|
+
});
|
|
1726
|
+
if (outputPhase === "Recovering")
|
|
1727
|
+
this.recoveryPhase = "Recovering";
|
|
1728
|
+
if (attempts[recoveryKind] === 0 && outputPhase === "Recovering") {
|
|
1898
1729
|
attempts[recoveryKind]++;
|
|
1899
1730
|
if (!compactionAlreadyFailed) {
|
|
1900
1731
|
try {
|
|
@@ -1913,7 +1744,7 @@ export class WakeCycleRunner {
|
|
|
1913
1744
|
logger.system("SDK auto-compaction already failed — skipping same-session transcript repair and rotating context");
|
|
1914
1745
|
}
|
|
1915
1746
|
}
|
|
1916
|
-
if (attempts[recoveryKind] < MAX_OUTPUT_RECOVERY_ATTEMPTS) {
|
|
1747
|
+
if (attempts[recoveryKind] < MAX_OUTPUT_RECOVERY_ATTEMPTS && outputPhase === "Recovering") {
|
|
1917
1748
|
attempts[recoveryKind]++;
|
|
1918
1749
|
const previousId = session.activeSession.getSessionId();
|
|
1919
1750
|
try {
|