commandmate 0.44.1 → 0.44.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +169 -169
- package/.next/app-path-routes-manifest.json +35 -35
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +0 -6
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route.js +2 -2
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route.js +1 -1
- package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route.js +1 -1
- package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +2 -2
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +2 -2
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route.js +2 -2
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route.js +1 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route.js +2 -2
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route.js +2 -2
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -2
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -2
- package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +11 -11
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +35 -35
- package/.next/server/chunks/1191.js +2 -2
- package/.next/server/chunks/1210.js +1 -1
- package/.next/server/chunks/1559.js +2 -0
- package/.next/server/chunks/1789.js +1 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2460.js +1 -0
- package/.next/server/chunks/2710.js +1 -1
- package/.next/server/chunks/2908.js +1 -0
- package/.next/server/chunks/2980.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3480.js +1 -1
- package/.next/server/chunks/3718.js +1 -1
- package/.next/server/chunks/4207.js +2 -2
- package/.next/server/chunks/450.js +1 -1
- package/.next/server/chunks/4672.js +5 -0
- package/.next/server/chunks/{9353.js → 4718.js} +2 -2
- package/.next/server/chunks/4837.js +14 -0
- package/.next/server/chunks/5048.js +1 -1
- package/.next/server/chunks/5209.js +1 -0
- package/.next/server/chunks/5595.js +1 -0
- package/.next/server/chunks/5625.js +25 -0
- package/.next/server/chunks/5845.js +1 -0
- package/.next/server/chunks/611.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6781.js +1 -1
- package/.next/server/chunks/6793.js +3 -3
- package/.next/server/chunks/7491.js +2 -2
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/850.js +1 -0
- package/.next/server/chunks/8543.js +1 -1
- package/.next/server/chunks/8728.js +3 -3
- package/.next/server/chunks/8791.js +1 -1
- package/.next/server/chunks/8800.js +1 -1
- package/.next/server/chunks/8918.js +7 -7
- package/.next/server/chunks/9130.js +1 -5
- package/.next/server/chunks/9390.js +2 -3
- package/.next/server/chunks/9584.js +1 -1
- package/.next/server/chunks/9627.js +6 -6
- package/.next/server/chunks/9731.js +3 -3
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
- package/.next/static/chunks/{2407-f1f258d4a1d92620.js → 2407-06d35bb1aa02de80.js} +1 -1
- package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
- package/.next/static/chunks/4727-5d695d71e3fdf97b.js +1 -0
- package/.next/static/chunks/{8165-3853772f6ae1299b.js → 8165-3525fb42f1b4976e.js} +1 -1
- package/.next/static/chunks/app/{layout-da66300cc20244ed.js → layout-0d1750b833f5cc3e.js} +1 -1
- package/.next/static/chunks/app/sessions/page-2af68c63211c751f.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-e36898c3a80e7302.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
- package/.next/static/css/057f64a65726c439.css +1 -0
- package/.next/trace +13 -13
- package/dist/cli/commands/ask.d.ts.map +1 -1
- package/dist/cli/commands/ask.js +120 -119
- package/dist/cli/commands/attach.d.ts +94 -0
- package/dist/cli/commands/attach.d.ts.map +1 -1
- package/dist/cli/commands/attach.js +145 -7
- package/dist/cli/commands/auto-yes.js +1 -1
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +10 -13
- package/dist/cli/commands/command-target.d.ts +23 -0
- package/dist/cli/commands/command-target.d.ts.map +1 -0
- package/dist/cli/commands/command-target.js +25 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +41 -2
- package/dist/cli/commands/message-dispatch.d.ts +36 -0
- package/dist/cli/commands/message-dispatch.d.ts.map +1 -0
- package/dist/cli/commands/message-dispatch.js +63 -0
- package/dist/cli/commands/reply.d.ts.map +1 -1
- package/dist/cli/commands/reply.js +2 -5
- package/dist/cli/commands/respond.d.ts.map +1 -1
- package/dist/cli/commands/respond.js +3 -6
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +149 -146
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +608 -416
- package/dist/cli/types/api-responses.d.ts +174 -27
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/types/api-responses.js +4 -2
- package/dist/cli/utils/api-client.d.ts +25 -5
- package/dist/cli/utils/api-client.d.ts.map +1 -1
- package/dist/cli/utils/api-client.js +87 -55
- package/dist/cli/utils/server-url.d.ts +1 -0
- package/dist/cli/utils/server-url.d.ts.map +1 -1
- package/dist/cli/utils/server-url.js +7 -0
- package/dist/config/uat-isolation.d.ts +140 -0
- package/dist/config/uat-isolation.d.ts.map +1 -0
- package/dist/config/uat-isolation.js +246 -0
- package/dist/lib/global-state.d.ts +12 -0
- package/dist/lib/global-state.d.ts.map +1 -0
- package/dist/lib/global-state.js +16 -0
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts +33 -0
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -0
- package/dist/lib/polling/auto-yes-suppression-reason.js +2 -0
- package/dist/lib/session/prompt-view.d.ts +228 -0
- package/dist/lib/session/prompt-view.d.ts.map +1 -0
- package/dist/lib/session/prompt-view.js +290 -0
- package/dist/lib/session/status-evidence-type.d.ts +16 -0
- package/dist/lib/session/status-evidence-type.d.ts.map +1 -0
- package/dist/lib/session/status-evidence-type.js +2 -0
- package/dist/lib/tmux/legacy-session-alias.d.ts.map +1 -1
- package/dist/lib/tmux/legacy-session-alias.js +2 -1
- package/dist/server/locales/en/worktree.json +3 -1
- package/dist/server/locales/ja/worktree.json +3 -1
- package/dist/server/server.js +5 -3
- package/dist/server/src/cli/types/api-responses.js +4 -2
- package/dist/server/src/config/cli-tool-timing-config.js +1 -6
- package/dist/server/src/config/uat-isolation.js +246 -0
- package/dist/server/src/lib/assistant-response-saver.js +62 -3
- package/dist/server/src/lib/auto-yes-lifecycle.js +139 -0
- package/dist/server/src/lib/auto-yes-poller.js +465 -160
- package/dist/server/src/lib/auto-yes-state.js +2 -2
- package/dist/server/src/lib/cli-tools/antigravity.js +39 -80
- package/dist/server/src/lib/cli-tools/base.js +151 -0
- package/dist/server/src/lib/cli-tools/codex.js +44 -80
- package/dist/server/src/lib/cli-tools/command-code.js +24 -56
- package/dist/server/src/lib/cli-tools/copilot.js +25 -67
- package/dist/server/src/lib/cli-tools/direct-input.js +8 -0
- package/dist/server/src/lib/cli-tools/gemini.js +23 -73
- package/dist/server/src/lib/cli-tools/opencode-pane-width.js +53 -0
- package/dist/server/src/lib/cli-tools/opencode-v2.js +9 -7
- package/dist/server/src/lib/cli-tools/opencode.js +21 -85
- package/dist/server/src/lib/cli-tools/submit-verified-sender.js +127 -4
- package/dist/server/src/lib/cli-tools/vibe-local.js +21 -66
- package/dist/server/src/lib/detection/cli-patterns.js +374 -3047
- package/dist/server/src/lib/detection/idle-evidence-observation.js +2 -2
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +7 -32
- package/dist/server/src/lib/detection/prompt-detector.js +2 -35
- package/dist/server/src/lib/detection/selection-shape-patterns.js +69 -0
- package/dist/server/src/lib/detection/selection-shape.js +32 -520
- package/dist/server/src/lib/detection/shared/pasted-text.js +41 -0
- package/dist/server/src/lib/detection/shared/shell-pane-command.js +16 -0
- package/dist/server/src/lib/detection/shared/strip-box-drawing.js +25 -0
- package/dist/server/src/lib/detection/status-detector.js +1 -1
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +12 -60
- package/dist/server/src/lib/detection/tools/antigravity/dialog.js +2 -15
- package/dist/server/src/lib/detection/tools/antigravity/live-region.js +39 -0
- package/dist/server/src/lib/detection/tools/antigravity/patterns.js +286 -0
- package/dist/server/src/lib/detection/tools/claude/detect.js +11 -17
- package/dist/server/src/lib/detection/tools/claude/live-region.js +26 -0
- package/dist/server/src/lib/detection/tools/claude/patterns.js +264 -4
- package/dist/server/src/lib/detection/tools/claude/prompt.js +2 -10
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +1 -1
- package/dist/server/src/lib/detection/tools/codex/detect.js +71 -130
- package/dist/server/src/lib/detection/tools/codex/live-region.js +104 -0
- package/dist/server/src/lib/detection/tools/codex/patterns.js +855 -0
- package/dist/server/src/lib/detection/tools/codex/prompt.js +2 -10
- package/dist/server/src/lib/detection/tools/command-code/detect.js +19 -50
- package/dist/server/src/lib/detection/tools/command-code/dialog.js +2 -18
- package/dist/server/src/lib/detection/tools/command-code/live-region.js +36 -0
- package/dist/server/src/lib/detection/tools/command-code/patterns.js +234 -0
- package/dist/server/src/lib/detection/tools/command-code/selection-shape.js +461 -0
- package/dist/server/src/lib/detection/tools/context-above.js +20 -0
- package/dist/server/src/lib/detection/tools/copilot/detect.js +13 -35
- package/dist/server/src/lib/detection/tools/copilot/live-region.js +52 -0
- package/dist/server/src/lib/detection/tools/copilot/patterns.js +640 -0
- package/dist/server/src/lib/detection/tools/copilot/prompt.js +2 -10
- package/dist/server/src/lib/detection/tools/frame.js +36 -2
- package/dist/server/src/lib/detection/tools/gemini/patterns.js +29 -0
- package/dist/server/src/lib/detection/tools/live-region-specs.js +31 -0
- package/dist/server/src/lib/detection/tools/live-region.js +204 -0
- package/dist/server/src/lib/detection/tools/opencode/detect.js +11 -49
- package/dist/server/src/lib/detection/tools/opencode/live-region.js +24 -0
- package/dist/server/src/lib/detection/tools/opencode/patterns.js +508 -0
- package/dist/server/src/lib/detection/tools/opencode-gutter-live-region.js +72 -0
- package/dist/server/src/lib/detection/tools/opencode-v2/detect.js +10 -42
- package/dist/server/src/lib/detection/tools/opencode-v2/live-region.js +24 -0
- package/dist/server/src/lib/detection/tools/opencode-v2/patterns.js +63 -0
- package/dist/server/src/lib/detection/tools/run-detection.js +31 -50
- package/dist/server/src/lib/detection/tools/verdicts.js +59 -0
- package/dist/server/src/lib/detection/tools/vibe-local/patterns.js +20 -0
- package/dist/server/src/lib/detection/truncate-raw-content.js +38 -0
- package/dist/server/src/lib/detection/turn-abandoned.js +66 -0
- package/dist/server/src/lib/detection/unclassified-frame-tracker.js +2 -2
- package/dist/server/src/lib/global-state.js +16 -0
- package/dist/server/src/lib/hooks/agent-session-telemetry.js +4 -6
- package/dist/server/src/lib/hooks/permission-decision-state.js +2 -2
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +11 -76
- package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +63 -1
- package/dist/server/src/lib/hooks/sources/antigravity/source.js +16 -0
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +3 -12
- package/dist/server/src/lib/hooks/sources/claude/history.js +17 -156
- package/dist/server/src/lib/hooks/sources/claude/queued-notice.js +53 -0
- package/dist/server/src/lib/hooks/sources/claude/source.js +33 -3
- package/dist/server/src/lib/hooks/sources/claude/transcript.js +3 -13
- package/dist/server/src/lib/hooks/sources/codex/history.js +11 -74
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +147 -11
- package/dist/server/src/lib/hooks/sources/codex/relay-install.js +64 -21
- package/dist/server/src/lib/hooks/sources/codex/transcript.js +5 -15
- package/dist/server/src/lib/hooks/sources/command-code/history.js +20 -121
- package/dist/server/src/lib/hooks/sources/command-code/transcript.js +3 -13
- package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +161 -31
- package/dist/server/src/lib/hooks/sources/define-source.js +40 -55
- package/dist/server/src/lib/hooks/sources/event-mapper.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode/diff.js +3 -4
- package/dist/server/src/lib/hooks/sources/opencode/history.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode/launch-settings.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode/payloads.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode/ports.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode/subscription.js +4 -3
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +3 -16
- package/dist/server/src/lib/hooks/sources/opencode-v2/history.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode-v2/mappers.js +5 -4
- package/dist/server/src/lib/hooks/sources/opencode-v2/ports.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode-v2/subscription.js +3 -7
- package/dist/server/src/lib/hooks/sources/opencode-v2/usage.js +2 -1
- package/dist/server/src/lib/hooks/sources/pending-decisions.js +2 -1
- package/dist/server/src/lib/hooks/sources/registry.js +3 -2
- package/dist/server/src/lib/hooks/sources/transcript-history.js +262 -0
- package/dist/server/src/lib/hooks/sources/turn-body.js +31 -0
- package/dist/server/src/lib/hooks/tool-input-normalization-state.js +2 -2
- package/dist/server/src/lib/polling/antigravity-permission-receipts.js +2 -2
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +16 -4
- package/dist/server/src/lib/polling/auto-yes-enter-fallback-state.js +142 -0
- package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +187 -0
- package/dist/server/src/lib/polling/auto-yes-resolver.js +9 -3
- package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +2 -0
- package/dist/server/src/lib/polling/auto-yes-suppression-state.js +2 -2
- package/dist/server/src/lib/polling/pending-scraped-response.js +190 -0
- package/dist/server/src/lib/polling/prompt-dedup-state.js +2 -2
- package/dist/server/src/lib/polling/prompt-dedup.js +2 -2
- package/dist/server/src/lib/polling/response-checker-dialog-gate.js +95 -0
- package/dist/server/src/lib/polling/response-checker-extraction-result.js +50 -0
- package/dist/server/src/lib/polling/response-checker-extraction-steps.js +670 -0
- package/dist/server/src/lib/polling/response-checker.js +666 -1162
- package/dist/server/src/lib/polling/response-dedup.js +3 -4
- package/dist/server/src/lib/polling/response-poller-constants.js +17 -0
- package/dist/server/src/lib/polling/response-poller-core.js +54 -20
- package/dist/server/src/lib/polling/startup-screen.js +142 -0
- package/dist/server/src/lib/polling/structured-history-gate.js +3 -2
- package/dist/server/src/lib/prompt-answer-semantic.js +178 -0
- package/dist/server/src/lib/prompt-answer-sender.js +6 -5
- package/dist/server/src/lib/push/failure-episode-state.js +2 -2
- package/dist/server/src/lib/push/notification-dedup.js +3 -4
- package/dist/server/src/lib/push/prompt-card-state.js +2 -2
- package/dist/server/src/lib/push/waiting-push-notifier.js +3 -4
- package/dist/server/src/lib/realtime/publisher-registry.js +3 -2
- package/dist/server/src/lib/realtime/terminal-broadcast.js +38 -2
- package/dist/server/src/lib/realtime/terminal-session-ownership.js +45 -0
- package/dist/server/src/lib/relay/relay-delivery.js +6 -2
- package/dist/server/src/lib/relay/relay-readiness.js +38 -1
- package/dist/server/src/lib/relay/relay-triggers.js +9 -0
- package/dist/server/src/lib/resource-cleanup.js +6 -4
- package/dist/server/src/lib/response-cleaner.js +24 -1
- package/dist/server/src/lib/response-extractor.js +16 -0
- package/dist/server/src/lib/schedule-manager.js +8 -10
- package/dist/server/src/lib/session/agent-event-ask-user-question.js +168 -0
- package/dist/server/src/lib/session/agent-event-awaiting-instruction.js +104 -0
- package/dist/server/src/lib/session/agent-event-dedup.js +539 -0
- package/dist/server/src/lib/session/agent-event-model.js +562 -0
- package/dist/server/src/lib/session/agent-event-record.js +10 -0
- package/dist/server/src/lib/session/agent-event-state.js +106 -1854
- package/dist/server/src/lib/session/agent-event-structured-state.js +109 -0
- package/dist/server/src/lib/session/agent-event-turn.js +811 -0
- package/dist/server/src/lib/session/agent-session-lifecycle.js +11 -2
- package/dist/server/src/lib/session/chat-turn-progress.js +322 -0
- package/dist/server/src/lib/session/claude-executor.js +45 -5
- package/dist/server/src/lib/session/claude-session.js +21 -65
- package/dist/server/src/lib/session/cli-session.js +17 -0
- package/dist/server/src/lib/session/current-output-builder.js +454 -1103
- package/dist/server/src/lib/session/current-output-history-writers.js +255 -0
- package/dist/server/src/lib/session/current-output-types.js +9 -0
- package/dist/server/src/lib/session/detection-divergence.js +55 -0
- package/dist/server/src/lib/session/global-session-constants.js +2 -13
- package/dist/server/src/lib/session/hook-turn-hold.js +102 -0
- package/dist/server/src/lib/session/layer-disagreement.js +2 -2
- package/dist/server/src/lib/session/opencode-session-store.js +2 -1
- package/dist/server/src/lib/session/prompt-view.js +290 -0
- package/dist/server/src/lib/session/prompt-waiting-composition.js +35 -0
- package/dist/server/src/lib/session/provisional-turn.js +3 -1
- package/dist/server/src/lib/session/send-user-message.js +1 -1
- package/dist/server/src/lib/session/session-starting-state.js +4 -6
- package/dist/server/src/lib/session/status-evidence-type.js +2 -0
- package/dist/server/src/lib/session/status-evidence.js +2 -2
- package/dist/server/src/lib/session/structured-status-merge.js +335 -0
- package/dist/server/src/lib/session/waiting-episode-state.js +3 -4
- package/dist/server/src/lib/session/waiting-kind.js +3 -0
- package/dist/server/src/lib/session-cleanup.js +6 -8
- package/dist/server/src/lib/skills/install-plan.js +2 -1
- package/dist/server/src/lib/skills/snapshot-store.js +2 -2
- package/dist/server/src/lib/skills/uninstall-plan.js +2 -2
- package/dist/server/src/lib/timer-manager.js +6 -8
- package/dist/server/src/lib/tmux/geometry-delegation.js +3 -4
- package/dist/server/src/lib/tmux/legacy-session-alias.js +2 -1
- package/dist/server/src/lib/tmux/session-hooks.js +2 -1
- package/dist/server/src/lib/tmux/session-status-options.js +3 -3
- package/dist/server/src/lib/tmux/tmux-capture-cache.js +3 -2
- package/dist/server/src/lib/tmux/tmux.js +33 -59
- package/dist/server/src/lib/tui-accumulator.js +2 -2
- package/dist/server/src/lib/version-checker.js +6 -6
- package/dist/server/src/lib/ws-server.js +47 -11
- package/docs/en/user-guide/webapp-guide.md +27 -3
- package/package.json +1 -1
- package/release-notes/0.44.2.json +33 -0
- package/release-notes/0.44.3.json +82 -0
- package/scripts/hooks/cmate-agent-event.sh +18 -0
- package/.next/server/chunks/1068.js +0 -1
- package/.next/server/chunks/434.js +0 -1
- package/.next/server/chunks/5775.js +0 -1
- package/.next/server/chunks/6474.js +0 -14
- package/.next/server/chunks/650.js +0 -1
- package/.next/server/chunks/6661.js +0 -1
- package/.next/server/chunks/8583.js +0 -1
- package/.next/server/chunks/964.js +0 -1
- package/.next/server/chunks/967.js +0 -1
- package/.next/server/chunks/9882.js +0 -25
- package/.next/static/chunks/591-308072f285c34787.js +0 -1
- package/.next/static/chunks/app/sessions/page-049e06335187aa91.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-040c5f0f585e6812.js +0 -1
- package/.next/static/css/38070d879efa1371.css +0 -1
- package/dist/server/src/lib/cli-tools/index.js +0 -41
- package/dist/server/src/lib/polling/global-session-poller.js +0 -140
- /package/.next/static/{57lOiz8zSEHdw97XIm0af → tWwHQzmvc-rv9KKUtDWfQ}/_buildManifest.js +0 -0
- /package/.next/static/{57lOiz8zSEHdw97XIm0af → tWwHQzmvc-rv9KKUtDWfQ}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,811 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The turn model (Issue #1930): the generation fence, the turn record each
|
|
4
|
+
* instance is in, its transitions, and the decisions (dialogs) it holds.
|
|
5
|
+
*
|
|
6
|
+
* Split out of `agent-event-state` (Issue #3375), which re-exports the public
|
|
7
|
+
* names and drives the transitions from `recordAgentEvent`.
|
|
8
|
+
*
|
|
9
|
+
* @module lib/session/agent-event-turn
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.reopenedTurns = exports.agentTurns = exports.generationStartedAt = void 0;
|
|
13
|
+
exports.currentGeneration = currentGeneration;
|
|
14
|
+
exports.effectiveTurn = effectiveTurn;
|
|
15
|
+
exports.livePendingDecisions = livePendingDecisions;
|
|
16
|
+
exports.getPendingDecisions = getPendingDecisions;
|
|
17
|
+
exports.getAgentTurn = getAgentTurn;
|
|
18
|
+
exports.getPublishedAgentTurn = getPublishedAgentTurn;
|
|
19
|
+
exports.closeAgentTurn = closeAgentTurn;
|
|
20
|
+
exports.observeScraperCompletionEvidence = observeScraperCompletionEvidence;
|
|
21
|
+
exports.fenceTurnForNewGeneration = fenceTurnForNewGeneration;
|
|
22
|
+
exports.applyTurnTransition = applyTurnTransition;
|
|
23
|
+
exports.joinOpenTurnFromDuplicate = joinOpenTurnFromDuplicate;
|
|
24
|
+
exports.openDecision = openDecision;
|
|
25
|
+
exports.releaseAllDecisions = releaseAllDecisions;
|
|
26
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
27
|
+
const agent_event_types_1 = require("../../lib/hooks/agent-event-types");
|
|
28
|
+
// Issue #1930: the turn model. Pure, so importing it here costs nothing at
|
|
29
|
+
// runtime beyond the two bounds it owns.
|
|
30
|
+
const provisional_turn_1 = require("../../lib/session/provisional-turn");
|
|
31
|
+
const agent_event_dedup_1 = require("../../lib/session/agent-event-dedup");
|
|
32
|
+
const global_state_1 = require("../global-state");
|
|
33
|
+
/** compositeKey -> epoch ms the current generation began. See {@link beginAgentEventGeneration}. */
|
|
34
|
+
exports.generationStartedAt = (0, global_state_1.getOrInitGlobal)('__agentEventGenerationStartedAt', () => new Map());
|
|
35
|
+
/**
|
|
36
|
+
* compositeKey -> the turn this instance is in, or the last one it was in
|
|
37
|
+
* (Issue #1930).
|
|
38
|
+
*
|
|
39
|
+
* The map that replaced "the newest event is the verdict". `lastAgentEvent`
|
|
40
|
+
* above is still written on every delivery and is still what
|
|
41
|
+
* `structuredEvents.lastEventType` publishes — it answers "did anything reach
|
|
42
|
+
* this server, and for the right instance?", which is a diagnostic question.
|
|
43
|
+
* This map answers the state question, and the two deliberately disagree
|
|
44
|
+
* whenever an event carries no verdict.
|
|
45
|
+
*
|
|
46
|
+
* The open dialogs #1725 kept in a map of their own live on the turn now
|
|
47
|
+
* ({@link TurnRecord.pendingDecisions}), because a dialog only ever happens
|
|
48
|
+
* *inside* a turn and holding them apart is what let a generation bump retire
|
|
49
|
+
* one and not the other.
|
|
50
|
+
*/
|
|
51
|
+
exports.agentTurns = (0, global_state_1.getOrInitGlobal)('__agentEventTurns', () => new Map());
|
|
52
|
+
/**
|
|
53
|
+
* compositeKey -> the open turn the newest unmarked `user_prompt_submit`
|
|
54
|
+
* replaced, under the id of the turn it opened in its place (Issue #3330).
|
|
55
|
+
*
|
|
56
|
+
* Kept so that a copy of that delivery which carries the queued-notice mark,
|
|
57
|
+
* and is dropped as a duplicate, can still undo the re-open; see
|
|
58
|
+
* {@link joinOpenTurnFromDuplicate}. One entry per instance, overwritten by the
|
|
59
|
+
* next re-open, and only ever read while the turn it names is still the
|
|
60
|
+
* instance's turn.
|
|
61
|
+
*/
|
|
62
|
+
exports.reopenedTurns = (0, global_state_1.getOrInitGlobal)('__agentEventReopenedTurns', () => new Map());
|
|
63
|
+
/**
|
|
64
|
+
* Monotonic suffix for {@link TurnRecord.turnId}.
|
|
65
|
+
*
|
|
66
|
+
* Two turns can open in the same millisecond — a `post_tool_use` closing one
|
|
67
|
+
* agent's turn while another's `user_prompt_submit` lands — and an id built from
|
|
68
|
+
* the timestamp alone would then compare equal across instances. `wait` reads a
|
|
69
|
+
* change of id as "a new turn began", so the collision would be a missed turn
|
|
70
|
+
* boundary rather than a cosmetic clash.
|
|
71
|
+
*/
|
|
72
|
+
const turnSequence = (0, global_state_1.getOrInitGlobal)('__agentEventTurnSeq', () => ({ value: 0 }));
|
|
73
|
+
// =============================================================================
|
|
74
|
+
// Turn model (Issue #1930)
|
|
75
|
+
// =============================================================================
|
|
76
|
+
/** Epoch ms the current generation began, or null when none was opened. */
|
|
77
|
+
function currentGeneration(key) {
|
|
78
|
+
return exports.generationStartedAt.get(key) ?? null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The turn this instance is in, with the generation fence applied.
|
|
82
|
+
*
|
|
83
|
+
* A turn whose {@link TurnRecord.generationAt} is not the current generation was
|
|
84
|
+
* opened by a process that has been replaced. It is not deleted — the fence is
|
|
85
|
+
* cheap and deleting would lose the eviction tally — it is simply not this
|
|
86
|
+
* instance's turn any more.
|
|
87
|
+
*/
|
|
88
|
+
function fencedTurn(key) {
|
|
89
|
+
const turn = exports.agentTurns.get(key);
|
|
90
|
+
if (!turn)
|
|
91
|
+
return null;
|
|
92
|
+
if (turn.generationAt !== currentGeneration(key))
|
|
93
|
+
return null;
|
|
94
|
+
return turn;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* {@link fencedTurn} with the staleness bound applied.
|
|
98
|
+
*
|
|
99
|
+
* The bound is applied by *closing* the turn rather than by hiding it, so
|
|
100
|
+
* `capture --json` says `closedBy: 'stale'` instead of going quiet — "the agent
|
|
101
|
+
* never reported the end of this turn" and "nothing has been reported at all"
|
|
102
|
+
* are different problems and an operator has to be able to tell them apart.
|
|
103
|
+
*
|
|
104
|
+
* Writes on read, which this module already does for corroboration, and is
|
|
105
|
+
* idempotent: the close is stamped from the event's own clock, so it does not
|
|
106
|
+
* move with the reader's `now`.
|
|
107
|
+
*/
|
|
108
|
+
function effectiveTurn(key, now) {
|
|
109
|
+
const turn = fencedTurn(key);
|
|
110
|
+
if (turn === null)
|
|
111
|
+
return null;
|
|
112
|
+
if (turn.closedAt === null && now - turn.displayEvent.at >= provisional_turn_1.TURN_STALE_AFTER_MS) {
|
|
113
|
+
turn.closedAt = turn.displayEvent.at + provisional_turn_1.TURN_STALE_AFTER_MS;
|
|
114
|
+
turn.closedBy = 'stale';
|
|
115
|
+
}
|
|
116
|
+
return turn;
|
|
117
|
+
}
|
|
118
|
+
/** Next {@link TurnRecord.turnId}. See {@link turnSequence}. */
|
|
119
|
+
function nextTurnId(at) {
|
|
120
|
+
turnSequence.value += 1;
|
|
121
|
+
return `turn-${at}-${turnSequence.value}`;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Drop the decisions this turn is holding, counting them.
|
|
125
|
+
*
|
|
126
|
+
* The generation path is the one §4 D3 決定 2 names: a process that has been
|
|
127
|
+
* replaced cannot have its approvals answered, and leaving them behind would
|
|
128
|
+
* publish `waiting` for a pane whose dialog went away with the process that
|
|
129
|
+
* drew it.
|
|
130
|
+
*/
|
|
131
|
+
function evictDecisions(key, turn) {
|
|
132
|
+
if (turn.pendingDecisions.length === 0)
|
|
133
|
+
return;
|
|
134
|
+
(0, agent_event_dedup_1.dropsFor)(key).decisionEvicted += turn.pendingDecisions.length;
|
|
135
|
+
turn.pendingDecisions = [];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The decisions still describing something, dropping the ones that are not.
|
|
139
|
+
*
|
|
140
|
+
* The retention bound of {@link DIALOG_PENDING_MAX_MS}, applied on read and
|
|
141
|
+
* counted as `dialogTimedOut` so the release is visible. Kept here rather than
|
|
142
|
+
* in a timer for the reason the rest of this module has no timers: the state
|
|
143
|
+
* describes a live tmux session, and a reader is the only thing that ever needs
|
|
144
|
+
* the answer.
|
|
145
|
+
*/
|
|
146
|
+
function livePendingDecisions(key, turn, now) {
|
|
147
|
+
const live = turn.pendingDecisions.filter((decision) => (0, provisional_turn_1.isDecisionLive)(decision, now));
|
|
148
|
+
const dropped = turn.pendingDecisions.length - live.length;
|
|
149
|
+
if (dropped > 0) {
|
|
150
|
+
(0, agent_event_dedup_1.dropsFor)(key).dialogTimedOut += dropped;
|
|
151
|
+
turn.pendingDecisions = live;
|
|
152
|
+
}
|
|
153
|
+
return live;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The approvals this instance is blocked on right now (Issue #1930).
|
|
157
|
+
*
|
|
158
|
+
* Published as `structuredEvents.pendingDecisions`; `#1932` is what teaches
|
|
159
|
+
* `commandmate respond` to name one of these ids.
|
|
160
|
+
*
|
|
161
|
+
* @param now - Epoch ms; defaults to now
|
|
162
|
+
*/
|
|
163
|
+
function getPendingDecisions(worktreeId, cliToolId, instanceId, now = Date.now()) {
|
|
164
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
|
|
165
|
+
const turn = effectiveTurn(key, now);
|
|
166
|
+
if (turn === null)
|
|
167
|
+
return [];
|
|
168
|
+
return livePendingDecisions(key, turn, now);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The turn record for one instance, fenced and aged, or null.
|
|
172
|
+
*
|
|
173
|
+
* The seam `current-output-builder` publishes from and the suites drive. The
|
|
174
|
+
* returned object is the live record; nothing outside this module writes to it.
|
|
175
|
+
*
|
|
176
|
+
* @param now - Epoch ms; defaults to now
|
|
177
|
+
*/
|
|
178
|
+
function getAgentTurn(worktreeId, cliToolId, instanceId, now = Date.now()) {
|
|
179
|
+
return effectiveTurn((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId), now);
|
|
180
|
+
}
|
|
181
|
+
/** {@link getAgentTurn} projected onto the four published fields. */
|
|
182
|
+
function getPublishedAgentTurn(worktreeId, cliToolId, instanceId, now = Date.now()) {
|
|
183
|
+
return (0, provisional_turn_1.derivePublishedTurn)(getAgentTurn(worktreeId, cliToolId, instanceId, now));
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Close the open turn on evidence that did not come from the agent (Issue #1930).
|
|
187
|
+
*
|
|
188
|
+
* The one seam for the two {@link TurnCloseReason} values nothing in the event
|
|
189
|
+
* stream can produce:
|
|
190
|
+
*
|
|
191
|
+
* - `scraper_evidence` — see {@link observeScraperCompletionEvidence}, which is
|
|
192
|
+
* the caller in this tree.
|
|
193
|
+
* - `resync_idle` — a source whose `capabilities.resync` lets it be re-read
|
|
194
|
+
* answering "not busy" after a dropped transport. The reconnect loop that
|
|
195
|
+
* would call it lives in `sources/opencode/subscription`, which is #1931's
|
|
196
|
+
* file and deliberately untouched here; the value is in the vocabulary and
|
|
197
|
+
* the seam accepts it, so wiring it is a call site rather than a new state.
|
|
198
|
+
*
|
|
199
|
+
* A no-op when no turn is open, which is the ordinary case: neither of these is
|
|
200
|
+
* a statement about a session that already reported it finished.
|
|
201
|
+
*
|
|
202
|
+
* @param at - Epoch ms; defaults to now
|
|
203
|
+
* @returns Whether a turn was closed
|
|
204
|
+
*/
|
|
205
|
+
function closeAgentTurn(worktreeId, cliToolId, instanceId, closedBy, at = Date.now()) {
|
|
206
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
|
|
207
|
+
const turn = fencedTurn(key);
|
|
208
|
+
if (turn === null || turn.closedAt !== null)
|
|
209
|
+
return false;
|
|
210
|
+
turn.closedAt = at;
|
|
211
|
+
turn.closedBy = closedBy;
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Feed one poll's reading of the pane into the turn's completion counter
|
|
216
|
+
* (Issue #1930).
|
|
217
|
+
*
|
|
218
|
+
* `completed` is the scraper's own verdict — `ready` with positive evidence —
|
|
219
|
+
* NOT the merged one, which would be circular: the merge is what the structured
|
|
220
|
+
* layer's `running` overrides, so reading it back would only ever confirm this
|
|
221
|
+
* layer's own answer.
|
|
222
|
+
*
|
|
223
|
+
* See {@link SCRAPER_COMPLETION_POLLS} for why three, and for why closing here
|
|
224
|
+
* does not complete a `commandmate wait`.
|
|
225
|
+
*
|
|
226
|
+
* ## `mayClose` — when the screen is not allowed to close (Issue #3337)
|
|
227
|
+
*
|
|
228
|
+
* The caller passes false while the agent's own hooks are speaking for the
|
|
229
|
+
* pane, the tool is one whose hook turns the screen may not end (codex;
|
|
230
|
+
* `lib/detection/turn-abandoned`), and nothing says the `Stop` will not come. Then the counter still
|
|
231
|
+
* counts, but the turn stays open and the structured `running` stands.
|
|
232
|
+
*
|
|
233
|
+
* The screen's "finished composer" is a reading of one frame, and a frame of a
|
|
234
|
+
* live turn can be misread: codex 0.160.0's status row blinks between `•` and
|
|
235
|
+
* `◦`, and the `◦` half read `ready`, so three polls in a row closed a
|
|
236
|
+
* nine-minute codex turn and `capture --json` published `ready` in the middle
|
|
237
|
+
* of it (`tests/fixtures/codex-mid-turn-3337/`). An operator who sent on that
|
|
238
|
+
* `ready` interrupted the running turn. On a hooks source the agent itself
|
|
239
|
+
* reports the end, so the screen can only add a wrong answer there — except
|
|
240
|
+
* when the `Stop` is known not to come. Two cases say so:
|
|
241
|
+
*
|
|
242
|
+
* - the turn has been unheard from for {@link TURN_STALE_AFTER_MS}: the
|
|
243
|
+
* existing `stale` close, which `effectiveTurn` applies regardless of this
|
|
244
|
+
* function. It stays the bound on a `Stop` that was simply lost.
|
|
245
|
+
* - the frame shows the turn was abandoned — codex's `■ Conversation
|
|
246
|
+
* interrupted` — which the caller folds into `mayClose`. Measured on codex
|
|
247
|
+
* 0.160.0 with hooks: an Esc fires no `Stop`.
|
|
248
|
+
*
|
|
249
|
+
* A source with no hooks (`scraper`), a pull source (`sse`) and a hooks tool
|
|
250
|
+
* with no such policy (Claude among them) pass true and keep the #1930
|
|
251
|
+
* behaviour.
|
|
252
|
+
*
|
|
253
|
+
* @param at - Epoch ms; defaults to now
|
|
254
|
+
* @param mayClose - Whether a third positive poll may close the turn
|
|
255
|
+
* @returns Whether this poll closed the turn
|
|
256
|
+
*/
|
|
257
|
+
function observeScraperCompletionEvidence(worktreeId, cliToolId, instanceId, completed, at = Date.now(), mayClose = true) {
|
|
258
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
|
|
259
|
+
const turn = fencedTurn(key);
|
|
260
|
+
if (turn === null || turn.closedAt !== null)
|
|
261
|
+
return false;
|
|
262
|
+
if (!completed) {
|
|
263
|
+
turn.scraperCompletionPolls = 0;
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
turn.scraperCompletionPolls += 1;
|
|
267
|
+
if (turn.scraperCompletionPolls < provisional_turn_1.SCRAPER_COMPLETION_POLLS)
|
|
268
|
+
return false;
|
|
269
|
+
if (!mayClose)
|
|
270
|
+
return false;
|
|
271
|
+
turn.closedAt = at;
|
|
272
|
+
turn.closedBy = 'scraper_evidence';
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* End the open turn because the process that owned it has been replaced
|
|
277
|
+
* (Issue #1930).
|
|
278
|
+
*
|
|
279
|
+
* The turn is closed and re-stamped into the new generation rather than
|
|
280
|
+
* deleted, which is the difference between `capture --json` reporting
|
|
281
|
+
* `closedBy: 'generation'` and reporting nothing at all. Its approvals go: they
|
|
282
|
+
* were raised by a process that no longer exists, and answering one would
|
|
283
|
+
* deliver a verdict into a slot nobody is holding.
|
|
284
|
+
*/
|
|
285
|
+
function fenceTurnForNewGeneration(key, at) {
|
|
286
|
+
const turn = exports.agentTurns.get(key);
|
|
287
|
+
if (!turn)
|
|
288
|
+
return;
|
|
289
|
+
evictDecisions(key, turn);
|
|
290
|
+
// A turn that had ALREADY ended is left where it is, which means the fence in
|
|
291
|
+
// `fencedTurn` hides it from here on. That asymmetry is deliberate: the
|
|
292
|
+
// previous process's `Stop` is not this process's, and re-stamping it into the
|
|
293
|
+
// new generation would publish `ready` — "the agent finished" — for a session
|
|
294
|
+
// nobody has typed into yet. Before #1930 the same protection came from
|
|
295
|
+
// comparing the event's timestamp against the generation.
|
|
296
|
+
if (turn.closedAt !== null)
|
|
297
|
+
return;
|
|
298
|
+
// An OPEN turn is closed and carried across, so `capture --json` can say
|
|
299
|
+
// `closedBy: 'generation'` rather than going quiet. `getStructuredSessionState`
|
|
300
|
+
// reads that reason as "nothing is known", so it publishes no verdict either
|
|
301
|
+
// way; what it buys is an operator being able to tell "the session was
|
|
302
|
+
// restarted under this turn" from "nothing was ever reported".
|
|
303
|
+
turn.closedAt = at;
|
|
304
|
+
turn.closedBy = 'generation';
|
|
305
|
+
turn.generationAt = at;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* The turn transition: what one delivery does to {@link TurnRecord}
|
|
309
|
+
* (Issue #1930, §4 D3 決定 2).
|
|
310
|
+
*
|
|
311
|
+
* | event | turn | dialog | display |
|
|
312
|
+
* |------------------------------------|-------------------------|----------|---------|
|
|
313
|
+
* | `user_prompt_submit` | **opens a new one** | release | yes |
|
|
314
|
+
* | `user_prompt_submit` (joins, #3330)| continues, else opens | release | yes |
|
|
315
|
+
* | `pre_tool_use` | continues, else opens | unchanged| yes |
|
|
316
|
+
* | `post_tool_use` | continues, else opens | release | yes |
|
|
317
|
+
* | `stop` (this session) | **closes** `stop` | release | yes |
|
|
318
|
+
* | `stop` (another session) | unchanged | unchanged| no |
|
|
319
|
+
* | `session_end` | **closes** `session_end`| release | no |
|
|
320
|
+
* | `session_start` | new generation (above) | evicted | no |
|
|
321
|
+
* | `notification(permission_prompt)` | unchanged | **open** | only to bootstrap |
|
|
322
|
+
* | `notification(permission_replied)` | unchanged | release | no |
|
|
323
|
+
* | `notification(idle_prompt)` | unchanged | release | yes |
|
|
324
|
+
* | `notification(anything else)` | unchanged | unchanged| no |
|
|
325
|
+
*
|
|
326
|
+
* Four rows are the whole point of the Issue, and each of them was a defect
|
|
327
|
+
* under "the newest event is the verdict":
|
|
328
|
+
*
|
|
329
|
+
* - **`user_prompt_submit` opens a new turn, the tool-call events continue the
|
|
330
|
+
* open one.** That is what makes {@link TurnRecord.turnId} an identity: #1926
|
|
331
|
+
* re-stamped it on every `pre_tool_use`, so a consumer reading a changed id
|
|
332
|
+
* as "a new turn began" false-positived several times inside one turn. `wait`
|
|
333
|
+
* reads it that way now.
|
|
334
|
+
* - **A `stop` naming another session changes nothing.** opencode publishes
|
|
335
|
+
* `session.idle` for every session its server holds, other processes'
|
|
336
|
+
* included (#1758 §5.6).
|
|
337
|
+
* - **`session_start` / `session_end` / an unknown notification /
|
|
338
|
+
* `permission_replied` do not become the displayed event.** An event carrying
|
|
339
|
+
* no verdict must not erase one. #1903 fixed the single measured instance
|
|
340
|
+
* (copilot's late `SessionStart`) by holding the delivery; the rule is
|
|
341
|
+
* general here, and the capability it reads is still the only reason a
|
|
342
|
+
* `session_start` is held rather than recorded.
|
|
343
|
+
* - **`notification(permission_prompt)` does not become the displayed event
|
|
344
|
+
* when a turn already exists.** The dialog is a fact about the *pane*, and
|
|
345
|
+
* it is published by the decision ledger below. Letting it overwrite the
|
|
346
|
+
* display is how the pre-#1898 `waiting` outlived the approval that caused
|
|
347
|
+
* it: released, the record still said `waiting`, because the only thing it
|
|
348
|
+
* could read was the event that opened the dialog.
|
|
349
|
+
*
|
|
350
|
+
* The `joins` row is the one exception to the first (Issue #3330). Claude Code
|
|
351
|
+
* fires `UserPromptSubmit` for every background-task notice it attaches to a
|
|
352
|
+
* turn that is already running, so a turn of an orchestrator that runs
|
|
353
|
+
* background work was re-opened once per notice. The source marks those
|
|
354
|
+
* deliveries ({@link AgentEventRecord.joinsOpenTurn}), and they continue the
|
|
355
|
+
* open turn of their session as a tool event does. In the server logs of
|
|
356
|
+
* 2026-10-02 to 2026-10-05, 188 of the 1,182 applied Claude
|
|
357
|
+
* `user_prompt_submit`s arrived with a turn of theirs still open, and the
|
|
358
|
+
* transcripts sort them as: 178 a queued notice (one `queue-operation: remove`
|
|
359
|
+
* of a `<task-notification>` per delivery), 0 a prompt the operator typed into
|
|
360
|
+
* the running turn (Claude attaches it without firing the hook), 0 a prompt
|
|
361
|
+
* sent after an interrupt, 6 after a turn that had ended with no `stop`
|
|
362
|
+
* applied, and 4 with nothing in the transcript to say. Only the first carry
|
|
363
|
+
* the mark; the others open a new turn, as before:
|
|
364
|
+
*
|
|
365
|
+
* - **After an interrupt** there is nothing on the hook channel to tell the
|
|
366
|
+
* prompt from one joining the turn — Claude Code has no interrupt hook, and
|
|
367
|
+
* the prompt is the operator's own text either way — so the turn the
|
|
368
|
+
* operator sent is a new one, which is what a resend is.
|
|
369
|
+
* - **After a `Stop` this server never got** the turn it opened is over, and a
|
|
370
|
+
* new one is right whatever the prompt was. A notice is the one case it
|
|
371
|
+
* cannot see: a lost `Stop` followed by a notice that opens a turn of its
|
|
372
|
+
* own is read as the notice joining the old turn, so the id does not change
|
|
373
|
+
* and the notice turn's `stop` closes it — the same `stop` a `wait` holding
|
|
374
|
+
* either turn was waiting for.
|
|
375
|
+
*
|
|
376
|
+
* Nothing in the row reads a clock. A burst of notices inside three seconds is
|
|
377
|
+
* still dropped by the window in front of it ({@link isDuplicateAgentEvent}),
|
|
378
|
+
* and dropped or applied, none of them moves the turn.
|
|
379
|
+
*
|
|
380
|
+
* `idle_prompt` is the one row that publishes `ready` **without** closing the
|
|
381
|
+
* turn, and that is a measurement rather than an oversight: #1839 caught Claude
|
|
382
|
+
* emitting it 62 s into a turn that ran nothing, so it cannot be a turn
|
|
383
|
+
* boundary. `wait`'s gate stays armed through it; what changes is only what the
|
|
384
|
+
* pane displays.
|
|
385
|
+
*/
|
|
386
|
+
function applyTurnTransition(key, record) {
|
|
387
|
+
const generation = currentGeneration(key);
|
|
388
|
+
// An event stamped before the current generation was produced by a process
|
|
389
|
+
// that has been replaced. Refusing it here is what makes re-recording a stale
|
|
390
|
+
// `user_prompt_submit` at its original timestamp a no-op.
|
|
391
|
+
if (generation !== null && record.at < generation)
|
|
392
|
+
return;
|
|
393
|
+
switch (record.event) {
|
|
394
|
+
case 'user_prompt_submit':
|
|
395
|
+
// Issue #3330: a queued notice the agent attached to its running turn
|
|
396
|
+
// continues that turn; any other prompt is a new one.
|
|
397
|
+
openTurn(key, record, generation, { continueOpen: record.joinsOpenTurn === true });
|
|
398
|
+
releaseAllDecisions(key);
|
|
399
|
+
return;
|
|
400
|
+
case 'post_tool_use':
|
|
401
|
+
openTurn(key, record, generation, { continueOpen: true });
|
|
402
|
+
// The tool call the dialog was gating has finished, so somebody answered
|
|
403
|
+
// it (Issue #1726). This is the release #1725 could not have: it had no
|
|
404
|
+
// event meaning "the human answered", only `Stop` meaning "the turn
|
|
405
|
+
// ended", which can be minutes later.
|
|
406
|
+
releaseAllDecisions(key);
|
|
407
|
+
return;
|
|
408
|
+
case 'pre_tool_use':
|
|
409
|
+
// Deliberately leaves the dialog alone (Issue #1726). It is the
|
|
410
|
+
// `AskUserQuestion` invocation, and a picker being *about to be drawn* is
|
|
411
|
+
// not a fact this state can carry.
|
|
412
|
+
openTurn(key, record, generation, { continueOpen: true });
|
|
413
|
+
return;
|
|
414
|
+
case 'stop':
|
|
415
|
+
applyStopToTurn(key, record, generation);
|
|
416
|
+
return;
|
|
417
|
+
case 'session_end':
|
|
418
|
+
applySessionEndToTurn(key, record);
|
|
419
|
+
releaseAllDecisions(key);
|
|
420
|
+
return;
|
|
421
|
+
case 'session_start':
|
|
422
|
+
// The generation was opened by `recordAgentEvent` before this ran, and
|
|
423
|
+
// `fenceTurnForNewGeneration` closed the turn with it. Nothing further:
|
|
424
|
+
// the frame carries no verdict, so it is not the displayed event either.
|
|
425
|
+
return;
|
|
426
|
+
case 'notification':
|
|
427
|
+
applyNotificationToTurn(key, record, generation);
|
|
428
|
+
return;
|
|
429
|
+
default:
|
|
430
|
+
// exhaustive check: a new AgentEventType must decide its transition here
|
|
431
|
+
record.event;
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/** The three fields the turn keeps from a record. */
|
|
436
|
+
function displayOf(record) {
|
|
437
|
+
return { event: record.event, at: record.at, detail: record.detail };
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Open a turn for this event, or move the display onto an open one.
|
|
441
|
+
*
|
|
442
|
+
* @param continueOpen - Whether an already-open turn of the same session is
|
|
443
|
+
* this event's turn. False for `user_prompt_submit`, which IS a new turn —
|
|
444
|
+
* unless the source marked it as joining the running one (Issue #3330).
|
|
445
|
+
*/
|
|
446
|
+
function openTurn(key, record, generation, { continueOpen }) {
|
|
447
|
+
const turn = fencedTurn(key);
|
|
448
|
+
const openHere = turn !== null &&
|
|
449
|
+
turn.closedAt === null &&
|
|
450
|
+
turn.openedAt !== null &&
|
|
451
|
+
(0, provisional_turn_1.closesTurn)(turn, record.sessionId);
|
|
452
|
+
if (continueOpen && openHere) {
|
|
453
|
+
turn.displayEvent = displayOf(record);
|
|
454
|
+
// A hand-configured relay posts no session id, so a turn can learn one
|
|
455
|
+
// partway through. Learning it is what lets a later `stop` be matched.
|
|
456
|
+
turn.sessionId ??= record.sessionId;
|
|
457
|
+
turn.scraperCompletionPolls = 0;
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
// A dialog-only record (openedAt null) is not a turn; its decisions belong to
|
|
461
|
+
// the turn that is opening now, because that is when they were raised.
|
|
462
|
+
const carried = turn !== null && turn.openedAt === null && turn.closedAt === null
|
|
463
|
+
? turn.pendingDecisions
|
|
464
|
+
: [];
|
|
465
|
+
const opened = {
|
|
466
|
+
turnId: nextTurnId(record.at),
|
|
467
|
+
sessionId: record.sessionId,
|
|
468
|
+
openedAt: record.at,
|
|
469
|
+
closedAt: null,
|
|
470
|
+
closedBy: null,
|
|
471
|
+
generationAt: generation,
|
|
472
|
+
displayEvent: displayOf(record),
|
|
473
|
+
pendingDecisions: carried,
|
|
474
|
+
scraperCompletionPolls: 0,
|
|
475
|
+
};
|
|
476
|
+
exports.agentTurns.set(key, opened);
|
|
477
|
+
boundTurnMap();
|
|
478
|
+
// Issue #3330: a prompt with no mark that replaced a running turn of its
|
|
479
|
+
// session. A marked copy of it may still arrive and be dropped as a repeat.
|
|
480
|
+
if (record.event === 'user_prompt_submit' && openHere) {
|
|
481
|
+
exports.reopenedTurns.set(key, { turnId: opened.turnId, replaced: turn });
|
|
482
|
+
(0, agent_event_dedup_1.trimOldestEntries)(exports.reopenedTurns, agent_event_dedup_1.MAX_RECENT_EVENT_KEYS);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Give a dropped copy's queued-notice mark its effect (Issue #3330).
|
|
487
|
+
*
|
|
488
|
+
* The injected `type: "http"` hook posts Claude's payload, prompt included,
|
|
489
|
+
* and is marked {@link AgentEventRecord.joinsOpenTurn} when the prompt is a
|
|
490
|
+
* queued notice. A hand-configured relay beside it posts the same event a few
|
|
491
|
+
* milliseconds earlier or later, and the two share the de-duplication key — so
|
|
492
|
+
* when the relay's copy lands first and carries no mark (an older relay, or a
|
|
493
|
+
* hook that never forwards it), it is the one applied, it re-opens the running
|
|
494
|
+
* turn, and the marked copy is dropped behind it.
|
|
495
|
+
*
|
|
496
|
+
* Called for a `user_prompt_submit` the window dropped and that carries the
|
|
497
|
+
* mark. When the instance's turn is still exactly the one an unmarked prompt
|
|
498
|
+
* opened in place of a running turn of the same session, the running turn is
|
|
499
|
+
* put back — under its own id and `openedAt` — with what the newer record had
|
|
500
|
+
* learned since (display, dialogs). Anything else, and this does nothing.
|
|
501
|
+
*
|
|
502
|
+
* The other ways to keep the mark were weighed and lost:
|
|
503
|
+
*
|
|
504
|
+
* - **Put the mark in the de-duplication key.** Both copies are then applied,
|
|
505
|
+
* but in arrival order: the unmarked one has already re-opened the turn by
|
|
506
|
+
* the time the marked one joins it, so the id has moved either way.
|
|
507
|
+
* - **Drop the unmarked copy instead.** Which copy is the duplicate is decided
|
|
508
|
+
* by whichever lands first, and the first has already been applied.
|
|
509
|
+
*
|
|
510
|
+
* What it cannot tell apart: an unmarked prompt that really begins a turn (a
|
|
511
|
+
* resend after an interrupt) followed, inside the window, by a queued notice
|
|
512
|
+
* of the same session. The notice is read as a copy of the prompt and the two
|
|
513
|
+
* become one turn under the older id; the next `stop` closes it, which is the
|
|
514
|
+
* `stop` a `wait` holding either turn was waiting for.
|
|
515
|
+
*
|
|
516
|
+
* @returns Whether a turn was put back.
|
|
517
|
+
*/
|
|
518
|
+
function joinOpenTurnFromDuplicate(worktreeId, cliToolId, instanceId, record) {
|
|
519
|
+
if (record.event !== 'user_prompt_submit' || record.joinsOpenTurn !== true)
|
|
520
|
+
return false;
|
|
521
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
|
|
522
|
+
const reopened = exports.reopenedTurns.get(key);
|
|
523
|
+
const current = fencedTurn(key);
|
|
524
|
+
if (!reopened || current === null || current.turnId !== reopened.turnId)
|
|
525
|
+
return false;
|
|
526
|
+
if (current.closedAt !== null)
|
|
527
|
+
return false;
|
|
528
|
+
if (!(0, provisional_turn_1.closesTurn)(current, record.sessionId))
|
|
529
|
+
return false;
|
|
530
|
+
const { replaced } = reopened;
|
|
531
|
+
if (replaced.generationAt !== current.generationAt)
|
|
532
|
+
return false;
|
|
533
|
+
exports.agentTurns.set(key, {
|
|
534
|
+
...replaced,
|
|
535
|
+
closedAt: null,
|
|
536
|
+
closedBy: null,
|
|
537
|
+
displayEvent: current.displayEvent,
|
|
538
|
+
pendingDecisions: current.pendingDecisions,
|
|
539
|
+
scraperCompletionPolls: 0,
|
|
540
|
+
});
|
|
541
|
+
exports.reopenedTurns.delete(key);
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Apply a `stop` — the only event that is the agent saying its turn is over.
|
|
546
|
+
*
|
|
547
|
+
* A `stop` for another session leaves everything alone; see {@link closesTurn}.
|
|
548
|
+
* A `stop` with no turn open still records one, because "this instance last
|
|
549
|
+
* reported it stopped at T" is the fact `ready` is published from, and the
|
|
550
|
+
* opening it never saw is published as null rather than guessed.
|
|
551
|
+
*/
|
|
552
|
+
function applyStopToTurn(key, record, generation) {
|
|
553
|
+
const turn = fencedTurn(key);
|
|
554
|
+
if (turn !== null && turn.closedAt === null && turn.openedAt !== null) {
|
|
555
|
+
if (!(0, provisional_turn_1.closesTurn)(turn, record.sessionId))
|
|
556
|
+
return;
|
|
557
|
+
turn.closedAt = record.at;
|
|
558
|
+
turn.closedBy = 'stop';
|
|
559
|
+
turn.displayEvent = displayOf(record);
|
|
560
|
+
releaseAllDecisions(key);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
exports.agentTurns.set(key, {
|
|
564
|
+
turnId: nextTurnId(record.at),
|
|
565
|
+
sessionId: record.sessionId,
|
|
566
|
+
openedAt: null,
|
|
567
|
+
closedAt: record.at,
|
|
568
|
+
closedBy: 'stop',
|
|
569
|
+
generationAt: generation,
|
|
570
|
+
displayEvent: displayOf(record),
|
|
571
|
+
pendingDecisions: [],
|
|
572
|
+
scraperCompletionPolls: 0,
|
|
573
|
+
});
|
|
574
|
+
boundTurnMap();
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* `session_end`: the agent session this instance was talking to is gone.
|
|
578
|
+
*
|
|
579
|
+
* **Overwrites an existing close reason**, which is the one place in this
|
|
580
|
+
* module where a later event rewrites an earlier verdict, and #1723's contract
|
|
581
|
+
* is why. `/clear` emits `SessionEnd(reason=clear)` on a session that is alive
|
|
582
|
+
* and about to keep going, and the turn before it may perfectly well have ended
|
|
583
|
+
* with a `Stop`. Leaving that `Stop` standing would keep publishing "the agent
|
|
584
|
+
* finished" about a conversation that no longer exists — the integration pin is
|
|
585
|
+
* `current-output-structured-status-1723`, which asserts the session goes back
|
|
586
|
+
* to the scraper the moment `SessionEnd` lands.
|
|
587
|
+
*
|
|
588
|
+
* `closedBy: 'session_end'` publishes no verdict of its own (see
|
|
589
|
+
* {@link getStructuredSessionState}), so this is a retirement rather than a
|
|
590
|
+
* different answer.
|
|
591
|
+
*/
|
|
592
|
+
function applySessionEndToTurn(key, record) {
|
|
593
|
+
const turn = fencedTurn(key);
|
|
594
|
+
if (turn === null)
|
|
595
|
+
return;
|
|
596
|
+
if (!(0, provisional_turn_1.closesTurn)(turn, record.sessionId))
|
|
597
|
+
return;
|
|
598
|
+
turn.closedAt = record.at;
|
|
599
|
+
turn.closedBy = 'session_end';
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* The notification rows of the transition table.
|
|
603
|
+
*
|
|
604
|
+
* Matched on `notification_type` ({@link AgentEventRecord.detail}), never on the
|
|
605
|
+
* human-facing `message` (D3): the observed messages are English prose the agent
|
|
606
|
+
* is free to reword.
|
|
607
|
+
*/
|
|
608
|
+
function applyNotificationToTurn(key, record, generation) {
|
|
609
|
+
if (record.detail === 'permission_prompt') {
|
|
610
|
+
if (record.promptSettled === true) {
|
|
611
|
+
// Issue #1898: adjudicated before it was recorded, and the verdict
|
|
612
|
+
// reached the agent. There is no dialog and there never was one for a
|
|
613
|
+
// human to answer — opening a record for it published `waiting` for the
|
|
614
|
+
// whole of the tool call that followed (measured at eight seconds).
|
|
615
|
+
releaseSettledDecision(key, record);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
openDecision(key, generation, {
|
|
619
|
+
source: 'notification',
|
|
620
|
+
at: record.at,
|
|
621
|
+
message: record.message ?? null,
|
|
622
|
+
// Issue #2031. Was a hard `null`, which is what left an opencode approval
|
|
623
|
+
// reaching the browser with no statement of what it was for: the tool
|
|
624
|
+
// name is not in `permission.asked` and has to be carried on the record
|
|
625
|
+
// by whoever correlated it. Absent still means "this source had nothing
|
|
626
|
+
// to say", and `openDecision` leaves an earlier name in place for that.
|
|
627
|
+
toolName: record.toolName ?? null,
|
|
628
|
+
patterns: record.decisionPatterns ?? null,
|
|
629
|
+
decisionId: record.decisionId ?? null,
|
|
630
|
+
bootstrapDisplay: displayOf(record),
|
|
631
|
+
});
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
if (record.detail === agent_event_types_1.PERMISSION_REPLIED_DETAIL) {
|
|
635
|
+
// Issue #1898. The agent's own statement that the dialog is gone — whoever
|
|
636
|
+
// answered it. Not a word this build reads a status from, so it decides
|
|
637
|
+
// nothing; all it does is retire the record.
|
|
638
|
+
if (record.promptSettled === true)
|
|
639
|
+
releaseSettledDecision(key, record);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
if (record.detail === 'idle_prompt') {
|
|
643
|
+
// The agent reporting it is sitting at the composer waiting for input is the
|
|
644
|
+
// agent saying nothing is in front of that composer.
|
|
645
|
+
releaseAllDecisions(key);
|
|
646
|
+
const turn = fencedTurn(key);
|
|
647
|
+
if (turn !== null && turn.closedAt === null) {
|
|
648
|
+
turn.displayEvent = displayOf(record);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (turn !== null)
|
|
652
|
+
return;
|
|
653
|
+
// Nothing to attach it to — the first thing this instance ever said, or the
|
|
654
|
+
// first since a generation. It still carries a verdict (`ready`), and #1723
|
|
655
|
+
// publishes it, so a display-only record is opened to hold it. `openedAt`
|
|
656
|
+
// stays null: an agent sitting at its composer is not in a turn, and a
|
|
657
|
+
// record that claimed otherwise would gate `wait` on a turn nobody opened.
|
|
658
|
+
exports.agentTurns.set(key, {
|
|
659
|
+
turnId: nextTurnId(record.at),
|
|
660
|
+
sessionId: record.sessionId,
|
|
661
|
+
openedAt: null,
|
|
662
|
+
closedAt: null,
|
|
663
|
+
closedBy: null,
|
|
664
|
+
generationAt: generation,
|
|
665
|
+
displayEvent: displayOf(record),
|
|
666
|
+
pendingDecisions: [],
|
|
667
|
+
scraperCompletionPolls: 0,
|
|
668
|
+
});
|
|
669
|
+
boundTurnMap();
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
// An unrecognised notification type is not evidence of anything, and guessing
|
|
673
|
+
// would be worse than the scraper.
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Open, or refresh, a dialog record on this instance's turn.
|
|
677
|
+
*
|
|
678
|
+
* `bootstrapDisplay` is used only when there is no record at all to hang the
|
|
679
|
+
* decision on. That record is deliberately **not** an open turn — its
|
|
680
|
+
* `openedAt` is null — so releasing the decision hands the pane back to the
|
|
681
|
+
* scraper rather than asserting `running` for a turn nobody ever saw open.
|
|
682
|
+
*/
|
|
683
|
+
function openDecision(key, generation, input) {
|
|
684
|
+
let turn = fencedTurn(key);
|
|
685
|
+
if (turn === null) {
|
|
686
|
+
turn = {
|
|
687
|
+
turnId: nextTurnId(input.at),
|
|
688
|
+
sessionId: null,
|
|
689
|
+
openedAt: null,
|
|
690
|
+
closedAt: null,
|
|
691
|
+
closedBy: null,
|
|
692
|
+
generationAt: generation,
|
|
693
|
+
displayEvent: input.bootstrapDisplay,
|
|
694
|
+
pendingDecisions: [],
|
|
695
|
+
scraperCompletionPolls: 0,
|
|
696
|
+
};
|
|
697
|
+
exports.agentTurns.set(key, turn);
|
|
698
|
+
boundTurnMap();
|
|
699
|
+
}
|
|
700
|
+
else if (turn.closedAt !== null) {
|
|
701
|
+
// The dialog is being raised after the turn it would have belonged to
|
|
702
|
+
// ended — a `PermissionRequest` racing a `Stop`, or a re-check landing
|
|
703
|
+
// late. Re-open a dialog-only record rather than resurrecting the turn.
|
|
704
|
+
turn = {
|
|
705
|
+
turnId: nextTurnId(input.at),
|
|
706
|
+
sessionId: null,
|
|
707
|
+
openedAt: null,
|
|
708
|
+
closedAt: null,
|
|
709
|
+
closedBy: null,
|
|
710
|
+
generationAt: generation,
|
|
711
|
+
displayEvent: input.bootstrapDisplay,
|
|
712
|
+
pendingDecisions: [],
|
|
713
|
+
scraperCompletionPolls: 0,
|
|
714
|
+
};
|
|
715
|
+
exports.agentTurns.set(key, turn);
|
|
716
|
+
boundTurnMap();
|
|
717
|
+
}
|
|
718
|
+
// Issue #1930 / S1: an id that fails validation is DISCARDED, not truncated —
|
|
719
|
+
// a truncated id compares equal to a different id sharing its prefix, and the
|
|
720
|
+
// reply to one approval would then retire another's record.
|
|
721
|
+
const decisionId = input.decisionId === null ? null : (0, provisional_turn_1.acceptExternalId)(input.decisionId);
|
|
722
|
+
if (input.decisionId !== null && decisionId === null)
|
|
723
|
+
(0, agent_event_dedup_1.dropsFor)(key).idsDiscarded += 1;
|
|
724
|
+
const confirmed = input.source === 'notification';
|
|
725
|
+
// Which record, if any, this report is a second sighting of.
|
|
726
|
+
//
|
|
727
|
+
// - an id matches its own record;
|
|
728
|
+
// - an id with no record of its own may still be *confirming* the anonymous
|
|
729
|
+
// prediction that forecast it. That is the measured pair: a
|
|
730
|
+
// `PermissionRequest` this server declined to decide fires ~6 s before the
|
|
731
|
+
// `Notification(permission_prompt)` that proves the dialog, and the
|
|
732
|
+
// request carries no id;
|
|
733
|
+
// - an anonymous report merges only with another anonymous one. A source
|
|
734
|
+
// that publishes no ids therefore keeps exactly one dialog record per
|
|
735
|
+
// instance, which is what #1725 did and the honest limit for it — matching
|
|
736
|
+
// an anonymous report against an *identified* record would let one
|
|
737
|
+
// approval's forecast confirm a different approval's dialog.
|
|
738
|
+
const existing = decisionId !== null
|
|
739
|
+
? (turn.pendingDecisions.find((decision) => decision.decisionId === decisionId) ??
|
|
740
|
+
turn.pendingDecisions.find((decision) => decision.decisionId === null && decision.source === 'permission-request'))
|
|
741
|
+
: turn.pendingDecisions.find((decision) => decision.decisionId === null);
|
|
742
|
+
if (existing) {
|
|
743
|
+
// The same dialog, reported twice: `PermissionRequest` predicted it and the
|
|
744
|
+
// `Notification` then proved it. Keep the earliest `at` — that is when the
|
|
745
|
+
// human was first blocked, and it is what the scraper-release grace and the
|
|
746
|
+
// age bound are measured from — and take the confirmation.
|
|
747
|
+
existing.message = (0, provisional_turn_1.boundDecisionMessage)(input.message) ?? existing.message;
|
|
748
|
+
existing.toolName = (0, provisional_turn_1.boundDecisionToolName)(input.toolName) ?? existing.toolName;
|
|
749
|
+
// Issue #2031, same rule as the two lines above it: a second sighting that
|
|
750
|
+
// knows the rules fills them in, one that does not leaves the earlier
|
|
751
|
+
// answer alone. The measured pair is exactly this — the `PermissionRequest`
|
|
752
|
+
// forecast carries no patterns, the `Notification` that confirms it does.
|
|
753
|
+
existing.patterns = (0, provisional_turn_1.boundDecisionPatterns)(input.patterns) ?? existing.patterns;
|
|
754
|
+
existing.decisionId ??= decisionId;
|
|
755
|
+
if (confirmed) {
|
|
756
|
+
existing.source = 'notification';
|
|
757
|
+
existing.confirmedAt ??= input.at;
|
|
758
|
+
}
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
if (turn.pendingDecisions.length >= provisional_turn_1.MAX_PENDING_DECISIONS_PER_TURN) {
|
|
762
|
+
// S14(d). Counted rather than dropped in silence: an agent raising more
|
|
763
|
+
// approvals than this in one turn is a fact an operator has to be able to
|
|
764
|
+
// see, and the oldest is the one a human has been looking at.
|
|
765
|
+
(0, agent_event_dedup_1.dropsFor)(key).decisionOverflow += 1;
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
turn.pendingDecisions.push({
|
|
769
|
+
decisionId,
|
|
770
|
+
at: input.at,
|
|
771
|
+
source: input.source,
|
|
772
|
+
message: (0, provisional_turn_1.boundDecisionMessage)(input.message),
|
|
773
|
+
toolName: (0, provisional_turn_1.boundDecisionToolName)(input.toolName),
|
|
774
|
+
patterns: (0, provisional_turn_1.boundDecisionPatterns)(input.patterns),
|
|
775
|
+
confirmedAt: confirmed ? input.at : null,
|
|
776
|
+
scraperCorroborated: false,
|
|
777
|
+
recorded: false,
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
/** Retire every dialog this instance was holding. */
|
|
781
|
+
function releaseAllDecisions(key) {
|
|
782
|
+
const turn = fencedTurn(key);
|
|
783
|
+
if (turn !== null)
|
|
784
|
+
turn.pendingDecisions = [];
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Retire the record a verdict was delivered for (Issue #1898).
|
|
788
|
+
*
|
|
789
|
+
* Matched on {@link AgentEventRecord.decisionId} when both sides have one: an
|
|
790
|
+
* agent that can run two approvals at once would otherwise have the reply to
|
|
791
|
+
* the first retire the record for the second. When either side is anonymous the
|
|
792
|
+
* release is unconditional — an unmatched id is a source that publishes none,
|
|
793
|
+
* and refusing to act there would leave the pre-#1898 stall in place for it.
|
|
794
|
+
*/
|
|
795
|
+
function releaseSettledDecision(key, record) {
|
|
796
|
+
const turn = fencedTurn(key);
|
|
797
|
+
if (turn === null || turn.pendingDecisions.length === 0)
|
|
798
|
+
return;
|
|
799
|
+
const settledId = record.decisionId === null || record.decisionId === undefined
|
|
800
|
+
? null
|
|
801
|
+
: (0, provisional_turn_1.acceptExternalId)(record.decisionId);
|
|
802
|
+
if (settledId === null) {
|
|
803
|
+
turn.pendingDecisions = [];
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
turn.pendingDecisions = turn.pendingDecisions.filter((decision) => decision.decisionId !== null && decision.decisionId !== settledId);
|
|
807
|
+
}
|
|
808
|
+
/** Keep the turn map bounded the way every other map in this module is. */
|
|
809
|
+
function boundTurnMap() {
|
|
810
|
+
(0, agent_event_dedup_1.trimOldestEntries)(exports.agentTurns, agent_event_dedup_1.MAX_RECENT_EVENT_KEYS);
|
|
811
|
+
}
|