commandmate 0.49.0 → 0.49.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +251 -248
- package/.next/app-path-routes-manifest.json +22 -21
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +9 -9
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +8 -0
- 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 +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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route.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 +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/[relayId]/route.js +1 -0
- package/.next/server/app/api/relays/[relayId]/route.js.nft.json +1 -0
- package/.next/server/app/api/relays/[relayId]/route_client-reference-manifest.js +1 -0
- 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_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_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.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.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.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.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 +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.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.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 +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_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.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.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.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.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.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.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.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.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.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 +2 -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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +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 +2 -2
- package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +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.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.js.nft.json +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 -1
- 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 -1
- 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]/prompt-response/strict/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route.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 +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 +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 +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 +144 -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 +2 -2
- 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.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 +103 -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.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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.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.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.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.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 +22 -21
- package/.next/server/chunks/1062.js +1 -0
- package/.next/server/chunks/{936.js → 110.js} +1 -1
- package/.next/server/chunks/1501.js +5 -4
- package/.next/server/chunks/1656.js +2 -2
- package/.next/server/chunks/1957.js +2 -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/2897.js +1 -0
- package/.next/server/chunks/3417.js +1 -0
- package/.next/server/chunks/3505.js +1 -1
- package/.next/server/chunks/{4280.js → 3756.js} +1 -1
- package/.next/server/chunks/3801.js +31 -0
- package/.next/server/chunks/4911.js +1 -0
- package/.next/server/chunks/4936.js +1 -0
- package/.next/server/chunks/5209.js +2 -1
- package/.next/server/chunks/5354.js +1 -1
- package/.next/server/chunks/{9130.js → 5630.js} +1 -1
- package/.next/server/chunks/610.js +1 -0
- package/.next/server/chunks/6119.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6486.js +1 -1
- package/.next/server/chunks/6781.js +1 -1
- package/.next/server/chunks/6808.js +4 -0
- package/.next/server/chunks/7023.js +14 -0
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8581.js +8 -8
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/8782.js +1 -1
- package/.next/server/chunks/8807.js +63 -53
- package/.next/server/chunks/8918.js +103 -1
- package/.next/server/chunks/9198.js +144 -0
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9584.js +1 -1
- package/.next/server/chunks/9627.js +1 -1
- package/.next/server/chunks/9731.js +3 -3
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{2407-ab92ae9837c39dce.js → 2407-07a237575e1ceb9e.js} +1 -1
- package/.next/static/chunks/3931-61ad1a4fc0208d0e.js +1 -0
- package/.next/static/chunks/5794-7975b8e51e731b19.js +1 -0
- package/.next/static/chunks/6966-d8dc6032410ffaba.js +1 -0
- package/.next/static/chunks/7197-ed3b3d99ac3bd450.js +1 -0
- package/.next/static/chunks/7636-a48cf0f7110250c5.js +1 -0
- package/.next/static/chunks/app/api/agents/update/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/agents/versions/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/app/release-notes/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/app/update/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/app/update-check/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/capabilities/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/status/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/external-apps/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/fs/browse/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/fs/recent-paths/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/hooks/agent-event/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/hooks/claude-done/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/hooks/permission-request/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/metrics/vibe/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/ollama/models/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/push/escalation/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/push/subscriptions/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/push/vapid/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/relays/[relayId]/cancel/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/relays/[relayId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/relays/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/remote/pair/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/excluded/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/restore/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/scan/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/sync/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/repositories/validate-path/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/settings/default-agents/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/settings/default-surface-mode/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/sidebar/group-order/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/skills/[id]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/skills/installations/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/skills/operations/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/skills/reindex/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/skills/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/slash-commands/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/templates/[id]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/templates/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-reference/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/direct-input/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/instances/notes/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/strict/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/layout-4f64316957b0a8e5.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/more/page-ff5af5ca48774c89.js +1 -0
- package/.next/static/chunks/app/page-b4863bfe0452e09d.js +1 -0
- package/.next/static/chunks/app/proxy/[...path]/route-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/review/page-ff3efb96fdf9bb4b.js +1 -0
- package/.next/static/chunks/app/sessions/page-c6eb7c02db2f4c80.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/layout-a4f129c451de7859.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-33afc6aa96289fb0.js +1 -0
- package/.next/static/css/c1e307d05daf93b6.css +1 -0
- package/.next/trace +13 -13
- package/.next/types/app/api/relays/[relayId]/route.ts +347 -0
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/dist/cli/commands/ask.d.ts.map +1 -1
- package/dist/cli/commands/ask.js +233 -17
- package/dist/cli/commands/attach.d.ts +4 -1
- package/dist/cli/commands/attach.d.ts.map +1 -1
- package/dist/cli/commands/attach.js +19 -7
- package/dist/cli/commands/command-target.d.ts +7 -0
- package/dist/cli/commands/command-target.d.ts.map +1 -1
- package/dist/cli/commands/command-target.js +10 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +38 -2
- package/dist/cli/commands/message-dispatch.d.ts +39 -5
- package/dist/cli/commands/message-dispatch.d.ts.map +1 -1
- package/dist/cli/commands/message-dispatch.js +100 -8
- package/dist/cli/commands/relays.d.ts +26 -2
- package/dist/cli/commands/relays.d.ts.map +1 -1
- package/dist/cli/commands/relays.js +70 -5
- package/dist/cli/commands/respond-strict.d.ts.map +1 -1
- package/dist/cli/commands/respond-strict.js +22 -5
- package/dist/cli/commands/respond.d.ts +12 -0
- package/dist/cli/commands/respond.d.ts.map +1 -1
- package/dist/cli/commands/respond.js +83 -18
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +14 -8
- package/dist/cli/commands/wait-hook-stop-settle.d.ts +66 -0
- package/dist/cli/commands/wait-hook-stop-settle.d.ts.map +1 -0
- package/dist/cli/commands/wait-hook-stop-settle.js +150 -0
- package/dist/cli/commands/wait-instance.d.ts +29 -0
- package/dist/cli/commands/wait-instance.d.ts.map +1 -0
- package/dist/cli/commands/wait-instance.js +56 -0
- package/dist/cli/commands/wait-notices.d.ts +87 -0
- package/dist/cli/commands/wait-notices.d.ts.map +1 -0
- package/dist/cli/commands/wait-notices.js +301 -0
- package/dist/cli/commands/wait-poll-bookkeeping.d.ts +15 -0
- package/dist/cli/commands/wait-poll-bookkeeping.d.ts.map +1 -0
- package/dist/cli/commands/wait-poll-bookkeeping.js +57 -0
- package/dist/cli/commands/wait-poll-state.d.ts +136 -0
- package/dist/cli/commands/wait-poll-state.d.ts.map +1 -0
- package/dist/cli/commands/wait-poll-state.js +6 -0
- package/dist/cli/commands/wait-timing.d.ts +46 -0
- package/dist/cli/commands/wait-timing.d.ts.map +1 -0
- package/dist/cli/commands/wait-timing.js +99 -0
- package/dist/cli/commands/wait-turn-boundary.d.ts +284 -0
- package/dist/cli/commands/wait-turn-boundary.d.ts.map +1 -0
- package/dist/cli/commands/wait-turn-boundary.js +427 -0
- package/dist/cli/commands/wait-verify.d.ts +51 -0
- package/dist/cli/commands/wait-verify.d.ts.map +1 -0
- package/dist/cli/commands/wait-verify.js +128 -0
- package/dist/cli/commands/wait.d.ts +6 -105
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +240 -968
- package/dist/cli/commands/whoami.d.ts.map +1 -1
- package/dist/cli/commands/whoami.js +3 -1
- package/dist/cli/docs/agent-operations.d.ts +2 -2
- package/dist/cli/docs/agent-operations.d.ts.map +1 -1
- package/dist/cli/docs/agent-operations.js +24 -1
- package/dist/cli/types/api-responses.d.ts +49 -3
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/utils/api-client.d.ts +69 -1
- package/dist/cli/utils/api-client.d.ts.map +1 -1
- package/dist/cli/utils/api-client.js +226 -18
- package/dist/cli/utils/follow-up-command.d.ts +38 -0
- package/dist/cli/utils/follow-up-command.d.ts.map +1 -0
- package/dist/cli/utils/follow-up-command.js +57 -0
- package/dist/cli/utils/reply-ledger.d.ts +80 -1
- package/dist/cli/utils/reply-ledger.d.ts.map +1 -1
- package/dist/cli/utils/reply-ledger.js +147 -2
- package/dist/cli/utils/server-capabilities.d.ts +18 -0
- package/dist/cli/utils/server-capabilities.d.ts.map +1 -1
- package/dist/cli/utils/server-capabilities.js +36 -3
- package/dist/cli/utils/session-target.d.ts +1 -1
- package/dist/cli/utils/session-target.d.ts.map +1 -1
- package/dist/cli/utils/session-target.js +3 -0
- package/dist/cli/utils/verify-runner.d.ts +7 -0
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +51 -15
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -1
- package/dist/lib/cli-tools/session-name.js +11 -3
- package/dist/lib/session/send-attempt-types.d.ts +48 -1
- package/dist/lib/session/send-attempt-types.d.ts.map +1 -1
- package/dist/lib/session/send-attempt-types.js +18 -1
- package/dist/lib/verification/session-kill-ledger.d.ts +110 -0
- package/dist/lib/verification/session-kill-ledger.d.ts.map +1 -0
- package/dist/lib/verification/session-kill-ledger.js +174 -0
- package/dist/server/locales/en/worktree.json +20 -3
- package/dist/server/locales/ja/worktree.json +20 -3
- package/dist/server/src/config/cli-tool-timing-config.js +1 -7
- package/dist/server/src/lib/auto-yes-poller.js +54 -11
- package/dist/server/src/lib/cli-tools/antigravity.js +45 -9
- package/dist/server/src/lib/cli-tools/base.js +39 -0
- package/dist/server/src/lib/cli-tools/codex.js +67 -15
- package/dist/server/src/lib/cli-tools/command-code-plan-review.js +24 -2
- package/dist/server/src/lib/cli-tools/command-code.js +7 -3
- package/dist/server/src/lib/cli-tools/copilot.js +125 -33
- package/dist/server/src/lib/cli-tools/gemini.js +37 -10
- package/dist/server/src/lib/cli-tools/launch-keys.js +39 -0
- package/dist/server/src/lib/cli-tools/opencode-v2.js +6 -2
- package/dist/server/src/lib/cli-tools/opencode.js +60 -15
- package/dist/server/src/lib/cli-tools/session-name.js +11 -3
- package/dist/server/src/lib/cli-tools/submit-composer-read.js +590 -0
- package/dist/server/src/lib/cli-tools/submit-verified-sender.js +512 -620
- package/dist/server/src/lib/cli-tools/vibe-local.js +4 -2
- package/dist/server/src/lib/db/db-migration-path.js +63 -2
- package/dist/server/src/lib/db/migrations/index.js +2 -0
- package/dist/server/src/lib/db/migrations/pre-migration-backup.js +266 -0
- package/dist/server/src/lib/db/migrations/runner.js +37 -4
- package/dist/server/src/lib/db/migrations/v62-session-relays-bind.js +102 -0
- package/dist/server/src/lib/db/relay-bind-db.js +437 -0
- package/dist/server/src/lib/db/relay-db.js +59 -96
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +5 -4
- package/dist/server/src/lib/detection/upstream-faults.js +40 -6
- package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +2 -3
- package/dist/server/src/lib/hooks/sources/opencode/client.js +12 -6
- package/dist/server/src/lib/polling/response-checker.js +7 -5
- package/dist/server/src/lib/prompt-answer-errors.js +362 -0
- package/dist/server/src/lib/prompt-answer-sender.js +264 -288
- package/dist/server/src/lib/push/failure-episode-state.js +4 -1
- package/dist/server/src/lib/realtime/terminal-broadcast.js +1 -4
- package/dist/server/src/lib/realtime-snippet.js +54 -0
- package/dist/server/src/lib/relay/relay-bind.js +294 -0
- package/dist/server/src/lib/relay/relay-boot.js +51 -0
- package/dist/server/src/lib/relay/relay-bound-reply.js +519 -0
- package/dist/server/src/lib/relay/relay-delivery.js +134 -220
- package/dist/server/src/lib/relay/relay-messages.js +39 -4
- package/dist/server/src/lib/relay/relay-overlap.js +92 -0
- package/dist/server/src/lib/relay/relay-system-line.js +3 -2
- package/dist/server/src/lib/relay/types.js +12 -1
- package/dist/server/src/lib/session/agent-event-state.js +4 -0
- package/dist/server/src/lib/session/agent-session-lifecycle.js +23 -0
- package/dist/server/src/lib/session/claude-session.js +59 -8
- package/dist/server/src/lib/session/composer-clear.js +54 -1
- package/dist/server/src/lib/session/current-output-builder.js +26 -8
- package/dist/server/src/lib/session/current-output-history-writers.js +1 -1
- package/dist/server/src/lib/session/instance-input-lock.js +664 -0
- package/dist/server/src/lib/session/prompt-submit-receipt.js +155 -0
- package/dist/server/src/lib/session/prompt-waiting-guard.js +10 -3
- package/dist/server/src/lib/session/send-attempt-state.js +65 -0
- package/dist/server/src/lib/session/send-attempt-types.js +18 -1
- package/dist/server/src/lib/session/send-user-message.js +84 -14
- package/dist/server/src/lib/session/session-launch-flight.js +243 -0
- package/dist/server/src/lib/session/session-starting-state.js +40 -4
- package/dist/server/src/lib/session/structured-prompt.js +12 -9
- package/dist/server/src/lib/session/waiting-episode-binding.js +4 -2
- package/dist/server/src/lib/session-cleanup.js +32 -0
- package/dist/server/src/lib/session-key-sender.js +0 -27
- package/dist/server/src/lib/verification/env-clean-gate.js +129 -0
- package/dist/server/src/lib/verification/env-snapshot.js +11 -2
- package/dist/server/src/lib/verification/session-kill-ledger.js +174 -0
- package/package.json +5 -1
- package/release-notes/0.49.1.json +66 -0
- package/release-notes/0.49.2.json +49 -0
- package/.next/server/chunks/1210.js +0 -1
- package/.next/server/chunks/1945.js +0 -14
- package/.next/server/chunks/1990.js +0 -103
- package/.next/server/chunks/4194.js +0 -67
- package/.next/server/chunks/5845.js +0 -1
- package/.next/server/chunks/720.js +0 -103
- package/.next/server/chunks/7604.js +0 -2
- package/.next/server/chunks/9540.js +0 -1
- package/.next/static/chunks/4768-ad6f82f034f21eae.js +0 -1
- package/.next/static/chunks/5794-80ac3f06f098ea29.js +0 -1
- package/.next/static/chunks/6654-f3534f35f16644bc.js +0 -1
- package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +0 -1
- package/.next/static/chunks/8606-cf6bdbff44a764cf.js +0 -1
- package/.next/static/chunks/9079-987939d231704218.js +0 -1
- package/.next/static/chunks/app/api/agents/update/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/agents/versions/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/app/release-notes/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/app/update/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/app/update-check/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/auth/login/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/auth/status/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/capabilities/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/status/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/external-apps/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/fs/browse/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/fs/recent-paths/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/hooks/agent-event/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/hooks/claude-done/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/hooks/permission-request/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/metrics/vibe/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/ollama/models/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/push/escalation/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/push/subscriptions/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/push/vapid/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/relays/[relayId]/cancel/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/relays/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/remote/pair/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/excluded/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/restore/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/scan/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/sync/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/repositories/validate-path/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/settings/default-agents/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/settings/default-surface-mode/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/sidebar/group-order/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/skills/[id]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/skills/installations/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/skills/operations/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/skills/reindex/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/skills/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/slash-commands/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/templates/[id]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/templates/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cli-reference/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/direct-input/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/instances/notes/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/strict/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/layout-aa8e66164a4367af.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/more/page-87c84987b2765213.js +0 -1
- package/.next/static/chunks/app/page-1b820c421db48c2c.js +0 -1
- package/.next/static/chunks/app/proxy/[...path]/route-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/review/page-e2fd4a590646a2d8.js +0 -1
- package/.next/static/chunks/app/sessions/page-cfd645305e25fd33.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/layout-c81284a9d8b35304.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-a8d7886703ffc7b4.js +0 -1
- package/.next/static/css/db8959555c3d9c96.css +0 -1
- /package/.next/static/{3_JtAZaKMJEDFIIfkHv4n → yGatWDsS532awSs51kXyd}/_buildManifest.js +0 -0
- /package/.next/static/{3_JtAZaKMJEDFIIfkHv4n → yGatWDsS532awSs51kXyd}/_ssgManifest.js +0 -0
|
@@ -22,21 +22,38 @@
|
|
|
22
22
|
* Infrastructure errors use ExitCode (1, 2, 99)
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.
|
|
26
|
-
exports.formatRestartReleaseNotice = formatRestartReleaseNotice;
|
|
25
|
+
exports.settleCurrentOutputPath = exports.HOOK_STOP_SETTLE_MAX_MS = exports.HOOK_STOP_SETTLE_INTERVAL_MS = exports.TURN_OPENING_EVENT_TYPES = exports.SELF_RESUME_PENDING_DETAIL = exports.SELF_RESUME_HOLD_MS = exports.SELF_RESUME_CAPABILITY = exports.formatRestartReleaseNotice = void 0;
|
|
27
26
|
exports.pollWorktree = pollWorktree;
|
|
28
27
|
exports.createWaitCommand = createWaitCommand;
|
|
29
28
|
const commander_1 = require("commander");
|
|
30
29
|
const types_1 = require("../types");
|
|
31
30
|
const api_client_1 = require("../utils/api-client");
|
|
32
31
|
const command_helpers_1 = require("../utils/command-helpers");
|
|
33
|
-
const verify_runner_1 = require("../utils/verify-runner");
|
|
34
32
|
const agent_target_options_1 = require("../config/agent-target-options");
|
|
35
33
|
const prompt_1 = require("./prompt");
|
|
36
34
|
const prompt_view_1 = require("../../lib/session/prompt-view");
|
|
37
35
|
const instances_1 = require("./instances");
|
|
38
|
-
|
|
39
|
-
const
|
|
36
|
+
const wait_timing_1 = require("./wait-timing");
|
|
37
|
+
const wait_notices_1 = require("./wait-notices");
|
|
38
|
+
const wait_turn_boundary_1 = require("./wait-turn-boundary");
|
|
39
|
+
const wait_hook_stop_settle_1 = require("./wait-hook-stop-settle");
|
|
40
|
+
const wait_verify_1 = require("./wait-verify");
|
|
41
|
+
const wait_instance_1 = require("./wait-instance");
|
|
42
|
+
const follow_up_command_1 = require("../utils/follow-up-command");
|
|
43
|
+
const wait_poll_bookkeeping_1 = require("./wait-poll-bookkeeping");
|
|
44
|
+
// Issue #3964: the split-out modules' exports, re-exported so every import of
|
|
45
|
+
// `./wait` keeps working.
|
|
46
|
+
var wait_notices_2 = require("./wait-notices");
|
|
47
|
+
Object.defineProperty(exports, "formatRestartReleaseNotice", { enumerable: true, get: function () { return wait_notices_2.formatRestartReleaseNotice; } });
|
|
48
|
+
var wait_turn_boundary_2 = require("./wait-turn-boundary");
|
|
49
|
+
Object.defineProperty(exports, "SELF_RESUME_CAPABILITY", { enumerable: true, get: function () { return wait_turn_boundary_2.SELF_RESUME_CAPABILITY; } });
|
|
50
|
+
Object.defineProperty(exports, "SELF_RESUME_HOLD_MS", { enumerable: true, get: function () { return wait_turn_boundary_2.SELF_RESUME_HOLD_MS; } });
|
|
51
|
+
Object.defineProperty(exports, "SELF_RESUME_PENDING_DETAIL", { enumerable: true, get: function () { return wait_turn_boundary_2.SELF_RESUME_PENDING_DETAIL; } });
|
|
52
|
+
Object.defineProperty(exports, "TURN_OPENING_EVENT_TYPES", { enumerable: true, get: function () { return wait_turn_boundary_2.TURN_OPENING_EVENT_TYPES; } });
|
|
53
|
+
var wait_hook_stop_settle_2 = require("./wait-hook-stop-settle");
|
|
54
|
+
Object.defineProperty(exports, "HOOK_STOP_SETTLE_INTERVAL_MS", { enumerable: true, get: function () { return wait_hook_stop_settle_2.HOOK_STOP_SETTLE_INTERVAL_MS; } });
|
|
55
|
+
Object.defineProperty(exports, "HOOK_STOP_SETTLE_MAX_MS", { enumerable: true, get: function () { return wait_hook_stop_settle_2.HOOK_STOP_SETTLE_MAX_MS; } });
|
|
56
|
+
Object.defineProperty(exports, "settleCurrentOutputPath", { enumerable: true, get: function () { return wait_hook_stop_settle_2.settleCurrentOutputPath; } });
|
|
40
57
|
/**
|
|
41
58
|
* `type` reported for a blocked-on-a-human frame that carries no parsable prompt
|
|
42
59
|
* (Issue #1628). Arrow-key menus — Codex's pager and `/model`, antigravity's
|
|
@@ -74,76 +91,6 @@ function waitAnswerVia(view) {
|
|
|
74
91
|
return 'api';
|
|
75
92
|
return 'terminal';
|
|
76
93
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Why `wait` decided the agent was done, printed on the completion line
|
|
79
|
-
* (Issue #1839).
|
|
80
|
-
*
|
|
81
|
-
* `Completed: <id>` used to be the whole story, which made two very different
|
|
82
|
-
* situations indistinguishable in a log: the agent's own `Stop` hook arrived, or
|
|
83
|
-
* nothing but the screen said so. The measurement behind this Issue is exactly
|
|
84
|
-
* that difference — a 529 storm returns Claude to its composer in ~3 s with the
|
|
85
|
-
* scraper reporting `ready`/`input_prompt` and no `Stop` ever sent — so the
|
|
86
|
-
* basis belongs next to the verdict rather than in a triage session afterwards.
|
|
87
|
-
*/
|
|
88
|
-
const COMPLETION_BASIS = {
|
|
89
|
-
/** The agent reported the turn ended, and the report postdates this wait's turn. */
|
|
90
|
-
HOOK_STOP: 'hook_stop',
|
|
91
|
-
/** The tmux session went away after we had seen it alive. */
|
|
92
|
-
SESSION_GONE: 'session_gone',
|
|
93
|
-
/** The terminal frame says the agent is back at its composer. Nothing corroborated it. */
|
|
94
|
-
SCRAPER_READY: 'scraper_ready',
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Structured event types that mean "a turn is under way" (Issue #1839).
|
|
98
|
-
*
|
|
99
|
-
* Mirrors AGENT_EVENT_TYPES in src/lib/hooks/agent-event-types.ts; duplicated
|
|
100
|
-
* rather than imported because the CLI bundle keeps its own copy of the API
|
|
101
|
-
* shapes (see api-responses.ts).
|
|
102
|
-
*
|
|
103
|
-
* `notification` is deliberately absent, and that is the one measured deviation
|
|
104
|
-
* from the design sketched in Issue #1839. The Issue proposed accepting
|
|
105
|
-
* `stop` **or** `idle_prompt` as the end of a turn; the live capture of
|
|
106
|
-
* 2026-08-20 (see docs/design/upstream-fault-turn-boundary-1839.md) shows
|
|
107
|
-
* Claude 2.1.236 emitting `Notification(idle_prompt)` 62 s into a turn that
|
|
108
|
-
* ran nothing at all, because the composer had been idle for a minute. Reading
|
|
109
|
-
* it as a turn boundary would have re-created the false completion this gate
|
|
110
|
-
* exists to stop, one minute later. Only `Stop` ends a turn.
|
|
111
|
-
*
|
|
112
|
-
* Exported for the cross-layer pin in
|
|
113
|
-
* `tests/unit/session/status-contract-1926.test.ts`. The server opens a turn on
|
|
114
|
-
* the same three events (`src/lib/session/provisional-turn.ts`
|
|
115
|
-
* TURN_ACTIVITY_EVENTS), and since Issue #1930 `adoptTurnStart` reads that
|
|
116
|
-
* turn's `openedAt` rather than this set — so a set that drifted would change
|
|
117
|
-
* this gate silently. The set is still read here for the pre-#1930 fallback
|
|
118
|
-
* path, and the CLI cannot import the server module (`tsconfig.cli.json` sets
|
|
119
|
-
* `"paths": {}`), so the test is the only thing holding the two together.
|
|
120
|
-
*/
|
|
121
|
-
exports.TURN_OPENING_EVENT_TYPES = new Set([
|
|
122
|
-
'user_prompt_submit',
|
|
123
|
-
'pre_tool_use',
|
|
124
|
-
'post_tool_use',
|
|
125
|
-
]);
|
|
126
|
-
/**
|
|
127
|
-
* How far *before* this wait started a turn-opening event may sit and still be
|
|
128
|
-
* read as the turn this wait is about (Issue #1839).
|
|
129
|
-
*
|
|
130
|
-
* `wait` does not know when `send` ran, and the honest proxy is its own start:
|
|
131
|
-
* an orchestrator sends and then waits, so the turn's `UserPromptSubmit` lands
|
|
132
|
-
* after `wait` is already polling (measured at +0.6 s from the send). One poll
|
|
133
|
-
* interval of slack covers a `wait` that starts a moment late.
|
|
134
|
-
*
|
|
135
|
-
* The bound is what keeps this from being a new way to hang, and Issue #1930
|
|
136
|
-
* narrowed what it has to defend against. It was written when structured events
|
|
137
|
-
* were NOT fenced by generation on the way into `structuredEvents`, so a stale
|
|
138
|
-
* `user_prompt_submit` from a previous agent process could still be the last
|
|
139
|
-
* event on the wire and this window was the only thing stopping it from gating
|
|
140
|
-
* a wait for ever. The server fences the turn now and publishes null when it
|
|
141
|
-
* does, so the window's remaining job is narrower and sharper: a turn that has
|
|
142
|
-
* already CLOSED must have closed inside this wait to count, or `wait` on a
|
|
143
|
-
* session that finished an hour ago would inherit that turn's gate. An open
|
|
144
|
-
* turn is adopted whatever its age — see {@link adoptTurnStart}.
|
|
145
|
-
*/
|
|
146
|
-
const TURN_ADOPTION_GRACE_MS = POLL_INTERVAL_MS;
|
|
147
94
|
/**
|
|
148
95
|
* How long `isUnclassifiedActive` must hold before `wait` treats it as a stop
|
|
149
96
|
* reason (Issue #1708).
|
|
@@ -163,625 +110,6 @@ const TURN_ADOPTION_GRACE_MS = POLL_INTERVAL_MS;
|
|
|
163
110
|
* for working around a detector bug, and the bug is the thing to fix.
|
|
164
111
|
*/
|
|
165
112
|
const UNCLASSIFIED_DWELL_MS = 60_000;
|
|
166
|
-
/**
|
|
167
|
-
* The keystroke that closes opencode's sidebar, in opencode's own notation
|
|
168
|
-
* (Issue #2095).
|
|
169
|
-
*
|
|
170
|
-
* A local copy of `OPENCODE_SIDEBAR_RECOVERY_CHORD` from
|
|
171
|
-
* `src/lib/detection/opencode-pane-obstruction.ts` and not an import: the CLI
|
|
172
|
-
* builds with `"paths": {}` (tsconfig.cli.json) and cannot reach `@/lib` at all,
|
|
173
|
-
* which is why `api-responses.ts` mirrors payload shapes rather than importing
|
|
174
|
-
* them. Taken from opencode's own keybind table, which its `ctrl+p` palette
|
|
175
|
-
* prints as `Show sidebar ctrl+x b`.
|
|
176
|
-
*/
|
|
177
|
-
const OPENCODE_SIDEBAR_RECOVERY_CHORD = 'ctrl+x b';
|
|
178
|
-
/**
|
|
179
|
-
* The cause sentence to append when the frame carries a pane obstruction, or ''
|
|
180
|
-
* (Issue #2095).
|
|
181
|
-
*
|
|
182
|
-
* Appended rather than substituted, and no exit code moves: the frame is
|
|
183
|
-
* genuinely unclassified and `wait` was already right to stop on it. What it
|
|
184
|
-
* could not say before is WHY, which left an operator with `capture --pane` and
|
|
185
|
-
* a screenful of box drawing to work it out from.
|
|
186
|
-
*
|
|
187
|
-
* Empty for a server too old to publish the field, which is the same output
|
|
188
|
-
* `wait` produced before this Issue.
|
|
189
|
-
*/
|
|
190
|
-
function describePaneObstruction(data) {
|
|
191
|
-
const obstruction = data.paneObstruction;
|
|
192
|
-
if (!obstruction)
|
|
193
|
-
return '';
|
|
194
|
-
return (` Cause: paneObstruction=${obstruction.id} — a second column is sharing rows with the ` +
|
|
195
|
-
`transcript (it reads ${JSON.stringify(obstruction.matchedText)}), which covers the marker ` +
|
|
196
|
-
`that ends a turn. Press \`${OPENCODE_SIDEBAR_RECOVERY_CHORD}\` in the pane to close ` +
|
|
197
|
-
`opencode's sidebar.`);
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* How recent `autoYes.lastSuppression` must be to be reported as the reason this
|
|
201
|
-
* wait is blocked (Issue #1699).
|
|
202
|
-
*
|
|
203
|
-
* The record is refreshed on every poll for as long as the suppressed prompt is
|
|
204
|
-
* on screen, so a fresh timestamp means "this is happening now" while an old one
|
|
205
|
-
* is a historical suppression of some earlier prompt. The window is generous
|
|
206
|
-
* against the server's own poll interval — being a few seconds late with a true
|
|
207
|
-
* report beats staying silent, which is the failure this exists to fix.
|
|
208
|
-
*
|
|
209
|
-
* Issue #2463 reads the same window as "the policy withheld THIS prompt", which
|
|
210
|
-
* is what ends the Auto-Yes hold at once. `current-output` publishes no start
|
|
211
|
-
* time for a scraped prompt, so the push gate's `suppression.at >= waitingSince`
|
|
212
|
-
* (`src/lib/push/prompt-push-gate.ts`) cannot be computed here; a record that is
|
|
213
|
-
* still being re-stamped is the CLI's reading of it. Using one window for both
|
|
214
|
-
* keeps the hold and the payload in agreement: an exit 10 carries
|
|
215
|
-
* `autoYesSuppression` exactly when the hold judged the answer withheld. The
|
|
216
|
-
* error runs towards reporting — a withheld answer to an earlier prompt, under a
|
|
217
|
-
* minute old, still ends the hold, which is the pre-#2463 exit rather than a
|
|
218
|
-
* new failure.
|
|
219
|
-
*
|
|
220
|
-
* Issue #3798: a server that names the waiting episodes does what the push gate
|
|
221
|
-
* does — the record's `episodeId` against the payload's
|
|
222
|
-
* `autoYes.waitingEpisodeId`, which decide when both are present: another id
|
|
223
|
-
* (or no wait open) is a record of an earlier wait, however recent; the same
|
|
224
|
-
* id is this wait's. Either one missing (an older server, a record written
|
|
225
|
-
* before any wait was open), this window decides as before. Whichever
|
|
226
|
-
* decides, a record the server marks `lastSuppressionAnswered` — Auto-Yes
|
|
227
|
-
* answered the open wait after it was written — is history, not this wait's
|
|
228
|
-
* reason, as the push gate reads it: the hold goes on.
|
|
229
|
-
*/
|
|
230
|
-
const SUPPRESSION_FRESH_MS = 60_000;
|
|
231
|
-
/**
|
|
232
|
-
* The suppression currently blocking this session, or null.
|
|
233
|
-
*
|
|
234
|
-
* Issue #3863: with the Auto-Yes answer mode in effect (`autoYesAnswerMode`)
|
|
235
|
-
* when the server publishes one — what `question-left-to-human` and
|
|
236
|
-
* `recommended-option-unidentified` depend on.
|
|
237
|
-
*/
|
|
238
|
-
function activeSuppression(data, now) {
|
|
239
|
-
// No `autoYes` at all (a session that is not running, Issue #3300) reads as
|
|
240
|
-
// "nothing was withheld", the same as a null record.
|
|
241
|
-
const suppression = data.autoYes?.lastSuppression;
|
|
242
|
-
if (!suppression)
|
|
243
|
-
return null;
|
|
244
|
-
const ageMs = now - suppression.at;
|
|
245
|
-
const waitId = data.autoYes?.waitingEpisodeId;
|
|
246
|
-
if (suppression.episodeId !== undefined && waitId !== undefined) {
|
|
247
|
-
if (suppression.episodeId !== waitId)
|
|
248
|
-
return null;
|
|
249
|
-
}
|
|
250
|
-
else if (ageMs > SUPPRESSION_FRESH_MS) {
|
|
251
|
-
// A negative age is clock skew between the CLI and the server, not staleness.
|
|
252
|
-
return null;
|
|
253
|
-
}
|
|
254
|
-
if (data.autoYes?.lastSuppressionAnswered === true)
|
|
255
|
-
return null;
|
|
256
|
-
const answerMode = data.autoYesAnswerMode;
|
|
257
|
-
return {
|
|
258
|
-
suppression,
|
|
259
|
-
ageSeconds: Math.max(0, Math.round(ageMs / 1000)),
|
|
260
|
-
...(answerMode !== undefined ? { answerMode } : {}),
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
/** The wording for the four reasons a contract's `autoYes` block really authors. */
|
|
264
|
-
const CONTRACT_POLICY_CAUSE = 'by contract policy';
|
|
265
|
-
/**
|
|
266
|
-
* What withheld the answer, in the words `wait` puts on stderr (Issue #1843).
|
|
267
|
-
*
|
|
268
|
-
* A Record over the whole reason union rather than one fixed phrase: adding a
|
|
269
|
-
* reason to {@link AutoYesSuppressionReason} without deciding what `wait` should
|
|
270
|
-
* say about it is a compile error here, which is the point. Until #1843 the
|
|
271
|
-
* notice hard-coded "by contract policy" for every reason, so #1829's
|
|
272
|
-
* `agent-launch-dialog` — a product-side decision the poller makes with no
|
|
273
|
-
* contract in sight (`suppressIfNotOursToAnswer` in
|
|
274
|
-
* `src/lib/polling/auto-yes-prompt-suppression.ts`: codex's lifecycle dialogs,
|
|
275
|
-
* gemini's folder trust since #3776 and copilot's since #3790) — sent operators
|
|
276
|
-
* of contract-less worktrees hunting for a `denyPatterns` entry that did not
|
|
277
|
-
* exist.
|
|
278
|
-
*
|
|
279
|
-
* The three sites that record a suppression are covered: the poller's launch-dialog
|
|
280
|
-
* branch (`agent-launch-dialog`), the poller's policy branch and
|
|
281
|
-
* `lib/hooks/permission-decision-service.ts` (both the four `evaluatePolicyAgainstTexts`
|
|
282
|
-
* verdicts, which is why those four keep the pre-#1843 wording exactly), and
|
|
283
|
-
* the poller's stopped-answer branch (`partial-answer`, Issue #3706 / #3713),
|
|
284
|
-
* and the poller's agy trust-screen branch (`startup-trust-unhandled`, Issue #3757),
|
|
285
|
-
* and the poller's question confirm-page branch (`question-confirm-page`, Issue #3748),
|
|
286
|
-
* and the poller's question branch (`question-left-to-human`, Issue #3822),
|
|
287
|
-
* and the resolver's permission-row reading (`allow-once-unidentified`, Issue #3822),
|
|
288
|
-
* and the resolver's choice of a question's recommended option
|
|
289
|
-
* (`recommended-option-unidentified`, Issue #3863),
|
|
290
|
-
* and the poller's agy receipt-gate branch (`no-hook-receipt`, Issue #3767),
|
|
291
|
-
* and a contract lookup that failed on either of the policy paths
|
|
292
|
-
* (`policy-lookup-failed`, Issue #3822).
|
|
293
|
-
*/
|
|
294
|
-
const SUPPRESSION_CAUSE = {
|
|
295
|
-
'mode-off': CONTRACT_POLICY_CAUSE,
|
|
296
|
-
'deny-pattern': CONTRACT_POLICY_CAUSE,
|
|
297
|
-
'deny-pattern-unusable': CONTRACT_POLICY_CAUSE,
|
|
298
|
-
'type-not-allowed': CONTRACT_POLICY_CAUSE,
|
|
299
|
-
// Issue #3822. Not "by contract policy": the contract could not be read at
|
|
300
|
-
// all, so nothing it says was applied. Withheld rather than answered, since
|
|
301
|
-
// the contract may state `off`; it clears once the server reads it again.
|
|
302
|
-
'policy-lookup-failed': 'because the server could not read the execution contract (the database lookup failed), so Auto-Yes does not answer until it can; check the server log for policy-lookup-failed',
|
|
303
|
-
// Issue #3790: after the launch window the poller still leaves copilot's and
|
|
304
|
-
// gemini's trust dialogs alone when the cursor is not on the safe row, and
|
|
305
|
-
// nobody else answers them then.
|
|
306
|
-
'agent-launch-dialog': "while the agent's launch dialog was on screen; if it stays after the launch (copilot's cursor on 2. or 3., gemini's not on 1. Trust folder), answer it at the pane",
|
|
307
|
-
// Issue #1924. Deliberately not "by contract policy": no contract was
|
|
308
|
-
// consulted. The frame looked like a numbered list to the generic estimator
|
|
309
|
-
// and like prose to the tool's own detector, and an operator who reads this
|
|
310
|
-
// should go and look at the pane rather than at `denyPatterns`.
|
|
311
|
-
'unclassified-frame': 'because no tool-specific dialog detector recognised the frame',
|
|
312
|
-
// Issue #3713 (#3706's reason). Not "by contract policy" either: an earlier
|
|
313
|
-
// Auto-Yes answer was stopped with some of its keys already in the input, and
|
|
314
|
-
// typing it again would append to them, so the prompt waits for a human.
|
|
315
|
-
// Issue #3880: or a send of it (Auto-Yes's, or a person's that failed) ended
|
|
316
|
-
// without tmux confirming it, and no key may be known to be there. The #3713
|
|
317
|
-
// sentence is kept as it was and the other case follows it.
|
|
318
|
-
'partial-answer': "because an earlier answer left partial input; Auto-Yes is waiting for a human (or that answer's send could not be confirmed, so the input may hold it: check the pane, then answer; an answer that goes through releases the hold)",
|
|
319
|
-
// Issue #3757. agy's startup folder-trust screen: the launch's to confirm, not
|
|
320
|
-
// Auto-Yes's, and agy drew it after the launch window had ended.
|
|
321
|
-
'startup-trust-unhandled': "because agy's startup folder-trust confirmation is the launch's to answer, not Auto-Yes's; the next send confirms it once, or answer it at the pane",
|
|
322
|
-
// Issue #3748. The AskUserQuestion confirm page (`Submit` / `Cancel`): the
|
|
323
|
-
// tool's own reader recognised it, and `Submit` commits whatever stands as the
|
|
324
|
-
// answers, so it waits for a human. Was recorded as `unclassified-frame`,
|
|
325
|
-
// whose wording above says the opposite (nothing recognised the frame).
|
|
326
|
-
'question-confirm-page': "because the question's Submit/Cancel confirmation commits the answers as they stand, so Auto-Yes leaves it to a human",
|
|
327
|
-
// Issue #3822. A question the agent asks the operator (an AskUserQuestion
|
|
328
|
-
// picker, OpenCode V2's question form): Auto-Yes answers permissions only,
|
|
329
|
-
// and no contract setting delegates the question. Issue #3863: since the
|
|
330
|
-
// answer modes, that is the `careful` mode's rule (and OpenCode V2's form
|
|
331
|
-
// under either mode); `answerMode=` on the line says which mode was on.
|
|
332
|
-
'question-left-to-human': 'because the agent is asking a question, and Auto-Yes answers permissions only (the careful answer mode, or a question form no mode answers); answer it at the pane (prompt --json, respond), or turn Auto-Yes on with --answer-mode recommended to have it pick the recommended option',
|
|
333
|
-
// Issue #3822. A permission dialog none of whose rows allows this call only
|
|
334
|
-
// (each saves a rule, changes the mode or denies), or two of which read so.
|
|
335
|
-
// Auto-Yes never picks a row that outlives this call, so it waits for a human.
|
|
336
|
-
'allow-once-unidentified': 'because no single option of the permission dialog allows this call only (the others save a rule, change the permission mode, or deny); Auto-Yes does not pick those, so answer it at the pane (prompt --json, respond)',
|
|
337
|
-
// Issue #3863. The recommended answer mode answers a question with its one
|
|
338
|
-
// recommended option (else its default), and could not tell which that is.
|
|
339
|
-
'recommended-option-unidentified': "because the question's recommended option could not be told (two or more marked recommended, a title it could not tell from its description, a typed-text or multi-select answer); answer it at the pane (prompt --json, respond)",
|
|
340
|
-
// Issue #3767. agy's approval dialog has no matching hook question (none, too
|
|
341
|
-
// late, already on screen, or the hook stopped arriving). Not a contract verdict.
|
|
342
|
-
// Issue #3789: nor one left unused — the last was spent on keys Auto-Yes sent,
|
|
343
|
-
// and a dialog is still up past the grace — so "no unused question" covers both.
|
|
344
|
-
'no-hook-receipt': "because there is no unused agy hook permission question for this dialog (none arrived in time, or the last one was spent on keys that did not clear it); answer it yourself (auto-yes --disable, prompt --json, respond --expect-screen) or check hooks.json",
|
|
345
|
-
};
|
|
346
|
-
/**
|
|
347
|
-
* {@link SUPPRESSION_CAUSE} for a reason that arrived over the wire.
|
|
348
|
-
*
|
|
349
|
-
* `reason` is a server-supplied string, so a server newer than this CLI can name
|
|
350
|
-
* a reason the union does not have. Naming it verbatim is the only honest answer:
|
|
351
|
-
* quietly folding an unknown reason into "by contract policy" is the same
|
|
352
|
-
* misattribution #1843 exists to remove, just for a future reason instead of
|
|
353
|
-
* `agent-launch-dialog`.
|
|
354
|
-
*/
|
|
355
|
-
function suppressionCause(reason) {
|
|
356
|
-
return Object.prototype.hasOwnProperty.call(SUPPRESSION_CAUSE, reason)
|
|
357
|
-
? SUPPRESSION_CAUSE[reason]
|
|
358
|
-
: `for a reason this CLI does not recognise (${reason})`;
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* One stderr line naming what is holding this prompt (Issue #1699).
|
|
362
|
-
*
|
|
363
|
-
* `wait` used to print only "Waiting for human response...", which reads the
|
|
364
|
-
* same whether a human was always going to answer or whether Auto-Yes silently
|
|
365
|
-
* refused to. That ambiguity is what let a deny pattern matching a finished turn
|
|
366
|
-
* stall two workers unnoticed; the pattern and the reason code belong on screen.
|
|
367
|
-
*
|
|
368
|
-
* Issue #1843: the cause is chosen per reason rather than asserted. `reason=` is
|
|
369
|
-
* in the payload either way, so the prefix is the only part that can lie — and it
|
|
370
|
-
* did, for every non-contract suppression.
|
|
371
|
-
*/
|
|
372
|
-
function formatSuppressionNotice(suppression, ageSeconds, answerMode) {
|
|
373
|
-
const parts = [
|
|
374
|
-
`reason=${suppression.reason}`,
|
|
375
|
-
`mode=${suppression.mode ?? 'none'}`,
|
|
376
|
-
`promptType=${suppression.promptType}`,
|
|
377
|
-
];
|
|
378
|
-
if (suppression.pattern !== undefined) {
|
|
379
|
-
parts.push(`pattern=${JSON.stringify(suppression.pattern)}`);
|
|
380
|
-
}
|
|
381
|
-
// Issue #3863: the Auto-Yes answer mode in effect, when the server says.
|
|
382
|
-
if (answerMode !== undefined) {
|
|
383
|
-
parts.push(`answerMode=${answerMode}`);
|
|
384
|
-
}
|
|
385
|
-
const cause = suppressionCause(suppression.reason);
|
|
386
|
-
return ` auto-yes suppressed this prompt ${cause}: ${parts.join(' ')} (${ageSeconds}s ago)`;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* One stderr line saying Auto-Yes is off on this instance because the server
|
|
390
|
-
* restarted (Issue #3730), or null.
|
|
391
|
-
*
|
|
392
|
-
* Only words: the prompt was going to be reported either way — an instance
|
|
393
|
-
* whose grant the restart released is an instance with Auto-Yes off, and exit
|
|
394
|
-
* 10 for it is exactly the hand-back it always was. What this adds is the WHY,
|
|
395
|
-
* so a delegating agent re-enables Auto-Yes instead of guessing. A server
|
|
396
|
-
* older than the reason sends none, and nothing is printed.
|
|
397
|
-
*
|
|
398
|
-
* The command it suggests names the instance this wait is about: without
|
|
399
|
-
* `--instance`, `auto-yes --enable` arms the worktree's default primary, which
|
|
400
|
-
* for an alias (or a non-default tool) is another instance — the waited-on one
|
|
401
|
-
* would stay off while a grant went somewhere nobody asked for. The instance is
|
|
402
|
-
* the resolved `--instance` when one was given, else the CLI tool the server
|
|
403
|
-
* answered for (a primary's instance ID is its tool ID).
|
|
404
|
-
*
|
|
405
|
-
* @param instanceId - The resolved `--instance` of this wait, if any
|
|
406
|
-
*/
|
|
407
|
-
function formatRestartReleaseNotice(worktreeId, data, instanceId) {
|
|
408
|
-
if (data.autoYes?.enabled !== false || data.autoYes.stopReason !== 'server-restart')
|
|
409
|
-
return null;
|
|
410
|
-
const target = instanceId ?? data.cliToolId;
|
|
411
|
-
const command = `commandmate auto-yes ${worktreeId} --enable${target ? ` --instance ${target}` : ''}`;
|
|
412
|
-
return ` auto-yes was released by a server restart on ${worktreeId} (it is not turned back on ` +
|
|
413
|
-
`automatically); re-enable it with \`${command}\` if this session should keep answering.`;
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* One stderr line saying Auto-Yes pressed Enter on THIS prompt (Issue #3397), or
|
|
417
|
-
* null when the record is absent or about another screen.
|
|
418
|
-
*
|
|
419
|
-
* The prompt is one CommandMate could not read (the window offers direct input
|
|
420
|
-
* for it). `sent` — Auto-Yes confirmed whatever was selected; `no-effect` — the
|
|
421
|
-
* same screen outlived the Enter, no second one was sent, and it is a human's
|
|
422
|
-
* again. An outcome this CLI does not know is named verbatim (#1843's rule).
|
|
423
|
-
* `currentPrompt` is the server's judgement that the record is about the
|
|
424
|
-
* `promptData` of the same response, so an Enter sent to an earlier screen is
|
|
425
|
-
* never reported against this one.
|
|
426
|
-
*/
|
|
427
|
-
function formatEnterFallbackNotice(data, now) {
|
|
428
|
-
const record = data.autoYes?.lastEnterFallback;
|
|
429
|
-
if (!record || record.currentPrompt !== true)
|
|
430
|
-
return null;
|
|
431
|
-
const detail = `refusal=${record.refusalReason} promptType=${record.promptType}`;
|
|
432
|
-
const ago = `(${Math.max(0, Math.round((now - record.at) / 1000))}s ago)`;
|
|
433
|
-
if (record.outcome === 'sent') {
|
|
434
|
-
return ` auto-yes sent Enter to this prompt (CommandMate could not read it): ${detail} ${ago}`;
|
|
435
|
-
}
|
|
436
|
-
if (record.outcome === 'no-effect') {
|
|
437
|
-
return ` auto-yes sent Enter to this prompt, but the same screen is still up (no-effect); ` +
|
|
438
|
-
`answer it in the terminal: ${detail} ${ago}`;
|
|
439
|
-
}
|
|
440
|
-
return ` auto-yes Enter record for this prompt: outcome=${record.outcome} ${detail} ${ago}`;
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Issue #3821: the server's own word that Auto-Yes left this prompt to a human
|
|
444
|
-
* (`autoYesDecision.state === 'withheld'`) — `server-poller-inactive` when no
|
|
445
|
-
* poller runs for the instance, or a stop the suppression record does not
|
|
446
|
-
* carry. Read only when the server publishes the field; an older one leaves
|
|
447
|
-
* `wait` holding as before.
|
|
448
|
-
*/
|
|
449
|
-
function decisionWithheldReason(data) {
|
|
450
|
-
const decision = data.autoYesDecision;
|
|
451
|
-
if (decision?.state !== 'withheld')
|
|
452
|
-
return null;
|
|
453
|
-
return decision.reason ?? 'unknown';
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Whether this server publishes a real turn record (Issue #1930).
|
|
457
|
-
*
|
|
458
|
-
* `dialogPendingMaxMs` landed with the turn model and is set on every payload a
|
|
459
|
-
* server of that vintage produces, so its presence is the version probe. A
|
|
460
|
-
* *value* rather than a version string, for the reason #1924 gives for the
|
|
461
|
-
* capability block: a payload that has to be interpreted by its sender's
|
|
462
|
-
* version number is a payload nobody can read forward.
|
|
463
|
-
*
|
|
464
|
-
* The probe is needed because the two readings below disagree in exactly the
|
|
465
|
-
* case that matters. On a #1930 server, `openedAt` being null while
|
|
466
|
-
* `lastEventType` is `user_prompt_submit` means the turn was fenced off by a
|
|
467
|
-
* generation or aged out — the server has *decided* it is not this instance's
|
|
468
|
-
* turn. Falling back to the event on such a payload would put back the stale
|
|
469
|
-
* adoption the turn record exists to remove.
|
|
470
|
-
*/
|
|
471
|
-
function publishesTurnRecord(data) {
|
|
472
|
-
return data.structuredEvents?.dialogPendingMaxMs != null;
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Adopt the turn this wait is about, if this poll shows one (Issue #1839,
|
|
476
|
-
* moved onto the turn record in #1930).
|
|
477
|
-
*
|
|
478
|
-
* ## What changed, and why the grace window is no longer the whole guard
|
|
479
|
-
*
|
|
480
|
-
* Before #1930 this read `lastEventType` / `lastEventAt` — the newest event of
|
|
481
|
-
* any kind — and refused anything older than {@link TURN_ADOPTION_GRACE_MS},
|
|
482
|
-
* because (in the words of that constant) structured events "are NOT fenced by
|
|
483
|
-
* generation on the way into `structuredEvents`", so a stale
|
|
484
|
-
* `user_prompt_submit` from a previous agent process could still be the last
|
|
485
|
-
* event on the wire. The bound was the only thing keeping such a record from
|
|
486
|
-
* gating a wait for ever.
|
|
487
|
-
*
|
|
488
|
-
* The server fences the turn now, and publishes null when it does. So an **open**
|
|
489
|
-
* turn is adopted whatever its age — which closes a hole the old reading had:
|
|
490
|
-
* a turn that opened ten minutes before this `wait` started, and is still
|
|
491
|
-
* running, used to be adopted only because its *newest* event was fresh. An
|
|
492
|
-
* agent that goes quiet mid-turn (thinking, a long tool call) has no fresh
|
|
493
|
-
* event, so the #1839 gate came down at exactly the moment a 529 storm would
|
|
494
|
-
* exploit it.
|
|
495
|
-
*
|
|
496
|
-
* A **closed** turn still has to have opened inside this wait's window, and the
|
|
497
|
-
* reason is the one the grace constant gives: `wait` does not know when `send`
|
|
498
|
-
* ran, so the last turn of a session that finished an hour ago must not gate a
|
|
499
|
-
* wait that has only just started. `commandmate wait` on an already-idle
|
|
500
|
-
* session therefore adopts nothing and completes on its first poll, exactly as
|
|
501
|
-
* it did before — #1975 measured that at 234/242/259 ms and it is the
|
|
502
|
-
* orchestrator's normal path.
|
|
503
|
-
*
|
|
504
|
-
* @param previous - the turn start adopted so far, or null
|
|
505
|
-
* @returns the newest adopted turn start, or `previous` when nothing qualified
|
|
506
|
-
*/
|
|
507
|
-
function adoptTurnStart(data, waitStartedAt, previous) {
|
|
508
|
-
const events = data.structuredEvents;
|
|
509
|
-
if (!events)
|
|
510
|
-
return previous;
|
|
511
|
-
if (!publishesTurnRecord(data)) {
|
|
512
|
-
// A server older than #1930. Same reading this function has had since
|
|
513
|
-
// #1839, kept so a newer CLI pointed at an older server does not silently
|
|
514
|
-
// lose the gate.
|
|
515
|
-
if (events.lastEventAt == null || events.lastEventType == null)
|
|
516
|
-
return previous;
|
|
517
|
-
if (!exports.TURN_OPENING_EVENT_TYPES.has(events.lastEventType))
|
|
518
|
-
return previous;
|
|
519
|
-
if (events.lastEventAt < waitStartedAt - TURN_ADOPTION_GRACE_MS)
|
|
520
|
-
return previous;
|
|
521
|
-
return previous === null || events.lastEventAt > previous ? events.lastEventAt : previous;
|
|
522
|
-
}
|
|
523
|
-
const openedAt = events.openedAt;
|
|
524
|
-
// Null covers every "there is no turn to adopt" case the server knows about:
|
|
525
|
-
// nothing reported, a previous generation, aged out, or a `stop` whose
|
|
526
|
-
// opening was never observed.
|
|
527
|
-
if (openedAt == null)
|
|
528
|
-
return previous;
|
|
529
|
-
if (events.closedAt != null && openedAt < waitStartedAt - TURN_ADOPTION_GRACE_MS) {
|
|
530
|
-
return previous;
|
|
531
|
-
}
|
|
532
|
-
return previous === null || openedAt > previous ? openedAt : previous;
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* `structuredEvents.closedBy`, phrased for a diagnostic line (Issue #1930).
|
|
536
|
-
*
|
|
537
|
-
* The server's close-reason vocabulary and {@link COMPLETION_BASIS} answer two
|
|
538
|
-
* different questions — "why did the turn end" and "what did `wait` decide on"
|
|
539
|
-
* — and are deliberately printed side by side rather than folded together.
|
|
540
|
-
* `hook_stop` is the only place they meet: it is `closedBy: 'stop'` seen from
|
|
541
|
-
* the CLI's end. Everything else (`stale`, `scraper_evidence`, `session_end`,
|
|
542
|
-
* `generation`, `resync_idle`) is a reason the turn stopped being trusted, which
|
|
543
|
-
* is precisely what `wait` must NOT read as completion.
|
|
544
|
-
*/
|
|
545
|
-
function describeTurnClose(data) {
|
|
546
|
-
const events = data.structuredEvents;
|
|
547
|
-
if (!events)
|
|
548
|
-
return 'turn=unknown';
|
|
549
|
-
const id = events.turnId ?? 'none';
|
|
550
|
-
const closedBy = events.closedBy ?? (events.openedAt != null ? 'open' : 'none');
|
|
551
|
-
return `turn=${id} closedBy=${closedBy}`;
|
|
552
|
-
}
|
|
553
|
-
/**
|
|
554
|
-
* Whether the agent has reported the end of the turn this wait adopted
|
|
555
|
-
* (Issue #1839).
|
|
556
|
-
*
|
|
557
|
-
* True when no turn was adopted at all, which is the whole of the unchanged
|
|
558
|
-
* path: a session whose agent posts no hooks never adopts one, so every caller
|
|
559
|
-
* on a machine without hook injection sees precisely the pre-#1839 behaviour.
|
|
560
|
-
*/
|
|
561
|
-
function turnSettled(data, turnStartedAt) {
|
|
562
|
-
if (turnStartedAt === null)
|
|
563
|
-
return true;
|
|
564
|
-
const stoppedAt = data.lastStopEventAt;
|
|
565
|
-
return stoppedAt != null && stoppedAt >= turnStartedAt;
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* The structured event that ends a turn (Issue #1975).
|
|
569
|
-
*
|
|
570
|
-
* The counterpart of {@link TURN_OPENING_EVENT_TYPES}, kept as a bare constant
|
|
571
|
-
* because the vocabulary a source declares in `capabilities.supportedEvents` is
|
|
572
|
-
* the wire's, not this build's: a tool that cannot say `stop` cannot release the
|
|
573
|
-
* hold below, so asking for the word by name is the whole of the check.
|
|
574
|
-
*/
|
|
575
|
-
const TURN_CLOSING_EVENT_TYPE = 'stop';
|
|
576
|
-
/**
|
|
577
|
-
* How long `wait` will hold a composer frame open for an agent that has been
|
|
578
|
-
* handed a prompt it has not reported the end of (Issue #1975).
|
|
579
|
-
*
|
|
580
|
-
* The hold's *reason* is exact — see {@link outstandingPrompt} — so this is not
|
|
581
|
-
* a settling window standing in for evidence. It is the bound the contract of
|
|
582
|
-
* this Issue asks for: hooks are fail-open on every path, so a `Stop` that is
|
|
583
|
-
* simply lost (the receiver was restarted, the machine-wide
|
|
584
|
-
* `~/.copilot/settings.json` was rewritten by another server mid-session, the
|
|
585
|
-
* 4-second curl in the hook timed out) must not turn `wait` into a command that
|
|
586
|
-
* never returns. After this it completes on the frame alone, exactly as it did
|
|
587
|
-
* before this Issue, and says so.
|
|
588
|
-
*
|
|
589
|
-
* 60s is the same dwell {@link UNCLASSIFIED_DWELL_MS} uses for the same job, and
|
|
590
|
-
* it is ~55x the widest send-to-turn-open window measured for this Issue
|
|
591
|
-
* (2026-08-22, copilot 1.0.80 against an isolated server: 0.04s / 0.75s / 0.88s
|
|
592
|
-
* / 1.10s over four sends, the last of them a cold session start). `--timeout`
|
|
593
|
-
* and `--stall-timeout` below 60s still win, as they do for the unclassified
|
|
594
|
-
* dwell: this pre-empts long waits, it does not extend short ones.
|
|
595
|
-
*/
|
|
596
|
-
const PENDING_PROMPT_HOLD_MS = 60_000;
|
|
597
|
-
/**
|
|
598
|
-
* Whether this tool's event source claims it can report both ends of a turn
|
|
599
|
-
* (Issue #1975).
|
|
600
|
-
*
|
|
601
|
-
* The gate that keeps the hold below off every path it has no evidence for.
|
|
602
|
-
* `structuredEvents.source.capabilities` is #1924's declaration, published to
|
|
603
|
-
* the CLI already, and the compatibility source a tool with no implementation
|
|
604
|
-
* gets (`src/lib/hooks/sources/legacy-relay.ts`) declares `supportedEvents: []`
|
|
605
|
-
* — so a tool that posts no hooks answers `false` here and takes precisely the
|
|
606
|
-
* pre-#1975 path. So does a server older than #1924, which sends no `source` at
|
|
607
|
-
* all.
|
|
608
|
-
*
|
|
609
|
-
* Both words are required. Without a turn-opening word nothing would ever open
|
|
610
|
-
* the turn this waits for; without `stop` nothing could ever close it, and the
|
|
611
|
-
* hold would only ever end at its own bound.
|
|
612
|
-
*/
|
|
613
|
-
function reportsTurnBoundaries(data) {
|
|
614
|
-
const declared = data.structuredEvents?.source?.capabilities?.supportedEvents;
|
|
615
|
-
if (!Array.isArray(declared))
|
|
616
|
-
return false;
|
|
617
|
-
return (declared.includes(TURN_CLOSING_EVENT_TYPE) &&
|
|
618
|
-
declared.some(event => exports.TURN_OPENING_EVENT_TYPES.has(event)));
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* The `stop` detail meaning "the agent ended its turn with its own background
|
|
622
|
-
* work still running, and resumes by itself when that work finishes"
|
|
623
|
-
* (Issue #2614).
|
|
624
|
-
*
|
|
625
|
-
* A copy of `SELF_RESUME_PENDING_DETAIL` in `src/lib/hooks/agent-event-types.ts`
|
|
626
|
-
* for the reason {@link TURN_OPENING_EVENT_TYPES} is a copy: the CLI builds with
|
|
627
|
-
* `"paths": {}`. `tests/unit/cli/commands/wait-self-resume-2614.test.ts` pins the
|
|
628
|
-
* two together.
|
|
629
|
-
*/
|
|
630
|
-
exports.SELF_RESUME_PENDING_DETAIL = 'self_resume_pending';
|
|
631
|
-
/**
|
|
632
|
-
* The capability a source declares when its `stop` can carry
|
|
633
|
-
* {@link SELF_RESUME_PENDING_DETAIL} (Issue #2614).
|
|
634
|
-
*
|
|
635
|
-
* Read by name rather than through the mirrored type in `api-responses.ts`,
|
|
636
|
-
* which predates it: `structuredEvents.source.capabilities` is published as the
|
|
637
|
-
* source's whole declaration, so a newer server sends the key and an older one
|
|
638
|
-
* simply does not.
|
|
639
|
-
*/
|
|
640
|
-
exports.SELF_RESUME_CAPABILITY = 'stopReportsSelfResume';
|
|
641
|
-
/**
|
|
642
|
-
* How long `wait` holds a `stop` whose agent said it would resume by itself
|
|
643
|
-
* (Issue #2614).
|
|
644
|
-
*
|
|
645
|
-
* Measured 2026-09-17 against antigravity 1.2.4: a `schedule` of 60 s closed the
|
|
646
|
-
* turn, the agent woke 58 s after its `Stop` and did it again three more times,
|
|
647
|
-
* and the real end came five minutes after the first `Stop` — which is where
|
|
648
|
-
* `wait` had already reported `Completed (basis=hook_stop)` and started a
|
|
649
|
-
* verification against a half-finished worktree. The wake is not something to
|
|
650
|
-
* time: it is a `post_tool_use` that opens a new turn, and #1839's gate takes
|
|
651
|
-
* over from there. What needs a bound is only the case where it never comes.
|
|
652
|
-
*
|
|
653
|
-
* A timer's own length is not on the wire (the `schedule` arguments reach the
|
|
654
|
-
* permission receiver and stop there), and a command sent to the background has
|
|
655
|
-
* no length at all, so the bound is the one the server already uses for the
|
|
656
|
-
* same question the other way round: how long an open turn is trusted with
|
|
657
|
-
* nothing heard (`TURN_STALE_AFTER_MS` in `src/lib/session/provisional-turn.ts`,
|
|
658
|
-
* pinned equal by `wait-self-resume-2614.test.ts`). Every wake starts a new
|
|
659
|
-
* `stop` and a new hold, so an agent that keeps rescheduling never reaches it.
|
|
660
|
-
*
|
|
661
|
-
* A constant, like {@link PENDING_PROMPT_HOLD_MS}: `--timeout` and
|
|
662
|
-
* `--stall-timeout` below it still win.
|
|
663
|
-
*/
|
|
664
|
-
exports.SELF_RESUME_HOLD_MS = 30 * 60 * 1000;
|
|
665
|
-
/**
|
|
666
|
-
* Whether this tool's event source can say, on its `stop`, that the agent will
|
|
667
|
-
* resume by itself (Issue #2614).
|
|
668
|
-
*
|
|
669
|
-
* The same kind of gate as {@link reportsTurnBoundaries}, and it requires that
|
|
670
|
-
* one too: the hold below is released by a turn-opening event, and a source
|
|
671
|
-
* that cannot send one could only ever end the hold at its bound. A server that
|
|
672
|
-
* predates the declaration answers `false`, and so does every source but the one
|
|
673
|
-
* that writes the detail.
|
|
674
|
-
*/
|
|
675
|
-
function reportsSelfResume(data) {
|
|
676
|
-
const declared = data.structuredEvents?.source?.capabilities;
|
|
677
|
-
return declared?.[exports.SELF_RESUME_CAPABILITY] === true && reportsTurnBoundaries(data);
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* The instant of the `stop` this agent said it would resume from, or null
|
|
681
|
-
* (Issue #2614).
|
|
682
|
-
*
|
|
683
|
-
* Non-null only while that `stop` is still the newest thing the agent has said.
|
|
684
|
-
* The wake is a `post_tool_use` (antigravity reports the timer's own tool call
|
|
685
|
-
* finishing when it fires), which replaces the displayed event and opens a new
|
|
686
|
-
* turn, so this answers null from the first poll after it — and a later `stop`
|
|
687
|
-
* is a different instant, which is how a hold knows it is about a new one.
|
|
688
|
-
*
|
|
689
|
-
* On a server that publishes a turn record the `stop` must also be what closed
|
|
690
|
-
* that turn: a turn ended by `generation` or `session_end` belongs to a process
|
|
691
|
-
* that is gone, and nothing it scheduled is going to wake anything.
|
|
692
|
-
*/
|
|
693
|
-
function pendingSelfResumeStop(data) {
|
|
694
|
-
if (!reportsSelfResume(data))
|
|
695
|
-
return null;
|
|
696
|
-
const events = data.structuredEvents;
|
|
697
|
-
if (!events || events.lastEventType !== TURN_CLOSING_EVENT_TYPE)
|
|
698
|
-
return null;
|
|
699
|
-
if (events.lastEventDetail !== exports.SELF_RESUME_PENDING_DETAIL)
|
|
700
|
-
return null;
|
|
701
|
-
// `closedBy` is the server's close-reason vocabulary; `'stop'` there is the
|
|
702
|
-
// agent's own `Stop`, the only close this hold is about.
|
|
703
|
-
if (publishesTurnRecord(data) && events.closedBy !== 'stop')
|
|
704
|
-
return null;
|
|
705
|
-
return events.lastEventAt ?? null;
|
|
706
|
-
}
|
|
707
|
-
/**
|
|
708
|
-
* When this (worktree, instance) was last handed a prompt (Issue #1975).
|
|
709
|
-
*
|
|
710
|
-
* `limit=1&unit=pairs` is "every row at or after the newest user message"
|
|
711
|
-
* (src/lib/db/chat-db.ts), which is the smallest query that is *guaranteed* to
|
|
712
|
-
* contain that message: plain `limit=1` returns the newest row of either role,
|
|
713
|
-
* and for a turn the agent has already answered that row is the assistant's.
|
|
714
|
-
*
|
|
715
|
-
* Scoped the same way the poll above is: `--instance` when the caller named one,
|
|
716
|
-
* otherwise the `cliToolId` the server resolved for that same poll. Asking
|
|
717
|
-
* unscoped would let a message sent to claude decide a wait on codex.
|
|
718
|
-
*
|
|
719
|
-
* Never throws. An unreadable ledger is not evidence that nothing was sent, so
|
|
720
|
-
* it is reported as such rather than as "nothing was sent" — the call site
|
|
721
|
-
* degrades to the pre-#1975 behaviour instead of holding on a guess.
|
|
722
|
-
*/
|
|
723
|
-
async function readNewestPromptAt(client, worktreeId, options, data) {
|
|
724
|
-
const query = new URLSearchParams({ limit: '1', unit: 'pairs' });
|
|
725
|
-
if (options.instance)
|
|
726
|
-
query.set('instance', options.instance);
|
|
727
|
-
else if (data.cliToolId)
|
|
728
|
-
query.set('cliTool', data.cliToolId);
|
|
729
|
-
try {
|
|
730
|
-
const rows = await client.get(`/api/worktrees/${worktreeId}/messages?${query.toString()}`);
|
|
731
|
-
let newest = null;
|
|
732
|
-
for (const row of rows ?? []) {
|
|
733
|
-
if (row.role !== 'user')
|
|
734
|
-
continue;
|
|
735
|
-
// ISO string on the wire (a JSON-serialized Date), so this is the only
|
|
736
|
-
// place the two clocks meet — and both sides of the comparison below are
|
|
737
|
-
// stamped by the server, so no CLI/server skew enters the verdict.
|
|
738
|
-
const at = Date.parse(row.timestamp);
|
|
739
|
-
if (Number.isNaN(at))
|
|
740
|
-
continue;
|
|
741
|
-
if (newest === null || at > newest)
|
|
742
|
-
newest = at;
|
|
743
|
-
}
|
|
744
|
-
return { readable: true, submittedAt: newest };
|
|
745
|
-
}
|
|
746
|
-
catch (error) {
|
|
747
|
-
console.error(`Note: could not read the message ledger for ${worktreeId} ` +
|
|
748
|
-
`(${error instanceof Error ? error.message : String(error)}); ` +
|
|
749
|
-
'completion will be judged from the frame alone.');
|
|
750
|
-
return { readable: false };
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
/**
|
|
754
|
-
* Whether the newest prompt this instance was handed is still unanswered
|
|
755
|
-
* (Issue #1975).
|
|
756
|
-
*
|
|
757
|
-
* This is the distinction the whole Issue turns on, and it is a comparison of
|
|
758
|
-
* two server-stamped facts rather than a timer:
|
|
759
|
-
*
|
|
760
|
-
* - **idle before this wait began** — the agent's `Stop` postdates the newest
|
|
761
|
-
* prompt. Nothing is outstanding; `wait` completes on the first poll exactly
|
|
762
|
-
* as it always has. An orchestrator waiting on a session that finished long
|
|
763
|
-
* ago pays nothing.
|
|
764
|
-
* - **`send` a moment ago** — the newest prompt postdates the last `Stop`
|
|
765
|
-
* (or there has never been one). The agent has been given work and has not
|
|
766
|
-
* reported finishing it, so a composer frame is "it has not started yet",
|
|
767
|
-
* not "it is done".
|
|
768
|
-
*
|
|
769
|
-
* `wait` could not tell these apart before, because from `current-output` alone
|
|
770
|
-
* they are the same payload: in both, the last thing the agent said was the
|
|
771
|
-
* previous turn's `stop`, and `adoptTurnStart` adopts nothing. Measured against
|
|
772
|
-
* copilot 1.0.80 on 2026-08-22, the window in which that is true after a send is
|
|
773
|
-
* ~1s wide, and `wait`'s first poll is immediate — which is why the false
|
|
774
|
-
* completions came back in 0.3s with `basis=scraper_ready`, 3 times in 5.
|
|
775
|
-
*
|
|
776
|
-
* The fast-turn case falls out of the same comparison rather than needing a rule
|
|
777
|
-
* of its own: a turn that opens and closes between two polls leaves
|
|
778
|
-
* `lastEventType: 'stop'` (so no turn is adopted) but a `stop` that postdates
|
|
779
|
-
* the prompt — answered, and completed on the spot.
|
|
780
|
-
*/
|
|
781
|
-
function outstandingPrompt(data, submittedAt) {
|
|
782
|
-
const stoppedAt = data.lastStopEventAt;
|
|
783
|
-
return stoppedAt == null || stoppedAt < submittedAt;
|
|
784
|
-
}
|
|
785
113
|
/**
|
|
786
114
|
* How long `--on-prompt agent` holds a prompt the target's own Auto-Yes is
|
|
787
115
|
* answering before reporting it anyway, in seconds (Issue #2463).
|
|
@@ -815,25 +143,6 @@ function parseGraceSeconds(raw) {
|
|
|
815
143
|
const trimmed = raw.trim();
|
|
816
144
|
return /^\d+$/.test(trimmed) ? Number(trimmed) : Number.NaN;
|
|
817
145
|
}
|
|
818
|
-
/**
|
|
819
|
-
* Whether one more poll interval still lands inside `--timeout` and
|
|
820
|
-
* `--stall-timeout` (Issue #2463).
|
|
821
|
-
*
|
|
822
|
-
* The Auto-Yes hold asks before it sleeps. Otherwise a caller whose deadline
|
|
823
|
-
* lapses during the hold would hear 124 about a prompt it used to hear 10 about:
|
|
824
|
-
* the hold is there to give Auto-Yes a chance to answer, not to turn an open
|
|
825
|
-
* prompt into a timeout. The same two checks the top of {@link pollWorktree}'s
|
|
826
|
-
* loop makes, one interval ahead.
|
|
827
|
-
*/
|
|
828
|
-
function nextPollWithinDeadlines(options, startTime, lastActivityTime, now) {
|
|
829
|
-
const nextPollAt = now + POLL_INTERVAL_MS;
|
|
830
|
-
if (options.timeout && nextPollAt - startTime >= options.timeout * 1000)
|
|
831
|
-
return false;
|
|
832
|
-
if (options.stallTimeout && nextPollAt - lastActivityTime >= options.stallTimeout * 1000) {
|
|
833
|
-
return false;
|
|
834
|
-
}
|
|
835
|
-
return true;
|
|
836
|
-
}
|
|
837
146
|
/**
|
|
838
147
|
* The exit-10 payload for a prompt the detection layer parsed. `suppressed` is
|
|
839
148
|
* {@link activeSuppression}'s reading of the same poll.
|
|
@@ -912,17 +221,18 @@ function buildSelectionListOutput(worktreeId, data) {
|
|
|
912
221
|
* What `wait` says about a frame that stayed unclassified for the whole dwell
|
|
913
222
|
* (Issue #1708): the stderr line, and the `question` of its exit-10 payload.
|
|
914
223
|
*/
|
|
915
|
-
function describeUnclassifiedFrame(worktreeId, data, dwellMs) {
|
|
224
|
+
function describeUnclassifiedFrame(worktreeId, data, dwellMs, options) {
|
|
916
225
|
const dwellSeconds = Math.round(dwellMs / 1000);
|
|
917
226
|
return (`Unclassified interactive frame on ${worktreeId} for ${dwellSeconds}s ` +
|
|
918
227
|
`(status=${data.sessionStatus ?? 'unknown'}/${data.sessionStatusReason ?? 'unknown'}). ` +
|
|
919
228
|
`The detection layer could not parse it; inspect the raw pane with ` +
|
|
920
|
-
|
|
229
|
+
// Issue #3982: the instance waited on, and enough of its pane for a dialog.
|
|
230
|
+
`\`${(0, follow_up_command_1.dialogCaptureCommand)(worktreeId, (0, wait_instance_1.waitCommandTarget)(options))}\`.` +
|
|
921
231
|
// Issue #2095: the sidebar is exactly this frame's reason, and the
|
|
922
232
|
// one recovery is a keystroke in the pane. Riding the message keeps
|
|
923
233
|
// the exit-code table (10, `type: unclassified`) unchanged for every
|
|
924
234
|
// caller that already branches on it.
|
|
925
|
-
describePaneObstruction(data));
|
|
235
|
+
(0, wait_notices_1.describePaneObstruction)(data));
|
|
926
236
|
}
|
|
927
237
|
/** The exit-10 payload for a persistently unclassified frame (Issue #1708). */
|
|
928
238
|
function buildUnclassifiedOutput(worktreeId, data, question) {
|
|
@@ -1004,9 +314,9 @@ function promptStage(poll, state, data) {
|
|
|
1004
314
|
// Issue #1699: report a policy suppression on both exits — the human one
|
|
1005
315
|
// keeps polling and would otherwise say nothing about why nobody
|
|
1006
316
|
// answered, and the agent one is read by pipelines that never see stderr.
|
|
1007
|
-
const suppressed = activeSuppression(data, Date.now());
|
|
317
|
+
const suppressed = (0, wait_notices_1.activeSuppression)(data, Date.now());
|
|
1008
318
|
// Issue #3821: withheld by the server's decision, with no suppression to say so.
|
|
1009
|
-
const decisionWithheld = suppressed ? null : decisionWithheldReason(data);
|
|
319
|
+
const decisionWithheld = suppressed ? null : (0, wait_notices_1.decisionWithheldReason)(data);
|
|
1010
320
|
const decisionNotice = decisionWithheld === null
|
|
1011
321
|
? null
|
|
1012
322
|
: ` auto-yes is not answering this prompt (reason=${decisionWithheld}); it is a human's to answer.`;
|
|
@@ -1015,16 +325,16 @@ function promptStage(poll, state, data) {
|
|
|
1015
325
|
// Block and continue polling - user handles prompt manually
|
|
1016
326
|
console.error(`Prompt detected on ${worktreeId}. Waiting for human response...`);
|
|
1017
327
|
if (suppressed) {
|
|
1018
|
-
console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
|
|
328
|
+
console.error((0, wait_notices_1.formatSuppressionNotice)(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
|
|
1019
329
|
}
|
|
1020
330
|
if (decisionNotice)
|
|
1021
331
|
console.error(decisionNotice);
|
|
1022
332
|
// Issue #3397: and whether Auto-Yes already pressed Enter on it.
|
|
1023
|
-
const enterNotice = formatEnterFallbackNotice(data, Date.now());
|
|
333
|
+
const enterNotice = (0, wait_notices_1.formatEnterFallbackNotice)(data, Date.now());
|
|
1024
334
|
if (enterNotice)
|
|
1025
335
|
console.error(enterNotice);
|
|
1026
336
|
// Issue #3730: and whether a restart is why nothing is answering it.
|
|
1027
|
-
const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
|
|
337
|
+
const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
|
|
1028
338
|
if (restartNotice)
|
|
1029
339
|
console.error(restartNotice);
|
|
1030
340
|
return { kind: 'wait' };
|
|
@@ -1047,7 +357,7 @@ function promptStage(poll, state, data) {
|
|
|
1047
357
|
}
|
|
1048
358
|
const heldMs = now - state.autoYesAnsweringSince;
|
|
1049
359
|
if (heldMs < autoYesGraceMs &&
|
|
1050
|
-
nextPollWithinDeadlines(options, startTime, state.lastActivityTime, now)) {
|
|
360
|
+
(0, wait_timing_1.nextPollWithinDeadlines)(options, startTime, state.lastActivityTime, now)) {
|
|
1051
361
|
return { kind: 'wait' };
|
|
1052
362
|
}
|
|
1053
363
|
console.error(heldMs < autoYesGraceMs
|
|
@@ -1062,16 +372,16 @@ function promptStage(poll, state, data) {
|
|
|
1062
372
|
// Default (agent mode): output prompt info and exit 10
|
|
1063
373
|
const promptOutput = buildPromptOutput(worktreeId, data, data.promptData, suppressed);
|
|
1064
374
|
if (suppressed) {
|
|
1065
|
-
console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
|
|
375
|
+
console.error((0, wait_notices_1.formatSuppressionNotice)(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
|
|
1066
376
|
}
|
|
1067
377
|
if (decisionNotice)
|
|
1068
378
|
console.error(decisionNotice);
|
|
1069
379
|
// Issue #3397: stderr only, like the notice above; the exit-10 payload is unchanged.
|
|
1070
|
-
const enterNotice = formatEnterFallbackNotice(data, Date.now());
|
|
380
|
+
const enterNotice = (0, wait_notices_1.formatEnterFallbackNotice)(data, Date.now());
|
|
1071
381
|
if (enterNotice)
|
|
1072
382
|
console.error(enterNotice);
|
|
1073
383
|
// Issue #3730: stderr only as well.
|
|
1074
|
-
const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
|
|
384
|
+
const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
|
|
1075
385
|
if (restartNotice)
|
|
1076
386
|
console.error(restartNotice);
|
|
1077
387
|
return exitWith({ exitCode: types_1.WaitExitCode.PROMPT_DETECTED, output: promptOutput });
|
|
@@ -1091,18 +401,18 @@ function selectionListStage(poll, data) {
|
|
|
1091
401
|
'Waiting for human response...');
|
|
1092
402
|
// Issue #1699: the poller parses frames status-detector publishes as
|
|
1093
403
|
// selection lists, so a policy can be the reason this one is stuck too.
|
|
1094
|
-
const suppressed = activeSuppression(data, Date.now());
|
|
404
|
+
const suppressed = (0, wait_notices_1.activeSuppression)(data, Date.now());
|
|
1095
405
|
if (suppressed) {
|
|
1096
|
-
console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
|
|
406
|
+
console.error((0, wait_notices_1.formatSuppressionNotice)(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
|
|
1097
407
|
}
|
|
1098
408
|
// Issue #3730
|
|
1099
|
-
const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
|
|
409
|
+
const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
|
|
1100
410
|
if (restartNotice)
|
|
1101
411
|
console.error(restartNotice);
|
|
1102
412
|
return { kind: 'wait' };
|
|
1103
413
|
}
|
|
1104
414
|
// Issue #3730: stderr only; the exit-10 payload is unchanged.
|
|
1105
|
-
const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
|
|
415
|
+
const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
|
|
1106
416
|
if (restartNotice)
|
|
1107
417
|
console.error(restartNotice);
|
|
1108
418
|
return exitWith({
|
|
@@ -1159,9 +469,9 @@ function unclassifiedStage(poll, state, data) {
|
|
|
1159
469
|
state.unclassifiedSince = Date.now();
|
|
1160
470
|
const dwellMs = Date.now() - state.unclassifiedSince;
|
|
1161
471
|
if (dwellMs >= UNCLASSIFIED_DWELL_MS) {
|
|
1162
|
-
const question = describeUnclassifiedFrame(worktreeId, data, dwellMs);
|
|
472
|
+
const question = describeUnclassifiedFrame(worktreeId, data, dwellMs, poll.options);
|
|
1163
473
|
// Issue #3730: why Auto-Yes is not there to answer it, if a restart is why.
|
|
1164
|
-
const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
|
|
474
|
+
const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
|
|
1165
475
|
if (options.onPrompt === 'human') {
|
|
1166
476
|
console.error(question);
|
|
1167
477
|
if (restartNotice)
|
|
@@ -1203,14 +513,25 @@ function notRunningStage(poll, state, data, selfResumeSuffix) {
|
|
|
1203
513
|
return exitWith({ exitCode: types_1.VerifyExitCode.NOT_STARTED });
|
|
1204
514
|
}
|
|
1205
515
|
if (!data.isRunning) {
|
|
1206
|
-
console.error(`Completed: ${worktreeId} (basis=${COMPLETION_BASIS.SESSION_GONE}${selfResumeSuffix()})`);
|
|
516
|
+
console.error(`Completed: ${worktreeId} (basis=${wait_turn_boundary_1.COMPLETION_BASIS.SESSION_GONE}${selfResumeSuffix()})`);
|
|
1207
517
|
return exitWith({ exitCode: types_1.WaitExitCode.SUCCESS });
|
|
1208
518
|
}
|
|
1209
519
|
return { kind: 'next' };
|
|
1210
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* The upstream fault on the frame that `--fail-on-upstream-fault` reports, or
|
|
523
|
+
* null (Issue #1839). Prints nothing, so a caller can decide which frame the
|
|
524
|
+
* verdict is on before {@link upstreamFaultStage} reports it (Issue #3956).
|
|
525
|
+
*/
|
|
526
|
+
function reportableUpstreamFault(poll, data) {
|
|
527
|
+
if (!poll.options.failOnUpstreamFault)
|
|
528
|
+
return null;
|
|
529
|
+
return data.upstreamFault ?? null;
|
|
530
|
+
}
|
|
1211
531
|
/**
|
|
1212
532
|
* Stage of a `ready` frame: an upstream fault on the frame, under
|
|
1213
|
-
* `--fail-on-upstream-fault` (Issue #1839). Exit 11
|
|
533
|
+
* `--fail-on-upstream-fault` (Issue #1839). Exit 11, with its diagnosis on
|
|
534
|
+
* stderr.
|
|
1214
535
|
*/
|
|
1215
536
|
function upstreamFaultStage(poll, data) {
|
|
1216
537
|
const { worktreeId, options } = poll;
|
|
@@ -1219,8 +540,8 @@ function upstreamFaultStage(poll, data) {
|
|
|
1219
540
|
// because it is the answer to the question that gate can only ask: the
|
|
1220
541
|
// turn did not end, and this is why. Without it the same session runs
|
|
1221
542
|
// to --timeout and reports 124, which says nothing about the cause.
|
|
1222
|
-
const fault = data
|
|
1223
|
-
if (
|
|
543
|
+
const fault = reportableUpstreamFault(poll, data);
|
|
544
|
+
if (fault) {
|
|
1224
545
|
console.error(`Upstream fault on ${worktreeId}: id=${fault.id} — the agent is back at its ` +
|
|
1225
546
|
'composer with an upstream API failure on screen, so this turn did not run. ' +
|
|
1226
547
|
`Matched: ${JSON.stringify(fault.matchedText)}`);
|
|
@@ -1237,6 +558,32 @@ function upstreamFaultStage(poll, data) {
|
|
|
1237
558
|
}
|
|
1238
559
|
return { kind: 'next' };
|
|
1239
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* The chat-ledger read of a poll, bounded by `--timeout` / `--stall-timeout`
|
|
563
|
+
* (Issue #3974).
|
|
564
|
+
*
|
|
565
|
+
* On an ordinary poll, a ledger that does not answer in time ends the wait
|
|
566
|
+
* ({@link DeadlineReached} back to {@link deadlineStage}, exit 124), not
|
|
567
|
+
* "unreadable". On the frame a settle returned (`judgingSettledFrame`) it does
|
|
568
|
+
* not: that frame was read inside the deadlines and is judged even after them
|
|
569
|
+
* (#3956), so the ledger is reported unreadable and the frame decides alone —
|
|
570
|
+
* as {@link faultFrameHasStop} treats a ledger cut by the same deadlines.
|
|
571
|
+
*/
|
|
572
|
+
async function readLedgerWithinDeadlines(poll, state, data, judgingSettledFrame) {
|
|
573
|
+
const { client, worktreeId, options, startTime } = poll;
|
|
574
|
+
try {
|
|
575
|
+
// Quiet when aborted: what the deadline leads to is said here (settled
|
|
576
|
+
// frame) or by deadlineStage (124), not "judged from the frame alone".
|
|
577
|
+
return await (0, wait_timing_1.readWithinDeadlines)(options, startTime, state.lastActivityTime, signal => (0, wait_turn_boundary_1.readNewestPromptAt)(client, worktreeId, options, data, signal, true));
|
|
578
|
+
}
|
|
579
|
+
catch (error) {
|
|
580
|
+
if (!judgingSettledFrame || !(error instanceof wait_timing_1.DeadlineReached))
|
|
581
|
+
throw error;
|
|
582
|
+
console.error(`Note: the message ledger for ${worktreeId} could not be read within --timeout/--stall-timeout; ` +
|
|
583
|
+
'judging the settled frame alone.');
|
|
584
|
+
return { readable: false };
|
|
585
|
+
}
|
|
586
|
+
}
|
|
1240
587
|
/**
|
|
1241
588
|
* How long `wait` holds an orphan turn — see {@link releaseOrphanTurn} — before
|
|
1242
589
|
* completing on the `Stop` that answered the newest prompt (Issue #3429).
|
|
@@ -1247,7 +594,7 @@ function upstreamFaultStage(poll, data) {
|
|
|
1247
594
|
* is restarted by any change to the frame, so a pane that is still drawing is
|
|
1248
595
|
* never released. `--timeout` and `--stall-timeout` below it still win.
|
|
1249
596
|
*/
|
|
1250
|
-
const ORPHAN_TURN_HOLD_MS = PENDING_PROMPT_HOLD_MS;
|
|
597
|
+
const ORPHAN_TURN_HOLD_MS = wait_turn_boundary_1.PENDING_PROMPT_HOLD_MS;
|
|
1251
598
|
/**
|
|
1252
599
|
* Whether the unsettled turn this wait adopted is an orphan the agent will never
|
|
1253
600
|
* send a `Stop` for, held for {@link ORPHAN_TURN_HOLD_MS} (Issue #3429).
|
|
@@ -1268,13 +615,13 @@ const ORPHAN_TURN_HOLD_MS = PENDING_PROMPT_HOLD_MS;
|
|
|
1268
615
|
* prompt has no `Stop` after it — that one keeps holding to `--timeout`;
|
|
1269
616
|
* - the frame has not changed for {@link ORPHAN_TURN_HOLD_MS}.
|
|
1270
617
|
*/
|
|
1271
|
-
async function releaseOrphanTurn(poll, state, data) {
|
|
1272
|
-
const {
|
|
618
|
+
async function releaseOrphanTurn(poll, state, data, judgingSettledFrame) {
|
|
619
|
+
const { worktreeId } = poll;
|
|
1273
620
|
const events = data.structuredEvents;
|
|
1274
621
|
const closedByScreen = events?.closedBy === 'scraper_evidence' || events?.closedBy === 'stale';
|
|
1275
622
|
if (!events ||
|
|
1276
|
-
!publishesTurnRecord(data) ||
|
|
1277
|
-
!reportsTurnBoundaries(data) ||
|
|
623
|
+
!(0, wait_turn_boundary_1.publishesTurnRecord)(data) ||
|
|
624
|
+
!(0, wait_turn_boundary_1.reportsTurnBoundaries)(data) ||
|
|
1278
625
|
events.closedAt == null ||
|
|
1279
626
|
events.openedAt == null ||
|
|
1280
627
|
!closedByScreen ||
|
|
@@ -1283,9 +630,10 @@ async function releaseOrphanTurn(poll, state, data) {
|
|
|
1283
630
|
state.orphanTurnHold = null;
|
|
1284
631
|
return false;
|
|
1285
632
|
}
|
|
1286
|
-
|
|
633
|
+
// Issue #3974: bounded by --timeout / --stall-timeout.
|
|
634
|
+
const ledger = await readLedgerWithinDeadlines(poll, state, data, judgingSettledFrame);
|
|
1287
635
|
state.promptLedgerReadable = ledger.readable;
|
|
1288
|
-
if (!ledger.readable || ledger.submittedAt === null || outstandingPrompt(data, ledger.submittedAt)) {
|
|
636
|
+
if (!ledger.readable || ledger.submittedAt === null || (0, wait_turn_boundary_1.outstandingPrompt)(data, ledger.submittedAt)) {
|
|
1289
637
|
state.orphanTurnHold = null;
|
|
1290
638
|
return false;
|
|
1291
639
|
}
|
|
@@ -1298,7 +646,7 @@ async function releaseOrphanTurn(poll, state, data) {
|
|
|
1298
646
|
return false;
|
|
1299
647
|
console.error(`Note: ${worktreeId} answered its newest prompt with a stop ` +
|
|
1300
648
|
`(lastStopEventAt=${data.lastStopEventAt}), and the turn opened after it ` +
|
|
1301
|
-
`(turnStartedAt=${state.turnStartedAt}, ${describeTurnClose(data)}) has had no prompt, ` +
|
|
649
|
+
`(turnStartedAt=${state.turnStartedAt}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}) has had no prompt, ` +
|
|
1302
650
|
`no stop and no new output for ${Math.round(quietMs / 1000)}s; completing on that stop.`);
|
|
1303
651
|
return true;
|
|
1304
652
|
}
|
|
@@ -1306,7 +654,7 @@ async function releaseOrphanTurn(poll, state, data) {
|
|
|
1306
654
|
* Stage of a `ready` frame: the agent has not reported the end of the turn this
|
|
1307
655
|
* wait adopted (Issue #1839). Held, except for an orphan turn (Issue #3429).
|
|
1308
656
|
*/
|
|
1309
|
-
async function unsettledTurnStage(poll, state, data) {
|
|
657
|
+
async function unsettledTurnStage(poll, state, data, judgingSettledFrame) {
|
|
1310
658
|
const { worktreeId } = poll;
|
|
1311
659
|
// Issue #1839: `ready` off the terminal frame is the agent's composer,
|
|
1312
660
|
// not the agent's verdict. Measured 2026-08-20 against a stub upstream
|
|
@@ -1315,14 +663,14 @@ async function unsettledTurnStage(poll, state, data) {
|
|
|
1315
663
|
// hooks ARE reporting — the only case in which `turnStartedAt` is
|
|
1316
664
|
// non-null — that missing `Stop` is the difference between "finished"
|
|
1317
665
|
// and "never ran", and it is the only signal that carries it.
|
|
1318
|
-
if (!turnSettled(data, state.turnStartedAt)) {
|
|
1319
|
-
if (await releaseOrphanTurn(poll, state, data))
|
|
666
|
+
if (!(0, wait_turn_boundary_1.turnSettled)(data, state.turnStartedAt)) {
|
|
667
|
+
if (await releaseOrphanTurn(poll, state, data, judgingSettledFrame))
|
|
1320
668
|
return { kind: 'next' };
|
|
1321
669
|
console.error(`Waiting: ${worktreeId} is back at its composer, but its agent has not reported ` +
|
|
1322
670
|
`the end of this turn (turnStartedAt=${state.turnStartedAt}, ` +
|
|
1323
|
-
`lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
|
|
671
|
+
`lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}). ` +
|
|
1324
672
|
'Not reporting completion; inspect with ' +
|
|
1325
|
-
|
|
673
|
+
`\`${(0, follow_up_command_1.followUpCommand)('capture', worktreeId, (0, wait_instance_1.waitCommandTarget)(poll.options), undefined, '--json')}\`.`);
|
|
1326
674
|
return { kind: 'wait' };
|
|
1327
675
|
}
|
|
1328
676
|
return { kind: 'next' };
|
|
@@ -1352,13 +700,13 @@ function selfResumeHoldStage(poll, state, data, selfResumeStopAt) {
|
|
|
1352
700
|
state.selfResumeHold = { stopAt: selfResumeStopAt, since: now };
|
|
1353
701
|
const heldMs = now - state.selfResumeHold.since;
|
|
1354
702
|
const elapsedMs = Math.max(heldMs, now - selfResumeStopAt);
|
|
1355
|
-
if (elapsedMs <
|
|
703
|
+
if (elapsedMs < wait_turn_boundary_1.SELF_RESUME_HOLD_MS) {
|
|
1356
704
|
state.selfResumeHeld = true;
|
|
1357
705
|
console.error(`Waiting: ${worktreeId} ended its turn with background work still running ` +
|
|
1358
706
|
`(stoppedAt=${new Date(selfResumeStopAt).toISOString()}, ` +
|
|
1359
|
-
`lastEventDetail=${
|
|
707
|
+
`lastEventDetail=${wait_turn_boundary_1.SELF_RESUME_PENDING_DETAIL}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}); ` +
|
|
1360
708
|
'it resumes by itself when that work finishes. Not reporting completion ' +
|
|
1361
|
-
`(held ${Math.round(heldMs / 1000)}s, at most ${
|
|
709
|
+
`(held ${Math.round(heldMs / 1000)}s, at most ${wait_turn_boundary_1.SELF_RESUME_HOLD_MS / 1000}s ` +
|
|
1362
710
|
'after the stop).');
|
|
1363
711
|
return { kind: 'wait' };
|
|
1364
712
|
}
|
|
@@ -1374,8 +722,8 @@ function selfResumeHoldStage(poll, state, data, selfResumeStopAt) {
|
|
|
1374
722
|
* `next` carries whether the newest prompt was answered, which
|
|
1375
723
|
* {@link completionStage} needs for its basis.
|
|
1376
724
|
*/
|
|
1377
|
-
async function promptLedgerStage(poll, state, data) {
|
|
1378
|
-
const {
|
|
725
|
+
async function promptLedgerStage(poll, state, data, judgingSettledFrame) {
|
|
726
|
+
const { worktreeId, pollStartedAt } = poll;
|
|
1379
727
|
// Issue #1975: the same frame, one question further back. #1839's gate
|
|
1380
728
|
// above can only fire once a turn has been ADOPTED, and `send` leaves a
|
|
1381
729
|
// window ~1s wide in which nothing has been: the newest structured event
|
|
@@ -1393,18 +741,19 @@ async function promptLedgerStage(poll, state, data) {
|
|
|
1393
741
|
// {@link reportsTurnBoundaries} for why a tool that posts no hooks never
|
|
1394
742
|
// reaches it.
|
|
1395
743
|
let answeredNewestPrompt = false;
|
|
1396
|
-
if (state.turnStartedAt === null && state.promptLedgerReadable && reportsTurnBoundaries(data)) {
|
|
1397
|
-
|
|
744
|
+
if (state.turnStartedAt === null && state.promptLedgerReadable && (0, wait_turn_boundary_1.reportsTurnBoundaries)(data)) {
|
|
745
|
+
// Issue #3974: bounded by --timeout / --stall-timeout.
|
|
746
|
+
const ledger = await readLedgerWithinDeadlines(poll, state, data, judgingSettledFrame);
|
|
1398
747
|
// One notice, then stop asking: a ledger that failed once will fail
|
|
1399
748
|
// every poll, and the point of degrading is to stop paying for it.
|
|
1400
749
|
state.promptLedgerReadable = ledger.readable;
|
|
1401
750
|
if (ledger.readable && ledger.submittedAt !== null) {
|
|
1402
|
-
if (outstandingPrompt(data, ledger.submittedAt)) {
|
|
1403
|
-
const heldMs = Date.now() -
|
|
1404
|
-
if (heldMs < PENDING_PROMPT_HOLD_MS) {
|
|
751
|
+
if ((0, wait_turn_boundary_1.outstandingPrompt)(data, ledger.submittedAt)) {
|
|
752
|
+
const heldMs = Date.now() - pollStartedAt;
|
|
753
|
+
if (heldMs < wait_turn_boundary_1.PENDING_PROMPT_HOLD_MS) {
|
|
1405
754
|
console.error(`Waiting: ${worktreeId} is at its composer, but the newest prompt sent to it ` +
|
|
1406
755
|
`has no reported end (sentAt=${new Date(ledger.submittedAt).toISOString()}, ` +
|
|
1407
|
-
`lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
|
|
756
|
+
`lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}). ` +
|
|
1408
757
|
'Not reporting completion: the agent has not started this turn yet.');
|
|
1409
758
|
return { kind: 'wait' };
|
|
1410
759
|
}
|
|
@@ -1419,25 +768,34 @@ async function promptLedgerStage(poll, state, data) {
|
|
|
1419
768
|
}
|
|
1420
769
|
return { kind: 'next', answeredNewestPrompt };
|
|
1421
770
|
}
|
|
771
|
+
/**
|
|
772
|
+
* The basis of a completion on a `ready` frame (Issue #1839).
|
|
773
|
+
*
|
|
774
|
+
* `hook_stop` on both branches that have one, and they are the same statement
|
|
775
|
+
* made from two records: the agent reported the end of the turn this wait is
|
|
776
|
+
* about. `scraper_ready` keeps its documented meaning — "the screen said so and
|
|
777
|
+
* nothing corroborated it" — which is now exactly the set of cases that reach it.
|
|
778
|
+
*/
|
|
779
|
+
function readyCompletionBasis(state, answeredNewestPrompt) {
|
|
780
|
+
return state.turnStartedAt !== null || answeredNewestPrompt
|
|
781
|
+
? wait_turn_boundary_1.COMPLETION_BASIS.HOOK_STOP
|
|
782
|
+
: wait_turn_boundary_1.COMPLETION_BASIS.SCRAPER_READY;
|
|
783
|
+
}
|
|
1422
784
|
/** Last stage of a `ready` frame: the completion line with its basis. Exit 0. */
|
|
1423
785
|
function completionStage(poll, state, answeredNewestPrompt, selfResumeSuffix) {
|
|
1424
786
|
const { worktreeId } = poll;
|
|
1425
|
-
|
|
1426
|
-
// statement made from two records: the agent reported the end of the
|
|
1427
|
-
// turn this wait is about. `scraper_ready` keeps its documented meaning
|
|
1428
|
-
// — "the screen said so and nothing corroborated it" — which is now
|
|
1429
|
-
// exactly the set of cases that reach it.
|
|
1430
|
-
const basis = state.turnStartedAt !== null || answeredNewestPrompt
|
|
1431
|
-
? COMPLETION_BASIS.HOOK_STOP
|
|
1432
|
-
: COMPLETION_BASIS.SCRAPER_READY;
|
|
787
|
+
const basis = readyCompletionBasis(state, answeredNewestPrompt);
|
|
1433
788
|
console.error(`Completed: ${worktreeId} (basis=${basis}${selfResumeSuffix()})`);
|
|
1434
789
|
return exitWith({ exitCode: types_1.WaitExitCode.SUCCESS });
|
|
1435
790
|
}
|
|
1436
791
|
/**
|
|
1437
792
|
* Stage: the agent is back at its composer on a frame that was understood. Asks
|
|
1438
793
|
* the stages of a `ready` frame in order; the first that applies decides.
|
|
794
|
+
*
|
|
795
|
+
* `judgingSettledFrame` is true when `data` is the frame a settle returned
|
|
796
|
+
* (Issue #3956): it is judged as it stands and never settled again.
|
|
1439
797
|
*/
|
|
1440
|
-
async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix) {
|
|
798
|
+
async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix, judgingSettledFrame) {
|
|
1441
799
|
// Issue #1708 narrowed Path B: `ready` is only a completion when the frame
|
|
1442
800
|
// was actually understood. A structured `hook_stop` over an unreadable
|
|
1443
801
|
// pane is the degraded form of an overlay nobody could parse (see the note
|
|
@@ -1445,18 +803,41 @@ async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix)
|
|
|
1445
803
|
// merged. Path A is untouched — a session that went away really is
|
|
1446
804
|
// finished, and carries no flag anyway.
|
|
1447
805
|
if (data.sessionStatus === 'ready' && data.isUnclassifiedActive !== true) {
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
806
|
+
// Issue #3956: one bound for everything a `Stop` poll's settle waits on —
|
|
807
|
+
// the ledger read that confirms the `Stop` and the re-reads — measured
|
|
808
|
+
// from this poll, so the verdict comes at most HOOK_STOP_SETTLE_MAX_MS
|
|
809
|
+
// after it (`--timeout` is applied on top, where each wait is bounded).
|
|
810
|
+
const settleDeadline = Date.now() + wait_hook_stop_settle_1.HOOK_STOP_SETTLE_MAX_MS;
|
|
811
|
+
if (reportableUpstreamFault(poll, data) !== null) {
|
|
812
|
+
// Issue #3956: a fault on the frame of a `Stop` poll is on a pane that
|
|
813
|
+
// may still be drawing, as much as a clean one is; it is judged on the
|
|
814
|
+
// settled frame too. Without a `Stop` it is #1839's case, reported now.
|
|
815
|
+
// Nothing is printed before that is decided: the diagnosis is for the
|
|
816
|
+
// frame the verdict is on.
|
|
817
|
+
if (!judgingSettledFrame && (await (0, wait_hook_stop_settle_1.faultFrameHasStop)(poll, state, data, settleDeadline))) {
|
|
818
|
+
return { kind: 'settled', data: await (0, wait_hook_stop_settle_1.settleAfterHookStop)(poll, state, data, settleDeadline) };
|
|
819
|
+
}
|
|
820
|
+
return upstreamFaultStage(poll, data);
|
|
821
|
+
}
|
|
822
|
+
const turnOutcome = await unsettledTurnStage(poll, state, data, judgingSettledFrame);
|
|
1452
823
|
if (turnOutcome.kind !== 'next')
|
|
1453
824
|
return turnOutcome;
|
|
1454
825
|
const holdOutcome = selfResumeHoldStage(poll, state, data, selfResumeStopAt);
|
|
1455
826
|
if (holdOutcome.kind !== 'next')
|
|
1456
827
|
return holdOutcome;
|
|
1457
|
-
const ledgerOutcome = await promptLedgerStage(poll, state, data);
|
|
828
|
+
const ledgerOutcome = await promptLedgerStage(poll, state, data, judgingSettledFrame);
|
|
1458
829
|
if (ledgerOutcome.kind !== 'next')
|
|
1459
830
|
return ledgerOutcome;
|
|
831
|
+
// Issue #3956: the `Stop` can land before the end of the reply is on the
|
|
832
|
+
// pane, so a `hook_stop` completion is judged again on the settled frame —
|
|
833
|
+
// as a poll of its own, so a prompt or a new turn drawn meanwhile is not
|
|
834
|
+
// read as this completion. Only under the flag: a plain `wait` reads no
|
|
835
|
+
// fault and waits no longer.
|
|
836
|
+
if (!judgingSettledFrame &&
|
|
837
|
+
poll.options.failOnUpstreamFault &&
|
|
838
|
+
readyCompletionBasis(state, ledgerOutcome.answeredNewestPrompt) === wait_turn_boundary_1.COMPLETION_BASIS.HOOK_STOP) {
|
|
839
|
+
return { kind: 'settled', data: await (0, wait_hook_stop_settle_1.settleAfterHookStop)(poll, state, data, settleDeadline) };
|
|
840
|
+
}
|
|
1460
841
|
return completionStage(poll, state, ledgerOutcome.answeredNewestPrompt, selfResumeSuffix);
|
|
1461
842
|
}
|
|
1462
843
|
return { kind: 'next' };
|
|
@@ -1476,7 +857,10 @@ async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix)
|
|
|
1476
857
|
* {@link resolveWaitInstance}.
|
|
1477
858
|
*/
|
|
1478
859
|
async function pollWorktree(client, worktreeId, options) {
|
|
1479
|
-
const
|
|
860
|
+
const pollStartedAt = Date.now();
|
|
861
|
+
// Issue #3983: `--timeout` counts from the command's start when the caller
|
|
862
|
+
// passed it, so the reads before this poll are inside the deadline.
|
|
863
|
+
const startTime = options.timeoutStartedAt ?? pollStartedAt;
|
|
1480
864
|
const state = {
|
|
1481
865
|
lastActivityTime: Date.now(),
|
|
1482
866
|
lastContent: '',
|
|
@@ -1492,7 +876,15 @@ async function pollWorktree(client, worktreeId, options) {
|
|
|
1492
876
|
};
|
|
1493
877
|
const autoYesGraceSeconds = options.autoYesGrace ?? AUTO_YES_GRACE_DEFAULT_SECONDS;
|
|
1494
878
|
const autoYesGraceMs = autoYesGraceSeconds * 1000;
|
|
1495
|
-
const poll = {
|
|
879
|
+
const poll = {
|
|
880
|
+
client,
|
|
881
|
+
worktreeId,
|
|
882
|
+
options,
|
|
883
|
+
startTime,
|
|
884
|
+
pollStartedAt,
|
|
885
|
+
autoYesGraceSeconds,
|
|
886
|
+
autoYesGraceMs,
|
|
887
|
+
};
|
|
1496
888
|
/**
|
|
1497
889
|
* What the completion line adds when this wait held for a self-resume, or ''
|
|
1498
890
|
* (Issue #2614). `basis=` keeps its word: the verdict is still the agent's own
|
|
@@ -1504,23 +896,34 @@ async function pollWorktree(client, worktreeId, options) {
|
|
|
1504
896
|
const total = state.selfResumeHeldMs + (state.selfResumeHold ? Date.now() - state.selfResumeHold.since : 0);
|
|
1505
897
|
return `, heldForSelfResume=${Math.round(total / 1000)}s`;
|
|
1506
898
|
};
|
|
899
|
+
/**
|
|
900
|
+
* The frame a settle returned, judged as the next poll (Issue #3956). It was
|
|
901
|
+
* read inside the deadlines the settle kept to, so that poll does not ask
|
|
902
|
+
* {@link deadlineStage} again: a turn that completed in time is not a 124.
|
|
903
|
+
*/
|
|
904
|
+
let settledFrame = null;
|
|
1507
905
|
while (true) {
|
|
1508
|
-
const
|
|
1509
|
-
if (
|
|
1510
|
-
|
|
906
|
+
const judgingSettledFrame = settledFrame !== null;
|
|
907
|
+
if (!judgingSettledFrame) {
|
|
908
|
+
const deadlineOutcome = deadlineStage(poll, state);
|
|
909
|
+
if (deadlineOutcome.kind === 'exit')
|
|
910
|
+
return deadlineOutcome.result;
|
|
911
|
+
}
|
|
1511
912
|
try {
|
|
1512
913
|
// Issue #868: scope polling to a specific agent instance when provided.
|
|
1513
914
|
// Issue #3755: `observe=1` so an exit 10 carries the observation of the
|
|
1514
915
|
// very capture it was decided on (see {@link withObservation}).
|
|
1515
|
-
const data =
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
state.
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
916
|
+
const data = settledFrame ??
|
|
917
|
+
// Issue #3974: bounded by --timeout / --stall-timeout, so a server that
|
|
918
|
+
// does not answer cannot hold the wait past them.
|
|
919
|
+
(await (0, wait_timing_1.readWithinDeadlines)(options, startTime, state.lastActivityTime, signal => {
|
|
920
|
+
const path = (0, prompt_1.observedCurrentOutputPath)(worktreeId, options.instance);
|
|
921
|
+
return signal
|
|
922
|
+
? client.get(path, { signal })
|
|
923
|
+
: client.get(path);
|
|
924
|
+
}));
|
|
925
|
+
settledFrame = null;
|
|
926
|
+
(0, wait_poll_bookkeeping_1.trackPollActivity)(state, data);
|
|
1524
927
|
// Issue #3179: the agent is still launching. Work in progress, so keep
|
|
1525
928
|
// polling: no prompt or selection list is read off the launch's frame,
|
|
1526
929
|
// the unclassified dwell does not run, and a pane that does not exist yet
|
|
@@ -1529,220 +932,78 @@ async function pollWorktree(client, worktreeId, options) {
|
|
|
1529
932
|
// completion. The server bounds the launch, so this cannot hold forever.
|
|
1530
933
|
if (typeof data.startingSince === 'number') {
|
|
1531
934
|
state.unclassifiedSince = null;
|
|
1532
|
-
await sleep(POLL_INTERVAL_MS);
|
|
935
|
+
await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
|
|
1533
936
|
continue;
|
|
1534
937
|
}
|
|
1535
|
-
|
|
1536
|
-
// poll that ends in a prompt — the same turn is still open when the human
|
|
1537
|
-
// answers and `--on-prompt human` resumes polling.
|
|
1538
|
-
state.turnStartedAt = adoptTurnStart(data, startTime, state.turnStartedAt);
|
|
938
|
+
(0, wait_poll_bookkeeping_1.adoptAndPublishTurn)(state, data, pollStartedAt, options);
|
|
1539
939
|
// Issue #2614: a self-resume hold is about one `stop`, and ends the first
|
|
1540
940
|
// time that `stop` is no longer the newest word — the agent woke (a
|
|
1541
941
|
// turn-opening event) or stopped again. Checked on every poll, ahead of
|
|
1542
942
|
// every exit, because the wake usually lands on a `running` frame that
|
|
1543
943
|
// never reaches the hold itself.
|
|
1544
|
-
const selfResumeStopAt = pendingSelfResumeStop(data);
|
|
1545
|
-
|
|
1546
|
-
const heldMs = Date.now() - state.selfResumeHold.since;
|
|
1547
|
-
state.selfResumeHeldMs += heldMs;
|
|
1548
|
-
state.selfResumeHold = null;
|
|
1549
|
-
console.error(`Note: ${worktreeId} has moved past the stop it said it would resume from ` +
|
|
1550
|
-
`(held ${Math.round(heldMs / 1000)}s); judging its current state.`);
|
|
1551
|
-
}
|
|
944
|
+
const selfResumeStopAt = (0, wait_turn_boundary_1.pendingSelfResumeStop)(data);
|
|
945
|
+
(0, wait_poll_bookkeeping_1.releaseMovedSelfResumeHold)(worktreeId, state, selfResumeStopAt);
|
|
1552
946
|
const promptOutcome = promptStage(poll, state, data);
|
|
1553
947
|
if (promptOutcome.kind === 'exit')
|
|
1554
948
|
return withObservation(promptOutcome.result, data);
|
|
1555
949
|
if (promptOutcome.kind === 'wait') {
|
|
1556
|
-
await sleep(POLL_INTERVAL_MS);
|
|
950
|
+
await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
|
|
1557
951
|
continue;
|
|
1558
952
|
}
|
|
1559
953
|
// Issue #2463: the prompt the hold was waiting on has gone. Who answered it
|
|
1560
954
|
// is not on the wire — Auto-Yes, or a human at the pane — so the line says
|
|
1561
955
|
// only that it cleared; what the agent does next is for the checks below.
|
|
1562
|
-
|
|
1563
|
-
console.error(`Prompt on ${worktreeId} cleared after ` +
|
|
1564
|
-
`${Math.round((Date.now() - state.autoYesAnsweringSince) / 1000)}s; judging completion as usual.`);
|
|
1565
|
-
state.autoYesAnsweringSince = null;
|
|
1566
|
-
}
|
|
956
|
+
(0, wait_poll_bookkeeping_1.noteAutoYesPromptCleared)(worktreeId, state);
|
|
1567
957
|
const selectionListOutcome = selectionListStage(poll, data);
|
|
1568
958
|
if (selectionListOutcome.kind === 'exit')
|
|
1569
959
|
return withObservation(selectionListOutcome.result, data);
|
|
1570
960
|
if (selectionListOutcome.kind === 'wait') {
|
|
1571
|
-
await sleep(POLL_INTERVAL_MS);
|
|
961
|
+
await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
|
|
1572
962
|
continue;
|
|
1573
963
|
}
|
|
1574
964
|
const unclassifiedOutcome = unclassifiedStage(poll, state, data);
|
|
1575
965
|
if (unclassifiedOutcome.kind === 'exit')
|
|
1576
966
|
return withObservation(unclassifiedOutcome.result, data);
|
|
1577
967
|
if (unclassifiedOutcome.kind === 'wait') {
|
|
1578
|
-
await sleep(POLL_INTERVAL_MS);
|
|
968
|
+
await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
|
|
1579
969
|
continue;
|
|
1580
970
|
}
|
|
1581
971
|
const notRunningOutcome = notRunningStage(poll, state, data, selfResumeSuffix);
|
|
1582
972
|
if (notRunningOutcome.kind === 'exit')
|
|
1583
973
|
return notRunningOutcome.result;
|
|
1584
|
-
const readyOutcome = await readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix);
|
|
974
|
+
const readyOutcome = await readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix, judgingSettledFrame);
|
|
1585
975
|
if (readyOutcome.kind === 'exit')
|
|
1586
976
|
return readyOutcome.result;
|
|
977
|
+
if (readyOutcome.kind === 'settled') {
|
|
978
|
+
settledFrame = readyOutcome.data;
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
1587
981
|
if (readyOutcome.kind === 'wait') {
|
|
1588
|
-
|
|
982
|
+
// Issue #3974: the settled frame skipped deadlineStage, and its ledger
|
|
983
|
+
// read may have been cut by the deadline; ask it now rather than one
|
|
984
|
+
// interval late. With time left, the next poll comes as before.
|
|
985
|
+
if (judgingSettledFrame) {
|
|
986
|
+
const deadlineOutcome = deadlineStage(poll, state);
|
|
987
|
+
if (deadlineOutcome.kind === 'exit')
|
|
988
|
+
return deadlineOutcome.result;
|
|
989
|
+
}
|
|
990
|
+
await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
|
|
1589
991
|
continue;
|
|
1590
992
|
}
|
|
1591
993
|
// Progress indicator on stderr [DR1-05]
|
|
1592
994
|
console.error(`Waiting: ${worktreeId} (status=${data.sessionStatus}, running=${data.isRunning}, prompt=${data.isPromptWaiting})`);
|
|
1593
995
|
}
|
|
1594
996
|
catch (error) {
|
|
997
|
+
// Issue #3974: a read ended by --timeout / --stall-timeout. Not a failed
|
|
998
|
+
// poll: straight back to deadlineStage, which exits 124.
|
|
999
|
+
if (error instanceof wait_timing_1.DeadlineReached)
|
|
1000
|
+
continue;
|
|
1595
1001
|
if (error instanceof api_client_1.ApiError) {
|
|
1596
1002
|
throw error;
|
|
1597
1003
|
}
|
|
1598
1004
|
console.error(`Poll error for ${worktreeId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1599
1005
|
}
|
|
1600
|
-
await sleep(POLL_INTERVAL_MS);
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
function sleep(ms) {
|
|
1604
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
1605
|
-
}
|
|
1606
|
-
/** True when the caller asked for a verdict rather than "the agent stopped". */
|
|
1607
|
-
function verifyRequested(options) {
|
|
1608
|
-
return Boolean(options.verify || options.requireWork);
|
|
1609
|
-
}
|
|
1610
|
-
/**
|
|
1611
|
-
* Whether this poll outcome should still be handed to the verification gates.
|
|
1612
|
-
*
|
|
1613
|
-
* A completion is the obvious case. NOT_STARTED joins it (Issue #1628) so the
|
|
1614
|
-
* operator gets the gate results instead of a bare "no session": work committed
|
|
1615
|
-
* by an agent whose session has since gone away is still worth reporting. The
|
|
1616
|
-
* verdict is merged rather than substituted — mergeExitCode never lets a passing
|
|
1617
|
-
* run overwrite NOT_STARTED, so "wait never saw this agent" survives to the exit
|
|
1618
|
-
* code even when the gates are green.
|
|
1619
|
-
*/
|
|
1620
|
-
function shouldVerify(exitCode, options) {
|
|
1621
|
-
if (!verifyRequested(options))
|
|
1622
|
-
return false;
|
|
1623
|
-
return exitCode === types_1.WaitExitCode.SUCCESS || exitCode === types_1.VerifyExitCode.NOT_STARTED;
|
|
1624
|
-
}
|
|
1625
|
-
/**
|
|
1626
|
-
* Task statuses that mean "this wait is about that task".
|
|
1627
|
-
*
|
|
1628
|
-
* Mirrors ACTIVE_TASK_STATUSES in src/lib/db/tasks-db.ts. Deliberately narrower
|
|
1629
|
-
* than the set the server will attach a run to: this is a guess made from a
|
|
1630
|
-
* worktree id alone, and a task that had already finished before the wait began
|
|
1631
|
-
* is a different delegation, not this one.
|
|
1632
|
-
*/
|
|
1633
|
-
const IN_FLIGHT_TASK_STATUSES = new Set([
|
|
1634
|
-
'running',
|
|
1635
|
-
'waiting_input',
|
|
1636
|
-
'verifying',
|
|
1637
|
-
]);
|
|
1638
|
-
/**
|
|
1639
|
-
* Read the task this wait is about, before waiting for it (Issue #1620).
|
|
1640
|
-
*
|
|
1641
|
-
* Timing is the whole point. Agents are asked to run the gates themselves
|
|
1642
|
-
* before reporting completion, and doing so moves their task to a terminal
|
|
1643
|
-
* status — after which a verification run started with only a worktree id has
|
|
1644
|
-
* no contract to resolve, judges no scope, and still reports `passed`. Read
|
|
1645
|
-
* while the task is still in flight, the id survives that transition and the
|
|
1646
|
-
* run that follows is judged against the contract it was supposed to judge.
|
|
1647
|
-
*
|
|
1648
|
-
* Never throws: an unreadable ledger costs the attribution, and refusing to
|
|
1649
|
-
* verify over it would cost every gate.
|
|
1650
|
-
*
|
|
1651
|
-
* @returns the task id, or undefined to leave resolution to the server
|
|
1652
|
-
*/
|
|
1653
|
-
async function resolveWaitedTaskId(client, worktreeId) {
|
|
1654
|
-
try {
|
|
1655
|
-
const data = await client.get(`/api/worktrees/${worktreeId}/tasks?limit=1`);
|
|
1656
|
-
const task = data?.tasks?.[0];
|
|
1657
|
-
if (!task || !IN_FLIGHT_TASK_STATUSES.has(task.status))
|
|
1658
|
-
return undefined;
|
|
1659
|
-
return task.id;
|
|
1660
|
-
}
|
|
1661
|
-
catch (error) {
|
|
1662
|
-
console.error(`Note: could not read the task ledger for ${worktreeId} ` +
|
|
1663
|
-
`(${error instanceof Error ? error.message : String(error)}); ` +
|
|
1664
|
-
'verification will resolve its own task.');
|
|
1665
|
-
return undefined;
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
/**
|
|
1669
|
-
* Run verification for one worktree after its completion was detected.
|
|
1670
|
-
*
|
|
1671
|
-
* Swallows ApiError into an exit code: with several worktrees in flight, one
|
|
1672
|
-
* unreachable run must not abort the verdicts of the others.
|
|
1673
|
-
*/
|
|
1674
|
-
async function verifyAfterWait(client, worktreeId, options, taskId) {
|
|
1675
|
-
// --verify runs every gate, and work-evidence is always part of "every gate",
|
|
1676
|
-
// so combining it with --require-work is a superset rather than a conflict.
|
|
1677
|
-
const gateIds = options.verify ? undefined : [verify_runner_1.WORK_EVIDENCE_GATE_ID];
|
|
1678
|
-
try {
|
|
1679
|
-
const outcome = await (0, verify_runner_1.runVerification)(client, {
|
|
1680
|
-
worktreeId,
|
|
1681
|
-
trigger: 'wait',
|
|
1682
|
-
instanceId: options.instance,
|
|
1683
|
-
taskId,
|
|
1684
|
-
gateIds,
|
|
1685
|
-
// stdout stays reserved for the prompt JSON contract.
|
|
1686
|
-
resultStream: 'stderr',
|
|
1687
|
-
});
|
|
1688
|
-
return outcome.exitCode;
|
|
1689
|
-
}
|
|
1690
|
-
catch (error) {
|
|
1691
|
-
if (error instanceof api_client_1.ApiError) {
|
|
1692
|
-
console.error(`Error: ${error.message}`);
|
|
1693
|
-
return error.exitCode;
|
|
1694
|
-
}
|
|
1695
|
-
console.error(`Error: verification of ${worktreeId} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1696
|
-
return types_1.ExitCode.UNEXPECTED_ERROR;
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
/**
|
|
1700
|
-
* Fold one worktree's exit code into the aggregate.
|
|
1701
|
-
*
|
|
1702
|
-
* Ranked codes (see WAIT_EXIT_CODE_PRIORITY) beat unranked infrastructure
|
|
1703
|
-
* codes, and among equals the first one observed stands.
|
|
1704
|
-
*/
|
|
1705
|
-
function mergeExitCode(current, candidate) {
|
|
1706
|
-
if (candidate === types_1.WaitExitCode.SUCCESS)
|
|
1707
|
-
return current;
|
|
1708
|
-
if (current === types_1.WaitExitCode.SUCCESS)
|
|
1709
|
-
return candidate;
|
|
1710
|
-
const rank = (code) => {
|
|
1711
|
-
const index = types_1.WAIT_EXIT_CODE_PRIORITY.indexOf(code);
|
|
1712
|
-
return index === -1 ? Number.MAX_SAFE_INTEGER : index;
|
|
1713
|
-
};
|
|
1714
|
-
return rank(candidate) < rank(current) ? candidate : current;
|
|
1715
|
-
}
|
|
1716
|
-
/**
|
|
1717
|
-
* `options` with `--instance` resolved from a selector to an instance ID
|
|
1718
|
-
* (Issue #2376).
|
|
1719
|
-
*
|
|
1720
|
-
* `wait` polls `/current-output?instance=`, which matches instance IDs and
|
|
1721
|
-
* nothing else, so an alias that reached it would filter to no session and the
|
|
1722
|
-
* wait would report on the worktree default instead — the exact silent
|
|
1723
|
-
* wrong-session failure Issue #1638 catalogued for `--agent`.
|
|
1724
|
-
*
|
|
1725
|
-
* @param client - API client
|
|
1726
|
-
* @param worktreeId - Worktree the selector is resolved against
|
|
1727
|
-
* @param options - The options as given
|
|
1728
|
-
*/
|
|
1729
|
-
async function resolveWaitInstance(client, worktreeId, options) {
|
|
1730
|
-
if (!options.instance)
|
|
1731
|
-
return options;
|
|
1732
|
-
try {
|
|
1733
|
-
const target = await (0, instances_1.resolveInstanceTarget)(client, worktreeId, options.instance, undefined);
|
|
1734
|
-
return { ...options, instance: target.instanceId ?? options.instance };
|
|
1735
|
-
}
|
|
1736
|
-
catch (error) {
|
|
1737
|
-
// Degrade to the pre-#2376 behaviour rather than failing the wait. An
|
|
1738
|
-
// instance ID needs no resolution to reach `/current-output?instance=` —
|
|
1739
|
-
// resolution exists here so that an ALIAS can — so a resolver that cannot
|
|
1740
|
-
// be reached costs alias support for this call and nothing else. Failing
|
|
1741
|
-
// instead would turn a reachable session into a non-zero exit for an
|
|
1742
|
-
// orchestrator that has been waiting on it correctly for two years.
|
|
1743
|
-
console.error(`Warning: could not resolve --instance '${options.instance}' `
|
|
1744
|
-
+ `(${(0, types_1.getErrorMessage)(error)}); using it as an instance id.`);
|
|
1745
|
-
return options;
|
|
1006
|
+
await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
|
|
1746
1007
|
}
|
|
1747
1008
|
}
|
|
1748
1009
|
function createWaitCommand() {
|
|
@@ -1838,6 +1099,9 @@ The observation on exit 10 (Issue #3755):
|
|
|
1838
1099
|
a missing record does not mean Auto-Yes can answer.
|
|
1839
1100
|
`)
|
|
1840
1101
|
.action(async (worktreeIds, options) => {
|
|
1102
|
+
// Issue #3983: `--timeout` is the deadline of the whole command, counted
|
|
1103
|
+
// from here — the reads before the poll included.
|
|
1104
|
+
const commandStartedAt = Date.now();
|
|
1841
1105
|
try {
|
|
1842
1106
|
// [SEC4-04] Validate all worktree IDs
|
|
1843
1107
|
for (const id of worktreeIds) {
|
|
@@ -1860,34 +1124,42 @@ The observation on exit 10 (Issue #3755):
|
|
|
1860
1124
|
return;
|
|
1861
1125
|
}
|
|
1862
1126
|
const client = new api_client_1.ApiClient({ token: options.token });
|
|
1127
|
+
// Issue #3983: the reads before the poll go through a client bounded by
|
|
1128
|
+
// `--timeout`; one that runs out ends the command with 124 before any
|
|
1129
|
+
// poll or verification. The poll bounds its own reads by the same
|
|
1130
|
+
// clock (`timeoutStartedAt`), and verification — after the wait, and
|
|
1131
|
+
// not part of it — keeps the unbounded `client`.
|
|
1132
|
+
const timeoutStartedAt = options.timeout ? commandStartedAt : undefined;
|
|
1133
|
+
const preflightClient = client.withDeadline(options.timeout ? commandStartedAt + options.timeout * 1000 : undefined);
|
|
1134
|
+
const pollOptions = (resolved) => timeoutStartedAt === undefined ? resolved : { ...resolved, timeoutStartedAt };
|
|
1863
1135
|
// Issue #2376: resolve the selector PER worktree. `wait a b --instance
|
|
1864
1136
|
// "Codex 2"` is one alias against two rosters, and the id behind it can
|
|
1865
1137
|
// legitimately differ — resolving once and reusing the answer would poll
|
|
1866
1138
|
// the wrong session on the second worktree.
|
|
1867
|
-
const perWorktreeOptions = await Promise.all(worktreeIds.map(id => resolveWaitInstance(
|
|
1139
|
+
const perWorktreeOptions = await Promise.all(worktreeIds.map(id => (0, wait_instance_1.resolveWaitInstance)(preflightClient, id, options)));
|
|
1868
1140
|
// Issue #1620: resolved before any polling starts. Once the agent stops
|
|
1869
1141
|
// there is no reliable way left to tell which contract this wait was
|
|
1870
1142
|
// about — the agent's own verification may have closed it by then.
|
|
1871
|
-
const boundTaskIds = verifyRequested(options)
|
|
1872
|
-
? await Promise.all(worktreeIds.map(id => resolveWaitedTaskId(
|
|
1143
|
+
const boundTaskIds = (0, wait_verify_1.verifyRequested)(options)
|
|
1144
|
+
? await Promise.all(worktreeIds.map(id => (0, wait_verify_1.resolveWaitedTaskId)(preflightClient, id)))
|
|
1873
1145
|
: worktreeIds.map(() => undefined);
|
|
1874
1146
|
if (worktreeIds.length === 1) {
|
|
1875
1147
|
// Single worktree
|
|
1876
|
-
const result = await pollWorktree(client, worktreeIds[0], perWorktreeOptions[0]);
|
|
1148
|
+
const result = await pollWorktree(client, worktreeIds[0], pollOptions(perWorktreeOptions[0]));
|
|
1877
1149
|
if (result.output) {
|
|
1878
1150
|
// stdout for result (JSON output)
|
|
1879
1151
|
console.log(JSON.stringify(result.output));
|
|
1880
1152
|
}
|
|
1881
1153
|
// Issue #1544: only a detected completion is worth verifying — a
|
|
1882
1154
|
// prompt or a timeout means the agent never claimed to be done.
|
|
1883
|
-
const exitCode = shouldVerify(result.exitCode, options)
|
|
1884
|
-
? mergeExitCode(result.exitCode, await verifyAfterWait(client, worktreeIds[0], options, boundTaskIds[0]))
|
|
1155
|
+
const exitCode = (0, wait_verify_1.shouldVerify)(result.exitCode, options)
|
|
1156
|
+
? (0, wait_verify_1.mergeExitCode)(result.exitCode, await (0, wait_verify_1.verifyAfterWait)(client, worktreeIds[0], options, boundTaskIds[0]))
|
|
1885
1157
|
: result.exitCode;
|
|
1886
1158
|
process.exit(exitCode);
|
|
1887
1159
|
return;
|
|
1888
1160
|
}
|
|
1889
1161
|
// [DR1-07] Multiple worktrees: Promise.allSettled for error isolation
|
|
1890
|
-
const results = await Promise.allSettled(worktreeIds.map((id, index) => pollWorktree(client, id, perWorktreeOptions[index])));
|
|
1162
|
+
const results = await Promise.allSettled(worktreeIds.map((id, index) => pollWorktree(client, id, pollOptions(perWorktreeOptions[index]))));
|
|
1891
1163
|
// Collect results
|
|
1892
1164
|
const outputs = [];
|
|
1893
1165
|
let finalExitCode = types_1.WaitExitCode.SUCCESS;
|
|
@@ -1897,25 +1169,25 @@ The observation on exit 10 (Issue #3755):
|
|
|
1897
1169
|
if (result.value.output) {
|
|
1898
1170
|
outputs.push(result.value.output);
|
|
1899
1171
|
}
|
|
1900
|
-
if (shouldVerify(result.value.exitCode, options)) {
|
|
1172
|
+
if ((0, wait_verify_1.shouldVerify)(result.value.exitCode, options)) {
|
|
1901
1173
|
verifyTargets.push({ id: worktreeIds[index], taskId: boundTaskIds[index] });
|
|
1902
1174
|
// Issue #1628: fold NOT_STARTED in before verification so a green
|
|
1903
1175
|
// gate run cannot promote "no session was ever running" to success.
|
|
1904
|
-
finalExitCode = mergeExitCode(finalExitCode, result.value.exitCode);
|
|
1176
|
+
finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, result.value.exitCode);
|
|
1905
1177
|
return;
|
|
1906
1178
|
}
|
|
1907
|
-
finalExitCode = mergeExitCode(finalExitCode, result.value.exitCode);
|
|
1179
|
+
finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, result.value.exitCode);
|
|
1908
1180
|
}
|
|
1909
1181
|
else {
|
|
1910
1182
|
const err = result.reason;
|
|
1911
|
-
finalExitCode = mergeExitCode(finalExitCode, err instanceof api_client_1.ApiError ? err.exitCode : types_1.ExitCode.UNEXPECTED_ERROR);
|
|
1183
|
+
finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, err instanceof api_client_1.ApiError ? err.exitCode : types_1.ExitCode.UNEXPECTED_ERROR);
|
|
1912
1184
|
}
|
|
1913
1185
|
});
|
|
1914
1186
|
// Issue #1544: serial on purpose. The server caps concurrent runs
|
|
1915
1187
|
// process-wide, so firing them together only queues them behind each
|
|
1916
1188
|
// other while every gate competes for the same machine.
|
|
1917
1189
|
for (const target of verifyTargets) {
|
|
1918
|
-
finalExitCode = mergeExitCode(finalExitCode, await verifyAfterWait(client, target.id, options, target.taskId));
|
|
1190
|
+
finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, await (0, wait_verify_1.verifyAfterWait)(client, target.id, options, target.taskId));
|
|
1919
1191
|
}
|
|
1920
1192
|
if (outputs.length > 0) {
|
|
1921
1193
|
console.log(JSON.stringify(outputs));
|