commandmate 0.45.1 → 0.46.1
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 +319 -315
- package/.next/app-path-routes-manifest.json +15 -15
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +4 -4
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.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_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_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_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_client-reference-manifest.js +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_client-reference-manifest.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.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 +9 -9
- 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.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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.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.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.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_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.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_client-reference-manifest.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_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_client-reference-manifest.js +1 -1
- 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.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_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_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 +3 -3
- 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_client-reference-manifest.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_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_client-reference-manifest.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_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_client-reference-manifest.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_client-reference-manifest.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_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_client-reference-manifest.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_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_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_client-reference-manifest.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.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.js +9 -9
- 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_client-reference-manifest.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_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_client-reference-manifest.js +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_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 +3 -3
- 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 +3 -3
- 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_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.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_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_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_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_client-reference-manifest.js +1 -1
- 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_client-reference-manifest.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_client-reference-manifest.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_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.js +1 -1
- package/.next/server/app/login/page.js.nft.json +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.js +1 -1
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page.js +1 -1
- package/.next/server/app/offline/page.js.nft.json +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +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.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page.js +1 -1
- package/.next/server/app/review/page.js.nft.json +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.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +1 -1
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +1 -1
- package/.next/server/app/skills/page.js.nft.json +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +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 +12 -9
- 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.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +15 -15
- package/.next/server/chunks/1341.js +1 -1
- package/.next/server/chunks/1501.js +2 -2
- package/.next/server/chunks/1559.js +1 -1
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2283.js +15 -13
- package/.next/server/chunks/2404.js +4 -4
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2460.js +1 -1
- package/.next/server/chunks/2560.js +1 -1
- package/.next/server/chunks/2908.js +1 -1
- package/.next/server/chunks/2984.js +25 -0
- package/.next/server/chunks/3543.js +1 -1
- package/.next/server/chunks/3945.js +1 -1
- package/.next/server/chunks/4072.js +15 -0
- package/.next/server/chunks/4207.js +1 -1
- package/.next/server/chunks/4718.js +3 -3
- package/.next/server/chunks/4837.js +3 -3
- package/.next/server/chunks/5209.js +1 -1
- package/.next/server/chunks/5292.js +2 -2
- package/.next/server/chunks/5845.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6345.js +1 -0
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6722.js +1 -0
- package/.next/server/chunks/8098.js +1 -1
- package/.next/server/chunks/8356.js +1 -1
- package/.next/server/chunks/8581.js +25 -29
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/8791.js +1 -1
- package/.next/server/chunks/8800.js +4 -4
- package/.next/server/chunks/8918.js +5 -5
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9627.js +2 -1
- package/.next/server/chunks/9731.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- 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/pages/_error.js +2 -2
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{2407-86890b00eeecf391.js → 2407-9703c569370b8a9d.js} +1 -1
- package/.next/static/chunks/{2619-a305ad4810f1393a.js → 2619-04bc32f026a0d946.js} +1 -1
- package/.next/static/chunks/2717.1583400c272dc1d9.js +1 -0
- package/.next/static/chunks/2770-db80aedf6384d594.js +1 -0
- package/.next/static/chunks/2863-6a07ec82fb52f4dd.js +1 -0
- package/.next/static/chunks/3201-c01f1feed69020e6.js +1 -0
- package/.next/static/chunks/4768-ad6f82f034f21eae.js +1 -0
- package/.next/static/chunks/5371-0dc947683e46e78c.js +1 -0
- package/.next/static/chunks/5794-4eee51ff1e878aa6.js +1 -0
- package/.next/static/chunks/5927-54315d21f323e204.js +1 -0
- package/.next/static/chunks/602-25e45a2422d2a3ea.js +1 -0
- package/.next/static/chunks/6606-02ddc006686a6b7d.js +1 -0
- package/.next/static/chunks/6654-f3534f35f16644bc.js +1 -0
- package/.next/static/chunks/7730-011e137be64403ae.js +1 -0
- package/.next/static/chunks/8165-263172c17ae8e8c3.js +1 -0
- package/.next/static/chunks/{8407-9a72e6f07c5d5458.js → 8407-155f84e5ba05f1d5.js} +1 -1
- package/.next/static/chunks/8606-cf6bdbff44a764cf.js +1 -0
- package/.next/static/chunks/934-a37509667baa86ee.js +1 -0
- package/.next/static/chunks/9465-e5a351baa941f31b.js +1 -0
- package/.next/static/chunks/app/layout-3e357690446cd2da.js +1 -0
- package/.next/static/chunks/app/repositories/page-71f5a5ac29b0370d.js +1 -0
- package/.next/static/chunks/app/review/page-e2fd4a590646a2d8.js +1 -0
- package/.next/static/chunks/app/sessions/page-9859ed61e93e6890.js +1 -0
- package/.next/static/chunks/app/skills/[skillId]/page-52ba58712faf3378.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-effbf0796881dd5a.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/{page-c601f3b3ece6557e.js → page-373ea37b16d930c7.js} +1 -1
- package/.next/static/chunks/{webpack-ee3ccbe378c4aa06.js → webpack-468b7b33030234b3.js} +1 -1
- package/.next/static/css/743f79ff19ab91e9.css +1 -0
- package/.next/trace +13 -13
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +6 -1
- package/dist/cli/types/api-responses.d.ts +8 -6
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts +13 -1
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.js +3 -0
- package/dist/server/locales/en/worktree.json +46 -16
- package/dist/server/locales/ja/worktree.json +46 -16
- package/dist/server/src/config/activity-bar-config.js +56 -9
- package/dist/server/src/lib/assistant-response-saver.js +13 -0
- package/dist/server/src/lib/auto-yes-poller.js +252 -54
- package/dist/server/src/lib/conversation-logger.js +14 -2
- package/dist/server/src/lib/db/chat-db.js +2 -1
- package/dist/server/src/lib/history/user-turn-recorder.js +14 -0
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +28 -0
- package/dist/server/src/lib/hooks/sources/claude/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/codex/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/transcript-history.js +34 -0
- package/dist/server/src/lib/log-manager.js +7 -2
- package/dist/server/src/lib/polling/auto-yes-enter-fallback-state.js +22 -3
- package/dist/server/src/lib/polling/auto-yes-poller-state.js +234 -0
- package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +3 -0
- package/dist/server/src/lib/polling/pending-scraped-response.js +119 -3
- package/dist/server/src/lib/polling/poller-owner.js +110 -0
- package/dist/server/src/lib/polling/prompt-dedup-state.js +26 -7
- package/dist/server/src/lib/polling/prompt-dedup.js +50 -22
- package/dist/server/src/lib/polling/response-checker.js +212 -36
- package/dist/server/src/lib/polling/response-dedup.js +112 -20
- package/dist/server/src/lib/polling/response-poller-core.js +178 -38
- package/dist/server/src/lib/polling/structured-history-gate.js +20 -1
- package/dist/server/src/lib/prompt-answer-sender.js +59 -12
- package/dist/server/src/lib/realtime/terminal-broadcast.js +14 -0
- package/dist/server/src/lib/session/chat-turn-progress.js +57 -6
- package/dist/server/src/lib/session/current-output-builder.js +19 -0
- package/dist/server/src/lib/session/next-action-helper.js +2 -15
- package/dist/server/src/lib/session/worktree-session-reconcile.js +83 -10
- package/dist/server/src/lib/timer-manager.js +7 -0
- package/dist/server/src/lib/tmux/tmux.js +24 -2
- package/dist/server/src/lib/verification/env-clean-gate.js +41 -0
- package/dist/server/src/lib/verification/gate-runner.js +17 -11
- package/dist/server/src/lib/verification/scope-gate.js +169 -3
- package/dist/server/src/types/sidebar.js +1 -0
- package/docs/en/architecture.md +26 -14
- package/docs/en/user-guide/webapp-guide.md +31 -18
- package/package.json +1 -1
- package/release-notes/0.46.0.json +110 -0
- package/release-notes/0.46.1.json +40 -0
- package/.next/server/chunks/1674.js +0 -15
- package/.next/server/chunks/5625.js +0 -25
- package/.next/server/chunks/6927.js +0 -1
- package/.next/server/chunks/9355.js +0 -1
- package/.next/static/chunks/1642-0f1bf8fb8161e10a.js +0 -1
- package/.next/static/chunks/2770-827a64760bab8a3a.js +0 -1
- package/.next/static/chunks/3922.0bc2e4e168d2b522.js +0 -1
- package/.next/static/chunks/4727-4c69d1aa4118cc09.js +0 -1
- package/.next/static/chunks/4768-fc0aa1d0891cac08.js +0 -1
- package/.next/static/chunks/5371-af1c2b68e983da61.js +0 -1
- package/.next/static/chunks/5521-c358c31f60e5e689.js +0 -1
- package/.next/static/chunks/6192-a67df090838b9aad.js +0 -1
- package/.next/static/chunks/6322-f1b30ed0ee43518f.js +0 -1
- package/.next/static/chunks/6654-ac431270fac1a283.js +0 -1
- package/.next/static/chunks/8165-3525fb42f1b4976e.js +0 -1
- package/.next/static/chunks/8318-01e7d1e5ad0a15a3.js +0 -1
- package/.next/static/chunks/8606-79c36d4c204bbd38.js +0 -1
- package/.next/static/chunks/9619-6c17a271f7f98fbb.js +0 -1
- package/.next/static/chunks/998-2eb5883186abd0bd.js +0 -1
- package/.next/static/chunks/app/layout-eaa6365f8f942e88.js +0 -1
- package/.next/static/chunks/app/repositories/page-6f7511f4ac8449e2.js +0 -1
- package/.next/static/chunks/app/review/page-95f749caae382f46.js +0 -1
- package/.next/static/chunks/app/sessions/page-ebfed2c80e916fb8.js +0 -1
- package/.next/static/chunks/app/skills/[skillId]/page-e4b14031f946c007.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-3372b78fde232b1f.js +0 -1
- package/.next/static/css/6faeb04a0b6819d4.css +0 -1
- /package/.next/static/{vYIpFRCU_Mt0wtG8F_3-6 → QxDf7lm-JJkWoj-TyWiSB}/_buildManifest.js +0 -0
- /package/.next/static/{vYIpFRCU_Mt0wtG8F_3-6 → QxDf7lm-JJkWoj-TyWiSB}/_ssgManifest.js +0 -0
|
@@ -9,13 +9,17 @@ exports.stopPolling = stopPolling;
|
|
|
9
9
|
exports.stopAllPolling = stopAllPolling;
|
|
10
10
|
exports.getActivePollers = getActivePollers;
|
|
11
11
|
exports.migrateResponsePollerWorktreeIds = migrateResponsePollerWorktreeIds;
|
|
12
|
-
const async_hooks_1 = require("async_hooks");
|
|
13
12
|
const logger_1 = require("../../lib/logger");
|
|
14
13
|
const tui_accumulator_1 = require("../tui-accumulator");
|
|
15
14
|
const prompt_dedup_1 = require("./prompt-dedup");
|
|
16
15
|
const response_dedup_1 = require("./response-dedup");
|
|
17
16
|
const prompt_dedup_state_1 = require("./prompt-dedup-state");
|
|
18
17
|
const response_checker_1 = require("./response-checker");
|
|
18
|
+
// Issue #3663: the migration's own entry points into the held-scrape store,
|
|
19
|
+
// imported from the store itself rather than through `./response-checker`'s
|
|
20
|
+
// re-export (suites that replace the checker by path keep working unchanged).
|
|
21
|
+
const pending_scraped_response_1 = require("./pending-scraped-response");
|
|
22
|
+
const poller_owner_1 = require("./poller-owner");
|
|
19
23
|
const terminal_broadcast_1 = require("../../lib/realtime/terminal-broadcast");
|
|
20
24
|
const terminal_session_ownership_1 = require("../../lib/realtime/terminal-session-ownership");
|
|
21
25
|
const session_name_1 = require("../../lib/cli-tools/session-name");
|
|
@@ -58,7 +62,7 @@ const coordinator = (0, global_state_1.getOrInitGlobal)('__responsePollerCoordin
|
|
|
58
62
|
owners: new Map(),
|
|
59
63
|
running: new Map(),
|
|
60
64
|
pendingRestart: new Map(),
|
|
61
|
-
|
|
65
|
+
latestOwners: new Map(),
|
|
62
66
|
generationCounter: 0,
|
|
63
67
|
pausedOnPrompt: new Set(),
|
|
64
68
|
}));
|
|
@@ -68,6 +72,7 @@ const coordinator = (0, global_state_1.getOrInitGlobal)('__responsePollerCoordin
|
|
|
68
72
|
// `globalThis` across HMR, and a poller started before the reload would
|
|
69
73
|
// otherwise crash the first tick after it.
|
|
70
74
|
coordinator.pausedOnPrompt ??= new Set();
|
|
75
|
+
coordinator.latestOwners ??= new Map();
|
|
71
76
|
/**
|
|
72
77
|
* Active pollers map: "worktreeId:instanceId" -> NodeJS.Timeout
|
|
73
78
|
*
|
|
@@ -101,11 +106,17 @@ exports.pollingStartTimes = coordinator.pollingStartTimes;
|
|
|
101
106
|
* @param instanceId - Optional agent instance ID (defaults to cliToolId)
|
|
102
107
|
*/
|
|
103
108
|
function getPollerKey(worktreeId, cliToolId, instanceId) {
|
|
104
|
-
|
|
109
|
+
// Issue #3705: spelled in `./poller-owner`, so the writers that ask whether a
|
|
110
|
+
// tick may still act for this key name it the same way without importing here.
|
|
111
|
+
return (0, poller_owner_1.pollerKeyOf)(worktreeId, cliToolId, instanceId);
|
|
105
112
|
}
|
|
106
113
|
/** Hand `pollerKey` to a brand-new chain, retiring whichever chain held it. */
|
|
107
114
|
function takeOwnership(pollerKey) {
|
|
108
|
-
|
|
115
|
+
// Issue #3705: the newest chain the key ever had, not only the one holding it
|
|
116
|
+
// now. A chain that was stopped (a route, a migration that displaced it) has
|
|
117
|
+
// left `owners`, but a tick of it may still be in flight, and it has a
|
|
118
|
+
// successor from this moment on.
|
|
119
|
+
const previous = coordinator.owners.get(pollerKey) ?? coordinator.latestOwners.get(pollerKey);
|
|
109
120
|
if (previous)
|
|
110
121
|
previous.superseded = true;
|
|
111
122
|
const owner = {
|
|
@@ -116,6 +127,7 @@ function takeOwnership(pollerKey) {
|
|
|
116
127
|
selfStopped: false,
|
|
117
128
|
};
|
|
118
129
|
coordinator.owners.set(pollerKey, owner);
|
|
130
|
+
coordinator.latestOwners.set(pollerKey, owner);
|
|
119
131
|
return owner;
|
|
120
132
|
}
|
|
121
133
|
/**
|
|
@@ -171,7 +183,7 @@ function startPolling(worktreeId, cliToolId, instanceId) {
|
|
|
171
183
|
// previous turn.
|
|
172
184
|
inFlight.owner.superseded = true;
|
|
173
185
|
if (Date.now() - inFlight.since < exports.STALLED_TICK_TIMEOUT) {
|
|
174
|
-
coordinator.pendingRestart.set(pollerKey, target);
|
|
186
|
+
coordinator.pendingRestart.set(pollerKey, { target, behind: inFlight.owner });
|
|
175
187
|
return;
|
|
176
188
|
}
|
|
177
189
|
logger.warn('poller:restart-past-stalled-tick', {
|
|
@@ -293,7 +305,11 @@ async function runPollTick(target, owner) {
|
|
|
293
305
|
// Check for response
|
|
294
306
|
let recorded = false;
|
|
295
307
|
try {
|
|
296
|
-
|
|
308
|
+
// The token rides through `checkForResponse()` (`./poller-owner`), so a
|
|
309
|
+
// `stopPolling()` raised inside a superseded tick can be told apart from
|
|
310
|
+
// one raised by a route, `session-cleanup` or `kill-session` (#2223), and
|
|
311
|
+
// the held-scrape store can turn away a tick that was retired (#3663).
|
|
312
|
+
recorded = await poller_owner_1.pollerOwnerStorage.run(owner, () => (0, response_checker_1.checkForResponse)(target.worktreeId, target.cliToolId, target.instanceId));
|
|
297
313
|
}
|
|
298
314
|
catch (error) {
|
|
299
315
|
logger.error('error:', { error: error instanceof Error ? error.message : String(error) });
|
|
@@ -310,8 +326,14 @@ async function runPollTick(target, owner) {
|
|
|
310
326
|
// Issue #2223: skipped once another chain owns the key — a superseded tick
|
|
311
327
|
// would push the previous turn's screen on top of the live one, and its
|
|
312
328
|
// `version` counter would make the client drop the real frame that follows.
|
|
329
|
+
//
|
|
330
|
+
// Issue #3705: and the snapshot carries the owner explicitly
|
|
331
|
+
// (`snapshotOwnerStorage`), because this is only where it starts. Its
|
|
332
|
+
// capture and the writers inside `buildCurrentOutput` resume after awaits,
|
|
333
|
+
// and they ask again then (`maySnapshotPublish`): a successor that took the
|
|
334
|
+
// key in the meantime is not overwritten by the turn that ended.
|
|
313
335
|
if (!owner.superseded) {
|
|
314
|
-
void (0, terminal_broadcast_1.broadcastTerminalSnapshot)(target.worktreeId, target.cliToolId, target.instanceId);
|
|
336
|
+
void poller_owner_1.snapshotOwnerStorage.run(owner, () => (0, terminal_broadcast_1.broadcastTerminalSnapshot)(target.worktreeId, target.cliToolId, target.instanceId));
|
|
315
337
|
}
|
|
316
338
|
// Schedule next poll ONLY after current one completes
|
|
317
339
|
// Guard: only if THIS chain is still the poller for the key (Issue #2223)
|
|
@@ -326,10 +348,15 @@ async function runPollTick(target, owner) {
|
|
|
326
348
|
// Apply a restart that arrived while this tick was in flight. Doing it here
|
|
327
349
|
// rather than in startPolling() is what keeps the old and new chains from
|
|
328
350
|
// polling the same pane at the same time.
|
|
351
|
+
//
|
|
352
|
+
// Issue #3705: only the restart handed to THIS tick. One queued behind a
|
|
353
|
+
// later chain's tick belongs to that tick: applied here, by a tick that was
|
|
354
|
+
// cut loose past STALLED_TICK_TIMEOUT and came back, it would stop the chain
|
|
355
|
+
// whose tick is still running and start the next one beside it.
|
|
329
356
|
const pending = coordinator.pendingRestart.get(pollerKey);
|
|
330
|
-
if (pending) {
|
|
357
|
+
if (pending && pending.behind === owner) {
|
|
331
358
|
coordinator.pendingRestart.delete(pollerKey);
|
|
332
|
-
restartChain(pollerKey, pending);
|
|
359
|
+
restartChain(pollerKey, pending.target);
|
|
333
360
|
}
|
|
334
361
|
}
|
|
335
362
|
}
|
|
@@ -391,7 +418,7 @@ function stopPollingByKey(pollerKey, options = {}) {
|
|
|
391
418
|
// (worktree gone, session not running, prompt detected, TUI reply saved).
|
|
392
419
|
// Honouring that verdict would kill the chain that replaced it — the old
|
|
393
420
|
// tick is describing a turn that is already over.
|
|
394
|
-
const caller =
|
|
421
|
+
const caller = poller_owner_1.pollerOwnerStorage.getStore();
|
|
395
422
|
if (caller && caller.pollerKey === pollerKey && (caller.superseded || caller.stopped)) {
|
|
396
423
|
logger.info('poller:stale-stop-ignored', {
|
|
397
424
|
pollerKey,
|
|
@@ -532,8 +559,23 @@ function splitPollerKey(pollerKey) {
|
|
|
532
559
|
* one in-flight TUI response may be truncated at the rename boundary; the next
|
|
533
560
|
* turn accumulates normally.
|
|
534
561
|
*
|
|
535
|
-
* Takes the whole batch because IDs can swap (A→B, B→A)
|
|
536
|
-
* removed before any destination key is written.
|
|
562
|
+
* Takes the whole batch because IDs can swap (A→B, B→A) or chain (A→B→C):
|
|
563
|
+
* every source key is removed before any destination key is written. That
|
|
564
|
+
* includes the dedup state (Issue #3553) — of running pollers and paused chains
|
|
565
|
+
* alike — which is lifted off every source key in one pass and only then
|
|
566
|
+
* written, so a pair handled early cannot overwrite a source handled later.
|
|
567
|
+
*
|
|
568
|
+
* Issue #3663: the held scrapes (#2436) move too, by the same lift-then-place
|
|
569
|
+
* rule, keeping everything but their worktree ID, which becomes the new one.
|
|
570
|
+
* Every chain whose key changes hands is retired (`stopped`), so a tick still
|
|
571
|
+
* awaiting the transcript reader cannot come back and hold, drop or write
|
|
572
|
+
* under it: the moved chains' old owners, and a chain already running on a
|
|
573
|
+
* destination key that no source vacates — that one is stopped like any
|
|
574
|
+
* other, which writes its held scrape under the ID it carries before the moved
|
|
575
|
+
* one arrives. A chain that cannot be resolved has its held scrape written
|
|
576
|
+
* under the NEW ID: the old one is gone from the table, and a row for it fails
|
|
577
|
+
* the foreign key and is lost. A chain with a tick running at the moment of
|
|
578
|
+
* the migration does not hand its response hash on (see the dedup move below).
|
|
537
579
|
*
|
|
538
580
|
* @param renames - Worktree ID pairs being applied
|
|
539
581
|
* @param resolveCliToolId - Maps a poller's (worktree, instance) back to its CLI
|
|
@@ -562,7 +604,7 @@ function migrateResponsePollerWorktreeIds(renames, resolveCliToolId) {
|
|
|
562
604
|
continue;
|
|
563
605
|
const cliToolId = resolveCliToolId(parts.worktreeId, parts.instanceId);
|
|
564
606
|
if (!cliToolId) {
|
|
565
|
-
abandoned.push(pollerKey);
|
|
607
|
+
abandoned.push({ pollerKey, newWorktreeId });
|
|
566
608
|
continue;
|
|
567
609
|
}
|
|
568
610
|
moves.push({
|
|
@@ -576,6 +618,16 @@ function migrateResponsePollerWorktreeIds(renames, resolveCliToolId) {
|
|
|
576
618
|
// Phase 1: stop every affected timer and lift the state off the old keys.
|
|
577
619
|
// Done for the whole batch before any write so a swap cannot self-collide.
|
|
578
620
|
const carried = new Map();
|
|
621
|
+
// Issue #3663: the moves whose chain has a tick running right now — read
|
|
622
|
+
// before anything below touches the coordinator. See the response hash below.
|
|
623
|
+
// The chain that holds the key now, not merely some tick under the key: a
|
|
624
|
+
// chain retired earlier leaves its `running` entry until its own tick
|
|
625
|
+
// returns (the epilogue removes it by owner), and the chain that replaced it
|
|
626
|
+
// may not have started a tick yet.
|
|
627
|
+
const midTick = moves.filter((move) => {
|
|
628
|
+
const inFlight = coordinator.running.get(move.oldKey);
|
|
629
|
+
return inFlight !== undefined && inFlight.owner === coordinator.owners.get(move.oldKey);
|
|
630
|
+
});
|
|
579
631
|
for (const move of moves) {
|
|
580
632
|
const timerId = exports.activePollers.get(move.oldKey);
|
|
581
633
|
if (timerId)
|
|
@@ -596,33 +648,26 @@ function migrateResponsePollerWorktreeIds(renames, resolveCliToolId) {
|
|
|
596
648
|
coordinator.pendingRestart.delete(move.oldKey);
|
|
597
649
|
carried.set(move.newKey, { startedAt: exports.pollingStartTimes.get(move.oldKey) });
|
|
598
650
|
exports.pollingStartTimes.delete(move.oldKey);
|
|
599
|
-
(0, prompt_dedup_1.renamePromptHashCacheKey)(move.oldKey, move.newKey);
|
|
600
|
-
(0, response_dedup_1.renameResponseHashCacheKey)(move.oldKey, move.newKey);
|
|
601
|
-
// Issue #1695: the prompt hash moved on the line above, so the guard keeps
|
|
602
|
-
// suppressing the prompt on screen under the new ID. Its tally has to move
|
|
603
|
-
// with it, or `capture --json` reports zero skips for a session that is
|
|
604
|
-
// still skipping. Old worktree ID comes back out of the key we just left.
|
|
605
|
-
const movedFrom = splitPollerKey(move.oldKey);
|
|
606
|
-
if (movedFrom) {
|
|
607
|
-
(0, prompt_dedup_state_1.renamePromptDedupSkips)(movedFrom.worktreeId, move.newWorktreeId, move.cliToolId, move.instanceId);
|
|
608
|
-
}
|
|
609
651
|
(0, tui_accumulator_1.clearTuiAccumulator)(move.oldKey);
|
|
610
652
|
}
|
|
611
|
-
|
|
653
|
+
// Stop the abandoned pollers before any dedup state is written: the stop
|
|
654
|
+
// clears every cache under its key, and that key can be the destination of
|
|
655
|
+
// another move in this batch (A:x paused → B:x while B:x is abandoned).
|
|
656
|
+
// Stopped afterwards, it erased the state that had just arrived (#3553).
|
|
657
|
+
// An abandoned key is never a move source, so nothing still to be moved is
|
|
658
|
+
// lost here; and the paused chains are collected after it, as before, so a
|
|
659
|
+
// pause the stop ends is not carried.
|
|
660
|
+
//
|
|
661
|
+
// Issue #3663: its held scrape is pointed at the new ID first, so the stop
|
|
662
|
+
// writes it there — the old ID is no longer in the table.
|
|
663
|
+
for (const { pollerKey, newWorktreeId } of abandoned) {
|
|
664
|
+
(0, pending_scraped_response_1.retargetPendingScrapedResponse)(pollerKey, newWorktreeId);
|
|
612
665
|
stopPollingByKey(pollerKey);
|
|
613
666
|
logger.warn('poller:migrate-abandoned', { pollerKey });
|
|
614
667
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
exports.pollingStartTimes.set(move.newKey, startedAt ?? Date.now());
|
|
619
|
-
if (isFullScreenTui(move.cliToolId)) {
|
|
620
|
-
(0, tui_accumulator_1.initTuiAccumulator)(move.newKey);
|
|
621
|
-
}
|
|
622
|
-
scheduleNextResponsePoll(move.newWorktreeId, move.cliToolId, move.instanceId);
|
|
623
|
-
}
|
|
624
|
-
// Issue #2230: a chain paused on a prompt has no timer, so the loop above
|
|
625
|
-
// never sees it — but it is holding the response hash for the turn it paused
|
|
668
|
+
const abandonedKeys = new Set(abandoned.map(({ pollerKey }) => pollerKey));
|
|
669
|
+
// Issue #2230: a chain paused on a prompt has no timer, so the loops here
|
|
670
|
+
// never see it — but it is holding the response hash for the turn it paused
|
|
626
671
|
// on, and `/respond` will resume it under the NEW ID. Move the hash and the
|
|
627
672
|
// pause mark with it; the chain itself stays paused until that resume.
|
|
628
673
|
const pausedMoves = [];
|
|
@@ -635,11 +680,106 @@ function migrateResponsePollerWorktreeIds(renames, resolveCliToolId) {
|
|
|
635
680
|
continue;
|
|
636
681
|
pausedMoves.push({ oldKey: pollerKey, newKey: `${newWorktreeId}:${parts.instanceId}` });
|
|
637
682
|
}
|
|
683
|
+
// Issue #3663: every held scrape under a renamed worktree ID moves — a
|
|
684
|
+
// running chain's, a paused chain's, and one whose chain is already gone.
|
|
685
|
+
// The abandoned ones were written above and are no longer held.
|
|
686
|
+
const pendingMoves = [];
|
|
687
|
+
for (const pollerKey of (0, pending_scraped_response_1.listPendingScrapedResponseKeys)()) {
|
|
688
|
+
if (abandonedKeys.has(pollerKey))
|
|
689
|
+
continue;
|
|
690
|
+
const parts = splitPollerKey(pollerKey);
|
|
691
|
+
if (!parts)
|
|
692
|
+
continue;
|
|
693
|
+
const newWorktreeId = targets.get(parts.worktreeId);
|
|
694
|
+
if (!newWorktreeId)
|
|
695
|
+
continue;
|
|
696
|
+
pendingMoves.push({ oldKey: pollerKey, newKey: `${newWorktreeId}:${parts.instanceId}`, newWorktreeId });
|
|
697
|
+
}
|
|
698
|
+
// Issue #3663: a destination a chain (running or paused) moves onto, that no
|
|
699
|
+
// source of this batch vacates, may already be held by another chain — B:x
|
|
700
|
+
// running while A:x moves to B:x. That chain loses the key, so it is stopped
|
|
701
|
+
// here like any other stop: its held scrape is written under the ID it
|
|
702
|
+
// carries (the current one), its owner is retired so its in-flight tick can
|
|
703
|
+
// no longer hold or drop anything, and its caches are cleared before the
|
|
704
|
+
// moved state is written. A destination nothing is on is left alone, and so
|
|
705
|
+
// is every other instance of the destination worktree.
|
|
706
|
+
const vacated = new Set([
|
|
707
|
+
...moves.map((move) => move.oldKey),
|
|
708
|
+
...pausedMoves.map((move) => move.oldKey),
|
|
709
|
+
...pendingMoves.map((move) => move.oldKey),
|
|
710
|
+
]);
|
|
711
|
+
// A held scrape moved on its own (no chain, no pause) changes the key's
|
|
712
|
+
// owner just the same, so its destination is handled alike (#3663 review).
|
|
713
|
+
const occupied = new Set([
|
|
714
|
+
...moves.map((move) => move.newKey),
|
|
715
|
+
...pausedMoves.map((move) => move.newKey),
|
|
716
|
+
...pendingMoves.map((move) => move.newKey),
|
|
717
|
+
]);
|
|
718
|
+
for (const pollerKey of occupied) {
|
|
719
|
+
if (vacated.has(pollerKey) || abandonedKeys.has(pollerKey))
|
|
720
|
+
continue;
|
|
721
|
+
const held = coordinator.owners.has(pollerKey) ||
|
|
722
|
+
exports.activePollers.has(pollerKey) ||
|
|
723
|
+
coordinator.pausedOnPrompt.has(pollerKey) ||
|
|
724
|
+
(0, pending_scraped_response_1.hasPendingScrapedResponse)(pollerKey);
|
|
725
|
+
if (!held)
|
|
726
|
+
continue;
|
|
727
|
+
stopPollingByKey(pollerKey);
|
|
728
|
+
logger.warn('poller:migrate-displaced', { pollerKey });
|
|
729
|
+
}
|
|
730
|
+
// Issue #3553: the dedup state of the whole batch moves in one call per map
|
|
731
|
+
// family, each lifting every source before writing any destination. Re-keyed
|
|
732
|
+
// pair by pair, a swap left A with its own state and B empty.
|
|
733
|
+
//
|
|
734
|
+
// Issue #3663: except the response hash of a chain whose tick is running.
|
|
735
|
+
// That tick may have registered the hash of a reply it has not yet saved or
|
|
736
|
+
// held — it is awaiting the transcript reader, and the hold it comes back
|
|
737
|
+
// with is refused (its owner is retired above). Handed on, the hash would
|
|
738
|
+
// make the successor skip a reply nobody wrote. Dropped, the successor judges
|
|
739
|
+
// the screen itself and holds or saves it. The price, taken knowingly: a
|
|
740
|
+
// reply that tick HAD already saved may be saved once more by the successor
|
|
741
|
+
// — a duplicate row rather than a lost one, the trade #2436 makes. Deciding
|
|
742
|
+
// here, once, replaces marking the hash and taking it back later, whose
|
|
743
|
+
// lifetime every later move, resume and restart would have to carry.
|
|
744
|
+
// The prompt hash and the prompt-skip tally move as before.
|
|
745
|
+
// Dropped on the source key only, before the batch moves: the destination is
|
|
746
|
+
// left as the batch leaves it, so what another source of a many-to-one move
|
|
747
|
+
// brings there (a chain that saved its reply and is waiting) still stands.
|
|
748
|
+
for (const move of midTick)
|
|
749
|
+
(0, response_dedup_1.clearResponseHashCache)(move.oldKey);
|
|
750
|
+
(0, prompt_dedup_1.renamePromptHashCacheKeys)(moves);
|
|
751
|
+
(0, response_dedup_1.renameResponseHashCacheKeys)([...moves, ...pausedMoves]);
|
|
752
|
+
(0, pending_scraped_response_1.movePendingScrapedResponses)(pendingMoves);
|
|
753
|
+
// Issue #1695: the prompt hash moved above, so the guard keeps suppressing
|
|
754
|
+
// the prompt on screen under the new ID. Its tally has to move with it, or
|
|
755
|
+
// `capture --json` reports zero skips for a session that is still skipping.
|
|
756
|
+
// Old worktree ID comes back out of the key being left.
|
|
757
|
+
(0, prompt_dedup_state_1.renamePromptDedupSkipsBatch)(moves.flatMap((move) => {
|
|
758
|
+
const movedFrom = splitPollerKey(move.oldKey);
|
|
759
|
+
return movedFrom
|
|
760
|
+
? [{
|
|
761
|
+
oldWorktreeId: movedFrom.worktreeId,
|
|
762
|
+
newWorktreeId: move.newWorktreeId,
|
|
763
|
+
cliToolId: move.cliToolId,
|
|
764
|
+
instanceId: move.instanceId,
|
|
765
|
+
}]
|
|
766
|
+
: [];
|
|
767
|
+
}));
|
|
768
|
+
// Phase 2: restart each poller under its new identity.
|
|
769
|
+
for (const move of moves) {
|
|
770
|
+
const startedAt = carried.get(move.newKey)?.startedAt;
|
|
771
|
+
exports.pollingStartTimes.set(move.newKey, startedAt ?? Date.now());
|
|
772
|
+
if (isFullScreenTui(move.cliToolId)) {
|
|
773
|
+
(0, tui_accumulator_1.initTuiAccumulator)(move.newKey);
|
|
774
|
+
}
|
|
775
|
+
scheduleNextResponsePoll(move.newWorktreeId, move.cliToolId, move.instanceId);
|
|
776
|
+
}
|
|
777
|
+
// Issue #2230: the pause marks of the chains collected above follow their
|
|
778
|
+
// hashes (moved with the batch). All removed before any is added, for the
|
|
779
|
+
// same swap reason.
|
|
638
780
|
for (const move of pausedMoves)
|
|
639
781
|
coordinator.pausedOnPrompt.delete(move.oldKey);
|
|
640
|
-
for (const move of pausedMoves)
|
|
641
|
-
(0, response_dedup_1.renameResponseHashCacheKey)(move.oldKey, move.newKey);
|
|
782
|
+
for (const move of pausedMoves)
|
|
642
783
|
coordinator.pausedOnPrompt.add(move.newKey);
|
|
643
|
-
}
|
|
644
784
|
return moves;
|
|
645
785
|
}
|
|
@@ -84,6 +84,7 @@ const tool_id_4 = require("../../lib/hooks/sources/command-code/tool-id");
|
|
|
84
84
|
const registry_1 = require("../../lib/hooks/sources/registry");
|
|
85
85
|
const relay_triggers_1 = require("../../lib/relay/relay-triggers");
|
|
86
86
|
const global_state_1 = require("../global-state");
|
|
87
|
+
const poller_owner_1 = require("./poller-owner");
|
|
87
88
|
const logger = (0, logger_1.createLogger)('lib/polling/structured-history-gate');
|
|
88
89
|
/**
|
|
89
90
|
* One in-flight capture per instance (Issue #2246).
|
|
@@ -382,7 +383,25 @@ async function captureStructuredHistoryTurn(worktreeId, cliToolId, instanceId, c
|
|
|
382
383
|
// back. So a provisional capture announces nothing at all; the relay
|
|
383
384
|
// keeps waiting on the deadline it already has, and the settled capture
|
|
384
385
|
// that follows announces the finished body.
|
|
385
|
-
|
|
386
|
+
//
|
|
387
|
+
// Issue #3701: a poller tick retired while it awaited the reader
|
|
388
|
+
// announces nothing under the key it lost, and claims nothing, so its
|
|
389
|
+
// successor still announces this completion. Asked by the poller key
|
|
390
|
+
// (`getPollerKey`'s `worktreeId:instanceId`), not `captureKey`. The
|
|
391
|
+
// Stop hook runs outside any tick and is never refused. Issue #3705:
|
|
392
|
+
// what the reader itself writes during the `await` (rows, user rows,
|
|
393
|
+
// the cursor, agy's follow list) is asked the same question by the
|
|
394
|
+
// reader, after its own last `await` (`mayReaderWrite`).
|
|
395
|
+
const pollerKey = (0, poller_owner_1.pollerKeyOf)(worktreeId, cliToolId, resolvedInstanceId);
|
|
396
|
+
if (captured && completion === 'settled' && !(0, poller_owner_1.mayActForPollerKey)(pollerKey)) {
|
|
397
|
+
logger.info('structured-history-completion-refused', {
|
|
398
|
+
worktreeId,
|
|
399
|
+
cliToolId,
|
|
400
|
+
instanceId: resolvedInstanceId,
|
|
401
|
+
generation: (0, poller_owner_1.currentPollerOwner)()?.generation,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
else if (captured && completion === 'settled') {
|
|
386
405
|
if (claimCompletionAnnouncement(captureKey, readerReport.completionKey)) {
|
|
387
406
|
(0, relay_triggers_1.onRelayTurnCompleted)(worktreeId, cliToolId, resolvedInstanceId, true);
|
|
388
407
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* the promptType/defaultOptionNumber fallback introduced in Bug1).
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.MultiSelectAnswerRejectedError = exports.MULTI_SELECT_NOT_COMMITTED_REASON = exports.FreeTextAtChoiceOnlyPromptError = exports.FreeTextAnswerRejectedError = exports.FREE_TEXT_AT_MENU_ROW_REASON = exports.PromptAnswerRejectedError = exports.ANSWER_MODE_KEYS_REASON = void 0;
|
|
10
|
+
exports.PromptAnswerAbortedError = exports.MultiSelectAnswerRejectedError = exports.MULTI_SELECT_NOT_COMMITTED_REASON = exports.FreeTextAtChoiceOnlyPromptError = exports.FreeTextAnswerRejectedError = exports.FREE_TEXT_AT_MENU_ROW_REASON = exports.PromptAnswerRejectedError = exports.ANSWER_MODE_KEYS_REASON = void 0;
|
|
11
11
|
exports.sendPromptAnswer = sendPromptAnswer;
|
|
12
12
|
const tmux_1 = require("./tmux/tmux");
|
|
13
13
|
const frame_1 = require("../lib/detection/tools/frame");
|
|
@@ -665,7 +665,7 @@ async function recaptureAfterKeys(sessionName) {
|
|
|
665
665
|
* @throws {MultiSelectAnswerRejectedError} whenever the question was not
|
|
666
666
|
* committed; `keysSent` says whether the pane was touched.
|
|
667
667
|
*/
|
|
668
|
-
async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted) {
|
|
668
|
+
async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted, stillCurrent) {
|
|
669
669
|
const cursor = promptData.options.find((option) => option.isDefault === true);
|
|
670
670
|
if (cursor === undefined) {
|
|
671
671
|
throw new MultiSelectAnswerRejectedError('cursor-unknown', false, wanted);
|
|
@@ -679,12 +679,13 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted)
|
|
|
679
679
|
...current.filter((n) => !wanted.includes(n)),
|
|
680
680
|
].sort((a, b) => a - b);
|
|
681
681
|
if (toggles.length > 0) {
|
|
682
|
-
await (
|
|
682
|
+
await sendSpecialKeysWhileCurrent(sessionName, toggles.map(String), stillCurrent);
|
|
683
683
|
}
|
|
684
684
|
const keysSent = toggles.length > 0;
|
|
685
685
|
// 2. Read the screen back and refuse unless it is the same question with
|
|
686
686
|
// exactly the requested boxes ticked.
|
|
687
687
|
const afterToggle = await recaptureAfterKeys(sessionName);
|
|
688
|
+
assertStillCurrent(stillCurrent, keysSent);
|
|
688
689
|
if (afterToggle === null) {
|
|
689
690
|
throw new MultiSelectAnswerRejectedError('recapture-failed', keysSent, wanted);
|
|
690
691
|
}
|
|
@@ -711,14 +712,12 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted)
|
|
|
711
712
|
if (cursorNow === undefined) {
|
|
712
713
|
throw new MultiSelectAnswerRejectedError('cursor-unknown', keysSent, wanted);
|
|
713
714
|
}
|
|
714
|
-
await (
|
|
715
|
-
...downKeys(verified.options.length - cursorNow.number + 1),
|
|
716
|
-
'Enter',
|
|
717
|
-
]);
|
|
715
|
+
await sendSpecialKeysWhileCurrent(sessionName, [...downKeys(verified.options.length - cursorNow.number + 1), 'Enter'], stillCurrent);
|
|
718
716
|
// 4. The second stage. `Submit` opens the Review page and the answer is sent
|
|
719
717
|
// from there; `Next` advances to the following question, which IS the
|
|
720
718
|
// commit for this one (its tab turns `✔`).
|
|
721
719
|
const afterConfirm = await recaptureAfterKeys(sessionName);
|
|
720
|
+
assertStillCurrent(stillCurrent, true);
|
|
722
721
|
if (afterConfirm === null) {
|
|
723
722
|
throw new MultiSelectAnswerRejectedError('recapture-failed', true, wanted);
|
|
724
723
|
}
|
|
@@ -729,7 +728,7 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted)
|
|
|
729
728
|
if (review.hasUnansweredWarning) {
|
|
730
729
|
throw new MultiSelectAnswerRejectedError('review-unanswered', true, wanted);
|
|
731
730
|
}
|
|
732
|
-
await (
|
|
731
|
+
await sendSpecialKeysWhileCurrent(sessionName, ['Enter'], stillCurrent);
|
|
733
732
|
return;
|
|
734
733
|
}
|
|
735
734
|
const next = (0, dialog_1.readCommandCodeQuestionDialog)(afterConfirm);
|
|
@@ -740,6 +739,50 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted)
|
|
|
740
739
|
throw new MultiSelectAnswerRejectedError('not-committed', true, wanted);
|
|
741
740
|
}
|
|
742
741
|
}
|
|
742
|
+
/**
|
|
743
|
+
* The caller's `stillCurrent` said no after one of the send's waits
|
|
744
|
+
* (Issue #3706): the keys not yet sent were not sent. Keys already typed cannot
|
|
745
|
+
* be taken back, so {@link keysSent} says whether the pane was touched; either
|
|
746
|
+
* way the answer was NOT completed and must not be recorded as one.
|
|
747
|
+
*/
|
|
748
|
+
class PromptAnswerAbortedError extends Error {
|
|
749
|
+
keysSent;
|
|
750
|
+
constructor(
|
|
751
|
+
/** Whether any key reached the pane before the stop. */
|
|
752
|
+
keysSent) {
|
|
753
|
+
super(`Prompt answer stopped by its caller (${keysSent ? 'some keys were sent' : 'no key was sent'})`);
|
|
754
|
+
this.keysSent = keysSent;
|
|
755
|
+
this.name = 'PromptAnswerAbortedError';
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
exports.PromptAnswerAbortedError = PromptAnswerAbortedError;
|
|
759
|
+
/** Stop here when the caller's `stillCurrent` says no (Issue #3706). */
|
|
760
|
+
function assertStillCurrent(stillCurrent, keysSent) {
|
|
761
|
+
if (stillCurrent && !stillCurrent())
|
|
762
|
+
throw new PromptAnswerAbortedError(keysSent);
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* `sendSpecialKeys`, asking `stillCurrent` between the keys when the caller
|
|
766
|
+
* gave one (Issue #3706). Without it the call is exactly the old two-argument
|
|
767
|
+
* one, so manual answers and every other caller send as before.
|
|
768
|
+
*/
|
|
769
|
+
async function sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent) {
|
|
770
|
+
if (!stillCurrent) {
|
|
771
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
try {
|
|
775
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys, { shouldContinue: stillCurrent });
|
|
776
|
+
}
|
|
777
|
+
catch (error) {
|
|
778
|
+
// By name rather than `instanceof`: test doubles of `./tmux/tmux` need not
|
|
779
|
+
// export the class.
|
|
780
|
+
if (error instanceof Error && error.name === 'SpecialKeysAbortedError') {
|
|
781
|
+
throw new PromptAnswerAbortedError(true);
|
|
782
|
+
}
|
|
783
|
+
throw error;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
743
786
|
/**
|
|
744
787
|
* Send an answer to a tmux session, using cursor-key navigation for
|
|
745
788
|
* Claude Code / Antigravity multiple-choice prompts and text input for
|
|
@@ -750,7 +793,7 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted)
|
|
|
750
793
|
* - src/lib/auto-yes-manager.ts (L340-399)
|
|
751
794
|
*/
|
|
752
795
|
async function sendPromptAnswer(params) {
|
|
753
|
-
const { sessionName, answer, cliToolId, promptData, fallbackPromptType, fallbackDefaultOptionNumber } = params;
|
|
796
|
+
const { sessionName, answer, cliToolId, promptData, fallbackPromptType, fallbackDefaultOptionNumber, stillCurrent } = params;
|
|
754
797
|
// Issue #2755: Command Code's checkbox question, before every guard below.
|
|
755
798
|
// Its answer is a SET (`"1,3"`), which none of them can read — `/^\d+$/` is
|
|
756
799
|
// how all three ask "is this a number?", so a set would be judged as free
|
|
@@ -760,7 +803,7 @@ async function sendPromptAnswer(params) {
|
|
|
760
803
|
// a two-stage confirm, not a digit and an Enter.
|
|
761
804
|
const multiSelect = readMultiSelectRequest(params);
|
|
762
805
|
if (multiSelect !== null) {
|
|
763
|
-
await sendCommandCodeMultiSelectAnswer(sessionName, multiSelect.promptData, multiSelect.wanted);
|
|
806
|
+
await sendCommandCodeMultiSelectAnswer(sessionName, multiSelect.promptData, multiSelect.wanted, stillCurrent);
|
|
764
807
|
(0, tmux_capture_cache_1.invalidateCache)(sessionName);
|
|
765
808
|
return;
|
|
766
809
|
}
|
|
@@ -781,6 +824,8 @@ async function sendPromptAnswer(params) {
|
|
|
781
824
|
// the Enter after them confirms that row — so the cursor has to be checked
|
|
782
825
|
// here too, before the branch.
|
|
783
826
|
assertFreeTextCursorIsOnTheField(params);
|
|
827
|
+
// Issue #3706: the guard above may have read the pane; nothing is typed yet.
|
|
828
|
+
assertStillCurrent(stillCurrent, false);
|
|
784
829
|
// Determine if this is an arrow-key-navigated multiple-choice prompt.
|
|
785
830
|
// Claude Code and Antigravity (agy) both render selection menus that only
|
|
786
831
|
// respond to cursor navigation + Enter, not to typed option numbers
|
|
@@ -829,7 +874,7 @@ async function sendPromptAnswer(params) {
|
|
|
829
874
|
keys.push(...buildNavigationKeys(downToNext));
|
|
830
875
|
// 4. Enter to submit
|
|
831
876
|
keys.push('Enter');
|
|
832
|
-
await (
|
|
877
|
+
await sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent);
|
|
833
878
|
}
|
|
834
879
|
else {
|
|
835
880
|
// Single-select: navigate and Enter to select
|
|
@@ -847,7 +892,7 @@ async function sendPromptAnswer(params) {
|
|
|
847
892
|
const keys = (isAskUserQuestionPicker && offset === 0)
|
|
848
893
|
? ['Down', 'Up', 'Enter']
|
|
849
894
|
: [...navigationKeys, 'Enter'];
|
|
850
|
-
await (
|
|
895
|
+
await sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent);
|
|
851
896
|
}
|
|
852
897
|
}
|
|
853
898
|
else {
|
|
@@ -858,6 +903,8 @@ async function sendPromptAnswer(params) {
|
|
|
858
903
|
if (!shouldSuppressEnter(params, resolvedSubmitMode, dialog)) {
|
|
859
904
|
// Wait a moment for the input to be processed
|
|
860
905
|
await new Promise(resolve => setTimeout(resolve, cli_tool_timing_config_1.TUI_TEXT_INPUT_WAIT_MS));
|
|
906
|
+
// Issue #3706: the text is typed; the Enter that submits it is not.
|
|
907
|
+
assertStillCurrent(stillCurrent, true);
|
|
861
908
|
// Send Enter
|
|
862
909
|
await (0, tmux_1.sendKeys)(sessionName, '', true);
|
|
863
910
|
}
|
|
@@ -24,6 +24,7 @@ const manager_1 = require("../../lib/cli-tools/manager");
|
|
|
24
24
|
const tmux_capture_cache_1 = require("../../lib/tmux/tmux-capture-cache");
|
|
25
25
|
const global_state_1 = require("../global-state");
|
|
26
26
|
const terminal_session_ownership_1 = require("./terminal-session-ownership");
|
|
27
|
+
const poller_owner_1 = require("../../lib/polling/poller-owner");
|
|
27
28
|
const logger = (0, logger_1.createLogger)('terminal-broadcast');
|
|
28
29
|
const versionCounters = (0, global_state_1.getOrInitGlobal)('__terminalSnapshotVersions', () => new Map());
|
|
29
30
|
exports.INTERACTION_SNAPSHOT_RETRY_DELAYS_MS = [100, 250, 500, 750];
|
|
@@ -43,11 +44,24 @@ async function broadcastTerminalSnapshot(worktreeId, cliToolId, instanceId) {
|
|
|
43
44
|
try {
|
|
44
45
|
if (!(await isPushableSession(worktreeId, cliToolId, instanceId)))
|
|
45
46
|
return;
|
|
47
|
+
// Issue #3705: the response poller starts this snapshot inside its tick's
|
|
48
|
+
// owner (`snapshotOwnerStorage`) and the question is asked again after each
|
|
49
|
+
// `await`: a successor that took the key meanwhile is not overwritten by
|
|
50
|
+
// the turn that ended, and its `version` is not spent on it. Outside a
|
|
51
|
+
// poller tick, always yes.
|
|
52
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
53
|
+
throw new poller_owner_1.RetiredSnapshotError();
|
|
46
54
|
const db = (0, db_instance_1.getDbInstance)();
|
|
47
55
|
const payload = await (0, current_output_builder_1.buildCurrentOutput)(db, worktreeId, cliToolId, instanceId);
|
|
56
|
+
if (!(0, poller_owner_1.maySnapshotPublish)())
|
|
57
|
+
throw new poller_owner_1.RetiredSnapshotError();
|
|
48
58
|
emitTerminalSnapshot(worktreeId, cliToolId, payload, instanceId);
|
|
49
59
|
}
|
|
50
60
|
catch (error) {
|
|
61
|
+
if (error instanceof poller_owner_1.RetiredSnapshotError) {
|
|
62
|
+
logger.info('terminal-snapshot:retired', { worktreeId, cliToolId, instanceId });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
51
65
|
logger.error('terminal-snapshot:failed', {
|
|
52
66
|
worktreeId,
|
|
53
67
|
error: error instanceof Error ? error.message : String(error),
|