commandmate 0.47.2 → 0.49.0
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 +180 -180
- package/.next/app-path-routes-manifest.json +30 -30
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +9 -9
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_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.js +3 -3
- 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.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.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_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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page_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.js +2 -2
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +12 -12
- 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 +30 -30
- package/.next/server/chunks/1191.js +11 -4
- package/.next/server/chunks/1501.js +1 -1
- package/.next/server/chunks/1601.js +2 -2
- package/.next/server/chunks/1656.js +2 -2
- package/.next/server/chunks/1945.js +3 -3
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2069.js +1 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2422.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2534.js +1 -1
- package/.next/server/chunks/255.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3505.js +2 -2
- package/.next/server/chunks/4243.js +1 -1
- package/.next/server/chunks/4248.js +1 -1
- package/.next/server/chunks/4280.js +1 -0
- package/.next/server/chunks/5209.js +1 -1
- 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 +9 -8
- package/.next/server/chunks/6781.js +1 -1
- package/.next/server/chunks/720.js +103 -0
- package/.next/server/chunks/7604.js +2 -0
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8581.js +8 -8
- package/.next/server/chunks/8728.js +3 -3
- package/.next/server/chunks/8791.js +1 -1
- package/.next/server/chunks/8807.js +19 -18
- package/.next/server/chunks/8918.js +2 -104
- package/.next/server/chunks/936.js +1 -1
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9540.js +1 -1
- package/.next/server/chunks/9627.js +5 -5
- package/.next/server/chunks/9731.js +2 -2
- 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/1128-914c559913546bbc.js +1 -0
- package/.next/static/chunks/{2407-a6533805a86d05bd.js → 2407-ab92ae9837c39dce.js} +1 -1
- package/.next/static/chunks/{2863-6a07ec82fb52f4dd.js → 2863-7173dc305dffc4f6.js} +1 -1
- package/.next/static/chunks/6288-6fadbba6e84393b2.js +1 -0
- package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +1 -0
- package/.next/static/chunks/8407-35bbfc84793d7004.js +1 -0
- package/.next/static/chunks/9079-987939d231704218.js +1 -0
- package/.next/static/chunks/app/{layout-538d8d2746ad1588.js → layout-aa8e66164a4367af.js} +1 -1
- package/.next/static/chunks/app/sessions/page-cfd645305e25fd33.js +1 -0
- package/.next/static/chunks/app/skills/[skillId]/{page-52ba58712faf3378.js → page-cb6e74fd9a6a571d.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-704086656fb45699.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-a8d7886703ffc7b4.js +1 -0
- package/.next/static/css/{743f79ff19ab91e9.css → db8959555c3d9c96.css} +1 -1
- package/.next/trace +13 -13
- package/dist/cli/commands/auto-yes.d.ts +24 -0
- package/dist/cli/commands/auto-yes.d.ts.map +1 -1
- package/dist/cli/commands/auto-yes.js +76 -8
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +5 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +10 -1
- package/dist/cli/commands/prompt.d.ts.map +1 -1
- package/dist/cli/commands/prompt.js +5 -3
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +19 -6
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +8 -1
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +101 -13
- package/dist/cli/config/duration-constants.d.ts +16 -13
- package/dist/cli/config/duration-constants.d.ts.map +1 -1
- package/dist/cli/config/duration-constants.js +21 -21
- 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 +29 -1
- package/dist/cli/types/api-responses.d.ts +145 -3
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/types/index.d.ts +4 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/utils/resource-resolvers.d.ts +0 -18
- package/dist/cli/utils/resource-resolvers.d.ts.map +1 -1
- package/dist/cli/utils/resource-resolvers.js +1 -51
- package/dist/cli/utils/verify-runner.d.ts +24 -1
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +54 -1
- package/dist/config/auto-yes-duration.d.ts +56 -0
- package/dist/config/auto-yes-duration.d.ts.map +1 -0
- package/dist/config/auto-yes-duration.js +76 -0
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts +54 -2
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.js +33 -2
- package/dist/lib/prompt-observation/types.d.ts +13 -0
- package/dist/lib/prompt-observation/types.d.ts.map +1 -1
- package/dist/server/locales/en/worktree.json +2 -1
- package/dist/server/locales/ja/worktree.json +2 -1
- package/dist/server/src/config/auto-yes-config.js +14 -19
- package/dist/server/src/config/auto-yes-duration.js +76 -0
- package/dist/server/src/lib/auto-yes-poller-answer-target.js +38 -0
- package/dist/server/src/lib/auto-yes-poller-keys.js +35 -0
- package/dist/server/src/lib/auto-yes-poller-session-presence.js +26 -0
- package/dist/server/src/lib/auto-yes-poller-tick.js +233 -0
- package/dist/server/src/lib/auto-yes-poller.js +337 -376
- package/dist/server/src/lib/auto-yes-state.js +59 -4
- package/dist/server/src/lib/cli-tools/submit-verified-sender.js +235 -19
- package/dist/server/src/lib/db/chat-db.js +5 -1
- package/dist/server/src/lib/db/verification-db.js +23 -2
- package/dist/server/src/lib/detection/composer-text.js +215 -11
- package/dist/server/src/lib/detection/option-recommendation.js +120 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice-approval-context.js +290 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice-chrome.js +193 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +402 -539
- package/dist/server/src/lib/detection/prompt-detector.js +92 -21
- package/dist/server/src/lib/detection/prompt-screen-key.js +60 -0
- package/dist/server/src/lib/detection/tools/antigravity/dialog.js +158 -35
- package/dist/server/src/lib/detection/tools/claude/detect.js +111 -10
- package/dist/server/src/lib/detection/tools/command-code/dialog.js +67 -0
- package/dist/server/src/lib/detection/tools/dialog-block.js +16 -0
- package/dist/server/src/lib/detection/upstream-faults.js +19 -2
- package/dist/server/src/lib/detection/waiting-screen-reading.js +98 -0
- package/dist/server/src/lib/hooks/permission-decision-service.js +7 -0
- package/dist/server/src/lib/hooks/structured-decision-response.js +1 -1
- package/dist/server/src/lib/polling/auto-yes-confirm-page.js +2 -2
- package/dist/server/src/lib/polling/auto-yes-confirmation-ledger-types.js +3 -0
- package/dist/server/src/lib/polling/auto-yes-confirmation-ledger.js +34 -3
- package/dist/server/src/lib/polling/auto-yes-decision-state.js +195 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +139 -10
- package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +14 -0
- package/dist/server/src/lib/polling/auto-yes-manual-answer.js +124 -0
- package/dist/server/src/lib/polling/auto-yes-option-effect.js +157 -0
- package/dist/server/src/lib/polling/auto-yes-policy.js +11 -5
- package/dist/server/src/lib/polling/auto-yes-poller-capture.js +15 -2
- package/dist/server/src/lib/polling/auto-yes-poller-generation.js +42 -1
- package/dist/server/src/lib/polling/auto-yes-poller-receipt-log.js +42 -5
- package/dist/server/src/lib/polling/auto-yes-poller-state.js +147 -49
- package/dist/server/src/lib/polling/auto-yes-poller-steps.js +172 -2
- package/dist/server/src/lib/polling/auto-yes-prompt-suppression.js +2 -2
- package/dist/server/src/lib/polling/auto-yes-question-choice.js +57 -0
- package/dist/server/src/lib/polling/auto-yes-resolver.js +96 -21
- package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +33 -2
- package/dist/server/src/lib/polling/auto-yes-suppression-state.js +25 -1
- package/dist/server/src/lib/polling/prompt-screen-reading.js +232 -0
- package/dist/server/src/lib/polling/response-checker-dialog-gate.js +39 -0
- package/dist/server/src/lib/polling/response-checker.js +145 -58
- package/dist/server/src/lib/prompt-answer-sender.js +104 -10
- package/dist/server/src/lib/push/notification-dedup.js +15 -2
- package/dist/server/src/lib/push/prompt-card-state.js +140 -19
- package/dist/server/src/lib/push/prompt-push-gate.js +158 -12
- package/dist/server/src/lib/push/push-sender.js +23 -3
- package/dist/server/src/lib/push/resolution-push-notifier.js +14 -0
- package/dist/server/src/lib/push/waiting-push-notifier.js +139 -17
- package/dist/server/src/lib/realtime/terminal-broadcast.js +16 -0
- package/dist/server/src/lib/session/agent-event-state.js +25 -5
- package/dist/server/src/lib/session/agent-event-turn.js +140 -46
- package/dist/server/src/lib/session/cli-session.js +21 -2
- package/dist/server/src/lib/session/composer-clear.js +56 -4
- package/dist/server/src/lib/session/current-output-builder.js +66 -12
- package/dist/server/src/lib/session/send-attempt-state.js +24 -7
- package/dist/server/src/lib/session/waiting-episode-binding-observation.js +289 -0
- package/dist/server/src/lib/session/waiting-episode-binding-resolve.js +38 -0
- package/dist/server/src/lib/session/waiting-episode-binding.js +276 -0
- package/dist/server/src/lib/session/waiting-episode-state-ops.js +152 -0
- package/dist/server/src/lib/session/waiting-episode-state-store.js +202 -0
- package/dist/server/src/lib/session/waiting-episode-state-types.js +6 -0
- package/dist/server/src/lib/session/waiting-episode-state.js +68 -91
- package/dist/server/src/lib/session/waiting-episode-verdict.js +174 -0
- package/dist/server/src/lib/tmux/tmux-capture-cache.js +76 -11
- package/dist/server/src/lib/tmux/tmux.js +79 -9
- package/dist/server/src/lib/verification/gate-runner.js +172 -16
- package/dist/server/src/lib/verification/machine-lock.js +5 -0
- package/dist/server/src/lib/ws-server.js +18 -3
- package/dist/server/src/types/auto-yes-answer-mode.js +38 -0
- package/dist/server/src/types/auto-yes-decision.js +61 -0
- package/dist/server/src/types/auto-yes.js +6 -0
- package/dist/server/src/types/prompt-reading.js +32 -0
- package/dist/types/auto-yes-answer-mode.d.ts +35 -0
- package/dist/types/auto-yes-answer-mode.d.ts.map +1 -0
- package/dist/types/auto-yes-answer-mode.js +38 -0
- package/docs/en/user-guide/webapp-guide.md +47 -13
- package/package.json +1 -1
- package/public/sw.js +76 -4
- package/release-notes/0.48.0.json +57 -0
- package/release-notes/0.49.0.json +45 -0
- package/.next/server/chunks/1559.js +0 -2
- package/.next/server/chunks/2460.js +0 -1
- package/.next/server/chunks/5595.js +0 -1
- package/.next/server/chunks/610.js +0 -1
- package/.next/server/chunks/6722.js +0 -1
- package/.next/static/chunks/5371-a549a0d2c2044d41.js +0 -1
- package/.next/static/chunks/602-1c1488959215e140.js +0 -1
- package/.next/static/chunks/6288-09feba367cc2c65e.js +0 -1
- package/.next/static/chunks/8407-155f84e5ba05f1d5.js +0 -1
- package/.next/static/chunks/9079-24f9fa549ed298f1.js +0 -1
- package/.next/static/chunks/app/sessions/page-e02f1adb1d1c1ccc.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9cf1ecc59e36a004.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-46aced20b2b1c010.js +0 -1
- /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_buildManifest.js +0 -0
- /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Which turn a waiting episode belongs to, and what the turn transitions do to
|
|
4
|
+
* it (Issue #3798).
|
|
5
|
+
*
|
|
6
|
+
* The episode store (`waiting-episode-state`) knows when a wait began and what
|
|
7
|
+
* it is bound to; the turn model (`agent-event-turn`) knows how each delivery
|
|
8
|
+
* moved the instance's turn. This module joins the two:
|
|
9
|
+
*
|
|
10
|
+
* - {@link resolveEpisodeBinding} decides what a new episode is bound to, from
|
|
11
|
+
* the turn model as it stands (design §2.4 規則 1). It is registered with the
|
|
12
|
+
* store, so an episode `observeWaitingEdge` opens is bound like any other.
|
|
13
|
+
* - {@link applyTurnOutcomesToEpisode} is the T table (design §2.4): what a
|
|
14
|
+
* transition's outcome does to the open episode. It runs in the synchronous
|
|
15
|
+
* step that recorded the delivery (`recordAgentEvent`'s end,
|
|
16
|
+
* `beginAgentEventGeneration`, the two `report*Pending`, the duplicate-window
|
|
17
|
+
* restore) and never after an `await`, so a closer that resumes later
|
|
18
|
+
* cannot reach a wait that opened meanwhile (design §2.5).
|
|
19
|
+
* - {@link captureLegacyStopTarget} / {@link settleLegacyStop} are the one
|
|
20
|
+
* closer that cannot be synchronous: `/api/hooks/claude-done` names no
|
|
21
|
+
* session and awaits a capture and a log before it is done (design 規則 6).
|
|
22
|
+
* - {@link planWaitingObservation} / {@link commitWaitingObservation} are the
|
|
23
|
+
* tables O-1 and O-2 (design §2.4 規則 3・4・5): what one observer's reading
|
|
24
|
+
* of a frame does to the open episode. The three observers — the status
|
|
25
|
+
* probe, the response poller and the Auto-Yes poller — fix an
|
|
26
|
+
* {@link ObservationStart} before their first `await` and are refused when
|
|
27
|
+
* the episode moved meanwhile (I5 (b)), or when the frame was fetched
|
|
28
|
+
* before the close of the very confirmation it shows (I6).
|
|
29
|
+
*
|
|
30
|
+
* The store is a leaf and does not import this module; this module registers
|
|
31
|
+
* itself with the store and with the turn model through `globalThis` when it is
|
|
32
|
+
* loaded. `agent-event-state` imports it, and so does every module that calls
|
|
33
|
+
* the observation functions — the resolver is registered by the import that
|
|
34
|
+
* uses it, not by a transitive one (design R2-10, PR 1a review P3-2).
|
|
35
|
+
*
|
|
36
|
+
* Design: `docs/design/issue-3798-waiting-episode.md`.
|
|
37
|
+
*
|
|
38
|
+
* @module lib/session/waiting-episode-binding
|
|
39
|
+
*/
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.startWorktreeWaitingObservations = exports.startWaitingObservation = exports.planWaitingObservation = exports.captureObservedFrame = exports.captureFrameTime = exports.resolveEpisodeBinding = exports.verdictForOutcome = void 0;
|
|
42
|
+
exports.applyTurnOutcomesToEpisode = applyTurnOutcomesToEpisode;
|
|
43
|
+
exports.commitWaitingObservation = commitWaitingObservation;
|
|
44
|
+
exports.observeWaiting = observeWaiting;
|
|
45
|
+
exports.captureLegacyStopTarget = captureLegacyStopTarget;
|
|
46
|
+
exports.settleLegacyStop = settleLegacyStop;
|
|
47
|
+
exports.clearWaitingEpisodeBindingState = clearWaitingEpisodeBindingState;
|
|
48
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
49
|
+
const logger_1 = require("../../lib/logger");
|
|
50
|
+
const agent_event_turn_1 = require("../../lib/session/agent-event-turn");
|
|
51
|
+
const waiting_episode_binding_observation_1 = require("../../lib/session/waiting-episode-binding-observation");
|
|
52
|
+
const waiting_episode_binding_resolve_1 = require("../../lib/session/waiting-episode-binding-resolve");
|
|
53
|
+
Object.defineProperty(exports, "resolveEpisodeBinding", { enumerable: true, get: function () { return waiting_episode_binding_resolve_1.resolveEpisodeBinding; } });
|
|
54
|
+
const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
|
|
55
|
+
const waiting_episode_verdict_1 = require("../../lib/session/waiting-episode-verdict");
|
|
56
|
+
Object.defineProperty(exports, "verdictForOutcome", { enumerable: true, get: function () { return waiting_episode_verdict_1.verdictForOutcome; } });
|
|
57
|
+
const global_state_1 = require("../global-state");
|
|
58
|
+
const logger = (0, logger_1.createLogger)('waiting-episode-binding');
|
|
59
|
+
/**
|
|
60
|
+
* compositeKey -> the generation in which a structured `stop` was last
|
|
61
|
+
* applied. While it names the current generation, the agent's own hook speaks
|
|
62
|
+
* for the end of its turns and `claude-done` does not close (規則 6).
|
|
63
|
+
*/
|
|
64
|
+
const hookStopGeneration = (0, global_state_1.getOrInitGlobal)('__waitingHookStopGeneration', () => new Map());
|
|
65
|
+
/** Mark that the agent's own hook reported a stop in this generation (規則 6). */
|
|
66
|
+
function noteHookStop(key, outcome) {
|
|
67
|
+
if (outcome.kind === 'stopped' || outcome.kind === 'stop-without-turn') {
|
|
68
|
+
hookStopGeneration.set(key, outcome.generation);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function applyVerdict(parts, episode, outcome, verdict, at) {
|
|
72
|
+
const base = { outcome: outcome.kind, episodeId: episode.episodeId };
|
|
73
|
+
if (verdict.action === 'close') {
|
|
74
|
+
const closed = (0, waiting_episode_state_1.closeEpisode)(parts, episode.episodeId, verdict.reason, at);
|
|
75
|
+
if (closed) {
|
|
76
|
+
logger.info('waiting-episode-closed-by-turn', {
|
|
77
|
+
worktreeId: parts.worktreeId,
|
|
78
|
+
cliToolId: parts.cliToolId,
|
|
79
|
+
instanceId: parts.instanceId ?? parts.cliToolId,
|
|
80
|
+
episodeId: episode.episodeId,
|
|
81
|
+
outcome: outcome.kind,
|
|
82
|
+
reason: verdict.reason,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return { ...base, action: closed ? 'closed' : 'none', ...(closed ? { reason: verdict.reason } : {}) };
|
|
86
|
+
}
|
|
87
|
+
if (verdict.action === 'rebind') {
|
|
88
|
+
const rebound = (0, waiting_episode_state_1.rebindEpisode)(parts, episode.episodeId, verdict.binding, at);
|
|
89
|
+
if (rebound) {
|
|
90
|
+
logger.debug('waiting-episode-rebound', {
|
|
91
|
+
worktreeId: parts.worktreeId,
|
|
92
|
+
instanceId: parts.instanceId ?? parts.cliToolId,
|
|
93
|
+
episodeId: episode.episodeId,
|
|
94
|
+
outcome: outcome.kind,
|
|
95
|
+
binding: verdict.binding.kind,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return { ...base, action: rebound ? 'rebound' : 'none' };
|
|
99
|
+
}
|
|
100
|
+
if (verdict.action === 'unmatched') {
|
|
101
|
+
logger.warn('waiting-episode-unmatched', {
|
|
102
|
+
worktreeId: parts.worktreeId,
|
|
103
|
+
instanceId: parts.instanceId ?? parts.cliToolId,
|
|
104
|
+
episodeId: episode.episodeId,
|
|
105
|
+
outcome: outcome.kind,
|
|
106
|
+
binding: episode.binding.kind,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return { ...base, action: 'none' };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Apply a delivery's transition outcomes to the instance's open episode
|
|
113
|
+
* (Issue #3798, design §2.4 T table), in order.
|
|
114
|
+
*
|
|
115
|
+
* Called in the synchronous step that produced the outcomes. Never throws: the
|
|
116
|
+
* turn has been recorded already, and a failure here must not cost the hook
|
|
117
|
+
* its answer (design §2.6). An episode it leaves open is still closed by the
|
|
118
|
+
* screen observers.
|
|
119
|
+
*
|
|
120
|
+
* @param at - Epoch ms of the change; defaults to now
|
|
121
|
+
*/
|
|
122
|
+
function applyTurnOutcomesToEpisode(parts, outcomes, at = Date.now()) {
|
|
123
|
+
const effects = [];
|
|
124
|
+
try {
|
|
125
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(parts.worktreeId, parts.cliToolId, parts.instanceId);
|
|
126
|
+
for (const outcome of outcomes) {
|
|
127
|
+
noteHookStop(key, outcome);
|
|
128
|
+
const episode = (0, waiting_episode_state_1.getWaitingEpisodeRecord)(parts.worktreeId, parts.cliToolId, parts.instanceId);
|
|
129
|
+
if (episode === null) {
|
|
130
|
+
effects.push({ outcome: outcome.kind, action: 'none', episodeId: null });
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const verdict = (0, waiting_episode_verdict_1.verdictForOutcome)(outcome, episode.binding, (0, waiting_episode_binding_resolve_1.generationOf)(parts));
|
|
134
|
+
effects.push(applyVerdict(parts, episode, outcome, verdict, at));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
logger.warn('waiting-episode-turn-sync-failed', {
|
|
139
|
+
worktreeId: parts.worktreeId,
|
|
140
|
+
instanceId: parts.instanceId ?? parts.cliToolId,
|
|
141
|
+
error: error instanceof Error ? error.message : String(error),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return effects;
|
|
145
|
+
}
|
|
146
|
+
var waiting_episode_binding_observation_2 = require("../../lib/session/waiting-episode-binding-observation");
|
|
147
|
+
Object.defineProperty(exports, "captureFrameTime", { enumerable: true, get: function () { return waiting_episode_binding_observation_2.captureFrameTime; } });
|
|
148
|
+
Object.defineProperty(exports, "captureObservedFrame", { enumerable: true, get: function () { return waiting_episode_binding_observation_2.captureObservedFrame; } });
|
|
149
|
+
Object.defineProperty(exports, "planWaitingObservation", { enumerable: true, get: function () { return waiting_episode_binding_observation_2.planWaitingObservation; } });
|
|
150
|
+
Object.defineProperty(exports, "startWaitingObservation", { enumerable: true, get: function () { return waiting_episode_binding_observation_2.startWaitingObservation; } });
|
|
151
|
+
Object.defineProperty(exports, "startWorktreeWaitingObservations", { enumerable: true, get: function () { return waiting_episode_binding_observation_2.startWorktreeWaitingObservations; } });
|
|
152
|
+
/**
|
|
153
|
+
* Carry out a plan (design I5 (b)). Each write names the episode the plan was
|
|
154
|
+
* made about, so a plan committed late changes nothing that moved since.
|
|
155
|
+
*
|
|
156
|
+
* @returns What was done — `ignored` also when the episode moved after the plan
|
|
157
|
+
*/
|
|
158
|
+
function commitWaitingObservation(plan) {
|
|
159
|
+
const obs = plan.observation;
|
|
160
|
+
const parts = { worktreeId: obs.worktreeId, cliToolId: obs.cliToolId, instanceId: obs.instanceId };
|
|
161
|
+
try {
|
|
162
|
+
switch (plan.action) {
|
|
163
|
+
case 'kept':
|
|
164
|
+
if (plan.episodeId === null || obs.reading.kind !== 'waiting')
|
|
165
|
+
return 'ignored';
|
|
166
|
+
return (0, waiting_episode_state_1.updateEpisodeKind)(parts, plan.episodeId, obs.reading.waitingKind) ? 'kept' : 'ignored';
|
|
167
|
+
case 'opened':
|
|
168
|
+
if (plan.next === null || (0, waiting_episode_state_1.getWaitingEpisodeRecord)(obs.worktreeId, obs.cliToolId, obs.instanceId) !== null) {
|
|
169
|
+
return 'ignored';
|
|
170
|
+
}
|
|
171
|
+
(0, waiting_episode_state_1.openEpisode)(parts, plan.next, plan.at);
|
|
172
|
+
return 'opened';
|
|
173
|
+
case 'replaced':
|
|
174
|
+
if (plan.next === null || plan.episodeId === null || plan.closeReason === null)
|
|
175
|
+
return 'ignored';
|
|
176
|
+
return (0, waiting_episode_state_1.replaceEpisode)(parts, plan.episodeId, plan.next, plan.closeReason, plan.at) !== null
|
|
177
|
+
? 'replaced'
|
|
178
|
+
: 'ignored';
|
|
179
|
+
case 'rebound':
|
|
180
|
+
if (plan.binding === null || plan.episodeId === null)
|
|
181
|
+
return 'ignored';
|
|
182
|
+
return (0, waiting_episode_state_1.rebindEpisode)(parts, plan.episodeId, plan.binding, plan.at) ? 'rebound' : 'ignored';
|
|
183
|
+
case 'closed':
|
|
184
|
+
if (plan.episodeId === null || plan.closeReason === null)
|
|
185
|
+
return 'ignored';
|
|
186
|
+
return (0, waiting_episode_state_1.closeEpisode)(parts, plan.episodeId, plan.closeReason, plan.at) ? 'closed' : 'ignored';
|
|
187
|
+
case 'ignored':
|
|
188
|
+
if (plan.ignoredBecause === 'version' || plan.ignoredBecause === 'stale-frame' || plan.ignoredBecause === 'generation') {
|
|
189
|
+
logger.debug('waiting-observation-ignored', {
|
|
190
|
+
worktreeId: obs.worktreeId,
|
|
191
|
+
instanceId: obs.instanceId ?? obs.cliToolId,
|
|
192
|
+
observer: obs.observer,
|
|
193
|
+
reading: obs.reading.kind,
|
|
194
|
+
because: plan.ignoredBecause,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return 'ignored';
|
|
198
|
+
default:
|
|
199
|
+
plan.action;
|
|
200
|
+
return 'ignored';
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
logger.warn('waiting-observation-failed', {
|
|
205
|
+
worktreeId: obs.worktreeId,
|
|
206
|
+
instanceId: obs.instanceId ?? obs.cliToolId,
|
|
207
|
+
observer: obs.observer,
|
|
208
|
+
error: error instanceof Error ? error.message : String(error),
|
|
209
|
+
});
|
|
210
|
+
return 'ignored';
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/** {@link planWaitingObservation} and {@link commitWaitingObservation} in one step; the plan with what was done. */
|
|
214
|
+
function observeWaiting(obs) {
|
|
215
|
+
const plan = (0, waiting_episode_binding_observation_1.planWaitingObservation)(obs);
|
|
216
|
+
const action = commitWaitingObservation(plan);
|
|
217
|
+
return action === plan.action ? plan : { ...plan, action };
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Fix the episode a legacy (`claude-done`) stop is about, before its first
|
|
221
|
+
* capture `await` (design 規則 6). The body read before it cannot be helped: the
|
|
222
|
+
* worktree id is in the body — a known limit (design §8).
|
|
223
|
+
*/
|
|
224
|
+
function captureLegacyStopTarget(worktreeId, cliToolId, instanceId) {
|
|
225
|
+
const parts = { worktreeId, cliToolId, instanceId };
|
|
226
|
+
return {
|
|
227
|
+
generation: (0, waiting_episode_binding_resolve_1.generationOf)(parts),
|
|
228
|
+
episodeId: (0, waiting_episode_state_1.getWaitingEpisodeRecord)(worktreeId, cliToolId, instanceId)?.episodeId ?? null,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Close the episode a legacy stop was fixed on, if it is still the open one
|
|
233
|
+
* (design 規則 6). Nothing when the hook reported a stop in this generation
|
|
234
|
+
* (the hook speaks for the end of turns; closing again is the double close the
|
|
235
|
+
* rule forbids), when another episode opened meanwhile, or for a screen only a
|
|
236
|
+
* person drives.
|
|
237
|
+
*
|
|
238
|
+
* @param at - Epoch ms; defaults to now
|
|
239
|
+
*/
|
|
240
|
+
function settleLegacyStop(worktreeId, cliToolId, instanceId, target, at = Date.now()) {
|
|
241
|
+
try {
|
|
242
|
+
const parts = { worktreeId, cliToolId, instanceId };
|
|
243
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
|
|
244
|
+
const episode = (0, waiting_episode_state_1.getWaitingEpisodeRecord)(worktreeId, cliToolId, instanceId);
|
|
245
|
+
if (episode === null)
|
|
246
|
+
return 'nothing-open';
|
|
247
|
+
const current = (0, waiting_episode_binding_resolve_1.generationOf)(parts);
|
|
248
|
+
if (target.episodeId === null ||
|
|
249
|
+
episode.episodeId !== target.episodeId ||
|
|
250
|
+
!(0, waiting_episode_verdict_1.sameGeneration)(target.generation, current)) {
|
|
251
|
+
return 'target-gone';
|
|
252
|
+
}
|
|
253
|
+
const hookStop = hookStopGeneration.get(key);
|
|
254
|
+
if (hookStop !== undefined && (0, waiting_episode_verdict_1.sameGeneration)(hookStop, current))
|
|
255
|
+
return 'hook-authority';
|
|
256
|
+
if (episode.binding.kind === 'screen')
|
|
257
|
+
return 'screen';
|
|
258
|
+
return (0, waiting_episode_state_1.closeEpisode)(parts, episode.episodeId, 'legacy-stop', at) ? 'closed' : 'target-gone';
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
logger.warn('waiting-episode-legacy-stop-failed', {
|
|
262
|
+
worktreeId,
|
|
263
|
+
instanceId: instanceId ?? cliToolId,
|
|
264
|
+
error: error instanceof Error ? error.message : String(error),
|
|
265
|
+
});
|
|
266
|
+
return 'nothing-open';
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/** Forget the hook-stop marks. Test seam, called by `clearAgentStopEvents`. */
|
|
270
|
+
function clearWaitingEpisodeBindingState() {
|
|
271
|
+
hookStopGeneration.clear();
|
|
272
|
+
}
|
|
273
|
+
(0, waiting_episode_state_1.registerEpisodeBindingResolver)(waiting_episode_binding_resolve_1.resolveEpisodeBinding);
|
|
274
|
+
(0, agent_event_turn_1.registerTurnOutcomeSink)((parts, outcomes) => {
|
|
275
|
+
applyTurnOutcomesToEpisode(parts, outcomes);
|
|
276
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The low-level episode writes: open / close / replace / rebind / updateKind
|
|
4
|
+
* (Issue #3798). Each one emits through the store's listeners.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.openEpisode = openEpisode;
|
|
8
|
+
exports.closeEpisode = closeEpisode;
|
|
9
|
+
exports.replaceEpisode = replaceEpisode;
|
|
10
|
+
exports.rebindEpisode = rebindEpisode;
|
|
11
|
+
exports.updateEpisodeKind = updateEpisodeKind;
|
|
12
|
+
const waiting_episode_state_store_1 = require("../../lib/session/waiting-episode-state-store");
|
|
13
|
+
/**
|
|
14
|
+
* Open an episode (Issue #3798). Low-level: the caller has decided there is
|
|
15
|
+
* none open and what it is bound to. Emits the opening edge.
|
|
16
|
+
*/
|
|
17
|
+
function openEpisode(parts, next, at) {
|
|
18
|
+
const key = (0, waiting_episode_state_store_1.keyOf)(parts);
|
|
19
|
+
const view = { since: next.since, kind: next.kind };
|
|
20
|
+
const meta = {
|
|
21
|
+
episodeId: (0, waiting_episode_state_store_1.nextEpisodeId)(),
|
|
22
|
+
openedAt: at,
|
|
23
|
+
boundAt: at,
|
|
24
|
+
binding: next.binding,
|
|
25
|
+
openedBy: next.openedBy,
|
|
26
|
+
promptScreenKey: next.promptScreenKey ?? null,
|
|
27
|
+
};
|
|
28
|
+
waiting_episode_state_store_1.episodes.set(key, view);
|
|
29
|
+
waiting_episode_state_store_1.metas.set(view, meta);
|
|
30
|
+
(0, waiting_episode_state_store_1.bumpVersion)(key);
|
|
31
|
+
(0, waiting_episode_state_store_1.emit)({
|
|
32
|
+
worktreeId: parts.worktreeId,
|
|
33
|
+
cliToolId: parts.cliToolId,
|
|
34
|
+
instanceId: parts.instanceId,
|
|
35
|
+
waiting: true,
|
|
36
|
+
since: view.since,
|
|
37
|
+
kind: view.kind,
|
|
38
|
+
at,
|
|
39
|
+
cause: 'opened',
|
|
40
|
+
episodeId: meta.episodeId,
|
|
41
|
+
previousEpisodeId: null,
|
|
42
|
+
closeReason: null,
|
|
43
|
+
});
|
|
44
|
+
return { ...view, ...meta };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Close the open episode when it is still `expectedId` (Issue #3798). A closer
|
|
48
|
+
* that names the episode it decided about cannot close a later one.
|
|
49
|
+
*
|
|
50
|
+
* @returns Whether an episode was closed
|
|
51
|
+
*/
|
|
52
|
+
function closeEpisode(parts, expectedId, reason, at) {
|
|
53
|
+
const key = (0, waiting_episode_state_store_1.keyOf)(parts);
|
|
54
|
+
const view = waiting_episode_state_store_1.episodes.get(key);
|
|
55
|
+
if (view === undefined)
|
|
56
|
+
return false;
|
|
57
|
+
const meta = (0, waiting_episode_state_store_1.metaOf)(view);
|
|
58
|
+
if (meta.episodeId !== expectedId)
|
|
59
|
+
return false;
|
|
60
|
+
waiting_episode_state_store_1.episodes.delete(key);
|
|
61
|
+
waiting_episode_state_store_1.lastClosed.set(key, { at, promptScreenKey: meta.promptScreenKey });
|
|
62
|
+
(0, waiting_episode_state_store_1.bumpVersion)(key);
|
|
63
|
+
(0, waiting_episode_state_store_1.emit)({
|
|
64
|
+
worktreeId: parts.worktreeId,
|
|
65
|
+
cliToolId: parts.cliToolId,
|
|
66
|
+
instanceId: parts.instanceId,
|
|
67
|
+
waiting: false,
|
|
68
|
+
since: null,
|
|
69
|
+
kind: null,
|
|
70
|
+
at,
|
|
71
|
+
cause: 'closed',
|
|
72
|
+
episodeId: null,
|
|
73
|
+
previousEpisodeId: meta.episodeId,
|
|
74
|
+
closeReason: reason,
|
|
75
|
+
});
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Put a new episode in place of `expectedId` as one operation (Issue #3798):
|
|
80
|
+
* listeners hear a single opening edge for the new wait and no closing one
|
|
81
|
+
* in between, so nothing reports "nobody is waiting" mid-swap.
|
|
82
|
+
*
|
|
83
|
+
* @returns The new episode, or null when `expectedId` is no longer open
|
|
84
|
+
*/
|
|
85
|
+
function replaceEpisode(parts, expectedId, next, reason, at) {
|
|
86
|
+
const key = (0, waiting_episode_state_store_1.keyOf)(parts);
|
|
87
|
+
const old = waiting_episode_state_store_1.episodes.get(key);
|
|
88
|
+
if (old === undefined)
|
|
89
|
+
return null;
|
|
90
|
+
const oldMeta = (0, waiting_episode_state_store_1.metaOf)(old);
|
|
91
|
+
if (oldMeta.episodeId !== expectedId)
|
|
92
|
+
return null;
|
|
93
|
+
waiting_episode_state_store_1.lastClosed.set(key, { at, promptScreenKey: oldMeta.promptScreenKey });
|
|
94
|
+
const view = { since: next.since, kind: next.kind };
|
|
95
|
+
const meta = {
|
|
96
|
+
episodeId: (0, waiting_episode_state_store_1.nextEpisodeId)(),
|
|
97
|
+
openedAt: at,
|
|
98
|
+
boundAt: at,
|
|
99
|
+
binding: next.binding,
|
|
100
|
+
openedBy: next.openedBy,
|
|
101
|
+
promptScreenKey: next.promptScreenKey ?? null,
|
|
102
|
+
};
|
|
103
|
+
waiting_episode_state_store_1.episodes.set(key, view);
|
|
104
|
+
waiting_episode_state_store_1.metas.set(view, meta);
|
|
105
|
+
(0, waiting_episode_state_store_1.bumpVersion)(key);
|
|
106
|
+
(0, waiting_episode_state_store_1.emit)({
|
|
107
|
+
worktreeId: parts.worktreeId,
|
|
108
|
+
cliToolId: parts.cliToolId,
|
|
109
|
+
instanceId: parts.instanceId,
|
|
110
|
+
waiting: true,
|
|
111
|
+
since: view.since,
|
|
112
|
+
kind: view.kind,
|
|
113
|
+
at,
|
|
114
|
+
cause: 'replaced',
|
|
115
|
+
episodeId: meta.episodeId,
|
|
116
|
+
previousEpisodeId: oldMeta.episodeId,
|
|
117
|
+
closeReason: reason,
|
|
118
|
+
});
|
|
119
|
+
return { ...view, ...meta };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Change what the open episode `expectedId` is bound to (Issue #3798). Not an
|
|
123
|
+
* edge: the wait goes on, so nothing is emitted and `since` stays.
|
|
124
|
+
*
|
|
125
|
+
* @returns Whether the episode was rebound
|
|
126
|
+
*/
|
|
127
|
+
function rebindEpisode(parts, expectedId, binding, at) {
|
|
128
|
+
const key = (0, waiting_episode_state_store_1.keyOf)(parts);
|
|
129
|
+
const view = waiting_episode_state_store_1.episodes.get(key);
|
|
130
|
+
if (view === undefined)
|
|
131
|
+
return false;
|
|
132
|
+
const meta = (0, waiting_episode_state_store_1.metaOf)(view);
|
|
133
|
+
if (meta.episodeId !== expectedId)
|
|
134
|
+
return false;
|
|
135
|
+
meta.binding = binding;
|
|
136
|
+
meta.boundAt = at;
|
|
137
|
+
(0, waiting_episode_state_store_1.bumpVersion)(key);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Refresh the kind of the open episode `expectedId` (Issue #3798, I10). The
|
|
142
|
+
* wait goes on: no edge, and the version does not move.
|
|
143
|
+
*
|
|
144
|
+
* @returns Whether the episode was still open
|
|
145
|
+
*/
|
|
146
|
+
function updateEpisodeKind(parts, expectedId, kind) {
|
|
147
|
+
const view = waiting_episode_state_store_1.episodes.get((0, waiting_episode_state_store_1.keyOf)(parts));
|
|
148
|
+
if (view === undefined || (0, waiting_episode_state_store_1.metaOf)(view).episodeId !== expectedId)
|
|
149
|
+
return false;
|
|
150
|
+
view.kind = kind;
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The waiting-episode store's state tables, its listeners and the reads
|
|
4
|
+
* (Issue #1786 / #3798). The single place that initialises each `globalThis` slot.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.UNKNOWN_BINDING = exports.lastClosed = exports.metas = exports.episodes = void 0;
|
|
8
|
+
exports.nextEpisodeId = nextEpisodeId;
|
|
9
|
+
exports.keyOf = keyOf;
|
|
10
|
+
exports.bumpVersion = bumpVersion;
|
|
11
|
+
exports.onWaitingTransition = onWaitingTransition;
|
|
12
|
+
exports.onWaitingEpisodeTransition = onWaitingEpisodeTransition;
|
|
13
|
+
exports.emit = emit;
|
|
14
|
+
exports.metaOf = metaOf;
|
|
15
|
+
exports.getWaitingEpisodeRecord = getWaitingEpisodeRecord;
|
|
16
|
+
exports.getEpisodeVersion = getEpisodeVersion;
|
|
17
|
+
exports.snapshotEpisodeVersions = snapshotEpisodeVersions;
|
|
18
|
+
exports.getLastClosedEpisode = getLastClosedEpisode;
|
|
19
|
+
exports.getWaitingEpisode = getWaitingEpisode;
|
|
20
|
+
exports.hasOpenWaitingEpisode = hasOpenWaitingEpisode;
|
|
21
|
+
exports.clearWaitingEpisodes = clearWaitingEpisodes;
|
|
22
|
+
exports.clearWaitingTransitionListeners = clearWaitingTransitionListeners;
|
|
23
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
24
|
+
const logger_1 = require("../../lib/logger");
|
|
25
|
+
const global_state_1 = require("../global-state");
|
|
26
|
+
const logger = (0, logger_1.createLogger)('waiting-episode-state');
|
|
27
|
+
/** compositeKey -> the wait currently in progress for that instance. */
|
|
28
|
+
exports.episodes = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodes', () => new Map());
|
|
29
|
+
/** Subscribers to the edge. See the module docblock. */
|
|
30
|
+
const listeners = (0, global_state_1.getOrInitGlobal)('__sessionWaitingTransitionListeners', () => new Set());
|
|
31
|
+
exports.metas = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeMeta', () => new WeakMap());
|
|
32
|
+
const versions = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeVersions', () => new Map());
|
|
33
|
+
exports.lastClosed = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeLastClosed', () => new Map());
|
|
34
|
+
const episodeSeq = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeSeq', () => ({
|
|
35
|
+
value: 0,
|
|
36
|
+
nonce: Math.random().toString(36).slice(2, 10),
|
|
37
|
+
}));
|
|
38
|
+
const episodeListeners = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeListeners', () => new Set());
|
|
39
|
+
/** The binding used when no resolver is registered: nothing is known. */
|
|
40
|
+
exports.UNKNOWN_BINDING = {
|
|
41
|
+
kind: 'unattributed',
|
|
42
|
+
generation: { kind: 'none' },
|
|
43
|
+
lastClosedTurnId: null,
|
|
44
|
+
};
|
|
45
|
+
function nextEpisodeId() {
|
|
46
|
+
episodeSeq.value += 1;
|
|
47
|
+
return `wep-${episodeSeq.nonce}-${episodeSeq.value}`;
|
|
48
|
+
}
|
|
49
|
+
function keyOf(parts) {
|
|
50
|
+
return (0, auto_yes_state_1.buildCompositeKey)(parts.worktreeId, parts.cliToolId, parts.instanceId);
|
|
51
|
+
}
|
|
52
|
+
function bumpVersion(key) {
|
|
53
|
+
versions.set(key, (versions.get(key) ?? 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Subscribe to waiting edges.
|
|
57
|
+
*
|
|
58
|
+
* @returns An unsubscribe function. Idempotent — calling it twice is harmless.
|
|
59
|
+
*/
|
|
60
|
+
function onWaitingTransition(listener) {
|
|
61
|
+
listeners.add(listener);
|
|
62
|
+
return () => {
|
|
63
|
+
listeners.delete(listener);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Subscribe to waiting edges with the episode's identity (Issue #3798).
|
|
68
|
+
*
|
|
69
|
+
* The same crossings `onWaitingTransition` delivers, in the same order, with
|
|
70
|
+
* the cause, the episode ids and the close reason added.
|
|
71
|
+
*/
|
|
72
|
+
function onWaitingEpisodeTransition(listener) {
|
|
73
|
+
episodeListeners.add(listener);
|
|
74
|
+
return () => {
|
|
75
|
+
episodeListeners.delete(listener);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Notify subscribers, containing anything they throw. */
|
|
79
|
+
function emit(transition) {
|
|
80
|
+
const { cause: _cause, episodeId: _id, previousEpisodeId: _prev, closeReason: _reason, ...plain } = transition;
|
|
81
|
+
for (const listener of listeners) {
|
|
82
|
+
try {
|
|
83
|
+
listener(plain);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
logListenerFailure(transition, error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const listener of episodeListeners) {
|
|
90
|
+
try {
|
|
91
|
+
listener(transition);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
logListenerFailure(transition, error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function logListenerFailure(transition, error) {
|
|
99
|
+
logger.error('waiting-transition-listener-failed', {
|
|
100
|
+
worktreeId: transition.worktreeId,
|
|
101
|
+
cliToolId: transition.cliToolId,
|
|
102
|
+
instanceId: transition.instanceId ?? transition.cliToolId,
|
|
103
|
+
waiting: transition.waiting,
|
|
104
|
+
error: error instanceof Error ? error.message : String(error),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The meta of an episode in the map. An episode put there without one (a test
|
|
109
|
+
* that wrote the map directly) is given an unattributed identity on first read.
|
|
110
|
+
*/
|
|
111
|
+
function metaOf(view) {
|
|
112
|
+
let meta = exports.metas.get(view);
|
|
113
|
+
if (meta === undefined) {
|
|
114
|
+
meta = {
|
|
115
|
+
episodeId: nextEpisodeId(),
|
|
116
|
+
openedAt: view.since,
|
|
117
|
+
boundAt: view.since,
|
|
118
|
+
binding: exports.UNKNOWN_BINDING,
|
|
119
|
+
openedBy: 'legacy-edge',
|
|
120
|
+
promptScreenKey: null,
|
|
121
|
+
};
|
|
122
|
+
exports.metas.set(view, meta);
|
|
123
|
+
}
|
|
124
|
+
return meta;
|
|
125
|
+
}
|
|
126
|
+
/** The open episode with its identity and binding, or null (Issue #3798). */
|
|
127
|
+
function getWaitingEpisodeRecord(worktreeId, cliToolId, instanceId) {
|
|
128
|
+
const view = exports.episodes.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId));
|
|
129
|
+
if (view === undefined)
|
|
130
|
+
return null;
|
|
131
|
+
const meta = metaOf(view);
|
|
132
|
+
return { since: view.since, kind: view.kind, ...meta, binding: meta.binding };
|
|
133
|
+
}
|
|
134
|
+
/** The instance's episode version: it moves on every open, close, replacement and rebind. */
|
|
135
|
+
function getEpisodeVersion(worktreeId, cliToolId, instanceId) {
|
|
136
|
+
return versions.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)) ?? 0;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Every instance version of one worktree, as of now (Issue #3798): the status
|
|
140
|
+
* probe fixes them before it lists the tmux sessions. An instance missing from
|
|
141
|
+
* the map is at version 0.
|
|
142
|
+
*/
|
|
143
|
+
function snapshotEpisodeVersions(worktreeId) {
|
|
144
|
+
const prefix = `${worktreeId}${auto_yes_state_1.COMPOSITE_KEY_SEPARATOR}`;
|
|
145
|
+
const snapshot = new Map();
|
|
146
|
+
for (const [key, version] of versions) {
|
|
147
|
+
if (key.startsWith(prefix))
|
|
148
|
+
snapshot.set(key, version);
|
|
149
|
+
}
|
|
150
|
+
return snapshot;
|
|
151
|
+
}
|
|
152
|
+
/** The last episode that ended for this instance, or null. */
|
|
153
|
+
function getLastClosedEpisode(worktreeId, cliToolId, instanceId) {
|
|
154
|
+
return exports.lastClosed.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)) ?? null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* @returns The wait in progress for this instance, or null when it is not
|
|
158
|
+
* waiting. Read-only: observing the edge is {@link observeWaitingEdge}'s job.
|
|
159
|
+
*/
|
|
160
|
+
function getWaitingEpisode(worktreeId, cliToolId, instanceId) {
|
|
161
|
+
return exports.episodes.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)) ?? null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Whether **any** instance in this worktree is still waiting (Issue #2001).
|
|
165
|
+
*
|
|
166
|
+
* The cross-device dismissal is keyed on the worktree, because that is what the
|
|
167
|
+
* Service Worker `tag` names (`<worktreeId>:prompt`, `push-sender`): two agent
|
|
168
|
+
* instances waiting in one worktree share a single notification card on the
|
|
169
|
+
* phone. So one instance crossing the closing edge is not on its own a reason
|
|
170
|
+
* to clear that card — the card is still telling the truth until the last of
|
|
171
|
+
* them has been answered.
|
|
172
|
+
*
|
|
173
|
+
* The prefix test is exact rather than heuristic: `buildCompositeKey` puts the
|
|
174
|
+
* worktree id first and rejects a worktree id containing
|
|
175
|
+
* {@link COMPOSITE_KEY_SEPARATOR}, so no other worktree's key can start with
|
|
176
|
+
* `<worktreeId>:`.
|
|
177
|
+
*/
|
|
178
|
+
function hasOpenWaitingEpisode(worktreeId) {
|
|
179
|
+
const prefix = `${worktreeId}${auto_yes_state_1.COMPOSITE_KEY_SEPARATOR}`;
|
|
180
|
+
for (const key of exports.episodes.keys()) {
|
|
181
|
+
if (key.startsWith(prefix))
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Drop every episode. Test seam.
|
|
188
|
+
*
|
|
189
|
+
* CI runs with `fileParallelism: false`, so one process holds this map for the
|
|
190
|
+
* whole suite: a test that opens an episode and does not clear it hands the next
|
|
191
|
+
* file a session that is already waiting.
|
|
192
|
+
*/
|
|
193
|
+
function clearWaitingEpisodes() {
|
|
194
|
+
exports.episodes.clear();
|
|
195
|
+
versions.clear();
|
|
196
|
+
exports.lastClosed.clear();
|
|
197
|
+
}
|
|
198
|
+
/** Drop every subscriber. Test seam, paired with {@link clearWaitingEpisodes}. */
|
|
199
|
+
function clearWaitingTransitionListeners() {
|
|
200
|
+
listeners.clear();
|
|
201
|
+
episodeListeners.clear();
|
|
202
|
+
}
|