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
|
@@ -37,12 +37,17 @@
|
|
|
37
37
|
*
|
|
38
38
|
* A `yes_no` prompt is a different inference — `detectPrompt` requires an
|
|
39
39
|
* explicit `(y/n)`-shaped token in the text rather than deriving it from layout
|
|
40
|
-
* — and NO tool in the registry has a measured yes/no dialog rule
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* the
|
|
40
|
+
* — and NO tool in the registry has a measured yes/no dialog rule. Until Issue
|
|
41
|
+
* #3822 that was the reason to leave it ungated. It is now the reason to refuse
|
|
42
|
+
* it on an `enforce` tool, in {@link evaluateAutoYesDialogGate} only: none of
|
|
43
|
+
* those tools draws a `(y/n)` dialog, so a `(y/n)` on their pane is text — a
|
|
44
|
+
* reply quoting one, a shell command's prompt — and typing `y` at it answers
|
|
45
|
+
* nothing the tool asked (the user's decision of 2026-10-20: a generic yes/no
|
|
46
|
+
* without the tool's own evidence is left to a human). The tool can still vouch
|
|
47
|
+
* for the frame through `detectDialog`, exactly as for a numbered list. The
|
|
48
|
+
* `legacy` tools are unchanged (#3823), and so is
|
|
49
|
+
* {@link evaluateDialogPresence}: a `(y/n)` row a human may answer still
|
|
50
|
+
* belongs in History.
|
|
46
51
|
*
|
|
47
52
|
* ## What "allowed" does NOT mean
|
|
48
53
|
*
|
|
@@ -54,9 +59,12 @@
|
|
|
54
59
|
* @module lib/polling/auto-yes-dialog-gate
|
|
55
60
|
*/
|
|
56
61
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
-
exports.COMMAND_CODE_UNSUPPORTED_QUESTION_MESSAGE = exports.UNSUPPORTED_DIALOG_LAYOUT_REASON = exports.PROMPT_NO_LONGER_ACTIVE_REASON = exports.AUTO_YES_DIALOG_GATE_ENV_VAR = exports.AUTO_YES_DIALOG_GATE_DEFAULT_MODE = exports.AUTO_YES_DIALOG_GATE_MODES = void 0;
|
|
62
|
+
exports.COMMAND_CODE_UNSUPPORTED_QUESTION_MESSAGE = exports.UNSUPPORTED_DIALOG_LAYOUT_REASON = exports.PROMPT_NO_LONGER_ACTIVE_REASON = exports.QUESTION_EVIDENCE_UNREAD_TOOLS = exports.AUTO_YES_QUESTION_DIALOG_KINDS = exports.AUTO_YES_DIALOG_GATE_ENV_VAR = exports.AUTO_YES_DIALOG_GATE_DEFAULT_MODE = exports.AUTO_YES_DIALOG_GATE_MODES = void 0;
|
|
58
63
|
exports.resolveAutoYesDialogGateMode = resolveAutoYesDialogGateMode;
|
|
59
64
|
exports.evaluateAutoYesDialogGate = evaluateAutoYesDialogGate;
|
|
65
|
+
exports.classifyAutoYesQuestion = classifyAutoYesQuestion;
|
|
66
|
+
exports.autoYesQuestionTreatment = autoYesQuestionTreatment;
|
|
67
|
+
exports.isAutoYesQuestionPrompt = isAutoYesQuestionPrompt;
|
|
60
68
|
exports.evaluateDialogPresence = evaluateDialogPresence;
|
|
61
69
|
exports.judgePromptResponse = judgePromptResponse;
|
|
62
70
|
exports.assessPromptAnswerability = assessPromptAnswerability;
|
|
@@ -67,6 +75,7 @@ const prompt_detector_1 = require("../../lib/detection/prompt-detector");
|
|
|
67
75
|
const cli_patterns_1 = require("../../lib/detection/cli-patterns");
|
|
68
76
|
const dialog_1 = require("../../lib/detection/tools/antigravity/dialog");
|
|
69
77
|
const dialog_2 = require("../../lib/detection/tools/command-code/dialog");
|
|
78
|
+
const auto_yes_option_effect_1 = require("./auto-yes-option-effect");
|
|
70
79
|
/** Every accepted value of {@link AutoYesDialogGateMode}, for parsing and tests. */
|
|
71
80
|
exports.AUTO_YES_DIALOG_GATE_MODES = ['enforce', 'legacy'];
|
|
72
81
|
/**
|
|
@@ -193,7 +202,10 @@ function resolveAutoYesDialogGateMode(tool, env = process.env) {
|
|
|
193
202
|
}
|
|
194
203
|
return specific ?? wildcard ?? exports.AUTO_YES_DIALOG_GATE_DEFAULT_MODE[tool] ?? 'legacy';
|
|
195
204
|
}
|
|
196
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* The only prompt family the presence gate judges. Auto-Yes's gate also judges
|
|
207
|
+
* `yes_no` (Issue #3822); see the module docstring.
|
|
208
|
+
*/
|
|
197
209
|
const GATED_PROMPT_TYPE = 'multiple_choice';
|
|
198
210
|
/**
|
|
199
211
|
* May Auto-Yes answer the prompt the generic inference found on this frame?
|
|
@@ -216,7 +228,10 @@ function evaluateAutoYesDialogGate(cliToolId, promptType, cleanOutput, env = pro
|
|
|
216
228
|
// `judgeDialogPresence` holds that rule; Issue #2457 split it out so the
|
|
217
229
|
// history-save and `/prompt-response` paths judge a frame the same way this
|
|
218
230
|
// one does instead of re-deriving the rollout table.
|
|
219
|
-
const
|
|
231
|
+
const mode = resolveAutoYesDialogGateMode(cliToolId, env);
|
|
232
|
+
const presence = promptType === 'yes_no'
|
|
233
|
+
? judgeYesNoPresence(cliToolId, cleanOutput, mode)
|
|
234
|
+
: judgeDialogPresence(cliToolId, promptType, cleanOutput, mode);
|
|
220
235
|
return {
|
|
221
236
|
// `keys` is a dialog and still not answerable: opencode's button strip takes
|
|
222
237
|
// ←/→ + Enter, so the digit is swallowed and the Enter confirms whatever is
|
|
@@ -245,6 +260,119 @@ function judgeDialogPresence(cliToolId, promptType, frame, mode) {
|
|
|
245
260
|
const dialog = detector.detectDialog(typeof frame === 'string' ? (0, frame_1.normalizeFrame)(frame, cliToolId) : frame);
|
|
246
261
|
return { present: dialog !== null, dialog, mode, gated: true };
|
|
247
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Issue #3822: the Auto-Yes gate's reading of a `yes_no` candidate. Judged on
|
|
265
|
+
* the same terms as a numbered one — the rollout table and the `hasDialogRules`
|
|
266
|
+
* cross-check — so a `legacy` tool, or one with no rules, stays ungated. An
|
|
267
|
+
* `enforce` tool answers only where its own `detectDialog` vouched for the
|
|
268
|
+
* frame; none of their rules reads a `(y/n)` row, so in practice it is refused.
|
|
269
|
+
*/
|
|
270
|
+
function judgeYesNoPresence(cliToolId, frame, mode) {
|
|
271
|
+
const detector = (0, registry_1.getToolStatusDetector)(cliToolId);
|
|
272
|
+
if (!detector.hasDialogRules || mode === 'legacy') {
|
|
273
|
+
return { present: true, dialog: null, mode, gated: false };
|
|
274
|
+
}
|
|
275
|
+
const dialog = detector.detectDialog(typeof frame === 'string' ? (0, frame_1.normalizeFrame)(frame, cliToolId) : frame);
|
|
276
|
+
return { present: dialog !== null, dialog, mode, gated: true };
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The dialog kinds that are a question to the operator, not a permission
|
|
280
|
+
* (Issue #3822): OpenCode V2's question form, read off its own key hints.
|
|
281
|
+
*
|
|
282
|
+
* Not Claude's `ask_user`: Claude classifies by the context rows above the
|
|
283
|
+
* options, which on a permission dialog are the command being approved — a
|
|
284
|
+
* `grep "Ready to submit your answers?"` approval reads `ask_user` (#3748's
|
|
285
|
+
* controls), and it is a permission.
|
|
286
|
+
*/
|
|
287
|
+
exports.AUTO_YES_QUESTION_DIALOG_KINDS = new Set(['question']);
|
|
288
|
+
/**
|
|
289
|
+
* What kind of question to the operator a prompt is, if it is one (Issue
|
|
290
|
+
* #3863):
|
|
291
|
+
*
|
|
292
|
+
* - `'question-form'` — a question form the tool's own dialog rules read
|
|
293
|
+
* ({@link AUTO_YES_QUESTION_DIALOG_KINDS}: OpenCode V2's). Left to a human
|
|
294
|
+
* under every answer mode, as before; only on a gated frame, where those
|
|
295
|
+
* rules ran;
|
|
296
|
+
* - `'picker'` — a picker a question reader read: Claude's AskUserQuestion
|
|
297
|
+
* (the parser's own footer, `Enter to select · … navigate`) or Command
|
|
298
|
+
* Code's question screen (its reader). Both set `isAskUserQuestion`, off the
|
|
299
|
+
* picker's chrome rather than its text. Answered under the `recommended`
|
|
300
|
+
* answer mode, left to a human under `careful`;
|
|
301
|
+
* - null — not a question (a permission, a yes/no, a list).
|
|
302
|
+
*
|
|
303
|
+
* The picker is judged WITHOUT the dialog gate (#3863): the gate's mode
|
|
304
|
+
* (`enforce` / `legacy`, and the `CM_AUTOYES_DIALOG_GATE` kill switch) says
|
|
305
|
+
* whether a frame's numbered list may be answered at all, not whether it is a
|
|
306
|
+
* question, so `legacy` does not turn a question into something Auto-Yes
|
|
307
|
+
* answers under `careful`. Claude's dialog kind `ask_user` is not evidence:
|
|
308
|
+
* Claude classifies by the context rows above the options, which on a
|
|
309
|
+
* permission dialog are the command being approved (#3748).
|
|
310
|
+
*
|
|
311
|
+
* - `'unidentified'` (Issue #3881, the second half: finding 3) — given the
|
|
312
|
+
* tool, a numbered list on copilot or codex
|
|
313
|
+
* ({@link QUESTION_EVIDENCE_UNREAD_TOOLS}) that is neither of the above and
|
|
314
|
+
* whose rows do not read as a permission dialog
|
|
315
|
+
* (`auto-yes-option-effect`, the wording measured on their live captures).
|
|
316
|
+
* Copilot's question (`ask_user`) and codex's `request_user_input` draw the
|
|
317
|
+
* same picker as their menus: copilot calls anything without `do you want
|
|
318
|
+
* to` a `picker`, codex anything with a `?` above it a `permission`, and
|
|
319
|
+
* neither sets `isAskUserQuestion`. So such a list is not known to be a
|
|
320
|
+
* question, nor known not to be one. Left to a human under `careful`;
|
|
321
|
+
* under `recommended` it is answered exactly as before (not as a question).
|
|
322
|
+
*
|
|
323
|
+
* @param promptData - The prompt the tick read
|
|
324
|
+
* @param gate - {@link evaluateAutoYesDialogGate}'s verdict for the same frame, if it ran
|
|
325
|
+
* @param cliToolId - The tool that drew it; omitted, no list is `'unidentified'`
|
|
326
|
+
* (the reading before #3881's second half)
|
|
327
|
+
*/
|
|
328
|
+
function classifyAutoYesQuestion(promptData, gate, cliToolId) {
|
|
329
|
+
if (gate?.gated === true && gate.dialog !== null && exports.AUTO_YES_QUESTION_DIALOG_KINDS.has(gate.dialog.kind)) {
|
|
330
|
+
return 'question-form';
|
|
331
|
+
}
|
|
332
|
+
if (promptData.type !== 'multiple_choice')
|
|
333
|
+
return null;
|
|
334
|
+
if (promptData.isAskUserQuestion === true)
|
|
335
|
+
return 'picker';
|
|
336
|
+
if (cliToolId !== undefined && exports.QUESTION_EVIDENCE_UNREAD_TOOLS.has(cliToolId)
|
|
337
|
+
&& (0, auto_yes_option_effect_1.selectAllowOnceOption)(promptData.options, cliToolId).kind === 'not-a-permission-dialog') {
|
|
338
|
+
return 'unidentified';
|
|
339
|
+
}
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
/** See {@link AutoYesQuestionTreatment}. */
|
|
343
|
+
function autoYesQuestionTreatment(kind, answerMode) {
|
|
344
|
+
if (kind === null)
|
|
345
|
+
return 'base-rules';
|
|
346
|
+
if (kind === 'question-form')
|
|
347
|
+
return 'left-to-human';
|
|
348
|
+
if (answerMode === 'careful')
|
|
349
|
+
return 'left-to-human';
|
|
350
|
+
return kind === 'picker' ? 'recommended-choice' : 'base-rules';
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* The tools whose question screens nothing on the screen tells from their
|
|
354
|
+
* other pickers (Issue #3881, finding 3): copilot's `ask_user`, codex's
|
|
355
|
+
* `request_user_input`. Neither module reads a question's chrome; their dialog
|
|
356
|
+
* kinds are guesses from the words above the options
|
|
357
|
+
* (`tools/copilot/prompt.ts`, `tools/codex/prompt.ts`).
|
|
358
|
+
*/
|
|
359
|
+
exports.QUESTION_EVIDENCE_UNREAD_TOOLS = new Set(['copilot', 'codex']);
|
|
360
|
+
/**
|
|
361
|
+
* Is the prompt a question to the operator rather than a permission, on a
|
|
362
|
+
* GATED frame? (Issue #3822.)
|
|
363
|
+
*
|
|
364
|
+
* The reading #3822 first shipped: a question only where the tool's own rules
|
|
365
|
+
* ran. Since Issue #3863 the poller reads {@link classifyAutoYesQuestion},
|
|
366
|
+
* which judges the picker without the gate (so the kill switch and the
|
|
367
|
+
* `legacy` tools do not change how a question is treated); this stays the
|
|
368
|
+
* gated half of that reading.
|
|
369
|
+
*
|
|
370
|
+
* @param promptData - The prompt the tick read
|
|
371
|
+
* @param gate - {@link evaluateAutoYesDialogGate}'s verdict for the same frame
|
|
372
|
+
*/
|
|
373
|
+
function isAutoYesQuestionPrompt(promptData, gate) {
|
|
374
|
+
return gate.gated && classifyAutoYesQuestion(promptData, gate) !== null;
|
|
375
|
+
}
|
|
248
376
|
/**
|
|
249
377
|
* Does this frame POSITIVELY carry a dialog for the numbered-list candidate the
|
|
250
378
|
* generic parser found on it? (Issue #2457)
|
|
@@ -395,8 +523,9 @@ function assessPromptAnswerability(cliToolId, frame) {
|
|
|
395
523
|
// Issue #3808: a numbered agy screen agy's reader declines (the login-method
|
|
396
524
|
// screen, a permission dialog whose `tab Amend` footer is cut or off the
|
|
397
525
|
// pane) is no prompt — not the generic parser's reading of its `1. / 2.` rows.
|
|
526
|
+
// #3818: by default, so a run with a number missing is declined too.
|
|
398
527
|
const declinedAgyScreen = cliToolId === 'antigravity' && toolDialog === null
|
|
399
|
-
&& (0, dialog_1.
|
|
528
|
+
&& (0, dialog_1.isAntigravityUnansweredNumberedScreen)(cleanOutput);
|
|
400
529
|
const isCommandCodeQuestion = commandCodeQuestion.kind === 'prompt';
|
|
401
530
|
const candidate = (commandCodeQuestion.kind === 'prompt' ? commandCodeQuestion.prompt : null)
|
|
402
531
|
?? toolDialog
|
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Auto-Yes's Enter on a choice screen CommandMate cannot read (Issue #3397).
|
|
4
4
|
*
|
|
5
|
+
* ## Retired (Issue #3821)
|
|
6
|
+
*
|
|
7
|
+
* Nothing sends this Enter any more. The poller leaves every frame the dialog
|
|
8
|
+
* gate refuses to a human (`unclassified-frame`), whatever
|
|
9
|
+
* {@link judgeEnterFallback} would say and whatever
|
|
10
|
+
* {@link AUTO_YES_ENTER_FALLBACK_ENV_VAR} is set to: a bare Enter confirms
|
|
11
|
+
* whatever happens to be selected, and on a screen nothing here can read,
|
|
12
|
+
* nothing here can say what that is. {@link judgeEnterFallback} stays as a
|
|
13
|
+
* reading of the frame only; no sending path calls it. The session epoch the
|
|
14
|
+
* record was keyed on (`./auto-yes-enter-fallback-state`) is still what every
|
|
15
|
+
* send's generation check and the partial-answer record belong to.
|
|
16
|
+
*
|
|
17
|
+
* What follows is how the Enter was decided while it existed.
|
|
18
|
+
*
|
|
5
19
|
* ## The screen
|
|
6
20
|
*
|
|
7
21
|
* `assessPromptAnswerability` refuses some frames that are plainly a choice
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A person's answer through `/prompt-response`, as Auto-Yes's poller sees it
|
|
4
|
+
* (Issue #3821, review 2).
|
|
5
|
+
*
|
|
6
|
+
* Dropping the published decision is not enough to keep the poller's keys off
|
|
7
|
+
* a confirmation a person is answering: a tick already past its checks — the
|
|
8
|
+
* ownership check, a wait inside the send — acts for its generation (#3706),
|
|
9
|
+
* which a manual answer did not touch. So the start of a manual answer
|
|
10
|
+
*
|
|
11
|
+
* - moves the instance's manual-answer sequence on; a tick whose generation
|
|
12
|
+
* was taken under an earlier one is no longer current (`isTickCurrent`) and
|
|
13
|
+
* sends no further key;
|
|
14
|
+
* - holds the instance for {@link MANUAL_ANSWER_HOLD_MS}: a tick that reads a
|
|
15
|
+
* confirmation meanwhile leaves it to the person (`answered-by-human`)
|
|
16
|
+
* instead of answering what they may be answering right now;
|
|
17
|
+
* - drops the published decision.
|
|
18
|
+
*
|
|
19
|
+
* How the answer ENDED decides what happens to an answer the poller holds at
|
|
20
|
+
* that confirmation (Issue #3880, {@link settleManualAnswer}).
|
|
21
|
+
*
|
|
22
|
+
* Auto-Yes itself stays on: past the hold the poller answers again.
|
|
23
|
+
*
|
|
24
|
+
* In-memory and on `globalThis` (the route and the poller are bundled apart
|
|
25
|
+
* under `next dev`).
|
|
26
|
+
*
|
|
27
|
+
* @module lib/polling/auto-yes-manual-answer
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.ANSWERED_BY_HUMAN_DECISION_REASON = exports.MANUAL_ANSWER_HOLD_MS = void 0;
|
|
31
|
+
exports.noteManualAnswerStarted = noteManualAnswerStarted;
|
|
32
|
+
exports.noteManualSendStarting = noteManualSendStarting;
|
|
33
|
+
exports.settleManualAnswer = settleManualAnswer;
|
|
34
|
+
exports.abandonManualSend = abandonManualSend;
|
|
35
|
+
exports.getManualAnswerSeq = getManualAnswerSeq;
|
|
36
|
+
exports.isManualAnswerHolding = isManualAnswerHolding;
|
|
37
|
+
exports.clearManualAnswers = clearManualAnswers;
|
|
38
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
39
|
+
const global_state_1 = require("../global-state");
|
|
40
|
+
const auto_yes_decision_state_1 = require("./auto-yes-decision-state");
|
|
41
|
+
const auto_yes_poller_state_1 = require("./auto-yes-poller-state");
|
|
42
|
+
/** How long a manual answer keeps the poller off the instance's confirmations. */
|
|
43
|
+
exports.MANUAL_ANSWER_HOLD_MS = auto_yes_state_1.DUPLICATE_RETRY_EXPIRY_MS;
|
|
44
|
+
/** The decision reason a tick withholds under while the hold lasts. */
|
|
45
|
+
exports.ANSWERED_BY_HUMAN_DECISION_REASON = 'answered-by-human';
|
|
46
|
+
const marks = (0, global_state_1.getOrInitGlobal)('__autoYesManualAnswers', () => new Map());
|
|
47
|
+
/** A person began answering on this instance (called before the first key or API call). */
|
|
48
|
+
function noteManualAnswerStarted(compositeKey, at = Date.now()) {
|
|
49
|
+
marks.set(compositeKey, { seq: (marks.get(compositeKey)?.seq ?? 0) + 1, at });
|
|
50
|
+
(0, auto_yes_decision_state_1.forgetAutoYesDecision)(compositeKey);
|
|
51
|
+
return { compositeKey, order: (0, auto_yes_poller_state_1.nextSendOrder)(), attempt: null };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The person's keys are about to go out (Issue #3880), at the confirmation
|
|
55
|
+
* `promptData` is — or, when no prompt could be read off the screen (the
|
|
56
|
+
* capture before the send failed), at an unidentified one. Registered as a
|
|
57
|
+
* send in flight, so a screen seen gone, a relaunch, or a worktree going away
|
|
58
|
+
* before it ends keeps its end from recording a hold.
|
|
59
|
+
*/
|
|
60
|
+
function noteManualSendStarting(ticket, promptData) {
|
|
61
|
+
if (ticket.attempt !== null)
|
|
62
|
+
return;
|
|
63
|
+
const screenKey = promptData ? (0, auto_yes_poller_state_1.partialAnswerScreenKey)(promptData) : auto_yes_poller_state_1.UNIDENTIFIED_SCREEN_KEY;
|
|
64
|
+
ticket.attempt = (0, auto_yes_poller_state_1.beginManualSendAttempt)(ticket.compositeKey, screenKey);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A person's answer ended (Issue #3880). Starting one does not touch what
|
|
68
|
+
* Auto-Yes holds — the start only stops the tick under way and holds the
|
|
69
|
+
* poller off for {@link MANUAL_ANSWER_HOLD_MS} — so a manual send that fails
|
|
70
|
+
* cannot leave the confirmation free for Auto-Yes to type at again once that
|
|
71
|
+
* hold passes. Everything is matched to THIS answer (`ticket`), not to the
|
|
72
|
+
* instance's key alone:
|
|
73
|
+
*
|
|
74
|
+
* - `answered` / `not-sent`: the hold recorded before this answer began is
|
|
75
|
+
* released (the person answered, or saw the screen and nothing of theirs is
|
|
76
|
+
* on it). One recorded since — by another person's send that may be on the
|
|
77
|
+
* pane, or a tick's — stays.
|
|
78
|
+
* - `may-be-on-pane`: the send records a hold at its screen (unidentified
|
|
79
|
+
* when none was read), as Auto-Yes's own does: only for the session epoch it
|
|
80
|
+
* went to, never over a hold of a send registered after it, and not at all when
|
|
81
|
+
* the screen it typed at was seen gone since. And every tick under way stops
|
|
82
|
+
* (the manual-answer sequence moves on): one that read no hold before its
|
|
83
|
+
* last wait does not type over this one.
|
|
84
|
+
*
|
|
85
|
+
* An end nobody reports (a send that threw saying nothing of its keys, a
|
|
86
|
+
* verdict the agent's API gave no receipt for — both only abandoned; a
|
|
87
|
+
* structured verdict `/prompt-response` refused) leaves the hold as it was. A verdict delivered over the
|
|
88
|
+
* agent's API reports its receipt like a send (Issue #3925).
|
|
89
|
+
*/
|
|
90
|
+
function settleManualAnswer(ticket, outcome, at = Date.now()) {
|
|
91
|
+
const { compositeKey, attempt } = ticket;
|
|
92
|
+
if (outcome !== 'may-be-on-pane') {
|
|
93
|
+
if (attempt !== null)
|
|
94
|
+
(0, auto_yes_poller_state_1.settleSendAttempt)(attempt, false, at);
|
|
95
|
+
(0, auto_yes_poller_state_1.releasePartialAnswerToHuman)(compositeKey, ticket.order);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (attempt !== null)
|
|
99
|
+
(0, auto_yes_poller_state_1.settleSendAttempt)(attempt, true, at);
|
|
100
|
+
const mark = marks.get(compositeKey);
|
|
101
|
+
if (mark !== undefined)
|
|
102
|
+
marks.set(compositeKey, { ...mark, seq: mark.seq + 1 });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A person's send ended in a way that says nothing of its keys (Issue #3880):
|
|
106
|
+
* it is no longer in flight, and the hold is left as it was.
|
|
107
|
+
*/
|
|
108
|
+
function abandonManualSend(ticket) {
|
|
109
|
+
if (ticket.attempt !== null)
|
|
110
|
+
(0, auto_yes_poller_state_1.settleSendAttempt)(ticket.attempt, false);
|
|
111
|
+
}
|
|
112
|
+
/** The instance's manual-answer sequence (0 until a person answers there). */
|
|
113
|
+
function getManualAnswerSeq(compositeKey) {
|
|
114
|
+
return marks.get(compositeKey)?.seq ?? 0;
|
|
115
|
+
}
|
|
116
|
+
/** Whether a manual answer began on this instance less than {@link MANUAL_ANSWER_HOLD_MS} ago. */
|
|
117
|
+
function isManualAnswerHolding(compositeKey, now = Date.now()) {
|
|
118
|
+
const mark = marks.get(compositeKey);
|
|
119
|
+
return mark !== undefined && now - mark.at < exports.MANUAL_ANSWER_HOLD_MS;
|
|
120
|
+
}
|
|
121
|
+
/** Drop every mark: a test seam. The sequences only ever move forward otherwise. */
|
|
122
|
+
function clearManualAnswers() {
|
|
123
|
+
marks.clear();
|
|
124
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auto-Yes option effects - what picking one row of a permission dialog does
|
|
4
|
+
* (Issue #3822).
|
|
5
|
+
*
|
|
6
|
+
* Until #3822 the resolver picked the default row, or row 1, of any numbered
|
|
7
|
+
* dialog. On every tool measured here the rows of a permission dialog do not
|
|
8
|
+
* mean the same thing: one allows this call only, the others save a rule
|
|
9
|
+
* (`don't ask again`, `always allow`, `Persist to settings.json`), switch the
|
|
10
|
+
* permission mode for the session (`allow all edits`, `Full Access`), or deny.
|
|
11
|
+
* Where the cursor rests is the tool's choice, not a promise that the row is
|
|
12
|
+
* the narrow one — agy keeps the `>` where the operator left it — so Auto-Yes
|
|
13
|
+
* answers only the row that reads as "allow this call once", by its number,
|
|
14
|
+
* and nothing when no single row reads that way.
|
|
15
|
+
*
|
|
16
|
+
* ## Where the wording comes from
|
|
17
|
+
*
|
|
18
|
+
* Every rule below is a row read off a live capture in the repository, named
|
|
19
|
+
* next to it. Nothing is inferred from another tool's wording. A tool without
|
|
20
|
+
* a table (gemini, vibe-local, opencode, opencode-v2) keeps the pre-#3822
|
|
21
|
+
* reading: opencode's and OpenCode V2's permission strips are unnumbered and
|
|
22
|
+
* never reach the resolver as a prompt (they are answered through the hook,
|
|
23
|
+
* whose `allow` is `allowOnce`), and gemini / vibe-local have no captured
|
|
24
|
+
* permission dialog to read.
|
|
25
|
+
*
|
|
26
|
+
* ## When a dialog counts as a permission dialog
|
|
27
|
+
*
|
|
28
|
+
* When at least one of its rows reads as an allow — this call once, a saved
|
|
29
|
+
* rule, or a mode change. A `No` row alone does not make one: a launch dialog
|
|
30
|
+
* (`Yes, continue` / `No, quit`, `Yes, I trust this folder` / `No, exit`) is
|
|
31
|
+
* judged where it always was (the launch-dialog branch, the contract's deny
|
|
32
|
+
* patterns). A numbered list none of whose rows the tool's table recognises (a
|
|
33
|
+
* question's options, a dialog whose wording was never captured) keeps the
|
|
34
|
+
* pre-#3822 default-row reading — this module only narrows what a recognised
|
|
35
|
+
* permission dialog may be answered with, it does not decide which screens are
|
|
36
|
+
* dialogs.
|
|
37
|
+
*
|
|
38
|
+
* Client-safe: no server-only imports (the resolver is bundled into
|
|
39
|
+
* `hooks/useAutoYes.ts`).
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.OPTION_EFFECT_TOOLS = void 0;
|
|
43
|
+
exports.readOptionEffect = readOptionEffect;
|
|
44
|
+
exports.selectAllowOnceOption = selectAllowOnceOption;
|
|
45
|
+
/** `don't` with a straight or a typographic apostrophe. */
|
|
46
|
+
const DONT = "don['’]t";
|
|
47
|
+
/** `No`, alone or followed by its explanation (`No, cancel`, `No, and tell … differently`). */
|
|
48
|
+
const DENY_NO = ['deny', /^No(?:,|$)/];
|
|
49
|
+
/**
|
|
50
|
+
* Each tool's rows, first match wins. A rule is anchored at the start of the
|
|
51
|
+
* label and reads only the words that say what the row does, so the command or
|
|
52
|
+
* path a row quotes after them does not matter.
|
|
53
|
+
*/
|
|
54
|
+
const OPTION_EFFECT_RULES = {
|
|
55
|
+
// tests/fixtures/canary/permission-dialog.raw.txt, permission-hook-no-decision.raw.txt,
|
|
56
|
+
// tests/unit/lib/detection/fixtures/claude-live-1708/bash-approval-taskpanel.txt,
|
|
57
|
+
// tests/fixtures/tui-frame-footer-2776/claude-2.1.278-bash-approval-task-panel.txt
|
|
58
|
+
claude: [
|
|
59
|
+
['allow-once', /^Yes$/],
|
|
60
|
+
['allow-persistent', /^Yes, and always allow\b/],
|
|
61
|
+
['mode-change', /^Yes, allow all edits\b/],
|
|
62
|
+
['mode-change', /^Yes, and switch to\b/],
|
|
63
|
+
DENY_NO,
|
|
64
|
+
],
|
|
65
|
+
// tests/unit/lib/detection/fixtures/codex-live-1628/approval-{run-command,apply-patch}.txt,
|
|
66
|
+
// tests/fixtures/codex-dialogs-0157/approval.txt, codex-hooks-review-0148.ts,
|
|
67
|
+
// tests/fixtures/codex-browser-use-2609/approval-form-browser-use.txt (`Allow` /
|
|
68
|
+
// `Always allow` / `Cancel`, each followed by its description), and
|
|
69
|
+
// tests/fixtures/codex-live-2310/dialog-permissions-picker.txt (the approval modes)
|
|
70
|
+
codex: [
|
|
71
|
+
['allow-once', /^Yes$/],
|
|
72
|
+
['allow-once', /^Yes, proceed\b/],
|
|
73
|
+
['allow-once', /^Allow(?:\s{2,}|$)/],
|
|
74
|
+
['allow-persistent', new RegExp(`^Yes, and ${DONT} ask again\\b`)],
|
|
75
|
+
['allow-persistent', /^Always allow\b/],
|
|
76
|
+
['mode-change', /^Ask for approval\b/],
|
|
77
|
+
['mode-change', /^Approve for me\b/],
|
|
78
|
+
['mode-change', /^Full Access\b/],
|
|
79
|
+
['deny', /^Cancel\b/],
|
|
80
|
+
DENY_NO,
|
|
81
|
+
],
|
|
82
|
+
// tests/fixtures/antigravity-live-2364/dialog-bash-*.txt, dialog-create-file.txt,
|
|
83
|
+
// tests/fixtures/strict-respond-3812/permission-run-command.txt. `always allow in
|
|
84
|
+
// this conversation` is as much a saved rule as `(Persist to settings.json)`:
|
|
85
|
+
// neither is this call only.
|
|
86
|
+
antigravity: [
|
|
87
|
+
['allow-once', /^Yes$/],
|
|
88
|
+
['allow-once', /^Yes, run command$/],
|
|
89
|
+
['allow-once', /^Yes, allow creation$/],
|
|
90
|
+
['allow-persistent', /^Yes, and always allow\b/],
|
|
91
|
+
DENY_NO,
|
|
92
|
+
],
|
|
93
|
+
// tests/fixtures/command-code-live-2250/dialog-shell-command.txt, dialog-create-file.txt,
|
|
94
|
+
// dialog-kill-task-1490.txt, tests/fixtures/command-code-plan-review-2763/after-approve.txt
|
|
95
|
+
'command-code': [
|
|
96
|
+
['allow-once', /^Yes$/],
|
|
97
|
+
['allow-persistent', new RegExp(`^Yes, ${DONT} ask again\\b`)],
|
|
98
|
+
['mode-change', /^Yes, allow all edits\b/],
|
|
99
|
+
DENY_NO,
|
|
100
|
+
],
|
|
101
|
+
// tests/unit/lib/detection/fixtures/copilot-live-1885/permission-dialog.txt and
|
|
102
|
+
// copilot-picker-1895/picker-permissions.txt (`Manual ✓` / `Allow all`, the modes)
|
|
103
|
+
copilot: [
|
|
104
|
+
['allow-once', /^Yes$/],
|
|
105
|
+
['allow-persistent', new RegExp(`^Yes, and ${DONT} ask again\\b`)],
|
|
106
|
+
['mode-change', /^Manual\b/],
|
|
107
|
+
['mode-change', /^Allow all\b/],
|
|
108
|
+
DENY_NO,
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
/** Every table, for a caller that does not say which tool drew the dialog. */
|
|
112
|
+
const ANY_TOOL_RULES = Object.values(OPTION_EFFECT_RULES).flat();
|
|
113
|
+
/** The tools whose permission rows are read (the others keep the pre-#3822 reading). */
|
|
114
|
+
exports.OPTION_EFFECT_TOOLS = Object.keys(OPTION_EFFECT_RULES);
|
|
115
|
+
function rulesFor(cliToolId) {
|
|
116
|
+
if (cliToolId === undefined)
|
|
117
|
+
return ANY_TOOL_RULES;
|
|
118
|
+
return OPTION_EFFECT_RULES[cliToolId] ?? null;
|
|
119
|
+
}
|
|
120
|
+
function readWith(rules, label) {
|
|
121
|
+
const text = label.trim();
|
|
122
|
+
for (const [effect, pattern] of rules) {
|
|
123
|
+
if (pattern.test(text))
|
|
124
|
+
return effect;
|
|
125
|
+
}
|
|
126
|
+
return 'unknown';
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* What choosing the row labelled `label` does on `cliToolId`'s dialog.
|
|
130
|
+
*
|
|
131
|
+
* @param cliToolId - The tool that drew the dialog. Omitted, every tool's
|
|
132
|
+
* table is read (the first rule that matches decides); a tool with no table
|
|
133
|
+
* reads every row as `unknown`.
|
|
134
|
+
*/
|
|
135
|
+
function readOptionEffect(label, cliToolId) {
|
|
136
|
+
const rules = rulesFor(cliToolId);
|
|
137
|
+
return rules === null ? 'unknown' : readWith(rules, label);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Pick the one "allow this call once" row of a permission dialog.
|
|
141
|
+
*
|
|
142
|
+
* @param options - The dialog's rows, as parsed
|
|
143
|
+
* @param cliToolId - The tool that drew it; see {@link readOptionEffect}
|
|
144
|
+
*/
|
|
145
|
+
function selectAllowOnceOption(options, cliToolId) {
|
|
146
|
+
const rules = rulesFor(cliToolId);
|
|
147
|
+
if (rules === null)
|
|
148
|
+
return { kind: 'not-a-permission-dialog' };
|
|
149
|
+
const effects = options.map((option) => readWith(rules, option.label));
|
|
150
|
+
if (!effects.some((effect) => effect === 'allow-once' || effect === 'allow-persistent' || effect === 'mode-change')) {
|
|
151
|
+
return { kind: 'not-a-permission-dialog' };
|
|
152
|
+
}
|
|
153
|
+
const once = options.filter((_option, index) => effects[index] === 'allow-once');
|
|
154
|
+
if (once.length === 1)
|
|
155
|
+
return { kind: 'allow-once', option: once[0] };
|
|
156
|
+
return { kind: 'unidentified', allowOnceCount: once.length };
|
|
157
|
+
}
|
|
@@ -95,11 +95,14 @@ function readPolicy(worktreeId, cliToolId, instanceId) {
|
|
|
95
95
|
* the resolver reads {@link AUTO_YES_POLICY_UNKNOWN} as withholding (Issue #3822).
|
|
96
96
|
*
|
|
97
97
|
* @param instanceId - Agent instance id (defaults to the primary, i.e. cliToolId)
|
|
98
|
+
* @param options - `fresh: true` reads the task past the cache (and refreshes
|
|
99
|
+
* it): the poller's last look before a key (Issue #3822), where a contract
|
|
100
|
+
* switched or a deny pattern added within the TTL must already count
|
|
98
101
|
* @returns The contract's autoYes block, null when no contract governs this
|
|
99
102
|
* instance, or {@link AUTO_YES_POLICY_UNKNOWN} when the lookup failed
|
|
100
103
|
*/
|
|
101
|
-
function getSessionAutoYesPolicy(worktreeId, cliToolId, instanceId) {
|
|
102
|
-
return lookupEntry(worktreeId, cliToolId, instanceId).policy;
|
|
104
|
+
function getSessionAutoYesPolicy(worktreeId, cliToolId, instanceId, options) {
|
|
105
|
+
return lookupEntry(worktreeId, cliToolId, instanceId, options?.fresh === true).policy;
|
|
103
106
|
}
|
|
104
107
|
/**
|
|
105
108
|
* The policy and the id of the task it came from, read in ONE lookup (Issue
|
|
@@ -162,17 +165,20 @@ function getSessionContractPolicySummary(worktreeId, cliToolId, instanceId) {
|
|
|
162
165
|
denyPatternCount: policy.denyPatterns.length,
|
|
163
166
|
};
|
|
164
167
|
}
|
|
165
|
-
function lookupEntry(worktreeId, cliToolId, instanceId) {
|
|
168
|
+
function lookupEntry(worktreeId, cliToolId, instanceId, fresh = false) {
|
|
166
169
|
const resolvedInstanceId = instanceId ?? cliToolId;
|
|
167
170
|
const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, resolvedInstanceId);
|
|
168
171
|
const now = Date.now();
|
|
169
172
|
const cached = policyCache.get(key);
|
|
170
|
-
if (cached && cached.expiresAt > now) {
|
|
173
|
+
if (!fresh && cached && cached.expiresAt > now) {
|
|
171
174
|
return cached;
|
|
172
175
|
}
|
|
173
176
|
const { policy, taskId } = readPolicy(worktreeId, cliToolId, resolvedInstanceId);
|
|
174
177
|
if ((0, auto_yes_resolver_1.isAutoYesPolicyUnknown)(policy)) {
|
|
175
|
-
// Issue #3822: not cached, so the next lookup reads again.
|
|
178
|
+
// Issue #3822: not cached, so the next lookup reads again. A fresh read
|
|
179
|
+
// that failed also drops what was cached: it is no longer known to hold.
|
|
180
|
+
if (fresh)
|
|
181
|
+
policyCache.delete(key);
|
|
176
182
|
return { policy, taskId, expiresAt: now };
|
|
177
183
|
}
|
|
178
184
|
if (policyCache.size >= MAX_CACHE_ENTRIES) {
|
|
@@ -13,9 +13,15 @@
|
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.capturePollerFrame = capturePollerFrame;
|
|
15
15
|
exports.captureAndCleanOutput = captureAndCleanOutput;
|
|
16
|
+
const async_hooks_1 = require("async_hooks");
|
|
16
17
|
const cli_session_1 = require("../session/cli-session");
|
|
18
|
+
const global_state_1 = require("../global-state");
|
|
17
19
|
const cli_patterns_1 = require("../detection/cli-patterns");
|
|
18
20
|
const auto_yes_config_1 = require("../../config/auto-yes-config");
|
|
21
|
+
/** Where `cli-session` reports whether the capture it runs inside cut the pane's top (Issue #3881 N4). */
|
|
22
|
+
function headCutSink() {
|
|
23
|
+
return (0, global_state_1.getOrInitGlobal)('__captureHeadCutSink', () => new async_hooks_1.AsyncLocalStorage());
|
|
24
|
+
}
|
|
19
25
|
/**
|
|
20
26
|
* Capture tmux session output once, keeping both spellings (Issue #2522).
|
|
21
27
|
*
|
|
@@ -28,8 +34,15 @@ const auto_yes_config_1 = require("../../config/auto-yes-config");
|
|
|
28
34
|
*/
|
|
29
35
|
async function capturePollerFrame(worktreeId, cliToolId, captureLines, instanceId) {
|
|
30
36
|
const lines = captureLines ?? auto_yes_config_1.FULL_CAPTURE_LINES;
|
|
31
|
-
const
|
|
32
|
-
|
|
37
|
+
const reported = {};
|
|
38
|
+
const output = await headCutSink().run((headCut) => {
|
|
39
|
+
reported.headCut = headCut;
|
|
40
|
+
}, () => (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, lines, instanceId));
|
|
41
|
+
return {
|
|
42
|
+
raw: output,
|
|
43
|
+
clean: (0, cli_patterns_1.stripBoxDrawing)((0, cli_patterns_1.stripAnsi)(output)),
|
|
44
|
+
...(reported.headCut !== undefined ? { headCut: reported.headCut } : {}),
|
|
45
|
+
};
|
|
33
46
|
}
|
|
34
47
|
/**
|
|
35
48
|
* Capture tmux session output and strip ANSI escape codes.
|
|
@@ -22,9 +22,13 @@ exports.isPollerCurrent = isPollerCurrent;
|
|
|
22
22
|
exports.isTickCurrent = isTickCurrent;
|
|
23
23
|
exports.isSameSession = isSameSession;
|
|
24
24
|
exports.isDuplicatePrompt = isDuplicatePrompt;
|
|
25
|
+
exports.reserveDuplicateRetry = reserveDuplicateRetry;
|
|
26
|
+
exports.isDuplicateRetryOf = isDuplicateRetryOf;
|
|
27
|
+
exports.releaseDuplicateRetry = releaseDuplicateRetry;
|
|
25
28
|
const auto_yes_enter_fallback_1 = require("./auto-yes-enter-fallback");
|
|
26
29
|
const auto_yes_state_1 = require("../auto-yes-state");
|
|
27
30
|
const global_state_1 = require("../global-state");
|
|
31
|
+
const auto_yes_manual_answer_1 = require("./auto-yes-manual-answer");
|
|
28
32
|
/** In-memory storage for poller states (globalThis for hot reload persistence) */
|
|
29
33
|
exports.autoYesPollerStates = (0, global_state_1.getOrInitGlobal)('__autoYesPollerStates', () => new Map());
|
|
30
34
|
// =============================================================================
|
|
@@ -113,7 +117,8 @@ function isPollerCurrent(generation) {
|
|
|
113
117
|
}
|
|
114
118
|
/**
|
|
115
119
|
* May the tick still act: its poller, its grant (the same enable, not expired)
|
|
116
|
-
* and its session (no relaunch since) are all still the ones it started under
|
|
120
|
+
* and its session (no relaunch since) are all still the ones it started under,
|
|
121
|
+
* and no person has begun answering on the instance since (Issue #3821).
|
|
117
122
|
* Checked after capture, after each wait before a key, and inside the send.
|
|
118
123
|
*/
|
|
119
124
|
function isTickCurrent(generation) {
|
|
@@ -124,6 +129,10 @@ function isTickCurrent(generation) {
|
|
|
124
129
|
const grant = (0, auto_yes_state_1.getAutoYesState)(generation.worktreeId, generation.cliToolId, generation.instanceId);
|
|
125
130
|
if (grant !== generation.grant || !grant.enabled)
|
|
126
131
|
return false;
|
|
132
|
+
// Issue #3821: a person began answering on this instance since the tick started
|
|
133
|
+
// (Issue #3880: or a person's send ended with keys maybe on the pane, holding it).
|
|
134
|
+
if ((generation.manualAnswerSeq ?? 0) !== (0, auto_yes_manual_answer_1.getManualAnswerSeq)(generation.compositeKey))
|
|
135
|
+
return false;
|
|
127
136
|
return isSameSession(generation);
|
|
128
137
|
}
|
|
129
138
|
/**
|
|
@@ -149,3 +158,35 @@ function isDuplicatePrompt(pollerState, promptKey) {
|
|
|
149
158
|
return false;
|
|
150
159
|
return (Date.now() - pollerState.lastAnsweredAt) < auto_yes_state_1.DUPLICATE_RETRY_EXPIRY_MS;
|
|
151
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Issue #3791 (review N1): publish that the duplicate guard held back the
|
|
163
|
+
* prompt on screen on this tick ({@link isDuplicatePrompt} was true), for the
|
|
164
|
+
* push gate to hold the wait until the guard's retry. Only the guard's own
|
|
165
|
+
* verdict sets it: an answer alone (`lastAnsweredAt`) says nothing about the
|
|
166
|
+
* screen now up — another prompt, or a failed tick, is not held by the guard.
|
|
167
|
+
*/
|
|
168
|
+
function reserveDuplicateRetry(pollerState, promptKey, now) {
|
|
169
|
+
if (pollerState.lastAnsweredAt === null)
|
|
170
|
+
return;
|
|
171
|
+
pollerState.duplicateRetryReservation = { promptKey, answeredAt: pollerState.lastAnsweredAt, observedAt: now };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Issue #3791 (review N3): is `promptKey` the prompt the guard reserved, its
|
|
175
|
+
* guard since expired — the tick about to send the retry the reservation
|
|
176
|
+
* waited for? Its reservation is then kept until that send is settled.
|
|
177
|
+
*/
|
|
178
|
+
function isDuplicateRetryOf(pollerState, promptKey) {
|
|
179
|
+
const reservation = pollerState.duplicateRetryReservation;
|
|
180
|
+
return (reservation !== undefined &&
|
|
181
|
+
reservation !== null &&
|
|
182
|
+
reservation.promptKey === promptKey &&
|
|
183
|
+
reservation.answeredAt === pollerState.lastAnsweredAt);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Issue #3791 (review N1): the tick did not hold the prompt back with the
|
|
187
|
+
* guard — another screen, no prompt, a failed tick, no session — so the wait
|
|
188
|
+
* is no longer the guard's retry to wait for.
|
|
189
|
+
*/
|
|
190
|
+
function releaseDuplicateRetry(pollerState) {
|
|
191
|
+
pollerState.duplicateRetryReservation = null;
|
|
192
|
+
}
|