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
|
@@ -12,11 +12,23 @@
|
|
|
12
12
|
*
|
|
13
13
|
* So the edge is detected exactly once, here, by {@link observeWaitingEdge}, and
|
|
14
14
|
* everything else either reads {@link getWaitingEpisode} or subscribes with
|
|
15
|
-
* {@link onWaitingTransition}.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
15
|
+
* {@link onWaitingTransition}. The observers are `worktree-status-helper`, on
|
|
16
|
+
* the list API's per-instance probe — it passes the *composed* verdict (scraper
|
|
17
|
+
* OR structured), so a wait that only the agent's own events can see opens an
|
|
18
|
+
* episode exactly like one the screen scraper read — and `response-checker`
|
|
19
|
+
* (#1790), which opens the episode for a prompt it saved and closes it when it
|
|
20
|
+
* records a reply.
|
|
21
|
+
*
|
|
22
|
+
* Issue #3798 added the agent's own turn transitions as closers: a `stop` that
|
|
23
|
+
* ended the turn an episode belongs to closes it in the same synchronous step
|
|
24
|
+
* that records the stop (`waiting-episode-binding`), so a tool whose reply
|
|
25
|
+
* arrives on a hook closes its wait with no browser open. That needs each
|
|
26
|
+
* episode to carry an identity and the turn it belongs to; see "identity and
|
|
27
|
+
* attribution" below. The screen observers — the status probe, the response
|
|
28
|
+
* poller and now the Auto-Yes poller — go through the same module's
|
|
29
|
+
* observation tables (`observeWaiting`), which refuse a reading made against an
|
|
30
|
+
* episode that has moved since the observer started; {@link observeWaitingEdge}
|
|
31
|
+
* stays for the callers and suites written against #1786.
|
|
20
32
|
*
|
|
21
33
|
* ## Where #1788 / #1790 plug in
|
|
22
34
|
*
|
|
@@ -39,46 +51,49 @@
|
|
|
39
51
|
* @module lib/session/waiting-episode-state
|
|
40
52
|
*/
|
|
41
53
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.onWaitingTransition =
|
|
54
|
+
exports.updateEpisodeKind = exports.replaceEpisode = exports.rebindEpisode = exports.openEpisode = exports.closeEpisode = exports.snapshotEpisodeVersions = exports.onWaitingTransition = exports.onWaitingEpisodeTransition = exports.hasOpenWaitingEpisode = exports.getWaitingEpisodeRecord = exports.getWaitingEpisode = exports.getLastClosedEpisode = exports.getEpisodeVersion = exports.clearWaitingTransitionListeners = exports.clearWaitingEpisodes = void 0;
|
|
55
|
+
exports.registerEpisodeBindingResolver = registerEpisodeBindingResolver;
|
|
43
56
|
exports.observeWaitingEdge = observeWaitingEdge;
|
|
44
|
-
exports.getWaitingEpisode = getWaitingEpisode;
|
|
45
|
-
exports.hasOpenWaitingEpisode = hasOpenWaitingEpisode;
|
|
46
|
-
exports.clearWaitingEpisodes = clearWaitingEpisodes;
|
|
47
|
-
exports.clearWaitingTransitionListeners = clearWaitingTransitionListeners;
|
|
48
|
-
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
49
57
|
const logger_1 = require("../../lib/logger");
|
|
50
|
-
const
|
|
58
|
+
const waiting_episode_state_ops_1 = require("../../lib/session/waiting-episode-state-ops");
|
|
59
|
+
const waiting_episode_state_store_1 = require("../../lib/session/waiting-episode-state-store");
|
|
60
|
+
var waiting_episode_state_store_2 = require("../../lib/session/waiting-episode-state-store");
|
|
61
|
+
Object.defineProperty(exports, "clearWaitingEpisodes", { enumerable: true, get: function () { return waiting_episode_state_store_2.clearWaitingEpisodes; } });
|
|
62
|
+
Object.defineProperty(exports, "clearWaitingTransitionListeners", { enumerable: true, get: function () { return waiting_episode_state_store_2.clearWaitingTransitionListeners; } });
|
|
63
|
+
Object.defineProperty(exports, "getEpisodeVersion", { enumerable: true, get: function () { return waiting_episode_state_store_2.getEpisodeVersion; } });
|
|
64
|
+
Object.defineProperty(exports, "getLastClosedEpisode", { enumerable: true, get: function () { return waiting_episode_state_store_2.getLastClosedEpisode; } });
|
|
65
|
+
Object.defineProperty(exports, "getWaitingEpisode", { enumerable: true, get: function () { return waiting_episode_state_store_2.getWaitingEpisode; } });
|
|
66
|
+
Object.defineProperty(exports, "getWaitingEpisodeRecord", { enumerable: true, get: function () { return waiting_episode_state_store_2.getWaitingEpisodeRecord; } });
|
|
67
|
+
Object.defineProperty(exports, "hasOpenWaitingEpisode", { enumerable: true, get: function () { return waiting_episode_state_store_2.hasOpenWaitingEpisode; } });
|
|
68
|
+
Object.defineProperty(exports, "onWaitingEpisodeTransition", { enumerable: true, get: function () { return waiting_episode_state_store_2.onWaitingEpisodeTransition; } });
|
|
69
|
+
Object.defineProperty(exports, "onWaitingTransition", { enumerable: true, get: function () { return waiting_episode_state_store_2.onWaitingTransition; } });
|
|
70
|
+
Object.defineProperty(exports, "snapshotEpisodeVersions", { enumerable: true, get: function () { return waiting_episode_state_store_2.snapshotEpisodeVersions; } });
|
|
71
|
+
var waiting_episode_state_ops_2 = require("../../lib/session/waiting-episode-state-ops");
|
|
72
|
+
Object.defineProperty(exports, "closeEpisode", { enumerable: true, get: function () { return waiting_episode_state_ops_2.closeEpisode; } });
|
|
73
|
+
Object.defineProperty(exports, "openEpisode", { enumerable: true, get: function () { return waiting_episode_state_ops_2.openEpisode; } });
|
|
74
|
+
Object.defineProperty(exports, "rebindEpisode", { enumerable: true, get: function () { return waiting_episode_state_ops_2.rebindEpisode; } });
|
|
75
|
+
Object.defineProperty(exports, "replaceEpisode", { enumerable: true, get: function () { return waiting_episode_state_ops_2.replaceEpisode; } });
|
|
76
|
+
Object.defineProperty(exports, "updateEpisodeKind", { enumerable: true, get: function () { return waiting_episode_state_ops_2.updateEpisodeKind; } });
|
|
51
77
|
const logger = (0, logger_1.createLogger)('waiting-episode-state');
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const listeners = (0, global_state_1.getOrInitGlobal)('__sessionWaitingTransitionListeners', () => new Set());
|
|
56
|
-
/**
|
|
57
|
-
* Subscribe to waiting edges.
|
|
58
|
-
*
|
|
59
|
-
* @returns An unsubscribe function. Idempotent — calling it twice is harmless.
|
|
60
|
-
*/
|
|
61
|
-
function onWaitingTransition(listener) {
|
|
62
|
-
listeners.add(listener);
|
|
63
|
-
return () => {
|
|
64
|
-
listeners.delete(listener);
|
|
65
|
-
};
|
|
78
|
+
/** Install the binding resolver `observeWaitingEdge` uses. The last one wins. */
|
|
79
|
+
function registerEpisodeBindingResolver(resolver) {
|
|
80
|
+
globalThis.__sessionWaitingEpisodeBindingResolver = resolver;
|
|
66
81
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
function resolveBinding(parts, at) {
|
|
83
|
+
const resolver = globalThis.__sessionWaitingEpisodeBindingResolver;
|
|
84
|
+
if (resolver === undefined)
|
|
85
|
+
return waiting_episode_state_store_1.UNKNOWN_BINDING;
|
|
86
|
+
try {
|
|
87
|
+
return resolver(parts, at);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
logger.warn('waiting-episode-binding-resolve-failed', {
|
|
91
|
+
worktreeId: parts.worktreeId,
|
|
92
|
+
cliToolId: parts.cliToolId,
|
|
93
|
+
instanceId: parts.instanceId ?? parts.cliToolId,
|
|
94
|
+
error: error instanceof Error ? error.message : String(error),
|
|
95
|
+
});
|
|
96
|
+
return waiting_episode_state_store_1.UNKNOWN_BINDING;
|
|
82
97
|
}
|
|
83
98
|
}
|
|
84
99
|
/**
|
|
@@ -89,16 +104,23 @@ function emit(transition) {
|
|
|
89
104
|
* `since` and emit nothing, so a listener hears one event per wait rather than
|
|
90
105
|
* one per poll.
|
|
91
106
|
*
|
|
107
|
+
* Issue #3798: an episode opened here is bound by the registered resolver
|
|
108
|
+
* (`waiting-episode-binding`), so the turn transitions can end it. The
|
|
109
|
+
* production observers no longer call it: they go through
|
|
110
|
+
* `waiting-episode-binding`'s `observeWaiting`, which also checks that the
|
|
111
|
+
* episode has not moved since they started and that the frame does not
|
|
112
|
+
* predate the close of what it shows.
|
|
113
|
+
*
|
|
92
114
|
* @returns The episode's `since` while waiting, or null when it is not.
|
|
93
115
|
*/
|
|
94
116
|
function observeWaitingEdge({ worktreeId, cliToolId, instanceId, waiting, kind = null, structuredSince = null, now = Date.now(), }) {
|
|
95
|
-
const
|
|
96
|
-
const
|
|
117
|
+
const parts = { worktreeId, cliToolId, instanceId };
|
|
118
|
+
const key = (0, waiting_episode_state_store_1.keyOf)(parts);
|
|
119
|
+
const existing = waiting_episode_state_store_1.episodes.get(key);
|
|
97
120
|
if (!waiting) {
|
|
98
121
|
if (existing === undefined)
|
|
99
122
|
return null;
|
|
100
|
-
|
|
101
|
-
emit({ worktreeId, cliToolId, instanceId, waiting: false, since: null, kind: null, at: now });
|
|
123
|
+
(0, waiting_episode_state_ops_1.closeEpisode)(parts, (0, waiting_episode_state_store_1.metaOf)(existing).episodeId, 'screen-cleared', now);
|
|
102
124
|
return null;
|
|
103
125
|
}
|
|
104
126
|
if (existing !== undefined) {
|
|
@@ -109,51 +131,6 @@ function observeWaitingEdge({ worktreeId, cliToolId, instanceId, waiting, kind =
|
|
|
109
131
|
return existing.since;
|
|
110
132
|
}
|
|
111
133
|
const since = structuredSince ?? now;
|
|
112
|
-
|
|
113
|
-
emit({ worktreeId, cliToolId, instanceId, waiting: true, since, kind, at: now });
|
|
134
|
+
(0, waiting_episode_state_ops_1.openEpisode)(parts, { since, kind, binding: resolveBinding(parts, now), openedBy: 'legacy-edge' }, now);
|
|
114
135
|
return since;
|
|
115
136
|
}
|
|
116
|
-
/**
|
|
117
|
-
* @returns The wait in progress for this instance, or null when it is not
|
|
118
|
-
* waiting. Read-only: observing the edge is {@link observeWaitingEdge}'s job.
|
|
119
|
-
*/
|
|
120
|
-
function getWaitingEpisode(worktreeId, cliToolId, instanceId) {
|
|
121
|
-
return episodes.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)) ?? null;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Whether **any** instance in this worktree is still waiting (Issue #2001).
|
|
125
|
-
*
|
|
126
|
-
* The cross-device dismissal is keyed on the worktree, because that is what the
|
|
127
|
-
* Service Worker `tag` names (`<worktreeId>:prompt`, `push-sender`): two agent
|
|
128
|
-
* instances waiting in one worktree share a single notification card on the
|
|
129
|
-
* phone. So one instance crossing the closing edge is not on its own a reason
|
|
130
|
-
* to clear that card — the card is still telling the truth until the last of
|
|
131
|
-
* them has been answered.
|
|
132
|
-
*
|
|
133
|
-
* The prefix test is exact rather than heuristic: `buildCompositeKey` puts the
|
|
134
|
-
* worktree id first and rejects a worktree id containing
|
|
135
|
-
* {@link COMPOSITE_KEY_SEPARATOR}, so no other worktree's key can start with
|
|
136
|
-
* `<worktreeId>:`.
|
|
137
|
-
*/
|
|
138
|
-
function hasOpenWaitingEpisode(worktreeId) {
|
|
139
|
-
const prefix = `${worktreeId}${auto_yes_state_1.COMPOSITE_KEY_SEPARATOR}`;
|
|
140
|
-
for (const key of episodes.keys()) {
|
|
141
|
-
if (key.startsWith(prefix))
|
|
142
|
-
return true;
|
|
143
|
-
}
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Drop every episode. Test seam.
|
|
148
|
-
*
|
|
149
|
-
* CI runs with `fileParallelism: false`, so one process holds this map for the
|
|
150
|
-
* whole suite: a test that opens an episode and does not clear it hands the next
|
|
151
|
-
* file a session that is already waiting.
|
|
152
|
-
*/
|
|
153
|
-
function clearWaitingEpisodes() {
|
|
154
|
-
episodes.clear();
|
|
155
|
-
}
|
|
156
|
-
/** Drop every subscriber. Test seam, paired with {@link clearWaitingEpisodes}. */
|
|
157
|
-
function clearWaitingTransitionListeners() {
|
|
158
|
-
listeners.clear();
|
|
159
|
-
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The T table (Issue #3798, design §2.4): what one turn transition's outcome
|
|
4
|
+
* does to the open waiting episode. Pure — it reads the outcome, the episode's
|
|
5
|
+
* binding and the current generation, and writes nothing. Applying the verdict
|
|
6
|
+
* is `waiting-episode-binding`'s job (Issue #3864 split it out of there).
|
|
7
|
+
*
|
|
8
|
+
* Design: `docs/design/issue-3798-waiting-episode.md`.
|
|
9
|
+
*
|
|
10
|
+
* @module lib/session/waiting-episode-verdict
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.sameGeneration = sameGeneration;
|
|
14
|
+
exports.verdictForOutcome = verdictForOutcome;
|
|
15
|
+
function sameGeneration(a, b) {
|
|
16
|
+
if (a.kind === 'none' || b.kind === 'none')
|
|
17
|
+
return a.kind === b.kind;
|
|
18
|
+
return a.at === b.at;
|
|
19
|
+
}
|
|
20
|
+
const NONE = { action: 'none' };
|
|
21
|
+
const close = (reason) => ({ action: 'close', reason });
|
|
22
|
+
/** The previous record's turn id, for the D and F columns. Null for `none`. */
|
|
23
|
+
function previousTurnId(previous) {
|
|
24
|
+
return previous.kind === 'none' ? null : previous.turnId;
|
|
25
|
+
}
|
|
26
|
+
/** T1–T5: a turn opened. */
|
|
27
|
+
function verdictForOpened(outcome, binding) {
|
|
28
|
+
const { previous, turnId: n, event } = outcome;
|
|
29
|
+
const asTurnN = { kind: 'turn', generation: outcome.generation, turnId: n };
|
|
30
|
+
if (binding.kind === 'screen')
|
|
31
|
+
return NONE;
|
|
32
|
+
if (binding.kind === 'turn' && binding.turnId === n)
|
|
33
|
+
return { action: 'unmatched' }; // ※1
|
|
34
|
+
const p = previousTurnId(previous);
|
|
35
|
+
const tookOverRecord = previous.kind === 'dialog-only' || previous.kind === 'display-only';
|
|
36
|
+
// D: the record this turn took over (R3-4). Only T2 / T3 / T4 have one (※5).
|
|
37
|
+
const isD = binding.kind === 'dialog-only' && binding.recordTurnId === p;
|
|
38
|
+
// T5 (R1-9): a turn replaced while it was open ends every wait but a screen's.
|
|
39
|
+
if (previous.kind === 'open-same-session' || previous.kind === 'open-other-session') {
|
|
40
|
+
return isD ? { action: 'unmatched' } : close('turn-superseded');
|
|
41
|
+
}
|
|
42
|
+
// T4 (R2-4): a prompt ends them too; the turn model drops every decision here.
|
|
43
|
+
if (event === 'user_prompt_submit')
|
|
44
|
+
return close('turn-superseded');
|
|
45
|
+
if (binding.kind === 'turn')
|
|
46
|
+
return close('turn-superseded');
|
|
47
|
+
if (binding.kind === 'dialog-only') {
|
|
48
|
+
if (!isD)
|
|
49
|
+
return close('turn-superseded');
|
|
50
|
+
return tookOverRecord ? { action: 'rebind', binding: asTurnN } : { action: 'unmatched' }; // T1: ※5
|
|
51
|
+
}
|
|
52
|
+
// unattributed — F: nothing opened between the wait and this turn (R2-4).
|
|
53
|
+
return binding.lastClosedTurnId === p ? { action: 'rebind', binding: asTurnN } : close('turn-superseded');
|
|
54
|
+
}
|
|
55
|
+
/** T9–T11: a stop with no turn open. */
|
|
56
|
+
function verdictForStopWithoutTurn(outcome, binding) {
|
|
57
|
+
const { previous } = outcome;
|
|
58
|
+
const p = previousTurnId(previous);
|
|
59
|
+
switch (previous.kind) {
|
|
60
|
+
case 'closed':
|
|
61
|
+
// T9: B (R1-2) and F (R2-1).
|
|
62
|
+
if (binding.kind === 'turn' && binding.turnId === p)
|
|
63
|
+
return close('turn-stop');
|
|
64
|
+
if (binding.kind === 'unattributed' && binding.lastClosedTurnId === p)
|
|
65
|
+
return close('turn-stop');
|
|
66
|
+
if (binding.kind === 'dialog-only' && binding.recordTurnId === p)
|
|
67
|
+
return { action: 'unmatched' }; // ※5
|
|
68
|
+
return NONE;
|
|
69
|
+
case 'dialog-only':
|
|
70
|
+
// T10: D, F and G.
|
|
71
|
+
if (binding.kind === 'dialog-only' && binding.recordTurnId === p)
|
|
72
|
+
return close('turn-stop');
|
|
73
|
+
if (binding.kind === 'unattributed')
|
|
74
|
+
return close('turn-stop');
|
|
75
|
+
return NONE;
|
|
76
|
+
case 'display-only':
|
|
77
|
+
case 'none':
|
|
78
|
+
// T11: D (R3-4) and F.
|
|
79
|
+
if (binding.kind === 'dialog-only' && binding.recordTurnId === p)
|
|
80
|
+
return close('turn-stop');
|
|
81
|
+
if (binding.kind === 'unattributed' && binding.lastClosedTurnId === p)
|
|
82
|
+
return close('turn-stop');
|
|
83
|
+
return NONE;
|
|
84
|
+
default:
|
|
85
|
+
// An open turn is `stopped` / `stop-rejected`, never this outcome.
|
|
86
|
+
return { action: 'unmatched' };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** T19 / T20 and the rest of the generation fence. */
|
|
90
|
+
function verdictForGenerationFenced(outcome, binding) {
|
|
91
|
+
// T19 / T20 (R2-8): a session start in the same process keeps a screen.
|
|
92
|
+
if (outcome.source === 'session-start' && binding.kind === 'screen') {
|
|
93
|
+
return sameGeneration(binding.generation, outcome.generation)
|
|
94
|
+
? NONE
|
|
95
|
+
: { action: 'rebind', binding: { ...binding, generation: outcome.generation } };
|
|
96
|
+
}
|
|
97
|
+
return sameGeneration(binding.generation, outcome.generation) ? NONE : close('generation');
|
|
98
|
+
}
|
|
99
|
+
/** T7. */
|
|
100
|
+
function verdictForRestored(outcome, binding) {
|
|
101
|
+
// T7: a wait opened under the discarded turn belongs to the one put back.
|
|
102
|
+
return binding.kind === 'turn' && binding.turnId === outcome.discardedTurnId
|
|
103
|
+
? { action: 'rebind', binding: { ...binding, turnId: outcome.restoredTurnId } }
|
|
104
|
+
: NONE;
|
|
105
|
+
}
|
|
106
|
+
/** T8. */
|
|
107
|
+
function verdictForStopped(outcome, binding) {
|
|
108
|
+
// T8.
|
|
109
|
+
return binding.kind === 'turn' && binding.turnId === outcome.turnId ? close('turn-stop') : NONE;
|
|
110
|
+
}
|
|
111
|
+
/** T13. */
|
|
112
|
+
function verdictForSessionEnded(outcome, binding) {
|
|
113
|
+
// T13.
|
|
114
|
+
return binding.kind === 'turn' && binding.turnId === outcome.turnId ? close('turn-session-end') : NONE;
|
|
115
|
+
}
|
|
116
|
+
/** T15 / T16. */
|
|
117
|
+
function verdictForDecisionOpened(outcome, binding, current) {
|
|
118
|
+
// T15 / T16 (R3-6): a dialog the hook reported for a wait the screen showed first.
|
|
119
|
+
return outcome.recordKind === 'dialog-only' && binding.kind === 'unattributed'
|
|
120
|
+
? {
|
|
121
|
+
action: 'rebind',
|
|
122
|
+
binding: { kind: 'dialog-only', generation: current, recordTurnId: outcome.recordTurnId, sessionId: null },
|
|
123
|
+
}
|
|
124
|
+
: NONE;
|
|
125
|
+
}
|
|
126
|
+
/** T17 / T18. */
|
|
127
|
+
function verdictForDecisionAnswered(outcome, binding) {
|
|
128
|
+
// T17 / T18 (R3-3): an explicit answer that left nothing pending.
|
|
129
|
+
if (outcome.before === 0 || outcome.remaining > 0)
|
|
130
|
+
return NONE;
|
|
131
|
+
const bound = (binding.kind === 'turn' && binding.turnId === outcome.recordTurnId) ||
|
|
132
|
+
(binding.kind === 'dialog-only' && binding.recordTurnId === outcome.recordTurnId);
|
|
133
|
+
return bound ? close('decision-settled') : NONE;
|
|
134
|
+
}
|
|
135
|
+
/** Rows that close a binding of another generation (the I column). */
|
|
136
|
+
const CLOSES_OTHER_GENERATION = new Set([
|
|
137
|
+
'opened',
|
|
138
|
+
'stopped',
|
|
139
|
+
'stop-without-turn',
|
|
140
|
+
'session-ended',
|
|
141
|
+
]);
|
|
142
|
+
/** The T table (design §2.4): one outcome on the open episode. */
|
|
143
|
+
function verdictForOutcome(outcome, binding, current) {
|
|
144
|
+
if (outcome.kind === 'generation-fenced')
|
|
145
|
+
return verdictForGenerationFenced(outcome, binding);
|
|
146
|
+
if (!sameGeneration(binding.generation, current)) {
|
|
147
|
+
return CLOSES_OTHER_GENERATION.has(outcome.kind) ? close('generation') : NONE;
|
|
148
|
+
}
|
|
149
|
+
switch (outcome.kind) {
|
|
150
|
+
case 'opened':
|
|
151
|
+
return verdictForOpened(outcome, binding);
|
|
152
|
+
case 'restored':
|
|
153
|
+
return verdictForRestored(outcome, binding);
|
|
154
|
+
case 'stopped':
|
|
155
|
+
return verdictForStopped(outcome, binding);
|
|
156
|
+
case 'stop-without-turn':
|
|
157
|
+
return verdictForStopWithoutTurn(outcome, binding);
|
|
158
|
+
case 'session-ended':
|
|
159
|
+
return verdictForSessionEnded(outcome, binding);
|
|
160
|
+
case 'decision-opened':
|
|
161
|
+
return verdictForDecisionOpened(outcome, binding, current);
|
|
162
|
+
case 'decision-answered':
|
|
163
|
+
return verdictForDecisionAnswered(outcome, binding);
|
|
164
|
+
case 'continued':
|
|
165
|
+
case 'stop-rejected':
|
|
166
|
+
case 'session-end-rejected':
|
|
167
|
+
case 'none':
|
|
168
|
+
// T6, T12, T14, T21.
|
|
169
|
+
return NONE;
|
|
170
|
+
default:
|
|
171
|
+
outcome;
|
|
172
|
+
return NONE;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -24,6 +24,7 @@ exports.isCaptureWindowSaturated = isCaptureWindowSaturated;
|
|
|
24
24
|
exports.getCaptureGeneration = getCaptureGeneration;
|
|
25
25
|
exports.isCaptureGenerationCurrent = isCaptureGenerationCurrent;
|
|
26
26
|
exports.sliceOutput = sliceOutput;
|
|
27
|
+
exports.sliceCutsHead = sliceCutsHead;
|
|
27
28
|
exports.getCachedCapture = getCachedCapture;
|
|
28
29
|
exports.setCachedCapture = setCachedCapture;
|
|
29
30
|
exports.invalidateCache = invalidateCache;
|
|
@@ -87,6 +88,10 @@ function getCache() {
|
|
|
87
88
|
function getInflight() {
|
|
88
89
|
return (0, global_state_1.getOrInitGlobal)('__tmuxCaptureCacheInflight', () => new Map());
|
|
89
90
|
}
|
|
91
|
+
/** When each in-flight fetch started (Issue #3798), for the callers that join it. */
|
|
92
|
+
function getInflightStartedAt() {
|
|
93
|
+
return (0, global_state_1.getOrInitGlobal)('__tmuxCaptureCacheInflightStartedAt', () => new WeakMap());
|
|
94
|
+
}
|
|
90
95
|
function getGenerationState() {
|
|
91
96
|
return (0, global_state_1.getOrInitGlobal)('__tmuxCaptureCacheGeneration', () => ({ global: 0, sessions: new Map() }));
|
|
92
97
|
}
|
|
@@ -122,8 +127,24 @@ function isCaptureGenerationCurrent(sessionName, generation) {
|
|
|
122
127
|
// sliceOutput()
|
|
123
128
|
// =========================================================================
|
|
124
129
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
130
|
+
* A capture's rows (Issue #3881 third review N4). tmux ends every row with a
|
|
131
|
+
* newline, so the last one terminates a row and is not a row of its own: a
|
|
132
|
+
* 1000-row pane comes back as 1000 rows and a terminator, which `split` makes
|
|
133
|
+
* 1001 elements.
|
|
134
|
+
*/
|
|
135
|
+
function rowsOf(output) {
|
|
136
|
+
const terminated = output.endsWith('\n');
|
|
137
|
+
return { rows: (terminated ? output.slice(0, -1) : output).split('\n'), terminated };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Slice output from the end to return the last requestedLines rows.
|
|
141
|
+
* If requestedLines >= total rows, returns the full output.
|
|
142
|
+
*
|
|
143
|
+
* Issue #3881 (third review N4): counted in rows, the terminator kept. Counted
|
|
144
|
+
* in `split` elements, the terminator took one of the requested rows, so a
|
|
145
|
+
* 1000-row pane asked for 1000 rows lost its first row — on an
|
|
146
|
+
* alternate-screen pane, the row that says whether the content begins at the
|
|
147
|
+
* top of the screen.
|
|
127
148
|
*
|
|
128
149
|
* @param fullOutput - Full captured output string
|
|
129
150
|
* @param requestedLines - Number of lines requested from the end
|
|
@@ -132,10 +153,21 @@ function isCaptureGenerationCurrent(sessionName, generation) {
|
|
|
132
153
|
function sliceOutput(fullOutput, requestedLines) {
|
|
133
154
|
if (fullOutput === '')
|
|
134
155
|
return '';
|
|
135
|
-
const
|
|
136
|
-
if (requestedLines >=
|
|
156
|
+
const { rows, terminated } = rowsOf(fullOutput);
|
|
157
|
+
if (requestedLines >= rows.length)
|
|
137
158
|
return fullOutput;
|
|
138
|
-
return
|
|
159
|
+
return rows.slice(-requestedLines).join('\n') + (terminated ? '\n' : '');
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Whether {@link sliceOutput} drops rows from the top of `fullOutput` (Issue
|
|
163
|
+
* #3881 third review N4): the one fact about a capture's top that its row count
|
|
164
|
+
* cannot tell when the window is exactly the pane's height.
|
|
165
|
+
*
|
|
166
|
+
* @param fullOutput - Full captured output string
|
|
167
|
+
* @param requestedLines - Number of lines requested from the end
|
|
168
|
+
*/
|
|
169
|
+
function sliceCutsHead(fullOutput, requestedLines) {
|
|
170
|
+
return fullOutput !== '' && requestedLines < rowsOf(fullOutput).rows.length;
|
|
139
171
|
}
|
|
140
172
|
// =========================================================================
|
|
141
173
|
// getCachedCapture()
|
|
@@ -180,8 +212,10 @@ function getCachedCapture(sessionName, requestedLines) {
|
|
|
180
212
|
* @param sessionName - tmux session name (cache key)
|
|
181
213
|
* @param output - Captured output string
|
|
182
214
|
* @param capturedLines - Number of lines the output was captured with
|
|
215
|
+
* @param fetchStartedAt - When the capture began (Issue #3798); every writer
|
|
216
|
+
* in this app passes it. Defaults to now, the write time
|
|
183
217
|
*/
|
|
184
|
-
function setCachedCapture(sessionName, output, capturedLines) {
|
|
218
|
+
function setCachedCapture(sessionName, output, capturedLines, fetchStartedAt) {
|
|
185
219
|
const cache = getCache();
|
|
186
220
|
const now = Date.now();
|
|
187
221
|
// [SEC4-002] Full sweep: remove all TTL-expired entries
|
|
@@ -209,8 +243,22 @@ function setCachedCapture(sessionName, output, capturedLines) {
|
|
|
209
243
|
output,
|
|
210
244
|
capturedLines,
|
|
211
245
|
timestamp: now,
|
|
246
|
+
fetchStartedAt: fetchStartedAt ?? now,
|
|
212
247
|
});
|
|
213
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* When the cached capture of `sessionName` was started, or null when nothing
|
|
251
|
+
* live is cached (Issue #3798). Read-only: an expired entry is left for the
|
|
252
|
+
* next read to evict.
|
|
253
|
+
*
|
|
254
|
+
* @param sessionName - tmux session name (cache key)
|
|
255
|
+
*/
|
|
256
|
+
function getCachedCaptureFetchStartedAt(sessionName) {
|
|
257
|
+
const entry = getCache().get(sessionName);
|
|
258
|
+
if (!entry || Date.now() - entry.timestamp > exports.CACHE_TTL_MS)
|
|
259
|
+
return null;
|
|
260
|
+
return entry.fetchStartedAt;
|
|
261
|
+
}
|
|
214
262
|
// =========================================================================
|
|
215
263
|
// invalidateCache()
|
|
216
264
|
// =========================================================================
|
|
@@ -262,10 +310,8 @@ function resetCacheForTesting() {
|
|
|
262
310
|
globalThis.__tmuxCaptureCache = undefined;
|
|
263
311
|
globalThis.__tmuxCaptureCacheInflight = undefined;
|
|
264
312
|
globalThis.__tmuxCaptureCacheGeneration = undefined;
|
|
313
|
+
globalThis.__tmuxCaptureCacheInflightStartedAt = undefined;
|
|
265
314
|
}
|
|
266
|
-
// =========================================================================
|
|
267
|
-
// getOrFetchCapture() - singleflight pattern
|
|
268
|
-
// =========================================================================
|
|
269
315
|
/**
|
|
270
316
|
* Get capture output from cache or fetch it.
|
|
271
317
|
* Implements singleflight pattern: concurrent requests for the same session
|
|
@@ -277,33 +323,52 @@ function resetCacheForTesting() {
|
|
|
277
323
|
* @param sessionName - tmux session name
|
|
278
324
|
* @param requestedLines - Number of lines requested
|
|
279
325
|
* @param fetchFn - Function to fetch output on cache miss
|
|
326
|
+
* @param onServed - Told where the returned frame came from (Issue #3798),
|
|
327
|
+
* right before it is returned; not called when the capture throws
|
|
328
|
+
* @param onSliced - Told whether the slice to `requestedLines` dropped rows
|
|
329
|
+
* from the top of what tmux returned (Issue #3881 third review N4,
|
|
330
|
+
* {@link sliceCutsHead}), right before it is returned
|
|
280
331
|
* @returns Captured output (sliced to requestedLines)
|
|
281
332
|
*/
|
|
282
|
-
async function getOrFetchCapture(sessionName, requestedLines, fetchFn) {
|
|
333
|
+
async function getOrFetchCapture(sessionName, requestedLines, fetchFn, onServed, onSliced) {
|
|
283
334
|
// 1. Check cache first
|
|
335
|
+
const cachedStartedAt = getCachedCaptureFetchStartedAt(sessionName);
|
|
284
336
|
const cached = getCachedCapture(sessionName, requestedLines);
|
|
285
337
|
if (cached !== null) {
|
|
338
|
+
if (cachedStartedAt !== null)
|
|
339
|
+
onServed?.({ fetchStartedAt: cachedStartedAt, source: 'cache' });
|
|
340
|
+
const entry = getCache().get(sessionName);
|
|
341
|
+
if (entry)
|
|
342
|
+
onSliced?.(sliceCutsHead(entry.output, requestedLines));
|
|
286
343
|
return cached;
|
|
287
344
|
}
|
|
288
345
|
// 2. Check for inflight request (singleflight)
|
|
289
346
|
const inflight = getInflight();
|
|
290
347
|
const existingPromise = inflight.get(sessionName);
|
|
291
348
|
if (existingPromise) {
|
|
349
|
+
const joinedStartedAt = getInflightStartedAt().get(existingPromise);
|
|
292
350
|
const result = await existingPromise;
|
|
351
|
+
if (joinedStartedAt !== undefined)
|
|
352
|
+
onServed?.({ fetchStartedAt: joinedStartedAt, source: 'joined' });
|
|
353
|
+
onSliced?.(sliceCutsHead(result, requestedLines));
|
|
293
354
|
return sliceOutput(result, requestedLines);
|
|
294
355
|
}
|
|
295
356
|
// 3. Create new fetch promise
|
|
296
357
|
// Issue #3734: snapshot the generation before fetchFn() starts
|
|
297
358
|
const generation = getCaptureGeneration(sessionName);
|
|
359
|
+
const fetchStartedAt = Date.now();
|
|
298
360
|
const fetchPromise = fetchFn();
|
|
299
361
|
inflight.set(sessionName, fetchPromise);
|
|
362
|
+
getInflightStartedAt().set(fetchPromise, fetchStartedAt);
|
|
300
363
|
try {
|
|
301
364
|
const output = await fetchPromise;
|
|
302
365
|
// Cache non-empty results only [SEC4-007], and only when no invalidation
|
|
303
366
|
// happened while waiting (Issue #3734)
|
|
304
367
|
if (output.length > 0 && isCaptureGenerationCurrent(sessionName, generation)) {
|
|
305
|
-
setCachedCapture(sessionName, output, exports.CACHE_MAX_CAPTURE_LINES);
|
|
368
|
+
setCachedCapture(sessionName, output, exports.CACHE_MAX_CAPTURE_LINES, fetchStartedAt);
|
|
306
369
|
}
|
|
370
|
+
onServed?.({ fetchStartedAt, source: 'fetched' });
|
|
371
|
+
onSliced?.(sliceCutsHead(output, requestedLines));
|
|
307
372
|
return sliceOutput(output, requestedLines);
|
|
308
373
|
}
|
|
309
374
|
finally {
|