@caupulican/pi-adaptative 0.81.37 → 0.81.39
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 +91 -0
- package/README.md +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +18 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +131 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +196 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +308 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +22 -2
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +585 -24
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +749 -27
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/__init__.py +43 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/fs.py +270 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/search.py +252 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/strings.py +399 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +575 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +52 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +49 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +734 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +238 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +132 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/nodes.py +116 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/parser.py +287 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/proc.py +137 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +100 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +579 -0
- package/dist/bundled-resources/skills/tool-call-repair/SKILL.md +19 -9
- package/dist/bundled-resources/skills/tool-call-repair/references/failure-grammar.md +22 -5
- package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +5 -5
- package/dist/bundled-resources/skills/tool-call-repair/references/text-protocol-grammar.md +28 -7
- package/dist/cli/args.d.ts +3 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-paths.d.ts +49 -0
- package/dist/core/agent-paths.d.ts.map +1 -0
- package/dist/core/agent-paths.js +107 -0
- package/dist/core/agent-paths.js.map +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +3 -3
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +234 -17
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +484 -62
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +9 -0
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/lane-tracker.d.ts +10 -1
- package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tracker.js +5 -1
- package/dist/core/autonomy/lane-tracker.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +122 -6
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +447 -90
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bash-execution-controller.d.ts +4 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -1
- package/dist/core/bash-execution-controller.js +7 -1
- package/dist/core/bash-execution-controller.js.map +1 -1
- package/dist/core/compaction-support.d.ts +13 -3
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +43 -7
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context/context-audit.d.ts +33 -1
- package/dist/core/context/context-audit.d.ts.map +1 -1
- package/dist/core/context/context-audit.js +31 -5
- package/dist/core/context/context-audit.js.map +1 -1
- package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
- package/dist/core/context/sqlite-runtime-index.js +13 -7
- package/dist/core/context/sqlite-runtime-index.js.map +1 -1
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +16 -1
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +26 -4
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +137 -14
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost-guard.d.ts +19 -3
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +18 -3
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/delegation/session-worker-result.d.ts +34 -4
- package/dist/core/delegation/session-worker-result.d.ts.map +1 -1
- package/dist/core/delegation/session-worker-result.js +64 -4
- package/dist/core/delegation/session-worker-result.js.map +1 -1
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js +1 -1
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/worker-result.d.ts +42 -1
- package/dist/core/delegation/worker-result.d.ts.map +1 -1
- package/dist/core/delegation/worker-result.js +68 -0
- package/dist/core/delegation/worker-result.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +23 -7
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +51 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +17 -1
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +79 -11
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-controller.d.ts +48 -2
- package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-controller.js +77 -0
- package/dist/core/goals/goal-continuation-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.d.ts +39 -0
- package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.js +42 -0
- package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts +4 -0
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +51 -10
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.d.ts +101 -2
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js +87 -4
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/goal-state.d.ts +89 -1
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +71 -5
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +56 -2
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +111 -5
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +11 -2
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js +32 -17
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/keybindings.d.ts +10 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +10 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/learning/observation-store.d.ts +12 -3
- package/dist/core/learning/observation-store.d.ts.map +1 -1
- package/dist/core/learning/observation-store.js +30 -15
- package/dist/core/learning/observation-store.js.map +1 -1
- package/dist/core/learning/skill-curator.d.ts +5 -1
- package/dist/core/learning/skill-curator.d.ts.map +1 -1
- package/dist/core/learning/skill-curator.js +21 -19
- package/dist/core/learning/skill-curator.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +65 -3
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js +186 -26
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/memory/providers/file-store.d.ts +1 -1
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +6 -6
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/model-capability.d.ts +34 -0
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +42 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-router/tool-escalation.d.ts +15 -0
- package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
- package/dist/core/model-router/tool-escalation.js +23 -1
- package/dist/core/model-router/tool-escalation.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +34 -7
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +95 -16
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/models/adaptation-store.d.ts +7 -0
- package/dist/core/models/adaptation-store.d.ts.map +1 -1
- package/dist/core/models/adaptation-store.js +47 -11
- package/dist/core/models/adaptation-store.js.map +1 -1
- package/dist/core/models/default-model-suggestions.d.ts.map +1 -1
- package/dist/core/models/default-model-suggestions.js +17 -0
- package/dist/core/models/default-model-suggestions.js.map +1 -1
- package/dist/core/models/fitness-store.d.ts +3 -0
- package/dist/core/models/fitness-store.d.ts.map +1 -1
- package/dist/core/models/fitness-store.js +11 -2
- package/dist/core/models/fitness-store.js.map +1 -1
- package/dist/core/models/llamacpp-runtime.d.ts +180 -0
- package/dist/core/models/llamacpp-runtime.d.ts.map +1 -0
- package/dist/core/models/llamacpp-runtime.js +475 -0
- package/dist/core/models/llamacpp-runtime.js.map +1 -0
- package/dist/core/models/local-registration.d.ts +40 -0
- package/dist/core/models/local-registration.d.ts.map +1 -1
- package/dist/core/models/local-registration.js +94 -5
- package/dist/core/models/local-registration.js.map +1 -1
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +9 -7
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/models/model-ref.d.ts +7 -0
- package/dist/core/models/model-ref.d.ts.map +1 -1
- package/dist/core/models/model-ref.js +26 -0
- package/dist/core/models/model-ref.js.map +1 -1
- package/dist/core/models/needle-runtime.d.ts +257 -0
- package/dist/core/models/needle-runtime.d.ts.map +1 -0
- package/dist/core/models/needle-runtime.js +519 -0
- package/dist/core/models/needle-runtime.js.map +1 -0
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts +89 -0
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts.map +1 -0
- package/dist/core/models/prism-llamacpp-lifecycle.js +121 -0
- package/dist/core/models/prism-llamacpp-lifecycle.js.map +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +11 -10
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/process-matrix/codes.d.ts +72 -0
- package/dist/core/process-matrix/codes.d.ts.map +1 -0
- package/dist/core/process-matrix/codes.js +15 -0
- package/dist/core/process-matrix/codes.js.map +1 -0
- package/dist/core/process-matrix/runtime.d.ts +63 -0
- package/dist/core/process-matrix/runtime.d.ts.map +1 -0
- package/dist/core/process-matrix/runtime.js +310 -0
- package/dist/core/process-matrix/runtime.js.map +1 -0
- package/dist/core/process-matrix/store.d.ts +22 -0
- package/dist/core/process-matrix/store.d.ts.map +1 -0
- package/dist/core/process-matrix/store.js +80 -0
- package/dist/core/process-matrix/store.js.map +1 -0
- package/dist/core/process-matrix/supervisor.d.ts +72 -0
- package/dist/core/process-matrix/supervisor.d.ts.map +1 -0
- package/dist/core/process-matrix/supervisor.js +130 -0
- package/dist/core/process-matrix/supervisor.js.map +1 -0
- package/dist/core/profile-registry.d.ts +7 -0
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +20 -0
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/python-runtime.d.ts.map +1 -1
- package/dist/core/python-runtime.js +3 -3
- package/dist/core/python-runtime.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +29 -5
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +215 -126
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/reload-blockers.d.ts +36 -0
- package/dist/core/reload-blockers.d.ts.map +1 -1
- package/dist/core/reload-blockers.js +44 -0
- package/dist/core/reload-blockers.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +8 -7
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +58 -5
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +209 -25
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts +6 -0
- package/dist/core/scout-controller.d.ts.map +1 -1
- package/dist/core/scout-controller.js +66 -52
- package/dist/core/scout-controller.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -3
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-role.d.ts +31 -0
- package/dist/core/session-role.d.ts.map +1 -0
- package/dist/core/session-role.js +52 -0
- package/dist/core/session-role.js.map +1 -0
- package/dist/core/settings-manager.d.ts +42 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +94 -60
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +12 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +6 -0
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.d.ts +14 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +20 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/session-task-state.d.ts +11 -2
- package/dist/core/tasks/session-task-state.d.ts.map +1 -1
- package/dist/core/tasks/session-task-state.js +27 -11
- package/dist/core/tasks/session-task-state.js.map +1 -1
- package/dist/core/tasks/task-contract-monitor.d.ts +45 -0
- package/dist/core/tasks/task-contract-monitor.d.ts.map +1 -0
- package/dist/core/tasks/task-contract-monitor.js +56 -0
- package/dist/core/tasks/task-contract-monitor.js.map +1 -0
- package/dist/core/tasks/task-state.d.ts +8 -0
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js +28 -1
- package/dist/core/tasks/task-state.js.map +1 -1
- package/dist/core/tool-gate-controller.d.ts.map +1 -1
- package/dist/core/tool-gate-controller.js +5 -0
- package/dist/core/tool-gate-controller.js.map +1 -1
- package/dist/core/tool-recovery-log-records.d.ts +7 -0
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-records.js +14 -6
- package/dist/core/tool-recovery-log-records.js.map +1 -1
- package/dist/core/tool-selection/promotion.d.ts +54 -0
- package/dist/core/tool-selection/promotion.d.ts.map +1 -0
- package/dist/core/tool-selection/promotion.js +81 -0
- package/dist/core/tool-selection/promotion.js.map +1 -0
- package/dist/core/tool-selection/tool-performance-store.d.ts +37 -0
- package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.js +87 -3
- package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
- package/dist/core/tool-selection/tool-selection-controller.d.ts +45 -0
- package/dist/core/tool-selection/tool-selection-controller.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-selection-controller.js +96 -0
- package/dist/core/tool-selection/tool-selection-controller.js.map +1 -1
- package/dist/core/tools/bash.d.ts +18 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +97 -18
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +14 -0
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +82 -7
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +25 -8
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +52 -44
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/goal.d.ts +94 -3
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +165 -15
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +5 -4
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/model-fitness.d.ts +7 -0
- package/dist/core/tools/model-fitness.d.ts.map +1 -1
- package/dist/core/tools/model-fitness.js +2 -2
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/shell-contract-router.d.ts +6 -1
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +69 -13
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/tools/shell-session.d.ts +89 -0
- package/dist/core/tools/shell-session.d.ts.map +1 -0
- package/dist/core/tools/shell-session.js +432 -0
- package/dist/core/tools/shell-session.js.map +1 -0
- package/dist/core/tools/task-steps.d.ts +4 -0
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +63 -8
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +86 -0
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -0
- package/dist/core/tools/tmux-dispatch.js +91 -0
- package/dist/core/tools/tmux-dispatch.js.map +1 -0
- package/dist/core/tools/windows-shell-engine.d.ts +42 -0
- package/dist/core/tools/windows-shell-engine.d.ts.map +1 -0
- package/dist/core/tools/windows-shell-engine.js +153 -0
- package/dist/core/tools/windows-shell-engine.js.map +1 -0
- package/dist/core/tools/windows-shell-state.d.ts +40 -0
- package/dist/core/tools/windows-shell-state.d.ts.map +1 -0
- package/dist/core/tools/windows-shell-state.js +59 -0
- package/dist/core/tools/windows-shell-state.js.map +1 -0
- package/dist/core/tools/worktree-sync.d.ts +24 -0
- package/dist/core/tools/worktree-sync.d.ts.map +1 -0
- package/dist/core/tools/worktree-sync.js +338 -0
- package/dist/core/tools/worktree-sync.js.map +1 -0
- package/dist/core/trust-manager.d.ts +4 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +20 -2
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +55 -0
- package/dist/core/util/atomic-file.d.ts.map +1 -0
- package/dist/core/util/atomic-file.js +255 -0
- package/dist/core/util/atomic-file.js.map +1 -0
- package/dist/core/util/minimatch-cache.d.ts +33 -0
- package/dist/core/util/minimatch-cache.d.ts.map +1 -0
- package/dist/core/util/minimatch-cache.js +0 -0
- package/dist/core/util/minimatch-cache.js.map +1 -0
- package/dist/core/worktree-sync/codes.d.ts +227 -0
- package/dist/core/worktree-sync/codes.d.ts.map +1 -0
- package/dist/core/worktree-sync/codes.js +14 -0
- package/dist/core/worktree-sync/codes.js.map +1 -0
- package/dist/core/worktree-sync/git-engine.d.ts +156 -0
- package/dist/core/worktree-sync/git-engine.d.ts.map +1 -0
- package/dist/core/worktree-sync/git-engine.js +1191 -0
- package/dist/core/worktree-sync/git-engine.js.map +1 -0
- package/dist/core/worktree-sync/lane-gate.d.ts +75 -0
- package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -0
- package/dist/core/worktree-sync/lane-gate.js +360 -0
- package/dist/core/worktree-sync/lane-gate.js.map +1 -0
- package/dist/core/worktree-sync/runtime.d.ts +47 -0
- package/dist/core/worktree-sync/runtime.d.ts.map +1 -0
- package/dist/core/worktree-sync/runtime.js +96 -0
- package/dist/core/worktree-sync/runtime.js.map +1 -0
- package/dist/core/worktree-sync/store.d.ts +69 -0
- package/dist/core/worktree-sync/store.d.ts.map +1 -0
- package/dist/core/worktree-sync/store.js +247 -0
- package/dist/core/worktree-sync/store.js.map +1 -0
- package/dist/core/worktree-sync/watcher.d.ts +29 -0
- package/dist/core/worktree-sync/watcher.d.ts.map +1 -0
- package/dist/core/worktree-sync/watcher.js +93 -0
- package/dist/core/worktree-sync/watcher.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +94 -0
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +9 -0
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +38 -0
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts +16 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +50 -8
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
- package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-resource-editor.js +23 -1
- package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +4 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/local-model-commands.d.ts +43 -0
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +290 -3
- package/dist/modes/interactive/local-model-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +24 -4
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/dist/utils/fs-watch.d.ts +11 -0
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +20 -2
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/highlight-js-languages.d.ts +4 -0
- package/dist/utils/highlight-js-languages.d.ts.map +1 -0
- package/dist/utils/highlight-js-languages.js +573 -0
- package/dist/utils/highlight-js-languages.js.map +1 -0
- package/dist/utils/shell.d.ts +7 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +39 -9
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +53 -5
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +112 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/development.md +2 -0
- package/docs/packages.md +1 -1
- package/docs/process-matrix.md +120 -0
- package/docs/settings.md +5 -2
- package/docs/tmux-agent-manager.md +85 -2
- package/docs/windows.md +52 -3
- package/docs/work-directory.md +29 -0
- package/docs/worktree-sync.md +250 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +10 -4
- package/docs/integration-sweep-builder-blueprint-2026-07-09.md +0 -365
- package/docs/integration-sweep-resume-2026-07-09.md +0 -407
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn-boundary task_steps contract monitor.
|
|
3
|
+
*
|
|
4
|
+
* Pure logic only: given the current task_steps state and the prior consecutive-violation streak,
|
|
5
|
+
* decides whether the workflow contract described in the task_steps tool's `promptGuidelines`
|
|
6
|
+
* (`tools/task-steps.ts`) — at most one in_progress step, and an in_progress step whenever open
|
|
7
|
+
* steps remain — has been broken for N consecutive turns, and if so returns a ONE-LINE harness
|
|
8
|
+
* note. No model calls, no I/O, no session access: the caller (`AutoLearnController`) owns reading
|
|
9
|
+
* the task_steps state, persisting the returned streak across turns, and delivering the note
|
|
10
|
+
* through the session's existing next-turn message surface. This is an advisory nudge, not an
|
|
11
|
+
* enforcement gate.
|
|
12
|
+
*/
|
|
13
|
+
import type { TaskStepsState } from "./task-state.ts";
|
|
14
|
+
/** Consecutive violating turns required before a harness note fires. */
|
|
15
|
+
export declare const TASK_CONTRACT_VIOLATION_THRESHOLD = 3;
|
|
16
|
+
export interface TaskContractStreak {
|
|
17
|
+
/** Number of consecutive turns the contract has been violated; reset to 0 on a compliant turn. */
|
|
18
|
+
consecutiveViolations: number;
|
|
19
|
+
/**
|
|
20
|
+
* Whether a note has already fired for the CURRENT streak. Re-arms to false only when the streak
|
|
21
|
+
* resets to 0 via a compliant turn, so a sustained violation emits exactly one note instead of
|
|
22
|
+
* repeating every turn past the threshold.
|
|
23
|
+
*/
|
|
24
|
+
noteFired: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare const INITIAL_TASK_CONTRACT_STREAK: TaskContractStreak;
|
|
27
|
+
export interface TaskContractCheckResult {
|
|
28
|
+
streak: TaskContractStreak;
|
|
29
|
+
/** Present only on the turn the streak first reaches the threshold. */
|
|
30
|
+
note?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* True when the task_steps contract is broken: more than one step is in_progress, or open
|
|
34
|
+
* (non-terminal) steps remain with none in_progress. An absent state (no task list ever created)
|
|
35
|
+
* is never a violation — there is nothing to enforce.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isTaskStepsContractViolation(state: TaskStepsState | undefined): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Advance the streak by one turn. Pure: takes the current task_steps state and the prior streak,
|
|
40
|
+
* returns the next streak plus, only on the exact turn the streak first reaches `threshold`, a
|
|
41
|
+
* ONE-LINE note. Callers must persist the returned streak and feed it back in as `priorStreak` on
|
|
42
|
+
* the next turn.
|
|
43
|
+
*/
|
|
44
|
+
export declare function checkTaskStepsContract(state: TaskStepsState | undefined, priorStreak: TaskContractStreak, threshold?: number): TaskContractCheckResult;
|
|
45
|
+
//# sourceMappingURL=task-contract-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-contract-monitor.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/task-contract-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,wEAAwE;AACxE,eAAO,MAAM,iCAAiC,IAAI,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IAClC,kGAAkG;IAClG,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,4BAA4B,EAAE,kBAAmE,CAAC;AAE/G,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAMvF;AAWD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,WAAW,EAAE,kBAAkB,EAC/B,SAAS,GAAE,MAA0C,GACnD,uBAAuB,CAYzB","sourcesContent":["/**\n * Turn-boundary task_steps contract monitor.\n *\n * Pure logic only: given the current task_steps state and the prior consecutive-violation streak,\n * decides whether the workflow contract described in the task_steps tool's `promptGuidelines`\n * (`tools/task-steps.ts`) — at most one in_progress step, and an in_progress step whenever open\n * steps remain — has been broken for N consecutive turns, and if so returns a ONE-LINE harness\n * note. No model calls, no I/O, no session access: the caller (`AutoLearnController`) owns reading\n * the task_steps state, persisting the returned streak across turns, and delivering the note\n * through the session's existing next-turn message surface. This is an advisory nudge, not an\n * enforcement gate.\n */\n\nimport type { TaskStepsState } from \"./task-state.ts\";\n\n/** Consecutive violating turns required before a harness note fires. */\nexport const TASK_CONTRACT_VIOLATION_THRESHOLD = 3;\n\nexport interface TaskContractStreak {\n\t/** Number of consecutive turns the contract has been violated; reset to 0 on a compliant turn. */\n\tconsecutiveViolations: number;\n\t/**\n\t * Whether a note has already fired for the CURRENT streak. Re-arms to false only when the streak\n\t * resets to 0 via a compliant turn, so a sustained violation emits exactly one note instead of\n\t * repeating every turn past the threshold.\n\t */\n\tnoteFired: boolean;\n}\n\nexport const INITIAL_TASK_CONTRACT_STREAK: TaskContractStreak = { consecutiveViolations: 0, noteFired: false };\n\nexport interface TaskContractCheckResult {\n\tstreak: TaskContractStreak;\n\t/** Present only on the turn the streak first reaches the threshold. */\n\tnote?: string;\n}\n\n/**\n * True when the task_steps contract is broken: more than one step is in_progress, or open\n * (non-terminal) steps remain with none in_progress. An absent state (no task list ever created)\n * is never a violation — there is nothing to enforce.\n */\nexport function isTaskStepsContractViolation(state: TaskStepsState | undefined): boolean {\n\tif (!state) return false;\n\tconst inProgressCount = state.steps.filter((step) => step.status === \"in_progress\").length;\n\tif (inProgressCount > 1) return true;\n\tconst openCount = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\").length;\n\treturn openCount > 0 && inProgressCount === 0;\n}\n\nfunction buildTaskContractNote(state: TaskStepsState | undefined, consecutiveViolations: number): string {\n\tconst inProgressCount = state?.steps.filter((step) => step.status === \"in_progress\").length ?? 0;\n\tconst reason =\n\t\tinProgressCount > 1\n\t\t\t? `${inProgressCount} steps are in_progress at once`\n\t\t\t: \"open task_steps have none in_progress\";\n\treturn `Harness note: task_steps contract violated for ${consecutiveViolations} consecutive turns (${reason}) — set exactly one open step to in_progress before continuing.`;\n}\n\n/**\n * Advance the streak by one turn. Pure: takes the current task_steps state and the prior streak,\n * returns the next streak plus, only on the exact turn the streak first reaches `threshold`, a\n * ONE-LINE note. Callers must persist the returned streak and feed it back in as `priorStreak` on\n * the next turn.\n */\nexport function checkTaskStepsContract(\n\tstate: TaskStepsState | undefined,\n\tpriorStreak: TaskContractStreak,\n\tthreshold: number = TASK_CONTRACT_VIOLATION_THRESHOLD,\n): TaskContractCheckResult {\n\tif (!isTaskStepsContractViolation(state)) {\n\t\treturn { streak: { consecutiveViolations: 0, noteFired: false } };\n\t}\n\tconst consecutiveViolations = priorStreak.consecutiveViolations + 1;\n\tif (consecutiveViolations >= threshold && !priorStreak.noteFired) {\n\t\treturn {\n\t\t\tstreak: { consecutiveViolations, noteFired: true },\n\t\t\tnote: buildTaskContractNote(state, consecutiveViolations),\n\t\t};\n\t}\n\treturn { streak: { consecutiveViolations, noteFired: priorStreak.noteFired } };\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn-boundary task_steps contract monitor.
|
|
3
|
+
*
|
|
4
|
+
* Pure logic only: given the current task_steps state and the prior consecutive-violation streak,
|
|
5
|
+
* decides whether the workflow contract described in the task_steps tool's `promptGuidelines`
|
|
6
|
+
* (`tools/task-steps.ts`) — at most one in_progress step, and an in_progress step whenever open
|
|
7
|
+
* steps remain — has been broken for N consecutive turns, and if so returns a ONE-LINE harness
|
|
8
|
+
* note. No model calls, no I/O, no session access: the caller (`AutoLearnController`) owns reading
|
|
9
|
+
* the task_steps state, persisting the returned streak across turns, and delivering the note
|
|
10
|
+
* through the session's existing next-turn message surface. This is an advisory nudge, not an
|
|
11
|
+
* enforcement gate.
|
|
12
|
+
*/
|
|
13
|
+
/** Consecutive violating turns required before a harness note fires. */
|
|
14
|
+
export const TASK_CONTRACT_VIOLATION_THRESHOLD = 3;
|
|
15
|
+
export const INITIAL_TASK_CONTRACT_STREAK = { consecutiveViolations: 0, noteFired: false };
|
|
16
|
+
/**
|
|
17
|
+
* True when the task_steps contract is broken: more than one step is in_progress, or open
|
|
18
|
+
* (non-terminal) steps remain with none in_progress. An absent state (no task list ever created)
|
|
19
|
+
* is never a violation — there is nothing to enforce.
|
|
20
|
+
*/
|
|
21
|
+
export function isTaskStepsContractViolation(state) {
|
|
22
|
+
if (!state)
|
|
23
|
+
return false;
|
|
24
|
+
const inProgressCount = state.steps.filter((step) => step.status === "in_progress").length;
|
|
25
|
+
if (inProgressCount > 1)
|
|
26
|
+
return true;
|
|
27
|
+
const openCount = state.steps.filter((step) => step.status !== "completed" && step.status !== "cancelled").length;
|
|
28
|
+
return openCount > 0 && inProgressCount === 0;
|
|
29
|
+
}
|
|
30
|
+
function buildTaskContractNote(state, consecutiveViolations) {
|
|
31
|
+
const inProgressCount = state?.steps.filter((step) => step.status === "in_progress").length ?? 0;
|
|
32
|
+
const reason = inProgressCount > 1
|
|
33
|
+
? `${inProgressCount} steps are in_progress at once`
|
|
34
|
+
: "open task_steps have none in_progress";
|
|
35
|
+
return `Harness note: task_steps contract violated for ${consecutiveViolations} consecutive turns (${reason}) — set exactly one open step to in_progress before continuing.`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Advance the streak by one turn. Pure: takes the current task_steps state and the prior streak,
|
|
39
|
+
* returns the next streak plus, only on the exact turn the streak first reaches `threshold`, a
|
|
40
|
+
* ONE-LINE note. Callers must persist the returned streak and feed it back in as `priorStreak` on
|
|
41
|
+
* the next turn.
|
|
42
|
+
*/
|
|
43
|
+
export function checkTaskStepsContract(state, priorStreak, threshold = TASK_CONTRACT_VIOLATION_THRESHOLD) {
|
|
44
|
+
if (!isTaskStepsContractViolation(state)) {
|
|
45
|
+
return { streak: { consecutiveViolations: 0, noteFired: false } };
|
|
46
|
+
}
|
|
47
|
+
const consecutiveViolations = priorStreak.consecutiveViolations + 1;
|
|
48
|
+
if (consecutiveViolations >= threshold && !priorStreak.noteFired) {
|
|
49
|
+
return {
|
|
50
|
+
streak: { consecutiveViolations, noteFired: true },
|
|
51
|
+
note: buildTaskContractNote(state, consecutiveViolations),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return { streak: { consecutiveViolations, noteFired: priorStreak.noteFired } };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=task-contract-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-contract-monitor.js","sourceRoot":"","sources":["../../../src/core/tasks/task-contract-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,wEAAwE;AACxE,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC;AAanD,MAAM,CAAC,MAAM,4BAA4B,GAAuB,EAAE,qBAAqB,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAQ/G;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,KAAiC,EAAW;IACxF,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,MAAM,CAAC;IAC3F,IAAI,eAAe,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IAClH,OAAO,SAAS,GAAG,CAAC,IAAI,eAAe,KAAK,CAAC,CAAC;AAAA,CAC9C;AAED,SAAS,qBAAqB,CAAC,KAAiC,EAAE,qBAA6B,EAAU;IACxG,MAAM,eAAe,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;IACjG,MAAM,MAAM,GACX,eAAe,GAAG,CAAC;QAClB,CAAC,CAAC,GAAG,eAAe,gCAAgC;QACpD,CAAC,CAAC,uCAAuC,CAAC;IAC5C,OAAO,kDAAkD,qBAAqB,uBAAuB,MAAM,mEAAiE,CAAC;AAAA,CAC7K;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACrC,KAAiC,EACjC,WAA+B,EAC/B,SAAS,GAAW,iCAAiC,EAC3B;IAC1B,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,MAAM,EAAE,EAAE,qBAAqB,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC;IACnE,CAAC;IACD,MAAM,qBAAqB,GAAG,WAAW,CAAC,qBAAqB,GAAG,CAAC,CAAC;IACpE,IAAI,qBAAqB,IAAI,SAAS,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QAClE,OAAO;YACN,MAAM,EAAE,EAAE,qBAAqB,EAAE,SAAS,EAAE,IAAI,EAAE;YAClD,IAAI,EAAE,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,CAAC;SACzD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,EAAE,qBAAqB,EAAE,SAAS,EAAE,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;AAAA,CAC/E","sourcesContent":["/**\n * Turn-boundary task_steps contract monitor.\n *\n * Pure logic only: given the current task_steps state and the prior consecutive-violation streak,\n * decides whether the workflow contract described in the task_steps tool's `promptGuidelines`\n * (`tools/task-steps.ts`) — at most one in_progress step, and an in_progress step whenever open\n * steps remain — has been broken for N consecutive turns, and if so returns a ONE-LINE harness\n * note. No model calls, no I/O, no session access: the caller (`AutoLearnController`) owns reading\n * the task_steps state, persisting the returned streak across turns, and delivering the note\n * through the session's existing next-turn message surface. This is an advisory nudge, not an\n * enforcement gate.\n */\n\nimport type { TaskStepsState } from \"./task-state.ts\";\n\n/** Consecutive violating turns required before a harness note fires. */\nexport const TASK_CONTRACT_VIOLATION_THRESHOLD = 3;\n\nexport interface TaskContractStreak {\n\t/** Number of consecutive turns the contract has been violated; reset to 0 on a compliant turn. */\n\tconsecutiveViolations: number;\n\t/**\n\t * Whether a note has already fired for the CURRENT streak. Re-arms to false only when the streak\n\t * resets to 0 via a compliant turn, so a sustained violation emits exactly one note instead of\n\t * repeating every turn past the threshold.\n\t */\n\tnoteFired: boolean;\n}\n\nexport const INITIAL_TASK_CONTRACT_STREAK: TaskContractStreak = { consecutiveViolations: 0, noteFired: false };\n\nexport interface TaskContractCheckResult {\n\tstreak: TaskContractStreak;\n\t/** Present only on the turn the streak first reaches the threshold. */\n\tnote?: string;\n}\n\n/**\n * True when the task_steps contract is broken: more than one step is in_progress, or open\n * (non-terminal) steps remain with none in_progress. An absent state (no task list ever created)\n * is never a violation — there is nothing to enforce.\n */\nexport function isTaskStepsContractViolation(state: TaskStepsState | undefined): boolean {\n\tif (!state) return false;\n\tconst inProgressCount = state.steps.filter((step) => step.status === \"in_progress\").length;\n\tif (inProgressCount > 1) return true;\n\tconst openCount = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\").length;\n\treturn openCount > 0 && inProgressCount === 0;\n}\n\nfunction buildTaskContractNote(state: TaskStepsState | undefined, consecutiveViolations: number): string {\n\tconst inProgressCount = state?.steps.filter((step) => step.status === \"in_progress\").length ?? 0;\n\tconst reason =\n\t\tinProgressCount > 1\n\t\t\t? `${inProgressCount} steps are in_progress at once`\n\t\t\t: \"open task_steps have none in_progress\";\n\treturn `Harness note: task_steps contract violated for ${consecutiveViolations} consecutive turns (${reason}) — set exactly one open step to in_progress before continuing.`;\n}\n\n/**\n * Advance the streak by one turn. Pure: takes the current task_steps state and the prior streak,\n * returns the next streak plus, only on the exact turn the streak first reaches `threshold`, a\n * ONE-LINE note. Callers must persist the returned streak and feed it back in as `priorStreak` on\n * the next turn.\n */\nexport function checkTaskStepsContract(\n\tstate: TaskStepsState | undefined,\n\tpriorStreak: TaskContractStreak,\n\tthreshold: number = TASK_CONTRACT_VIOLATION_THRESHOLD,\n): TaskContractCheckResult {\n\tif (!isTaskStepsContractViolation(state)) {\n\t\treturn { streak: { consecutiveViolations: 0, noteFired: false } };\n\t}\n\tconst consecutiveViolations = priorStreak.consecutiveViolations + 1;\n\tif (consecutiveViolations >= threshold && !priorStreak.noteFired) {\n\t\treturn {\n\t\t\tstreak: { consecutiveViolations, noteFired: true },\n\t\t\tnote: buildTaskContractNote(state, consecutiveViolations),\n\t\t};\n\t}\n\treturn { streak: { consecutiveViolations, noteFired: priorStreak.noteFired } };\n}\n"]}
|
|
@@ -55,6 +55,14 @@ export declare class TaskStepsError extends Error {
|
|
|
55
55
|
export declare function isTaskStepsState(value: unknown): value is TaskStepsState;
|
|
56
56
|
export declare function cloneTaskStepsState(state: TaskStepsState): TaskStepsState;
|
|
57
57
|
export declare function createTaskStepsState(now: string): TaskStepsState;
|
|
58
|
+
/**
|
|
59
|
+
* Find an OPEN (non-terminal) step whose content matches `content` case-insensitively.
|
|
60
|
+
* Terminal steps (completed/cancelled) are deliberately excluded so a legitimate re-add of
|
|
61
|
+
* previously finished work still creates a new step.
|
|
62
|
+
*/
|
|
63
|
+
export declare function findOpenDuplicateStep(steps: readonly TaskStep[], content: string): TaskStep | undefined;
|
|
64
|
+
/** True when a completed step has no evidence attached (a verification nudge candidate). */
|
|
65
|
+
export declare function hasUnverifiedCompletedStep(state: TaskStepsState): boolean;
|
|
58
66
|
export declare function setTaskSteps(state: TaskStepsState, inputs: readonly TaskStepInput[], now: string): TaskStepsState;
|
|
59
67
|
export declare function addTaskStep(state: TaskStepsState, input: TaskStepInput, now: string): TaskStepsState;
|
|
60
68
|
export declare function resolveTaskStepSelector(steps: readonly TaskStep[], selector: string): TaskStep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-state.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/task-state.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,0EAA2E,CAAC;AAC3G,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,eAAO,MAAM,oBAAoB,oCAAqC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAErE,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAMlD,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,qBAAa,cAAe,SAAQ,KAAK;IACxC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACD;AA2DD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAmBxE;AAMD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAMzE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAUhE;AA2GD,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,aAAa,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CA6BjH;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAQpG;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CA0B9F;AAED,wBAAgB,cAAc,CAC7B,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,MAAM,GACT,cAAc,CAqChB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAKjF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAYnF;AAED,wBAAgB,eAAe,CAC9B,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5D,MAAM,CA4BR;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,SAAK,GAAG,MAAM,GAAG,SAAS,CAmB/F;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAErE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAO5E","sourcesContent":["export const TASK_STEP_STATUSES = [\"pending\", \"in_progress\", \"completed\", \"blocked\", \"cancelled\"] as const;\nexport type TaskStepStatus = (typeof TASK_STEP_STATUSES)[number];\n\nexport const TASK_STEP_PRIORITIES = [\"low\", \"normal\", \"high\"] as const;\nexport type TaskStepPriority = (typeof TASK_STEP_PRIORITIES)[number];\n\nexport const MAX_TASK_STEPS = 100;\nexport const MAX_TASK_STEP_CONTENT_LENGTH = 2_000;\nconst MAX_TASK_STEP_NOTE_LENGTH = 4_000;\nconst MAX_TASK_STEP_OWNER_LENGTH = 200;\nconst MAX_TASK_STEP_EVIDENCE = 32;\nconst MAX_TASK_STEP_EVIDENCE_LENGTH = 2_000;\n\nexport interface TaskStepInput {\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tnotes?: readonly string[];\n\tevidence?: readonly string[];\n}\n\nexport interface TaskStep {\n\tid: string;\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnotes: readonly string[];\n\tevidence: readonly string[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepsArchive {\n\tcompleted: number;\n\tcancelled: number;\n\tcompactedAt?: string;\n}\n\nexport interface TaskStepsState {\n\tversion: 1;\n\trevision: number;\n\tnextStepNumber: number;\n\tsteps: readonly TaskStep[];\n\tarchive: TaskStepsArchive;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepUpdate {\n\tcontent?: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tevidence?: readonly string[];\n}\n\nexport class TaskStepsError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"TaskStepsError\";\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isTaskStepStatus(value: unknown): value is TaskStepStatus {\n\treturn TASK_STEP_STATUSES.some((status) => status === value);\n}\n\nfunction isTaskStepPriority(value: unknown): value is TaskStepPriority {\n\treturn TASK_STEP_PRIORITIES.some((priority) => priority === value);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string, maxLength: number): boolean {\n\tconst value = record[key];\n\treturn value === undefined || (typeof value === \"string\" && value.length <= maxLength);\n}\n\nfunction isBoundedStringArray(value: unknown, maxItems: number, maxLength: number): value is readonly string[] {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length <= maxItems &&\n\t\tvalue.every((item) => typeof item === \"string\" && item.length > 0 && item.length <= maxLength)\n\t);\n}\n\nfunction isTaskStep(value: unknown): value is TaskStep {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\t/^step-[1-9]\\d*$/.test(value.id) &&\n\t\ttypeof value.content === \"string\" &&\n\t\tvalue.content.length > 0 &&\n\t\tvalue.content.length <= MAX_TASK_STEP_CONTENT_LENGTH &&\n\t\thasOptionalString(value, \"activeForm\", MAX_TASK_STEP_CONTENT_LENGTH) &&\n\t\tisTaskStepStatus(value.status) &&\n\t\t(value.priority === undefined || isTaskStepPriority(value.priority)) &&\n\t\thasOptionalString(value, \"owner\", MAX_TASK_STEP_OWNER_LENGTH) &&\n\t\tisBoundedStringArray(value.notes, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_NOTE_LENGTH) &&\n\t\tisBoundedStringArray(value.evidence, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_EVIDENCE_LENGTH) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\"\n\t);\n}\n\nfunction isTaskStepsArchive(value: unknown): value is TaskStepsArchive {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\tNumber.isInteger(value.completed) &&\n\t\tNumber(value.completed) >= 0 &&\n\t\tNumber.isInteger(value.cancelled) &&\n\t\tNumber(value.cancelled) >= 0 &&\n\t\thasOptionalString(value, \"compactedAt\", 100)\n\t);\n}\n\nexport function isTaskStepsState(value: unknown): value is TaskStepsState {\n\tif (!isRecord(value)) return false;\n\tif (\n\t\tvalue.version !== 1 ||\n\t\t!Number.isInteger(value.revision) ||\n\t\tNumber(value.revision) < 0 ||\n\t\t!Number.isInteger(value.nextStepNumber) ||\n\t\tNumber(value.nextStepNumber) < 1 ||\n\t\t!Array.isArray(value.steps) ||\n\t\tvalue.steps.length > MAX_TASK_STEPS ||\n\t\t!value.steps.every(isTaskStep) ||\n\t\t!isTaskStepsArchive(value.archive) ||\n\t\ttypeof value.createdAt !== \"string\" ||\n\t\ttypeof value.updatedAt !== \"string\"\n\t) {\n\t\treturn false;\n\t}\n\tconst ids = new Set(value.steps.map((step) => step.id));\n\treturn ids.size === value.steps.length && value.steps.filter((step) => step.status === \"in_progress\").length <= 1;\n}\n\nfunction cloneTaskStep(step: TaskStep): TaskStep {\n\treturn { ...step, notes: [...step.notes], evidence: [...step.evidence] };\n}\n\nexport function cloneTaskStepsState(state: TaskStepsState): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\tsteps: state.steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t};\n}\n\nexport function createTaskStepsState(now: string): TaskStepsState {\n\treturn {\n\t\tversion: 1,\n\t\trevision: 0,\n\t\tnextStepNumber: 1,\n\t\tsteps: [],\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction requireBoundedText(value: string, label: string, maxLength: number): string {\n\tconst normalized = value.trim();\n\tif (!normalized) throw new TaskStepsError(`${label} is required.`);\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction optionalBoundedText(value: string | undefined, label: string, maxLength: number): string | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = value.trim();\n\tif (!normalized) return undefined;\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction normalizeStrings(values: readonly string[] | undefined, label: string, maxLength: number): string[] {\n\tif (!values) return [];\n\tconst normalized: string[] = [];\n\tfor (const value of values) {\n\t\tconst item = requireBoundedText(value, label, maxLength);\n\t\tif (!normalized.includes(item)) normalized.push(item);\n\t}\n\tif (normalized.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn normalized;\n}\n\nfunction appendUniqueStrings(\n\tcurrent: readonly string[],\n\tvalues: readonly string[] | undefined,\n\tlabel: string,\n\tmaxLength: number,\n): string[] {\n\tconst appended = [...current];\n\tfor (const value of normalizeStrings(values, label, maxLength)) {\n\t\tif (!appended.includes(value)) appended.push(value);\n\t}\n\tif (appended.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn appended;\n}\n\nfunction normalizeInputNotes(input: TaskStepInput): string[] {\n\tconst notes = normalizeStrings(input.notes, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst note = optionalBoundedText(input.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tif (note && !notes.includes(note)) notes.push(note);\n\treturn notes;\n}\n\nfunction demoteOtherActiveSteps(steps: TaskStep[], activeIndex: number): void {\n\tfor (let index = 0; index < steps.length; index++) {\n\t\tif (index !== activeIndex && steps[index].status === \"in_progress\") {\n\t\t\tsteps[index] = { ...steps[index], status: \"pending\" };\n\t\t}\n\t}\n}\n\nfunction nextState(state: TaskStepsState, steps: readonly TaskStep[], now: string): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\trevision: state.revision + 1,\n\t\tsteps: steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction createStep(args: {\n\tinput: TaskStepInput;\n\tid: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\texisting?: TaskStep;\n}): TaskStep {\n\tconst existing = args.existing;\n\tconst notes =\n\t\targs.input.note === undefined && args.input.notes === undefined\n\t\t\t? [...(existing?.notes ?? [])]\n\t\t\t: normalizeInputNotes(args.input);\n\tconst evidence =\n\t\targs.input.evidence === undefined\n\t\t\t? [...(existing?.evidence ?? [])]\n\t\t\t: normalizeStrings(args.input.evidence, \"Task step evidence\", MAX_TASK_STEP_EVIDENCE_LENGTH);\n\treturn {\n\t\tid: args.id,\n\t\tcontent: requireBoundedText(args.input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\targs.input.activeForm === undefined\n\t\t\t\t? existing?.activeForm\n\t\t\t\t: optionalBoundedText(args.input.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: args.input.status ?? existing?.status ?? \"pending\",\n\t\tpriority: args.input.priority ?? existing?.priority,\n\t\towner:\n\t\t\targs.input.owner === undefined\n\t\t\t\t? existing?.owner\n\t\t\t\t: optionalBoundedText(args.input.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tcreatedAt: args.createdAt,\n\t\tupdatedAt: args.updatedAt,\n\t};\n}\n\nexport function setTaskSteps(state: TaskStepsState, inputs: readonly TaskStepInput[], now: string): TaskStepsState {\n\tif (inputs.length > MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps supports at most ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst existingByContent = new Map<string, TaskStep[]>();\n\tfor (const step of state.steps) {\n\t\tconst key = step.content.toLocaleLowerCase();\n\t\tconst matches = existingByContent.get(key) ?? [];\n\t\tmatches.push(step);\n\t\texistingByContent.set(key, matches);\n\t}\n\n\tlet nextStepNumber = state.nextStepNumber;\n\tconst steps = inputs.map((input) => {\n\t\tconst content = requireBoundedText(input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH);\n\t\tconst matches = existingByContent.get(content.toLocaleLowerCase());\n\t\tconst existing = matches?.shift();\n\t\tconst id = existing?.id ?? `step-${nextStepNumber++}`;\n\t\treturn createStep({\n\t\t\tinput: { ...input, content },\n\t\t\tid,\n\t\t\tcreatedAt: existing?.createdAt ?? now,\n\t\t\tupdatedAt: now,\n\t\t\texisting,\n\t\t});\n\t});\n\tconst activeIndex = steps.findLastIndex((step) => step.status === \"in_progress\");\n\tif (activeIndex >= 0) demoteOtherActiveSteps(steps, activeIndex);\n\treturn { ...nextState(state, steps, now), nextStepNumber };\n}\n\nexport function addTaskStep(state: TaskStepsState, input: TaskStepInput, now: string): TaskStepsState {\n\tif (state.steps.length >= MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps already has the maximum ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst step = createStep({ input, id: `step-${state.nextStepNumber}`, createdAt: now, updatedAt: now });\n\tconst steps = [...state.steps.map(cloneTaskStep), step];\n\tif (step.status === \"in_progress\") demoteOtherActiveSteps(steps, steps.length - 1);\n\treturn { ...nextState(state, steps, now), nextStepNumber: state.nextStepNumber + 1 };\n}\n\nexport function resolveTaskStepSelector(steps: readonly TaskStep[], selector: string): TaskStep {\n\tconst normalized = selector.trim().toLocaleLowerCase();\n\tif (!normalized) throw new TaskStepsError(\"Task step selector is required.\");\n\tif (normalized === \"current\" || normalized === \"active\") {\n\t\tconst active = steps.find((step) => step.status === \"in_progress\");\n\t\tif (!active) throw new TaskStepsError(\"No in_progress task step was found.\");\n\t\treturn active;\n\t}\n\n\tconst exactId = steps.find((step) => step.id.toLocaleLowerCase() === normalized);\n\tif (exactId) return exactId;\n\tconst idPrefix = steps.filter((step) => step.id.toLocaleLowerCase().startsWith(normalized));\n\tif (idPrefix.length === 1) return idPrefix[0];\n\tif (idPrefix.length > 1) {\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${idPrefix.map((step) => step.id).join(\", \")}.`);\n\t}\n\n\tconst exactContent = steps.filter((step) => step.content.toLocaleLowerCase() === normalized);\n\tif (exactContent.length === 1) return exactContent[0];\n\tconst contentMatches = steps.filter((step) => step.content.toLocaleLowerCase().includes(normalized));\n\tif (contentMatches.length === 1) return contentMatches[0];\n\tif (exactContent.length > 1 || contentMatches.length > 1) {\n\t\tconst matches = exactContent.length > 1 ? exactContent : contentMatches;\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${matches.map((step) => step.id).join(\", \")}.`);\n\t}\n\tthrow new TaskStepsError(`Task step not found for selector: ${selector}.`);\n}\n\nexport function updateTaskStep(\n\tstate: TaskStepsState,\n\tselector: string,\n\tupdate: TaskStepUpdate,\n\tnow: string,\n): TaskStepsState {\n\tconst selected = resolveTaskStepSelector(state.steps, selector);\n\tconst selectedIndex = state.steps.findIndex((step) => step.id === selected.id);\n\tconst steps = state.steps.map(cloneTaskStep);\n\tconst current = steps[selectedIndex];\n\tconst note = optionalBoundedText(update.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst notes = note\n\t\t? appendUniqueStrings(current.notes, [note], \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH)\n\t\t: [...current.notes];\n\tconst evidence = appendUniqueStrings(\n\t\tcurrent.evidence,\n\t\tupdate.evidence,\n\t\t\"Task step evidence\",\n\t\tMAX_TASK_STEP_EVIDENCE_LENGTH,\n\t);\n\tsteps[selectedIndex] = {\n\t\t...current,\n\t\tcontent:\n\t\t\tupdate.content === undefined\n\t\t\t\t? current.content\n\t\t\t\t: requireBoundedText(update.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\tupdate.activeForm === undefined\n\t\t\t\t? current.activeForm\n\t\t\t\t: optionalBoundedText(update.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: update.status ?? current.status,\n\t\tpriority: update.priority ?? current.priority,\n\t\towner:\n\t\t\tupdate.owner === undefined\n\t\t\t\t? current.owner\n\t\t\t\t: optionalBoundedText(update.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tupdatedAt: now,\n\t};\n\tif (steps[selectedIndex].status === \"in_progress\") demoteOtherActiveSteps(steps, selectedIndex);\n\treturn nextState(state, steps, now);\n}\n\nexport function clearTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\treturn {\n\t\t...nextState(state, [], now),\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t};\n}\n\nexport function compactTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\tconst completed = state.steps.filter((step) => step.status === \"completed\").length;\n\tconst cancelled = state.steps.filter((step) => step.status === \"cancelled\").length;\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\treturn {\n\t\t...nextState(state, open, now),\n\t\tarchive: {\n\t\t\tcompleted: state.archive.completed + completed,\n\t\t\tcancelled: state.archive.cancelled + cancelled,\n\t\t\tcompactedAt: now,\n\t\t},\n\t};\n}\n\nexport function formatTaskSteps(\n\tstate: TaskStepsState,\n\toptions: { includeTerminal?: boolean; maxItems?: number } = {},\n): string {\n\tconst visible = options.includeTerminal\n\t\t? state.steps\n\t\t: state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tconst maxItems = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(options.maxItems ?? 20)));\n\tconst statusMarker: Record<TaskStepStatus, string> = {\n\t\tpending: \" \",\n\t\tin_progress: \">\",\n\t\tcompleted: \"x\",\n\t\tblocked: \"!\",\n\t\tcancelled: \"-\",\n\t};\n\tconst lines = [`Task steps (${visible.length} visible, ${state.steps.length} tracked):`];\n\tfor (const step of visible.slice(0, maxItems)) {\n\t\tconst details = [step.priority, step.owner].filter(Boolean).join(\", \");\n\t\tlines.push(\n\t\t\t`- [${statusMarker[step.status]}] ${step.id} ${step.activeForm || step.content}${details ? ` (${details})` : \"\"}`,\n\t\t);\n\t\tfor (const note of step.notes.slice(-2)) lines.push(` note: ${note}`);\n\t\tfor (const evidence of step.evidence.slice(-2)) lines.push(` evidence: ${evidence}`);\n\t}\n\tif (visible.length > maxItems) lines.push(`- … ${visible.length - maxItems} more`);\n\tif (state.archive.completed || state.archive.cancelled) {\n\t\tlines.push(\n\t\t\t`Archived terminal steps: ${state.archive.completed} completed, ${state.archive.cancelled} cancelled.`,\n\t\t);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatTaskStepsContext(state: TaskStepsState, maxItems = 12): string | undefined {\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tif (open.length === 0) return undefined;\n\tconst limit = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(maxItems)));\n\tconst lines = [\n\t\t\"Current native task_steps context for this session:\",\n\t\t\"Open task_steps:\",\n\t\t...open.slice(0, limit).map((step) => `- [${step.status}] ${step.activeForm || step.content}`),\n\t];\n\tif (open.length > limit) lines.push(`- … ${open.length - limit} more open step(s)`);\n\tconst active = open.find((step) => step.status === \"in_progress\");\n\tlines.push(\n\t\t\"\",\n\t\tactive\n\t\t\t? `Continue the in_progress step first: ${active.activeForm || active.content}. Update it completed, blocked, or cancelled as soon as evidence is known.`\n\t\t\t: `No step is in_progress. Start the first open step before unrelated work: ${open[0].activeForm || open[0].content}.`,\n\t\t\"Use task_steps to keep this checklist current and leave no stale in_progress step before the final response.\",\n\t);\n\treturn lines.join(\"\\n\");\n}\n\nexport function serializeTaskStepsState(state: TaskStepsState): string {\n\treturn JSON.stringify(cloneTaskStepsState(state), null, 2);\n}\n\nexport function parseTaskStepsState(text: string): TaskStepsState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\treturn isTaskStepsState(parsed) ? cloneTaskStepsState(parsed) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"task-state.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/task-state.ts"],"names":[],"mappings":"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","sourcesContent":["export const TASK_STEP_STATUSES = [\"pending\", \"in_progress\", \"completed\", \"blocked\", \"cancelled\"] as const;\nexport type TaskStepStatus = (typeof TASK_STEP_STATUSES)[number];\n\nexport const TASK_STEP_PRIORITIES = [\"low\", \"normal\", \"high\"] as const;\nexport type TaskStepPriority = (typeof TASK_STEP_PRIORITIES)[number];\n\nexport const MAX_TASK_STEPS = 100;\nexport const MAX_TASK_STEP_CONTENT_LENGTH = 2_000;\nconst MAX_TASK_STEP_NOTE_LENGTH = 4_000;\nconst MAX_TASK_STEP_OWNER_LENGTH = 200;\nconst MAX_TASK_STEP_EVIDENCE = 32;\nconst MAX_TASK_STEP_EVIDENCE_LENGTH = 2_000;\n\nexport interface TaskStepInput {\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tnotes?: readonly string[];\n\tevidence?: readonly string[];\n}\n\nexport interface TaskStep {\n\tid: string;\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnotes: readonly string[];\n\tevidence: readonly string[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepsArchive {\n\tcompleted: number;\n\tcancelled: number;\n\tcompactedAt?: string;\n}\n\nexport interface TaskStepsState {\n\tversion: 1;\n\trevision: number;\n\tnextStepNumber: number;\n\tsteps: readonly TaskStep[];\n\tarchive: TaskStepsArchive;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepUpdate {\n\tcontent?: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tevidence?: readonly string[];\n}\n\nexport class TaskStepsError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"TaskStepsError\";\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isTaskStepStatus(value: unknown): value is TaskStepStatus {\n\treturn TASK_STEP_STATUSES.some((status) => status === value);\n}\n\nfunction isTaskStepPriority(value: unknown): value is TaskStepPriority {\n\treturn TASK_STEP_PRIORITIES.some((priority) => priority === value);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string, maxLength: number): boolean {\n\tconst value = record[key];\n\treturn value === undefined || (typeof value === \"string\" && value.length <= maxLength);\n}\n\nfunction isBoundedStringArray(value: unknown, maxItems: number, maxLength: number): value is readonly string[] {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length <= maxItems &&\n\t\tvalue.every((item) => typeof item === \"string\" && item.length > 0 && item.length <= maxLength)\n\t);\n}\n\nfunction isTaskStep(value: unknown): value is TaskStep {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\t/^step-[1-9]\\d*$/.test(value.id) &&\n\t\ttypeof value.content === \"string\" &&\n\t\tvalue.content.length > 0 &&\n\t\tvalue.content.length <= MAX_TASK_STEP_CONTENT_LENGTH &&\n\t\thasOptionalString(value, \"activeForm\", MAX_TASK_STEP_CONTENT_LENGTH) &&\n\t\tisTaskStepStatus(value.status) &&\n\t\t(value.priority === undefined || isTaskStepPriority(value.priority)) &&\n\t\thasOptionalString(value, \"owner\", MAX_TASK_STEP_OWNER_LENGTH) &&\n\t\tisBoundedStringArray(value.notes, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_NOTE_LENGTH) &&\n\t\tisBoundedStringArray(value.evidence, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_EVIDENCE_LENGTH) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\"\n\t);\n}\n\nfunction isTaskStepsArchive(value: unknown): value is TaskStepsArchive {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\tNumber.isInteger(value.completed) &&\n\t\tNumber(value.completed) >= 0 &&\n\t\tNumber.isInteger(value.cancelled) &&\n\t\tNumber(value.cancelled) >= 0 &&\n\t\thasOptionalString(value, \"compactedAt\", 100)\n\t);\n}\n\nexport function isTaskStepsState(value: unknown): value is TaskStepsState {\n\tif (!isRecord(value)) return false;\n\tif (\n\t\tvalue.version !== 1 ||\n\t\t!Number.isInteger(value.revision) ||\n\t\tNumber(value.revision) < 0 ||\n\t\t!Number.isInteger(value.nextStepNumber) ||\n\t\tNumber(value.nextStepNumber) < 1 ||\n\t\t!Array.isArray(value.steps) ||\n\t\tvalue.steps.length > MAX_TASK_STEPS ||\n\t\t!value.steps.every(isTaskStep) ||\n\t\t!isTaskStepsArchive(value.archive) ||\n\t\ttypeof value.createdAt !== \"string\" ||\n\t\ttypeof value.updatedAt !== \"string\"\n\t) {\n\t\treturn false;\n\t}\n\tconst ids = new Set(value.steps.map((step) => step.id));\n\treturn ids.size === value.steps.length && value.steps.filter((step) => step.status === \"in_progress\").length <= 1;\n}\n\nfunction cloneTaskStep(step: TaskStep): TaskStep {\n\treturn { ...step, notes: [...step.notes], evidence: [...step.evidence] };\n}\n\nexport function cloneTaskStepsState(state: TaskStepsState): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\tsteps: state.steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t};\n}\n\nexport function createTaskStepsState(now: string): TaskStepsState {\n\treturn {\n\t\tversion: 1,\n\t\trevision: 0,\n\t\tnextStepNumber: 1,\n\t\tsteps: [],\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction requireBoundedText(value: string, label: string, maxLength: number): string {\n\tconst normalized = value.trim();\n\tif (!normalized) throw new TaskStepsError(`${label} is required.`);\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction optionalBoundedText(value: string | undefined, label: string, maxLength: number): string | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = value.trim();\n\tif (!normalized) return undefined;\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction normalizeStrings(values: readonly string[] | undefined, label: string, maxLength: number): string[] {\n\tif (!values) return [];\n\tconst normalized: string[] = [];\n\tfor (const value of values) {\n\t\tconst item = requireBoundedText(value, label, maxLength);\n\t\tif (!normalized.includes(item)) normalized.push(item);\n\t}\n\tif (normalized.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn normalized;\n}\n\nfunction appendUniqueStrings(\n\tcurrent: readonly string[],\n\tvalues: readonly string[] | undefined,\n\tlabel: string,\n\tmaxLength: number,\n): string[] {\n\tconst appended = [...current];\n\tfor (const value of normalizeStrings(values, label, maxLength)) {\n\t\tif (!appended.includes(value)) appended.push(value);\n\t}\n\tif (appended.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn appended;\n}\n\nfunction normalizeInputNotes(input: TaskStepInput): string[] {\n\tconst notes = normalizeStrings(input.notes, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst note = optionalBoundedText(input.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tif (note && !notes.includes(note)) notes.push(note);\n\treturn notes;\n}\n\n/**\n * Find an OPEN (non-terminal) step whose content matches `content` case-insensitively.\n * Terminal steps (completed/cancelled) are deliberately excluded so a legitimate re-add of\n * previously finished work still creates a new step.\n */\nexport function findOpenDuplicateStep(steps: readonly TaskStep[], content: string): TaskStep | undefined {\n\tconst normalized = content.trim().toLocaleLowerCase();\n\tif (!normalized) return undefined;\n\treturn steps.find(\n\t\t(step) =>\n\t\t\tstep.status !== \"completed\" && step.status !== \"cancelled\" && step.content.toLocaleLowerCase() === normalized,\n\t);\n}\n\n/** True when a completed step has no evidence attached (a verification nudge candidate). */\nexport function hasUnverifiedCompletedStep(state: TaskStepsState): boolean {\n\treturn state.steps.some((step) => step.status === \"completed\" && step.evidence.length === 0);\n}\n\nfunction demoteOtherActiveSteps(steps: TaskStep[], activeIndex: number): void {\n\tfor (let index = 0; index < steps.length; index++) {\n\t\tif (index !== activeIndex && steps[index].status === \"in_progress\") {\n\t\t\tsteps[index] = { ...steps[index], status: \"pending\" };\n\t\t}\n\t}\n}\n\nfunction nextState(state: TaskStepsState, steps: readonly TaskStep[], now: string): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\trevision: state.revision + 1,\n\t\tsteps: steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction createStep(args: {\n\tinput: TaskStepInput;\n\tid: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\texisting?: TaskStep;\n}): TaskStep {\n\tconst existing = args.existing;\n\tconst notes =\n\t\targs.input.note === undefined && args.input.notes === undefined\n\t\t\t? [...(existing?.notes ?? [])]\n\t\t\t: normalizeInputNotes(args.input);\n\tconst evidence =\n\t\targs.input.evidence === undefined\n\t\t\t? [...(existing?.evidence ?? [])]\n\t\t\t: normalizeStrings(args.input.evidence, \"Task step evidence\", MAX_TASK_STEP_EVIDENCE_LENGTH);\n\treturn {\n\t\tid: args.id,\n\t\tcontent: requireBoundedText(args.input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\targs.input.activeForm === undefined\n\t\t\t\t? existing?.activeForm\n\t\t\t\t: optionalBoundedText(args.input.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: args.input.status ?? existing?.status ?? \"pending\",\n\t\tpriority: args.input.priority ?? existing?.priority,\n\t\towner:\n\t\t\targs.input.owner === undefined\n\t\t\t\t? existing?.owner\n\t\t\t\t: optionalBoundedText(args.input.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tcreatedAt: args.createdAt,\n\t\tupdatedAt: args.updatedAt,\n\t};\n}\n\nexport function setTaskSteps(state: TaskStepsState, inputs: readonly TaskStepInput[], now: string): TaskStepsState {\n\tif (inputs.length > MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps supports at most ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst existingByContent = new Map<string, TaskStep[]>();\n\tfor (const step of state.steps) {\n\t\tconst key = step.content.toLocaleLowerCase();\n\t\tconst matches = existingByContent.get(key) ?? [];\n\t\tmatches.push(step);\n\t\texistingByContent.set(key, matches);\n\t}\n\n\tlet nextStepNumber = state.nextStepNumber;\n\tconst steps = inputs.map((input) => {\n\t\tconst content = requireBoundedText(input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH);\n\t\tconst matches = existingByContent.get(content.toLocaleLowerCase());\n\t\tconst existing = matches?.shift();\n\t\tconst id = existing?.id ?? `step-${nextStepNumber++}`;\n\t\treturn createStep({\n\t\t\tinput: { ...input, content },\n\t\t\tid,\n\t\t\tcreatedAt: existing?.createdAt ?? now,\n\t\t\tupdatedAt: now,\n\t\t\texisting,\n\t\t});\n\t});\n\tconst activeIndex = steps.findLastIndex((step) => step.status === \"in_progress\");\n\tif (activeIndex >= 0) demoteOtherActiveSteps(steps, activeIndex);\n\treturn { ...nextState(state, steps, now), nextStepNumber };\n}\n\nexport function addTaskStep(state: TaskStepsState, input: TaskStepInput, now: string): TaskStepsState {\n\t// Dedupe against OPEN steps only, before the capacity check: a duplicate re-add of an\n\t// already-open step is a no-op regardless of whether the list happens to be full. Terminal\n\t// (completed/cancelled) matches are excluded so a legitimate re-add still creates a step.\n\tif (findOpenDuplicateStep(state.steps, input.content)) return state;\n\tif (state.steps.length >= MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps already has the maximum ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst step = createStep({ input, id: `step-${state.nextStepNumber}`, createdAt: now, updatedAt: now });\n\tconst steps = [...state.steps.map(cloneTaskStep), step];\n\tif (step.status === \"in_progress\") demoteOtherActiveSteps(steps, steps.length - 1);\n\treturn { ...nextState(state, steps, now), nextStepNumber: state.nextStepNumber + 1 };\n}\n\nexport function resolveTaskStepSelector(steps: readonly TaskStep[], selector: string): TaskStep {\n\tconst normalized = selector.trim().toLocaleLowerCase();\n\tif (!normalized) throw new TaskStepsError(\"Task step selector is required.\");\n\tif (normalized === \"current\" || normalized === \"active\") {\n\t\tconst active = steps.find((step) => step.status === \"in_progress\");\n\t\tif (!active) throw new TaskStepsError(\"No in_progress task step was found.\");\n\t\treturn active;\n\t}\n\n\tconst exactId = steps.find((step) => step.id.toLocaleLowerCase() === normalized);\n\tif (exactId) return exactId;\n\tconst idPrefix = steps.filter((step) => step.id.toLocaleLowerCase().startsWith(normalized));\n\tif (idPrefix.length === 1) return idPrefix[0];\n\tif (idPrefix.length > 1) {\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${idPrefix.map((step) => step.id).join(\", \")}.`);\n\t}\n\n\tconst exactContent = steps.filter((step) => step.content.toLocaleLowerCase() === normalized);\n\tif (exactContent.length === 1) return exactContent[0];\n\tconst contentMatches = steps.filter((step) => step.content.toLocaleLowerCase().includes(normalized));\n\tif (contentMatches.length === 1) return contentMatches[0];\n\tif (exactContent.length > 1 || contentMatches.length > 1) {\n\t\tconst matches = exactContent.length > 1 ? exactContent : contentMatches;\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${matches.map((step) => step.id).join(\", \")}.`);\n\t}\n\tthrow new TaskStepsError(`Task step not found for selector: ${selector}.`);\n}\n\nexport function updateTaskStep(\n\tstate: TaskStepsState,\n\tselector: string,\n\tupdate: TaskStepUpdate,\n\tnow: string,\n): TaskStepsState {\n\tconst selected = resolveTaskStepSelector(state.steps, selector);\n\tconst selectedIndex = state.steps.findIndex((step) => step.id === selected.id);\n\tconst steps = state.steps.map(cloneTaskStep);\n\tconst current = steps[selectedIndex];\n\tconst note = optionalBoundedText(update.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst notes = note\n\t\t? appendUniqueStrings(current.notes, [note], \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH)\n\t\t: [...current.notes];\n\tconst evidence = appendUniqueStrings(\n\t\tcurrent.evidence,\n\t\tupdate.evidence,\n\t\t\"Task step evidence\",\n\t\tMAX_TASK_STEP_EVIDENCE_LENGTH,\n\t);\n\tsteps[selectedIndex] = {\n\t\t...current,\n\t\tcontent:\n\t\t\tupdate.content === undefined\n\t\t\t\t? current.content\n\t\t\t\t: requireBoundedText(update.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\tupdate.activeForm === undefined\n\t\t\t\t? current.activeForm\n\t\t\t\t: optionalBoundedText(update.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: update.status ?? current.status,\n\t\tpriority: update.priority ?? current.priority,\n\t\towner:\n\t\t\tupdate.owner === undefined\n\t\t\t\t? current.owner\n\t\t\t\t: optionalBoundedText(update.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tupdatedAt: now,\n\t};\n\tif (steps[selectedIndex].status === \"in_progress\") demoteOtherActiveSteps(steps, selectedIndex);\n\treturn nextState(state, steps, now);\n}\n\nexport function clearTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\treturn {\n\t\t...nextState(state, [], now),\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t};\n}\n\nexport function compactTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\tconst completed = state.steps.filter((step) => step.status === \"completed\").length;\n\tconst cancelled = state.steps.filter((step) => step.status === \"cancelled\").length;\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\treturn {\n\t\t...nextState(state, open, now),\n\t\tarchive: {\n\t\t\tcompleted: state.archive.completed + completed,\n\t\t\tcancelled: state.archive.cancelled + cancelled,\n\t\t\tcompactedAt: now,\n\t\t},\n\t};\n}\n\nexport function formatTaskSteps(\n\tstate: TaskStepsState,\n\toptions: { includeTerminal?: boolean; maxItems?: number } = {},\n): string {\n\tconst visible = options.includeTerminal\n\t\t? state.steps\n\t\t: state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tconst maxItems = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(options.maxItems ?? 20)));\n\tconst statusMarker: Record<TaskStepStatus, string> = {\n\t\tpending: \" \",\n\t\tin_progress: \">\",\n\t\tcompleted: \"x\",\n\t\tblocked: \"!\",\n\t\tcancelled: \"-\",\n\t};\n\tconst lines = [`Task steps (${visible.length} visible, ${state.steps.length} tracked):`];\n\tfor (const step of visible.slice(0, maxItems)) {\n\t\tconst details = [step.priority, step.owner].filter(Boolean).join(\", \");\n\t\tlines.push(\n\t\t\t`- [${statusMarker[step.status]}] ${step.id} ${step.activeForm || step.content}${details ? ` (${details})` : \"\"}`,\n\t\t);\n\t\tfor (const note of step.notes.slice(-2)) lines.push(` note: ${note}`);\n\t\tfor (const evidence of step.evidence.slice(-2)) lines.push(` evidence: ${evidence}`);\n\t}\n\tif (visible.length > maxItems) lines.push(`- … ${visible.length - maxItems} more`);\n\tif (state.archive.completed || state.archive.cancelled) {\n\t\tlines.push(\n\t\t\t`Archived terminal steps: ${state.archive.completed} completed, ${state.archive.cancelled} cancelled.`,\n\t\t);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatTaskStepsContext(state: TaskStepsState, maxItems = 12): string | undefined {\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tif (open.length === 0) return undefined;\n\tconst limit = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(maxItems)));\n\tconst lines = [\n\t\t\"Current native task_steps context for this session:\",\n\t\t\"Open task_steps:\",\n\t\t...open.slice(0, limit).map((step) => `- [${step.status}] ${step.activeForm || step.content}`),\n\t];\n\tif (open.length > limit) lines.push(`- … ${open.length - limit} more open step(s)`);\n\tconst active = open.find((step) => step.status === \"in_progress\");\n\tlines.push(\n\t\t\"\",\n\t\tactive\n\t\t\t? `Continue the in_progress step first: ${active.activeForm || active.content}. Update it completed, blocked, or cancelled as soon as evidence is known.`\n\t\t\t: `No step is in_progress. Start the first open step before unrelated work: ${open[0].activeForm || open[0].content}.`,\n\t\t\"Use task_steps to keep this checklist current and leave no stale in_progress step before the final response.\",\n\t);\n\tif (hasUnverifiedCompletedStep(state)) {\n\t\tlines.push(\n\t\t\t\"A completed step has no evidence attached; attach evidence via task_steps update before treating it as verified.\",\n\t\t);\n\t}\n\t// Wrapped in a marker (mirrors the <memory_context> precedent) so context-gc's\n\t// semantic-memory packer can recognize this as a deterministic, re-derivable context page and\n\t// pack stale copies down to the most recent one instead of letting a full page accumulate every\n\t// turn. The revision (monotonic per mutation) lets a reader tell which page is current.\n\treturn `<task_steps_context revision=${state.revision}>\\n${lines.join(\"\\n\")}\\n</task_steps_context>`;\n}\n\nexport function serializeTaskStepsState(state: TaskStepsState): string {\n\treturn JSON.stringify(cloneTaskStepsState(state), null, 2);\n}\n\nexport function parseTaskStepsState(text: string): TaskStepsState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\treturn isTaskStepsState(parsed) ? cloneTaskStepsState(parsed) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
|
|
@@ -149,6 +149,21 @@ function normalizeInputNotes(input) {
|
|
|
149
149
|
notes.push(note);
|
|
150
150
|
return notes;
|
|
151
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Find an OPEN (non-terminal) step whose content matches `content` case-insensitively.
|
|
154
|
+
* Terminal steps (completed/cancelled) are deliberately excluded so a legitimate re-add of
|
|
155
|
+
* previously finished work still creates a new step.
|
|
156
|
+
*/
|
|
157
|
+
export function findOpenDuplicateStep(steps, content) {
|
|
158
|
+
const normalized = content.trim().toLocaleLowerCase();
|
|
159
|
+
if (!normalized)
|
|
160
|
+
return undefined;
|
|
161
|
+
return steps.find((step) => step.status !== "completed" && step.status !== "cancelled" && step.content.toLocaleLowerCase() === normalized);
|
|
162
|
+
}
|
|
163
|
+
/** True when a completed step has no evidence attached (a verification nudge candidate). */
|
|
164
|
+
export function hasUnverifiedCompletedStep(state) {
|
|
165
|
+
return state.steps.some((step) => step.status === "completed" && step.evidence.length === 0);
|
|
166
|
+
}
|
|
152
167
|
function demoteOtherActiveSteps(steps, activeIndex) {
|
|
153
168
|
for (let index = 0; index < steps.length; index++) {
|
|
154
169
|
if (index !== activeIndex && steps[index].status === "in_progress") {
|
|
@@ -221,6 +236,11 @@ export function setTaskSteps(state, inputs, now) {
|
|
|
221
236
|
return { ...nextState(state, steps, now), nextStepNumber };
|
|
222
237
|
}
|
|
223
238
|
export function addTaskStep(state, input, now) {
|
|
239
|
+
// Dedupe against OPEN steps only, before the capacity check: a duplicate re-add of an
|
|
240
|
+
// already-open step is a no-op regardless of whether the list happens to be full. Terminal
|
|
241
|
+
// (completed/cancelled) matches are excluded so a legitimate re-add still creates a step.
|
|
242
|
+
if (findOpenDuplicateStep(state.steps, input.content))
|
|
243
|
+
return state;
|
|
224
244
|
if (state.steps.length >= MAX_TASK_STEPS) {
|
|
225
245
|
throw new TaskStepsError(`Task steps already has the maximum ${MAX_TASK_STEPS} steps.`);
|
|
226
246
|
}
|
|
@@ -355,7 +375,14 @@ export function formatTaskStepsContext(state, maxItems = 12) {
|
|
|
355
375
|
lines.push("", active
|
|
356
376
|
? `Continue the in_progress step first: ${active.activeForm || active.content}. Update it completed, blocked, or cancelled as soon as evidence is known.`
|
|
357
377
|
: `No step is in_progress. Start the first open step before unrelated work: ${open[0].activeForm || open[0].content}.`, "Use task_steps to keep this checklist current and leave no stale in_progress step before the final response.");
|
|
358
|
-
|
|
378
|
+
if (hasUnverifiedCompletedStep(state)) {
|
|
379
|
+
lines.push("A completed step has no evidence attached; attach evidence via task_steps update before treating it as verified.");
|
|
380
|
+
}
|
|
381
|
+
// Wrapped in a marker (mirrors the <memory_context> precedent) so context-gc's
|
|
382
|
+
// semantic-memory packer can recognize this as a deterministic, re-derivable context page and
|
|
383
|
+
// pack stale copies down to the most recent one instead of letting a full page accumulate every
|
|
384
|
+
// turn. The revision (monotonic per mutation) lets a reader tell which page is current.
|
|
385
|
+
return `<task_steps_context revision=${state.revision}>\n${lines.join("\n")}\n</task_steps_context>`;
|
|
359
386
|
}
|
|
360
387
|
export function serializeTaskStepsState(state) {
|
|
361
388
|
return JSON.stringify(cloneTaskStepsState(state), null, 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-state.js","sourceRoot":"","sources":["../../../src/core/tasks/task-state.ts"],"names":[],"mappings":"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","sourcesContent":["export const TASK_STEP_STATUSES = [\"pending\", \"in_progress\", \"completed\", \"blocked\", \"cancelled\"] as const;\nexport type TaskStepStatus = (typeof TASK_STEP_STATUSES)[number];\n\nexport const TASK_STEP_PRIORITIES = [\"low\", \"normal\", \"high\"] as const;\nexport type TaskStepPriority = (typeof TASK_STEP_PRIORITIES)[number];\n\nexport const MAX_TASK_STEPS = 100;\nexport const MAX_TASK_STEP_CONTENT_LENGTH = 2_000;\nconst MAX_TASK_STEP_NOTE_LENGTH = 4_000;\nconst MAX_TASK_STEP_OWNER_LENGTH = 200;\nconst MAX_TASK_STEP_EVIDENCE = 32;\nconst MAX_TASK_STEP_EVIDENCE_LENGTH = 2_000;\n\nexport interface TaskStepInput {\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tnotes?: readonly string[];\n\tevidence?: readonly string[];\n}\n\nexport interface TaskStep {\n\tid: string;\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnotes: readonly string[];\n\tevidence: readonly string[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepsArchive {\n\tcompleted: number;\n\tcancelled: number;\n\tcompactedAt?: string;\n}\n\nexport interface TaskStepsState {\n\tversion: 1;\n\trevision: number;\n\tnextStepNumber: number;\n\tsteps: readonly TaskStep[];\n\tarchive: TaskStepsArchive;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepUpdate {\n\tcontent?: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tevidence?: readonly string[];\n}\n\nexport class TaskStepsError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"TaskStepsError\";\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isTaskStepStatus(value: unknown): value is TaskStepStatus {\n\treturn TASK_STEP_STATUSES.some((status) => status === value);\n}\n\nfunction isTaskStepPriority(value: unknown): value is TaskStepPriority {\n\treturn TASK_STEP_PRIORITIES.some((priority) => priority === value);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string, maxLength: number): boolean {\n\tconst value = record[key];\n\treturn value === undefined || (typeof value === \"string\" && value.length <= maxLength);\n}\n\nfunction isBoundedStringArray(value: unknown, maxItems: number, maxLength: number): value is readonly string[] {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length <= maxItems &&\n\t\tvalue.every((item) => typeof item === \"string\" && item.length > 0 && item.length <= maxLength)\n\t);\n}\n\nfunction isTaskStep(value: unknown): value is TaskStep {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\t/^step-[1-9]\\d*$/.test(value.id) &&\n\t\ttypeof value.content === \"string\" &&\n\t\tvalue.content.length > 0 &&\n\t\tvalue.content.length <= MAX_TASK_STEP_CONTENT_LENGTH &&\n\t\thasOptionalString(value, \"activeForm\", MAX_TASK_STEP_CONTENT_LENGTH) &&\n\t\tisTaskStepStatus(value.status) &&\n\t\t(value.priority === undefined || isTaskStepPriority(value.priority)) &&\n\t\thasOptionalString(value, \"owner\", MAX_TASK_STEP_OWNER_LENGTH) &&\n\t\tisBoundedStringArray(value.notes, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_NOTE_LENGTH) &&\n\t\tisBoundedStringArray(value.evidence, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_EVIDENCE_LENGTH) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\"\n\t);\n}\n\nfunction isTaskStepsArchive(value: unknown): value is TaskStepsArchive {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\tNumber.isInteger(value.completed) &&\n\t\tNumber(value.completed) >= 0 &&\n\t\tNumber.isInteger(value.cancelled) &&\n\t\tNumber(value.cancelled) >= 0 &&\n\t\thasOptionalString(value, \"compactedAt\", 100)\n\t);\n}\n\nexport function isTaskStepsState(value: unknown): value is TaskStepsState {\n\tif (!isRecord(value)) return false;\n\tif (\n\t\tvalue.version !== 1 ||\n\t\t!Number.isInteger(value.revision) ||\n\t\tNumber(value.revision) < 0 ||\n\t\t!Number.isInteger(value.nextStepNumber) ||\n\t\tNumber(value.nextStepNumber) < 1 ||\n\t\t!Array.isArray(value.steps) ||\n\t\tvalue.steps.length > MAX_TASK_STEPS ||\n\t\t!value.steps.every(isTaskStep) ||\n\t\t!isTaskStepsArchive(value.archive) ||\n\t\ttypeof value.createdAt !== \"string\" ||\n\t\ttypeof value.updatedAt !== \"string\"\n\t) {\n\t\treturn false;\n\t}\n\tconst ids = new Set(value.steps.map((step) => step.id));\n\treturn ids.size === value.steps.length && value.steps.filter((step) => step.status === \"in_progress\").length <= 1;\n}\n\nfunction cloneTaskStep(step: TaskStep): TaskStep {\n\treturn { ...step, notes: [...step.notes], evidence: [...step.evidence] };\n}\n\nexport function cloneTaskStepsState(state: TaskStepsState): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\tsteps: state.steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t};\n}\n\nexport function createTaskStepsState(now: string): TaskStepsState {\n\treturn {\n\t\tversion: 1,\n\t\trevision: 0,\n\t\tnextStepNumber: 1,\n\t\tsteps: [],\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction requireBoundedText(value: string, label: string, maxLength: number): string {\n\tconst normalized = value.trim();\n\tif (!normalized) throw new TaskStepsError(`${label} is required.`);\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction optionalBoundedText(value: string | undefined, label: string, maxLength: number): string | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = value.trim();\n\tif (!normalized) return undefined;\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction normalizeStrings(values: readonly string[] | undefined, label: string, maxLength: number): string[] {\n\tif (!values) return [];\n\tconst normalized: string[] = [];\n\tfor (const value of values) {\n\t\tconst item = requireBoundedText(value, label, maxLength);\n\t\tif (!normalized.includes(item)) normalized.push(item);\n\t}\n\tif (normalized.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn normalized;\n}\n\nfunction appendUniqueStrings(\n\tcurrent: readonly string[],\n\tvalues: readonly string[] | undefined,\n\tlabel: string,\n\tmaxLength: number,\n): string[] {\n\tconst appended = [...current];\n\tfor (const value of normalizeStrings(values, label, maxLength)) {\n\t\tif (!appended.includes(value)) appended.push(value);\n\t}\n\tif (appended.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn appended;\n}\n\nfunction normalizeInputNotes(input: TaskStepInput): string[] {\n\tconst notes = normalizeStrings(input.notes, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst note = optionalBoundedText(input.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tif (note && !notes.includes(note)) notes.push(note);\n\treturn notes;\n}\n\nfunction demoteOtherActiveSteps(steps: TaskStep[], activeIndex: number): void {\n\tfor (let index = 0; index < steps.length; index++) {\n\t\tif (index !== activeIndex && steps[index].status === \"in_progress\") {\n\t\t\tsteps[index] = { ...steps[index], status: \"pending\" };\n\t\t}\n\t}\n}\n\nfunction nextState(state: TaskStepsState, steps: readonly TaskStep[], now: string): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\trevision: state.revision + 1,\n\t\tsteps: steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction createStep(args: {\n\tinput: TaskStepInput;\n\tid: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\texisting?: TaskStep;\n}): TaskStep {\n\tconst existing = args.existing;\n\tconst notes =\n\t\targs.input.note === undefined && args.input.notes === undefined\n\t\t\t? [...(existing?.notes ?? [])]\n\t\t\t: normalizeInputNotes(args.input);\n\tconst evidence =\n\t\targs.input.evidence === undefined\n\t\t\t? [...(existing?.evidence ?? [])]\n\t\t\t: normalizeStrings(args.input.evidence, \"Task step evidence\", MAX_TASK_STEP_EVIDENCE_LENGTH);\n\treturn {\n\t\tid: args.id,\n\t\tcontent: requireBoundedText(args.input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\targs.input.activeForm === undefined\n\t\t\t\t? existing?.activeForm\n\t\t\t\t: optionalBoundedText(args.input.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: args.input.status ?? existing?.status ?? \"pending\",\n\t\tpriority: args.input.priority ?? existing?.priority,\n\t\towner:\n\t\t\targs.input.owner === undefined\n\t\t\t\t? existing?.owner\n\t\t\t\t: optionalBoundedText(args.input.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tcreatedAt: args.createdAt,\n\t\tupdatedAt: args.updatedAt,\n\t};\n}\n\nexport function setTaskSteps(state: TaskStepsState, inputs: readonly TaskStepInput[], now: string): TaskStepsState {\n\tif (inputs.length > MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps supports at most ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst existingByContent = new Map<string, TaskStep[]>();\n\tfor (const step of state.steps) {\n\t\tconst key = step.content.toLocaleLowerCase();\n\t\tconst matches = existingByContent.get(key) ?? [];\n\t\tmatches.push(step);\n\t\texistingByContent.set(key, matches);\n\t}\n\n\tlet nextStepNumber = state.nextStepNumber;\n\tconst steps = inputs.map((input) => {\n\t\tconst content = requireBoundedText(input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH);\n\t\tconst matches = existingByContent.get(content.toLocaleLowerCase());\n\t\tconst existing = matches?.shift();\n\t\tconst id = existing?.id ?? `step-${nextStepNumber++}`;\n\t\treturn createStep({\n\t\t\tinput: { ...input, content },\n\t\t\tid,\n\t\t\tcreatedAt: existing?.createdAt ?? now,\n\t\t\tupdatedAt: now,\n\t\t\texisting,\n\t\t});\n\t});\n\tconst activeIndex = steps.findLastIndex((step) => step.status === \"in_progress\");\n\tif (activeIndex >= 0) demoteOtherActiveSteps(steps, activeIndex);\n\treturn { ...nextState(state, steps, now), nextStepNumber };\n}\n\nexport function addTaskStep(state: TaskStepsState, input: TaskStepInput, now: string): TaskStepsState {\n\tif (state.steps.length >= MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps already has the maximum ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst step = createStep({ input, id: `step-${state.nextStepNumber}`, createdAt: now, updatedAt: now });\n\tconst steps = [...state.steps.map(cloneTaskStep), step];\n\tif (step.status === \"in_progress\") demoteOtherActiveSteps(steps, steps.length - 1);\n\treturn { ...nextState(state, steps, now), nextStepNumber: state.nextStepNumber + 1 };\n}\n\nexport function resolveTaskStepSelector(steps: readonly TaskStep[], selector: string): TaskStep {\n\tconst normalized = selector.trim().toLocaleLowerCase();\n\tif (!normalized) throw new TaskStepsError(\"Task step selector is required.\");\n\tif (normalized === \"current\" || normalized === \"active\") {\n\t\tconst active = steps.find((step) => step.status === \"in_progress\");\n\t\tif (!active) throw new TaskStepsError(\"No in_progress task step was found.\");\n\t\treturn active;\n\t}\n\n\tconst exactId = steps.find((step) => step.id.toLocaleLowerCase() === normalized);\n\tif (exactId) return exactId;\n\tconst idPrefix = steps.filter((step) => step.id.toLocaleLowerCase().startsWith(normalized));\n\tif (idPrefix.length === 1) return idPrefix[0];\n\tif (idPrefix.length > 1) {\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${idPrefix.map((step) => step.id).join(\", \")}.`);\n\t}\n\n\tconst exactContent = steps.filter((step) => step.content.toLocaleLowerCase() === normalized);\n\tif (exactContent.length === 1) return exactContent[0];\n\tconst contentMatches = steps.filter((step) => step.content.toLocaleLowerCase().includes(normalized));\n\tif (contentMatches.length === 1) return contentMatches[0];\n\tif (exactContent.length > 1 || contentMatches.length > 1) {\n\t\tconst matches = exactContent.length > 1 ? exactContent : contentMatches;\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${matches.map((step) => step.id).join(\", \")}.`);\n\t}\n\tthrow new TaskStepsError(`Task step not found for selector: ${selector}.`);\n}\n\nexport function updateTaskStep(\n\tstate: TaskStepsState,\n\tselector: string,\n\tupdate: TaskStepUpdate,\n\tnow: string,\n): TaskStepsState {\n\tconst selected = resolveTaskStepSelector(state.steps, selector);\n\tconst selectedIndex = state.steps.findIndex((step) => step.id === selected.id);\n\tconst steps = state.steps.map(cloneTaskStep);\n\tconst current = steps[selectedIndex];\n\tconst note = optionalBoundedText(update.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst notes = note\n\t\t? appendUniqueStrings(current.notes, [note], \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH)\n\t\t: [...current.notes];\n\tconst evidence = appendUniqueStrings(\n\t\tcurrent.evidence,\n\t\tupdate.evidence,\n\t\t\"Task step evidence\",\n\t\tMAX_TASK_STEP_EVIDENCE_LENGTH,\n\t);\n\tsteps[selectedIndex] = {\n\t\t...current,\n\t\tcontent:\n\t\t\tupdate.content === undefined\n\t\t\t\t? current.content\n\t\t\t\t: requireBoundedText(update.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\tupdate.activeForm === undefined\n\t\t\t\t? current.activeForm\n\t\t\t\t: optionalBoundedText(update.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: update.status ?? current.status,\n\t\tpriority: update.priority ?? current.priority,\n\t\towner:\n\t\t\tupdate.owner === undefined\n\t\t\t\t? current.owner\n\t\t\t\t: optionalBoundedText(update.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tupdatedAt: now,\n\t};\n\tif (steps[selectedIndex].status === \"in_progress\") demoteOtherActiveSteps(steps, selectedIndex);\n\treturn nextState(state, steps, now);\n}\n\nexport function clearTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\treturn {\n\t\t...nextState(state, [], now),\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t};\n}\n\nexport function compactTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\tconst completed = state.steps.filter((step) => step.status === \"completed\").length;\n\tconst cancelled = state.steps.filter((step) => step.status === \"cancelled\").length;\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\treturn {\n\t\t...nextState(state, open, now),\n\t\tarchive: {\n\t\t\tcompleted: state.archive.completed + completed,\n\t\t\tcancelled: state.archive.cancelled + cancelled,\n\t\t\tcompactedAt: now,\n\t\t},\n\t};\n}\n\nexport function formatTaskSteps(\n\tstate: TaskStepsState,\n\toptions: { includeTerminal?: boolean; maxItems?: number } = {},\n): string {\n\tconst visible = options.includeTerminal\n\t\t? state.steps\n\t\t: state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tconst maxItems = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(options.maxItems ?? 20)));\n\tconst statusMarker: Record<TaskStepStatus, string> = {\n\t\tpending: \" \",\n\t\tin_progress: \">\",\n\t\tcompleted: \"x\",\n\t\tblocked: \"!\",\n\t\tcancelled: \"-\",\n\t};\n\tconst lines = [`Task steps (${visible.length} visible, ${state.steps.length} tracked):`];\n\tfor (const step of visible.slice(0, maxItems)) {\n\t\tconst details = [step.priority, step.owner].filter(Boolean).join(\", \");\n\t\tlines.push(\n\t\t\t`- [${statusMarker[step.status]}] ${step.id} ${step.activeForm || step.content}${details ? ` (${details})` : \"\"}`,\n\t\t);\n\t\tfor (const note of step.notes.slice(-2)) lines.push(` note: ${note}`);\n\t\tfor (const evidence of step.evidence.slice(-2)) lines.push(` evidence: ${evidence}`);\n\t}\n\tif (visible.length > maxItems) lines.push(`- … ${visible.length - maxItems} more`);\n\tif (state.archive.completed || state.archive.cancelled) {\n\t\tlines.push(\n\t\t\t`Archived terminal steps: ${state.archive.completed} completed, ${state.archive.cancelled} cancelled.`,\n\t\t);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatTaskStepsContext(state: TaskStepsState, maxItems = 12): string | undefined {\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tif (open.length === 0) return undefined;\n\tconst limit = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(maxItems)));\n\tconst lines = [\n\t\t\"Current native task_steps context for this session:\",\n\t\t\"Open task_steps:\",\n\t\t...open.slice(0, limit).map((step) => `- [${step.status}] ${step.activeForm || step.content}`),\n\t];\n\tif (open.length > limit) lines.push(`- … ${open.length - limit} more open step(s)`);\n\tconst active = open.find((step) => step.status === \"in_progress\");\n\tlines.push(\n\t\t\"\",\n\t\tactive\n\t\t\t? `Continue the in_progress step first: ${active.activeForm || active.content}. Update it completed, blocked, or cancelled as soon as evidence is known.`\n\t\t\t: `No step is in_progress. Start the first open step before unrelated work: ${open[0].activeForm || open[0].content}.`,\n\t\t\"Use task_steps to keep this checklist current and leave no stale in_progress step before the final response.\",\n\t);\n\treturn lines.join(\"\\n\");\n}\n\nexport function serializeTaskStepsState(state: TaskStepsState): string {\n\treturn JSON.stringify(cloneTaskStepsState(state), null, 2);\n}\n\nexport function parseTaskStepsState(text: string): TaskStepsState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\treturn isTaskStepsState(parsed) ? cloneTaskStepsState(parsed) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"task-state.js","sourceRoot":"","sources":["../../../src/core/tasks/task-state.ts"],"names":[],"mappings":"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","sourcesContent":["export const TASK_STEP_STATUSES = [\"pending\", \"in_progress\", \"completed\", \"blocked\", \"cancelled\"] as const;\nexport type TaskStepStatus = (typeof TASK_STEP_STATUSES)[number];\n\nexport const TASK_STEP_PRIORITIES = [\"low\", \"normal\", \"high\"] as const;\nexport type TaskStepPriority = (typeof TASK_STEP_PRIORITIES)[number];\n\nexport const MAX_TASK_STEPS = 100;\nexport const MAX_TASK_STEP_CONTENT_LENGTH = 2_000;\nconst MAX_TASK_STEP_NOTE_LENGTH = 4_000;\nconst MAX_TASK_STEP_OWNER_LENGTH = 200;\nconst MAX_TASK_STEP_EVIDENCE = 32;\nconst MAX_TASK_STEP_EVIDENCE_LENGTH = 2_000;\n\nexport interface TaskStepInput {\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tnotes?: readonly string[];\n\tevidence?: readonly string[];\n}\n\nexport interface TaskStep {\n\tid: string;\n\tcontent: string;\n\tactiveForm?: string;\n\tstatus: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnotes: readonly string[];\n\tevidence: readonly string[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepsArchive {\n\tcompleted: number;\n\tcancelled: number;\n\tcompactedAt?: string;\n}\n\nexport interface TaskStepsState {\n\tversion: 1;\n\trevision: number;\n\tnextStepNumber: number;\n\tsteps: readonly TaskStep[];\n\tarchive: TaskStepsArchive;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface TaskStepUpdate {\n\tcontent?: string;\n\tactiveForm?: string;\n\tstatus?: TaskStepStatus;\n\tpriority?: TaskStepPriority;\n\towner?: string;\n\tnote?: string;\n\tevidence?: readonly string[];\n}\n\nexport class TaskStepsError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"TaskStepsError\";\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isTaskStepStatus(value: unknown): value is TaskStepStatus {\n\treturn TASK_STEP_STATUSES.some((status) => status === value);\n}\n\nfunction isTaskStepPriority(value: unknown): value is TaskStepPriority {\n\treturn TASK_STEP_PRIORITIES.some((priority) => priority === value);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string, maxLength: number): boolean {\n\tconst value = record[key];\n\treturn value === undefined || (typeof value === \"string\" && value.length <= maxLength);\n}\n\nfunction isBoundedStringArray(value: unknown, maxItems: number, maxLength: number): value is readonly string[] {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length <= maxItems &&\n\t\tvalue.every((item) => typeof item === \"string\" && item.length > 0 && item.length <= maxLength)\n\t);\n}\n\nfunction isTaskStep(value: unknown): value is TaskStep {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\t/^step-[1-9]\\d*$/.test(value.id) &&\n\t\ttypeof value.content === \"string\" &&\n\t\tvalue.content.length > 0 &&\n\t\tvalue.content.length <= MAX_TASK_STEP_CONTENT_LENGTH &&\n\t\thasOptionalString(value, \"activeForm\", MAX_TASK_STEP_CONTENT_LENGTH) &&\n\t\tisTaskStepStatus(value.status) &&\n\t\t(value.priority === undefined || isTaskStepPriority(value.priority)) &&\n\t\thasOptionalString(value, \"owner\", MAX_TASK_STEP_OWNER_LENGTH) &&\n\t\tisBoundedStringArray(value.notes, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_NOTE_LENGTH) &&\n\t\tisBoundedStringArray(value.evidence, MAX_TASK_STEP_EVIDENCE, MAX_TASK_STEP_EVIDENCE_LENGTH) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\"\n\t);\n}\n\nfunction isTaskStepsArchive(value: unknown): value is TaskStepsArchive {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\tNumber.isInteger(value.completed) &&\n\t\tNumber(value.completed) >= 0 &&\n\t\tNumber.isInteger(value.cancelled) &&\n\t\tNumber(value.cancelled) >= 0 &&\n\t\thasOptionalString(value, \"compactedAt\", 100)\n\t);\n}\n\nexport function isTaskStepsState(value: unknown): value is TaskStepsState {\n\tif (!isRecord(value)) return false;\n\tif (\n\t\tvalue.version !== 1 ||\n\t\t!Number.isInteger(value.revision) ||\n\t\tNumber(value.revision) < 0 ||\n\t\t!Number.isInteger(value.nextStepNumber) ||\n\t\tNumber(value.nextStepNumber) < 1 ||\n\t\t!Array.isArray(value.steps) ||\n\t\tvalue.steps.length > MAX_TASK_STEPS ||\n\t\t!value.steps.every(isTaskStep) ||\n\t\t!isTaskStepsArchive(value.archive) ||\n\t\ttypeof value.createdAt !== \"string\" ||\n\t\ttypeof value.updatedAt !== \"string\"\n\t) {\n\t\treturn false;\n\t}\n\tconst ids = new Set(value.steps.map((step) => step.id));\n\treturn ids.size === value.steps.length && value.steps.filter((step) => step.status === \"in_progress\").length <= 1;\n}\n\nfunction cloneTaskStep(step: TaskStep): TaskStep {\n\treturn { ...step, notes: [...step.notes], evidence: [...step.evidence] };\n}\n\nexport function cloneTaskStepsState(state: TaskStepsState): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\tsteps: state.steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t};\n}\n\nexport function createTaskStepsState(now: string): TaskStepsState {\n\treturn {\n\t\tversion: 1,\n\t\trevision: 0,\n\t\tnextStepNumber: 1,\n\t\tsteps: [],\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction requireBoundedText(value: string, label: string, maxLength: number): string {\n\tconst normalized = value.trim();\n\tif (!normalized) throw new TaskStepsError(`${label} is required.`);\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction optionalBoundedText(value: string | undefined, label: string, maxLength: number): string | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = value.trim();\n\tif (!normalized) return undefined;\n\tif (normalized.length > maxLength) throw new TaskStepsError(`${label} must be at most ${maxLength} characters.`);\n\treturn normalized;\n}\n\nfunction normalizeStrings(values: readonly string[] | undefined, label: string, maxLength: number): string[] {\n\tif (!values) return [];\n\tconst normalized: string[] = [];\n\tfor (const value of values) {\n\t\tconst item = requireBoundedText(value, label, maxLength);\n\t\tif (!normalized.includes(item)) normalized.push(item);\n\t}\n\tif (normalized.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn normalized;\n}\n\nfunction appendUniqueStrings(\n\tcurrent: readonly string[],\n\tvalues: readonly string[] | undefined,\n\tlabel: string,\n\tmaxLength: number,\n): string[] {\n\tconst appended = [...current];\n\tfor (const value of normalizeStrings(values, label, maxLength)) {\n\t\tif (!appended.includes(value)) appended.push(value);\n\t}\n\tif (appended.length > MAX_TASK_STEP_EVIDENCE) {\n\t\tthrow new TaskStepsError(`${label} supports at most ${MAX_TASK_STEP_EVIDENCE} entries.`);\n\t}\n\treturn appended;\n}\n\nfunction normalizeInputNotes(input: TaskStepInput): string[] {\n\tconst notes = normalizeStrings(input.notes, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst note = optionalBoundedText(input.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tif (note && !notes.includes(note)) notes.push(note);\n\treturn notes;\n}\n\n/**\n * Find an OPEN (non-terminal) step whose content matches `content` case-insensitively.\n * Terminal steps (completed/cancelled) are deliberately excluded so a legitimate re-add of\n * previously finished work still creates a new step.\n */\nexport function findOpenDuplicateStep(steps: readonly TaskStep[], content: string): TaskStep | undefined {\n\tconst normalized = content.trim().toLocaleLowerCase();\n\tif (!normalized) return undefined;\n\treturn steps.find(\n\t\t(step) =>\n\t\t\tstep.status !== \"completed\" && step.status !== \"cancelled\" && step.content.toLocaleLowerCase() === normalized,\n\t);\n}\n\n/** True when a completed step has no evidence attached (a verification nudge candidate). */\nexport function hasUnverifiedCompletedStep(state: TaskStepsState): boolean {\n\treturn state.steps.some((step) => step.status === \"completed\" && step.evidence.length === 0);\n}\n\nfunction demoteOtherActiveSteps(steps: TaskStep[], activeIndex: number): void {\n\tfor (let index = 0; index < steps.length; index++) {\n\t\tif (index !== activeIndex && steps[index].status === \"in_progress\") {\n\t\t\tsteps[index] = { ...steps[index], status: \"pending\" };\n\t\t}\n\t}\n}\n\nfunction nextState(state: TaskStepsState, steps: readonly TaskStep[], now: string): TaskStepsState {\n\treturn {\n\t\t...state,\n\t\trevision: state.revision + 1,\n\t\tsteps: steps.map(cloneTaskStep),\n\t\tarchive: { ...state.archive },\n\t\tupdatedAt: now,\n\t};\n}\n\nfunction createStep(args: {\n\tinput: TaskStepInput;\n\tid: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\texisting?: TaskStep;\n}): TaskStep {\n\tconst existing = args.existing;\n\tconst notes =\n\t\targs.input.note === undefined && args.input.notes === undefined\n\t\t\t? [...(existing?.notes ?? [])]\n\t\t\t: normalizeInputNotes(args.input);\n\tconst evidence =\n\t\targs.input.evidence === undefined\n\t\t\t? [...(existing?.evidence ?? [])]\n\t\t\t: normalizeStrings(args.input.evidence, \"Task step evidence\", MAX_TASK_STEP_EVIDENCE_LENGTH);\n\treturn {\n\t\tid: args.id,\n\t\tcontent: requireBoundedText(args.input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\targs.input.activeForm === undefined\n\t\t\t\t? existing?.activeForm\n\t\t\t\t: optionalBoundedText(args.input.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: args.input.status ?? existing?.status ?? \"pending\",\n\t\tpriority: args.input.priority ?? existing?.priority,\n\t\towner:\n\t\t\targs.input.owner === undefined\n\t\t\t\t? existing?.owner\n\t\t\t\t: optionalBoundedText(args.input.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tcreatedAt: args.createdAt,\n\t\tupdatedAt: args.updatedAt,\n\t};\n}\n\nexport function setTaskSteps(state: TaskStepsState, inputs: readonly TaskStepInput[], now: string): TaskStepsState {\n\tif (inputs.length > MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps supports at most ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst existingByContent = new Map<string, TaskStep[]>();\n\tfor (const step of state.steps) {\n\t\tconst key = step.content.toLocaleLowerCase();\n\t\tconst matches = existingByContent.get(key) ?? [];\n\t\tmatches.push(step);\n\t\texistingByContent.set(key, matches);\n\t}\n\n\tlet nextStepNumber = state.nextStepNumber;\n\tconst steps = inputs.map((input) => {\n\t\tconst content = requireBoundedText(input.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH);\n\t\tconst matches = existingByContent.get(content.toLocaleLowerCase());\n\t\tconst existing = matches?.shift();\n\t\tconst id = existing?.id ?? `step-${nextStepNumber++}`;\n\t\treturn createStep({\n\t\t\tinput: { ...input, content },\n\t\t\tid,\n\t\t\tcreatedAt: existing?.createdAt ?? now,\n\t\t\tupdatedAt: now,\n\t\t\texisting,\n\t\t});\n\t});\n\tconst activeIndex = steps.findLastIndex((step) => step.status === \"in_progress\");\n\tif (activeIndex >= 0) demoteOtherActiveSteps(steps, activeIndex);\n\treturn { ...nextState(state, steps, now), nextStepNumber };\n}\n\nexport function addTaskStep(state: TaskStepsState, input: TaskStepInput, now: string): TaskStepsState {\n\t// Dedupe against OPEN steps only, before the capacity check: a duplicate re-add of an\n\t// already-open step is a no-op regardless of whether the list happens to be full. Terminal\n\t// (completed/cancelled) matches are excluded so a legitimate re-add still creates a step.\n\tif (findOpenDuplicateStep(state.steps, input.content)) return state;\n\tif (state.steps.length >= MAX_TASK_STEPS) {\n\t\tthrow new TaskStepsError(`Task steps already has the maximum ${MAX_TASK_STEPS} steps.`);\n\t}\n\tconst step = createStep({ input, id: `step-${state.nextStepNumber}`, createdAt: now, updatedAt: now });\n\tconst steps = [...state.steps.map(cloneTaskStep), step];\n\tif (step.status === \"in_progress\") demoteOtherActiveSteps(steps, steps.length - 1);\n\treturn { ...nextState(state, steps, now), nextStepNumber: state.nextStepNumber + 1 };\n}\n\nexport function resolveTaskStepSelector(steps: readonly TaskStep[], selector: string): TaskStep {\n\tconst normalized = selector.trim().toLocaleLowerCase();\n\tif (!normalized) throw new TaskStepsError(\"Task step selector is required.\");\n\tif (normalized === \"current\" || normalized === \"active\") {\n\t\tconst active = steps.find((step) => step.status === \"in_progress\");\n\t\tif (!active) throw new TaskStepsError(\"No in_progress task step was found.\");\n\t\treturn active;\n\t}\n\n\tconst exactId = steps.find((step) => step.id.toLocaleLowerCase() === normalized);\n\tif (exactId) return exactId;\n\tconst idPrefix = steps.filter((step) => step.id.toLocaleLowerCase().startsWith(normalized));\n\tif (idPrefix.length === 1) return idPrefix[0];\n\tif (idPrefix.length > 1) {\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${idPrefix.map((step) => step.id).join(\", \")}.`);\n\t}\n\n\tconst exactContent = steps.filter((step) => step.content.toLocaleLowerCase() === normalized);\n\tif (exactContent.length === 1) return exactContent[0];\n\tconst contentMatches = steps.filter((step) => step.content.toLocaleLowerCase().includes(normalized));\n\tif (contentMatches.length === 1) return contentMatches[0];\n\tif (exactContent.length > 1 || contentMatches.length > 1) {\n\t\tconst matches = exactContent.length > 1 ? exactContent : contentMatches;\n\t\tthrow new TaskStepsError(`Task step selector is ambiguous: ${matches.map((step) => step.id).join(\", \")}.`);\n\t}\n\tthrow new TaskStepsError(`Task step not found for selector: ${selector}.`);\n}\n\nexport function updateTaskStep(\n\tstate: TaskStepsState,\n\tselector: string,\n\tupdate: TaskStepUpdate,\n\tnow: string,\n): TaskStepsState {\n\tconst selected = resolveTaskStepSelector(state.steps, selector);\n\tconst selectedIndex = state.steps.findIndex((step) => step.id === selected.id);\n\tconst steps = state.steps.map(cloneTaskStep);\n\tconst current = steps[selectedIndex];\n\tconst note = optionalBoundedText(update.note, \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH);\n\tconst notes = note\n\t\t? appendUniqueStrings(current.notes, [note], \"Task step note\", MAX_TASK_STEP_NOTE_LENGTH)\n\t\t: [...current.notes];\n\tconst evidence = appendUniqueStrings(\n\t\tcurrent.evidence,\n\t\tupdate.evidence,\n\t\t\"Task step evidence\",\n\t\tMAX_TASK_STEP_EVIDENCE_LENGTH,\n\t);\n\tsteps[selectedIndex] = {\n\t\t...current,\n\t\tcontent:\n\t\t\tupdate.content === undefined\n\t\t\t\t? current.content\n\t\t\t\t: requireBoundedText(update.content, \"Task step content\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tactiveForm:\n\t\t\tupdate.activeForm === undefined\n\t\t\t\t? current.activeForm\n\t\t\t\t: optionalBoundedText(update.activeForm, \"Task step active form\", MAX_TASK_STEP_CONTENT_LENGTH),\n\t\tstatus: update.status ?? current.status,\n\t\tpriority: update.priority ?? current.priority,\n\t\towner:\n\t\t\tupdate.owner === undefined\n\t\t\t\t? current.owner\n\t\t\t\t: optionalBoundedText(update.owner, \"Task step owner\", MAX_TASK_STEP_OWNER_LENGTH),\n\t\tnotes,\n\t\tevidence,\n\t\tupdatedAt: now,\n\t};\n\tif (steps[selectedIndex].status === \"in_progress\") demoteOtherActiveSteps(steps, selectedIndex);\n\treturn nextState(state, steps, now);\n}\n\nexport function clearTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\treturn {\n\t\t...nextState(state, [], now),\n\t\tarchive: { completed: 0, cancelled: 0 },\n\t};\n}\n\nexport function compactTaskSteps(state: TaskStepsState, now: string): TaskStepsState {\n\tconst completed = state.steps.filter((step) => step.status === \"completed\").length;\n\tconst cancelled = state.steps.filter((step) => step.status === \"cancelled\").length;\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\treturn {\n\t\t...nextState(state, open, now),\n\t\tarchive: {\n\t\t\tcompleted: state.archive.completed + completed,\n\t\t\tcancelled: state.archive.cancelled + cancelled,\n\t\t\tcompactedAt: now,\n\t\t},\n\t};\n}\n\nexport function formatTaskSteps(\n\tstate: TaskStepsState,\n\toptions: { includeTerminal?: boolean; maxItems?: number } = {},\n): string {\n\tconst visible = options.includeTerminal\n\t\t? state.steps\n\t\t: state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tconst maxItems = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(options.maxItems ?? 20)));\n\tconst statusMarker: Record<TaskStepStatus, string> = {\n\t\tpending: \" \",\n\t\tin_progress: \">\",\n\t\tcompleted: \"x\",\n\t\tblocked: \"!\",\n\t\tcancelled: \"-\",\n\t};\n\tconst lines = [`Task steps (${visible.length} visible, ${state.steps.length} tracked):`];\n\tfor (const step of visible.slice(0, maxItems)) {\n\t\tconst details = [step.priority, step.owner].filter(Boolean).join(\", \");\n\t\tlines.push(\n\t\t\t`- [${statusMarker[step.status]}] ${step.id} ${step.activeForm || step.content}${details ? ` (${details})` : \"\"}`,\n\t\t);\n\t\tfor (const note of step.notes.slice(-2)) lines.push(` note: ${note}`);\n\t\tfor (const evidence of step.evidence.slice(-2)) lines.push(` evidence: ${evidence}`);\n\t}\n\tif (visible.length > maxItems) lines.push(`- … ${visible.length - maxItems} more`);\n\tif (state.archive.completed || state.archive.cancelled) {\n\t\tlines.push(\n\t\t\t`Archived terminal steps: ${state.archive.completed} completed, ${state.archive.cancelled} cancelled.`,\n\t\t);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatTaskStepsContext(state: TaskStepsState, maxItems = 12): string | undefined {\n\tconst open = state.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\");\n\tif (open.length === 0) return undefined;\n\tconst limit = Math.max(1, Math.min(MAX_TASK_STEPS, Math.floor(maxItems)));\n\tconst lines = [\n\t\t\"Current native task_steps context for this session:\",\n\t\t\"Open task_steps:\",\n\t\t...open.slice(0, limit).map((step) => `- [${step.status}] ${step.activeForm || step.content}`),\n\t];\n\tif (open.length > limit) lines.push(`- … ${open.length - limit} more open step(s)`);\n\tconst active = open.find((step) => step.status === \"in_progress\");\n\tlines.push(\n\t\t\"\",\n\t\tactive\n\t\t\t? `Continue the in_progress step first: ${active.activeForm || active.content}. Update it completed, blocked, or cancelled as soon as evidence is known.`\n\t\t\t: `No step is in_progress. Start the first open step before unrelated work: ${open[0].activeForm || open[0].content}.`,\n\t\t\"Use task_steps to keep this checklist current and leave no stale in_progress step before the final response.\",\n\t);\n\tif (hasUnverifiedCompletedStep(state)) {\n\t\tlines.push(\n\t\t\t\"A completed step has no evidence attached; attach evidence via task_steps update before treating it as verified.\",\n\t\t);\n\t}\n\t// Wrapped in a marker (mirrors the <memory_context> precedent) so context-gc's\n\t// semantic-memory packer can recognize this as a deterministic, re-derivable context page and\n\t// pack stale copies down to the most recent one instead of letting a full page accumulate every\n\t// turn. The revision (monotonic per mutation) lets a reader tell which page is current.\n\treturn `<task_steps_context revision=${state.revision}>\\n${lines.join(\"\\n\")}\\n</task_steps_context>`;\n}\n\nexport function serializeTaskStepsState(state: TaskStepsState): string {\n\treturn JSON.stringify(cloneTaskStepsState(state), null, 2);\n}\n\nexport function parseTaskStepsState(text: string): TaskStepsState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\treturn isTaskStepsState(parsed) ? cloneTaskStepsState(parsed) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-gate-controller.d.ts","sourceRoot":"","sources":["../../src/core/tool-gate-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAwB,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AAE7F,KAAK,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC3D,KAAK,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACtC,oFAAoF;IACpF,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACpG,MAAM,IAAI,MAAM,CAAC;IACjB,iGAA+F;IAC/F,qBAAqB,IAAI,kBAAkB,GAAG,SAAS,CAAC;IACxD,mFAAmF;IACnF,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9C,kBAAkB,IAAI,eAAe,CAAC;IACtC,4FAA4F;IAC5F,0BAA0B,CAAC,IAAI,uBAAuB,GAAG,SAAS,CAAC;CACnE;AAED,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAE9C,YAAY,IAAI,EAAE,sBAAsB,EAEvC;IAED,QAAQ,CAAC,cAAc,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"tool-gate-controller.d.ts","sourceRoot":"","sources":["../../src/core/tool-gate-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAwB,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AAE7F,KAAK,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC3D,KAAK,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACtC,oFAAoF;IACpF,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACpG,MAAM,IAAI,MAAM,CAAC;IACjB,iGAA+F;IAC/F,qBAAqB,IAAI,kBAAkB,GAAG,SAAS,CAAC;IACxD,mFAAmF;IACnF,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9C,kBAAkB,IAAI,eAAe,CAAC;IACtC,4FAA4F;IAC5F,0BAA0B,CAAC,IAAI,uBAAuB,GAAG,SAAS,CAAC;CACnE;AAED,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAE9C,YAAY,IAAI,EAAE,sBAAsB,EAEvC;IAED,QAAQ,CAAC,cAAc,EAAE,cAAc,CAmDrC;IAEF,QAAQ,CAAC,aAAa,EAAE,aAAa,CAuCnC;CACF","sourcesContent":["/**\n * Agent tool-call gate: model-router escalation, autonomy gating, extension tool hooks, and the\n * untrusted-content output boundary.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Provides the two agent-core\n * hooks (`beforeToolCall`/`afterToolCall`) as bound arrow-field members the session installs onto its\n * agent. `beforeToolCall` runs the router escalation, then the autonomy tool gate (recording the\n * outcome when a capability envelope is active), then extension `tool_call` handlers. `afterToolCall`\n * runs extension `tool_result` handlers and structurally fences output from untrusted-content sources.\n */\n\nimport type { Agent, BeforeToolCallResult } from \"@caupulican/pi-agent-core\";\nimport type { CapabilityEnvelope, GateOutcome } from \"./autonomy/contracts.ts\";\nimport { evaluateToolGate } from \"./autonomy/gates.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport { classifyToolTrust, wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { ToolSelectionController } from \"./tool-selection/tool-selection-controller.ts\";\n\ntype BeforeToolCall = NonNullable<Agent[\"beforeToolCall\"]>;\ntype AfterToolCall = NonNullable<Agent[\"afterToolCall\"]>;\n\nexport interface ToolGateControllerDeps {\n\t/** Router escalation: block a tool the active cheap route is not allowed to run. */\n\tmaybeEscalateToolCall(toolName: string, args: unknown): { block: true; reason: string } | undefined;\n\tgetCwd(): string;\n\t/** Active foreground capability envelope, if any — presence enables gate-outcome recording. */\n\tgetCapabilityEnvelope(): CapabilityEnvelope | undefined;\n\t/** Record an autonomy gate outcome (only when a capability envelope is active). */\n\trecordGateOutcome(outcome: GateOutcome): void;\n\tgetExtensionRunner(): ExtensionRunner;\n\t/** Observe an execution only after all pre-execution gates and extension hooks allow it. */\n\tgetToolSelectionController?(): ToolSelectionController | undefined;\n}\n\nexport class ToolGateController {\n\tprivate readonly deps: ToolGateControllerDeps;\n\n\tconstructor(deps: ToolGateControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\treadonly beforeToolCall: BeforeToolCall = async ({ toolCall, args }) => {\n\t\tconst escalation = this.deps.maybeEscalateToolCall(toolCall.name, args);\n\t\tif (escalation) {\n\t\t\treturn escalation;\n\t\t}\n\n\t\t// Autonomy tool gating\n\t\tconst envelope = this.deps.getCapabilityEnvelope();\n\t\tconst gateResult = evaluateToolGate({\n\t\t\ttoolName: toolCall.name,\n\t\t\targs,\n\t\t\tcwd: this.deps.getCwd(),\n\t\t\tenvelope,\n\t\t});\n\n\t\tif (envelope) {\n\t\t\tthis.deps.recordGateOutcome(gateResult);\n\t\t}\n\n\t\tif (gateResult.outcome === \"block\" || gateResult.outcome === \"ask-user\") {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\treason: `Tool execution blocked by autonomy gate [${gateResult.gate}]: ${gateResult.message} (${gateResult.reasonCode})`,\n\t\t\t};\n\t\t}\n\n\t\tconst runner = this.deps.getExtensionRunner();\n\t\tlet extensionResult: BeforeToolCallResult | undefined;\n\t\tif (runner.hasHandlers(\"tool_call\")) {\n\t\t\ttry {\n\t\t\t\textensionResult = await runner.emitToolCall({\n\t\t\t\t\ttype: \"tool_call\",\n\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error) {\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Extension failed, blocking execution: ${String(err)}`);\n\t\t\t}\n\t\t}\n\t\tif (extensionResult) return extensionResult;\n\t\t// begin()'s return value is intentionally unused here: it tracks the pending observation\n\t\t// internally (keyed by toolCall.id) and afterToolCall's complete() call below retrieves it\n\t\t// from there, records observe-mode agreement/hint-efficacy stats, and feeds the durable\n\t\t// evidence-gated promotion surfaced in system-prompt-builder.ts and getReport(). This is\n\t\t// a side-effecting call, not a discarded decision.\n\t\tthis.deps.getToolSelectionController?.()?.begin(toolCall.id, toolCall.name, args);\n\t\treturn undefined;\n\t};\n\n\treadonly afterToolCall: AfterToolCall = async ({ toolCall, args, result, isError }) => {\n\t\tconst runner = this.deps.getExtensionRunner();\n\t\tlet content = result.content;\n\t\tlet details = result.details;\n\t\tlet resolvedIsError = isError;\n\n\t\tif (runner.hasHandlers(\"tool_result\")) {\n\t\t\tconst hookResult = await runner.emitToolResult({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttoolName: toolCall.name,\n\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\tcontent,\n\t\t\t\tdetails,\n\t\t\t\tisError,\n\t\t\t});\n\t\t\tif (hookResult) {\n\t\t\t\tcontent = hookResult.content ?? content;\n\t\t\t\tdetails = hookResult.details;\n\t\t\t\tresolvedIsError = hookResult.isError ?? isError;\n\t\t\t}\n\t\t}\n\n\t\t// Untrusted-content boundary: structurally fence output from attacker-controllable sources\n\t\t// (web/search, subagents, recall, third-party tools) so injection payloads are framed as data.\n\t\t// First-party tools (read/grep/find/ls/edit/write/bash) are trusted and pass through unchanged.\n\t\tif (classifyToolTrust(toolCall.name) === \"untrusted\") {\n\t\t\tconst source = `tool:${toolCall.name}`;\n\t\t\tconst wrapped = content.map((block) =>\n\t\t\t\tblock.type === \"text\" ? { ...block, text: wrapUntrustedText(block.text, source) } : block,\n\t\t\t);\n\t\t\tcontent = wrapped;\n\t\t}\n\n\t\tthis.deps.getToolSelectionController?.()?.complete(toolCall.id, !resolvedIsError, content);\n\t\tif (content === result.content && details === result.details && resolvedIsError === isError) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn { content, details, isError: resolvedIsError };\n\t};\n}\n"]}
|
|
@@ -57,6 +57,11 @@ export class ToolGateController {
|
|
|
57
57
|
}
|
|
58
58
|
if (extensionResult)
|
|
59
59
|
return extensionResult;
|
|
60
|
+
// begin()'s return value is intentionally unused here: it tracks the pending observation
|
|
61
|
+
// internally (keyed by toolCall.id) and afterToolCall's complete() call below retrieves it
|
|
62
|
+
// from there, records observe-mode agreement/hint-efficacy stats, and feeds the durable
|
|
63
|
+
// evidence-gated promotion surfaced in system-prompt-builder.ts and getReport(). This is
|
|
64
|
+
// a side-effecting call, not a discarded decision.
|
|
60
65
|
this.deps.getToolSelectionController?.()?.begin(toolCall.id, toolCall.name, args);
|
|
61
66
|
return undefined;
|
|
62
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-gate-controller.js","sourceRoot":"","sources":["../../src/core/tool-gate-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Agent tool-call gate: model-router escalation, autonomy gating, extension tool hooks, and the\n * untrusted-content output boundary.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Provides the two agent-core\n * hooks (`beforeToolCall`/`afterToolCall`) as bound arrow-field members the session installs onto its\n * agent. `beforeToolCall` runs the router escalation, then the autonomy tool gate (recording the\n * outcome when a capability envelope is active), then extension `tool_call` handlers. `afterToolCall`\n * runs extension `tool_result` handlers and structurally fences output from untrusted-content sources.\n */\n\nimport type { Agent, BeforeToolCallResult } from \"@caupulican/pi-agent-core\";\nimport type { CapabilityEnvelope, GateOutcome } from \"./autonomy/contracts.ts\";\nimport { evaluateToolGate } from \"./autonomy/gates.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport { classifyToolTrust, wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { ToolSelectionController } from \"./tool-selection/tool-selection-controller.ts\";\n\ntype BeforeToolCall = NonNullable<Agent[\"beforeToolCall\"]>;\ntype AfterToolCall = NonNullable<Agent[\"afterToolCall\"]>;\n\nexport interface ToolGateControllerDeps {\n\t/** Router escalation: block a tool the active cheap route is not allowed to run. */\n\tmaybeEscalateToolCall(toolName: string, args: unknown): { block: true; reason: string } | undefined;\n\tgetCwd(): string;\n\t/** Active foreground capability envelope, if any — presence enables gate-outcome recording. */\n\tgetCapabilityEnvelope(): CapabilityEnvelope | undefined;\n\t/** Record an autonomy gate outcome (only when a capability envelope is active). */\n\trecordGateOutcome(outcome: GateOutcome): void;\n\tgetExtensionRunner(): ExtensionRunner;\n\t/** Observe an execution only after all pre-execution gates and extension hooks allow it. */\n\tgetToolSelectionController?(): ToolSelectionController | undefined;\n}\n\nexport class ToolGateController {\n\tprivate readonly deps: ToolGateControllerDeps;\n\n\tconstructor(deps: ToolGateControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\treadonly beforeToolCall: BeforeToolCall = async ({ toolCall, args }) => {\n\t\tconst escalation = this.deps.maybeEscalateToolCall(toolCall.name, args);\n\t\tif (escalation) {\n\t\t\treturn escalation;\n\t\t}\n\n\t\t// Autonomy tool gating\n\t\tconst envelope = this.deps.getCapabilityEnvelope();\n\t\tconst gateResult = evaluateToolGate({\n\t\t\ttoolName: toolCall.name,\n\t\t\targs,\n\t\t\tcwd: this.deps.getCwd(),\n\t\t\tenvelope,\n\t\t});\n\n\t\tif (envelope) {\n\t\t\tthis.deps.recordGateOutcome(gateResult);\n\t\t}\n\n\t\tif (gateResult.outcome === \"block\" || gateResult.outcome === \"ask-user\") {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\treason: `Tool execution blocked by autonomy gate [${gateResult.gate}]: ${gateResult.message} (${gateResult.reasonCode})`,\n\t\t\t};\n\t\t}\n\n\t\tconst runner = this.deps.getExtensionRunner();\n\t\tlet extensionResult: BeforeToolCallResult | undefined;\n\t\tif (runner.hasHandlers(\"tool_call\")) {\n\t\t\ttry {\n\t\t\t\textensionResult = await runner.emitToolCall({\n\t\t\t\t\ttype: \"tool_call\",\n\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error) {\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Extension failed, blocking execution: ${String(err)}`);\n\t\t\t}\n\t\t}\n\t\tif (extensionResult) return extensionResult;\n\t\tthis.deps.getToolSelectionController?.()?.begin(toolCall.id, toolCall.name, args);\n\t\treturn undefined;\n\t};\n\n\treadonly afterToolCall: AfterToolCall = async ({ toolCall, args, result, isError }) => {\n\t\tconst runner = this.deps.getExtensionRunner();\n\t\tlet content = result.content;\n\t\tlet details = result.details;\n\t\tlet resolvedIsError = isError;\n\n\t\tif (runner.hasHandlers(\"tool_result\")) {\n\t\t\tconst hookResult = await runner.emitToolResult({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttoolName: toolCall.name,\n\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\tcontent,\n\t\t\t\tdetails,\n\t\t\t\tisError,\n\t\t\t});\n\t\t\tif (hookResult) {\n\t\t\t\tcontent = hookResult.content ?? content;\n\t\t\t\tdetails = hookResult.details;\n\t\t\t\tresolvedIsError = hookResult.isError ?? isError;\n\t\t\t}\n\t\t}\n\n\t\t// Untrusted-content boundary: structurally fence output from attacker-controllable sources\n\t\t// (web/search, subagents, recall, third-party tools) so injection payloads are framed as data.\n\t\t// First-party tools (read/grep/find/ls/edit/write/bash) are trusted and pass through unchanged.\n\t\tif (classifyToolTrust(toolCall.name) === \"untrusted\") {\n\t\t\tconst source = `tool:${toolCall.name}`;\n\t\t\tconst wrapped = content.map((block) =>\n\t\t\t\tblock.type === \"text\" ? { ...block, text: wrapUntrustedText(block.text, source) } : block,\n\t\t\t);\n\t\t\tcontent = wrapped;\n\t\t}\n\n\t\tthis.deps.getToolSelectionController?.()?.complete(toolCall.id, !resolvedIsError, content);\n\t\tif (content === result.content && details === result.details && resolvedIsError === isError) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn { content, details, isError: resolvedIsError };\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool-gate-controller.js","sourceRoot":"","sources":["../../src/core/tool-gate-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Agent tool-call gate: model-router escalation, autonomy gating, extension tool hooks, and the\n * untrusted-content output boundary.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Provides the two agent-core\n * hooks (`beforeToolCall`/`afterToolCall`) as bound arrow-field members the session installs onto its\n * agent. `beforeToolCall` runs the router escalation, then the autonomy tool gate (recording the\n * outcome when a capability envelope is active), then extension `tool_call` handlers. `afterToolCall`\n * runs extension `tool_result` handlers and structurally fences output from untrusted-content sources.\n */\n\nimport type { Agent, BeforeToolCallResult } from \"@caupulican/pi-agent-core\";\nimport type { CapabilityEnvelope, GateOutcome } from \"./autonomy/contracts.ts\";\nimport { evaluateToolGate } from \"./autonomy/gates.ts\";\nimport type { ExtensionRunner } from \"./extensions/index.ts\";\nimport { classifyToolTrust, wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { ToolSelectionController } from \"./tool-selection/tool-selection-controller.ts\";\n\ntype BeforeToolCall = NonNullable<Agent[\"beforeToolCall\"]>;\ntype AfterToolCall = NonNullable<Agent[\"afterToolCall\"]>;\n\nexport interface ToolGateControllerDeps {\n\t/** Router escalation: block a tool the active cheap route is not allowed to run. */\n\tmaybeEscalateToolCall(toolName: string, args: unknown): { block: true; reason: string } | undefined;\n\tgetCwd(): string;\n\t/** Active foreground capability envelope, if any — presence enables gate-outcome recording. */\n\tgetCapabilityEnvelope(): CapabilityEnvelope | undefined;\n\t/** Record an autonomy gate outcome (only when a capability envelope is active). */\n\trecordGateOutcome(outcome: GateOutcome): void;\n\tgetExtensionRunner(): ExtensionRunner;\n\t/** Observe an execution only after all pre-execution gates and extension hooks allow it. */\n\tgetToolSelectionController?(): ToolSelectionController | undefined;\n}\n\nexport class ToolGateController {\n\tprivate readonly deps: ToolGateControllerDeps;\n\n\tconstructor(deps: ToolGateControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\treadonly beforeToolCall: BeforeToolCall = async ({ toolCall, args }) => {\n\t\tconst escalation = this.deps.maybeEscalateToolCall(toolCall.name, args);\n\t\tif (escalation) {\n\t\t\treturn escalation;\n\t\t}\n\n\t\t// Autonomy tool gating\n\t\tconst envelope = this.deps.getCapabilityEnvelope();\n\t\tconst gateResult = evaluateToolGate({\n\t\t\ttoolName: toolCall.name,\n\t\t\targs,\n\t\t\tcwd: this.deps.getCwd(),\n\t\t\tenvelope,\n\t\t});\n\n\t\tif (envelope) {\n\t\t\tthis.deps.recordGateOutcome(gateResult);\n\t\t}\n\n\t\tif (gateResult.outcome === \"block\" || gateResult.outcome === \"ask-user\") {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\treason: `Tool execution blocked by autonomy gate [${gateResult.gate}]: ${gateResult.message} (${gateResult.reasonCode})`,\n\t\t\t};\n\t\t}\n\n\t\tconst runner = this.deps.getExtensionRunner();\n\t\tlet extensionResult: BeforeToolCallResult | undefined;\n\t\tif (runner.hasHandlers(\"tool_call\")) {\n\t\t\ttry {\n\t\t\t\textensionResult = await runner.emitToolCall({\n\t\t\t\t\ttype: \"tool_call\",\n\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error) {\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Extension failed, blocking execution: ${String(err)}`);\n\t\t\t}\n\t\t}\n\t\tif (extensionResult) return extensionResult;\n\t\t// begin()'s return value is intentionally unused here: it tracks the pending observation\n\t\t// internally (keyed by toolCall.id) and afterToolCall's complete() call below retrieves it\n\t\t// from there, records observe-mode agreement/hint-efficacy stats, and feeds the durable\n\t\t// evidence-gated promotion surfaced in system-prompt-builder.ts and getReport(). This is\n\t\t// a side-effecting call, not a discarded decision.\n\t\tthis.deps.getToolSelectionController?.()?.begin(toolCall.id, toolCall.name, args);\n\t\treturn undefined;\n\t};\n\n\treadonly afterToolCall: AfterToolCall = async ({ toolCall, args, result, isError }) => {\n\t\tconst runner = this.deps.getExtensionRunner();\n\t\tlet content = result.content;\n\t\tlet details = result.details;\n\t\tlet resolvedIsError = isError;\n\n\t\tif (runner.hasHandlers(\"tool_result\")) {\n\t\t\tconst hookResult = await runner.emitToolResult({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttoolName: toolCall.name,\n\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\tcontent,\n\t\t\t\tdetails,\n\t\t\t\tisError,\n\t\t\t});\n\t\t\tif (hookResult) {\n\t\t\t\tcontent = hookResult.content ?? content;\n\t\t\t\tdetails = hookResult.details;\n\t\t\t\tresolvedIsError = hookResult.isError ?? isError;\n\t\t\t}\n\t\t}\n\n\t\t// Untrusted-content boundary: structurally fence output from attacker-controllable sources\n\t\t// (web/search, subagents, recall, third-party tools) so injection payloads are framed as data.\n\t\t// First-party tools (read/grep/find/ls/edit/write/bash) are trusted and pass through unchanged.\n\t\tif (classifyToolTrust(toolCall.name) === \"untrusted\") {\n\t\t\tconst source = `tool:${toolCall.name}`;\n\t\t\tconst wrapped = content.map((block) =>\n\t\t\t\tblock.type === \"text\" ? { ...block, text: wrapUntrustedText(block.text, source) } : block,\n\t\t\t);\n\t\t\tcontent = wrapped;\n\t\t}\n\n\t\tthis.deps.getToolSelectionController?.()?.complete(toolCall.id, !resolvedIsError, content);\n\t\tif (content === result.content && details === result.details && resolvedIsError === isError) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn { content, details, isError: resolvedIsError };\n\t};\n}\n"]}
|
|
@@ -20,5 +20,12 @@ export declare function createToolArgumentValidationLogRecord(args: {
|
|
|
20
20
|
ts: string;
|
|
21
21
|
}): ToolArgumentValidationLogRecord;
|
|
22
22
|
export declare function isToolArgumentValidationLogRecord(value: unknown): value is ToolArgumentValidationLogRecord;
|
|
23
|
+
/**
|
|
24
|
+
* Append + rotate under a single exclusive lock on `eventLogPath`. Without the lock, a concurrent
|
|
25
|
+
* writer (e.g. another session's tool-recovery worker) could append between this call's read and its
|
|
26
|
+
* rotated rewrite, and that append would be silently discarded when the rewrite lands; the atomic
|
|
27
|
+
* tmp+rename in {@link rotateToolRecoveryEventLogIfNeeded} additionally ensures a reader never observes
|
|
28
|
+
* a partially-rewritten (torn) log file.
|
|
29
|
+
*/
|
|
23
30
|
export declare function writeToolRecoveryLogRecord(entry: ToolRecoveryLogWorkerRecord): void;
|
|
24
31
|
//# sourceMappingURL=tool-recovery-log-records.d.ts.map
|