commandmate 0.21.5 → 0.22.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 +240 -233
- package/.next/app-path-routes-manifest.json +29 -28
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- 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/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route.js +1 -1
- package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route.js +1 -1
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/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/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.js +2 -2
- package/.next/server/app/api/fs/browse/route.js.nft.json +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 +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +1 -1
- 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 -0
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -0
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -0
- 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/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.js.nft.json +1 -1
- package/.next/server/app/api/push/vapid/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/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/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.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/validate-path/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/todos/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]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +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]/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]/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]/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]/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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +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 +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route.js +2 -6
- package/.next/server/app/api/worktrees/[id]/tasks/route.js.nft.json +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 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/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/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/chat/page_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_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +9 -9
- 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 +29 -28
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1356.js +4 -0
- package/.next/server/chunks/1841.js +1 -0
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2816.js +1 -1
- package/.next/server/chunks/3022.js +1 -0
- package/.next/server/chunks/3736.js +1 -1
- package/.next/server/chunks/5959.js +5 -4
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6274.js +8 -12
- package/.next/server/chunks/6919.js +1 -0
- package/.next/server/chunks/7685.js +1 -1
- package/.next/server/chunks/8856.js +1 -1
- package/.next/server/chunks/9067.js +1 -1
- package/.next/server/chunks/9373.js +8 -0
- package/.next/server/chunks/9687.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/server/src/middleware.js.map +1 -1
- package/.next/static/b69eWhjC1rRrFTa-g3lMS/_buildManifest.js +1 -0
- package/.next/static/chunks/{6488-572dbfd9986e8a92.js → 6488-2ad4f67779f8d00a.js} +1 -1
- package/.next/static/chunks/app/api/app/update/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/app/update-check/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/conversation/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/current-output/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/messages/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/session/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/start/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/terminal/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/assistant/tools/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/status/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/external-apps/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/fs/browse/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/fs/recent-paths/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/hooks/agent-event/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/hooks/claude-done/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/hooks/permission-request/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/metrics/vibe/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/ollama/models/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/push/subscriptions/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/push/vapid/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/excluded/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/restore/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/scan/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/sync/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/repositories/validate-path/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/sidebar/group-order/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/skills/[id]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/skills/installations/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/skills/operations/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/skills/reindex/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/skills/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/slash-commands/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/templates/[id]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/templates/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/todos/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/proxy/[...path]/route-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/layout-973ec48531555712.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-70704fe257e0cccc.js +1 -0
- package/.next/trace +12 -12
- package/.next/types/app/api/hooks/permission-request/route.ts +347 -0
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +27 -1
- package/dist/cli/commands/respond.d.ts.map +1 -1
- package/dist/cli/commands/respond.js +9 -3
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +35 -0
- package/dist/cli/commands/wait.d.ts +4 -1
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +109 -2
- package/dist/cli/docs/agent-operations.d.ts +1 -1
- package/dist/cli/docs/agent-operations.d.ts.map +1 -1
- package/dist/cli/docs/agent-operations.js +39 -0
- package/dist/cli/types/api-responses.d.ts +69 -4
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/types/index.d.ts +6 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +105 -1
- package/dist/server/src/lib/detection/unclassified-frame-tracker.js +96 -0
- package/dist/server/src/lib/env.js +27 -1
- package/dist/server/src/lib/hooks/agent-event-types.js +131 -0
- package/dist/server/src/lib/hooks/ask-user-question-payload.js +156 -0
- package/dist/server/src/lib/hooks/hook-settings-generator.js +411 -0
- package/dist/server/src/lib/hooks/permission-request-payload.js +144 -0
- package/dist/server/src/lib/polling/auto-yes-resolver.js +25 -10
- package/dist/server/src/lib/polling/auto-yes-suppression-state.js +2 -1
- package/dist/server/src/lib/session/agent-event-state.js +612 -11
- package/dist/server/src/lib/session/ask-user-question-prompt.js +295 -0
- package/dist/server/src/lib/session/claude-session.js +41 -2
- package/dist/server/src/lib/session/current-output-builder.js +375 -8
- package/dist/server/src/lib/session/prompt-waiting-composition.js +178 -0
- package/dist/server/src/lib/session/prompt-waiting-guard.js +147 -0
- package/dist/server/src/lib/session/send-user-message.js +35 -0
- package/dist/server/src/lib/session/status-mapping.js +121 -0
- package/dist/server/src/lib/session/structured-prompt.js +109 -0
- package/dist/server/src/types/models.js +30 -0
- package/package.json +3 -2
- package/scripts/hooks/cmate-agent-event.sh +44 -3
- package/.next/server/chunks/1355.js +0 -1
- package/.next/server/chunks/1598.js +0 -4
- package/.next/server/chunks/2366.js +0 -1
- package/.next/static/-A6IRK1c_KvFlxiDrsyVc/_buildManifest.js +0 -1
- package/.next/static/chunks/app/api/app/update/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/app/update-check/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/conversation/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/current-output/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/messages/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/session/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/start/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/terminal/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/assistant/tools/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/auth/login/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/auth/status/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/status/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/external-apps/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/fs/browse/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/fs/recent-paths/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/hooks/agent-event/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/hooks/claude-done/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/metrics/vibe/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/ollama/models/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/push/subscriptions/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/push/vapid/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/excluded/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/restore/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/scan/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/sync/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/repositories/validate-path/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/sidebar/group-order/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/skills/[id]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/skills/installations/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/skills/operations/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/skills/reindex/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/skills/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/slash-commands/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/templates/[id]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/templates/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/todos/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/proxy/[...path]/route-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/layout-be21650964d61b1d.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-de42fed52de80834.js +0 -1
- /package/.next/static/{-A6IRK1c_KvFlxiDrsyVc → b69eWhjC1rRrFTa-g3lMS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The `--settings` payload CommandMate injects when it starts a Claude session
|
|
4
|
+
* (Issue #1722).
|
|
5
|
+
*
|
|
6
|
+
* Issue #1549 gave the server a receiver for structured agent events and a
|
|
7
|
+
* relay script to post them, but left the wiring to the operator: the events
|
|
8
|
+
* only existed on machines where somebody had edited `~/.claude/settings.json`
|
|
9
|
+
* by hand. This module closes that gap by handing Claude its own hook config at
|
|
10
|
+
* launch, per (worktreeId, instanceId).
|
|
11
|
+
*
|
|
12
|
+
* Four facts from the live verification in Issue #1721
|
|
13
|
+
* (`docs/design/agent-hooks-live-verification.md`) shape everything below. They
|
|
14
|
+
* are not in Claude Code's documentation, and three of the four fail *silently*
|
|
15
|
+
* when ignored:
|
|
16
|
+
*
|
|
17
|
+
* - **`SessionStart` silently ignores `type: "http"`** (D1). The debug log says
|
|
18
|
+
* `HTTP hooks are not supported for SessionStart`; stdout and the TUI say
|
|
19
|
+
* nothing at all. So `SessionStart` — and only `SessionStart` — goes through
|
|
20
|
+
* a `type: "command"` relay.
|
|
21
|
+
* - **`$VAR` in `headers` expands only for names listed in `allowedEnvVars`**
|
|
22
|
+
* (D7). A bearer header without the matching entry authenticates as the
|
|
23
|
+
* literal string `$CM_AUTH_TOKEN` and 401s.
|
|
24
|
+
* - **`--settings` hooks are concatenated with the user's own, not substituted
|
|
25
|
+
* for them**, and `~/.claude/settings.json` is left byte-identical. Manual
|
|
26
|
+
* Stop hooks from #1549 keep firing; see `agent-event-state`'s dedup for
|
|
27
|
+
* what happens when both arrive.
|
|
28
|
+
* - **Every hook failure is fail-open.** A refused connection or a timeout
|
|
29
|
+
* costs the event, never the session.
|
|
30
|
+
*
|
|
31
|
+
* The generated file is written rather than passed inline. `--settings` does
|
|
32
|
+
* accept a JSON string (D2), but the launch command travels to the CLI through
|
|
33
|
+
* `tmux send-keys` as a single line, and a ~1 KB argument of braces, quotes and
|
|
34
|
+
* a deliberately unexpanded `$CM_AUTH_TOKEN` is a worse thing to put on that
|
|
35
|
+
* line than a path.
|
|
36
|
+
*
|
|
37
|
+
* @module lib/hooks/hook-settings-generator
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.PERMISSION_DENY_RULES = exports.TOOL_USE_MATCHER = exports.NOTIFICATION_MATCHER = exports.AUTH_TOKEN_ENV_VAR = exports.PERMISSION_REQUEST_TIMEOUT_SECONDS = exports.HOOK_TIMEOUT_SECONDS = exports.PERMISSION_REQUEST_PATH = exports.AGENT_EVENT_PATH = void 0;
|
|
41
|
+
exports.isHookInjectionEnabled = isHookInjectionEnabled;
|
|
42
|
+
exports.isAuthTokenExpected = isAuthTokenExpected;
|
|
43
|
+
exports.getHookSettingsDirectory = getHookSettingsDirectory;
|
|
44
|
+
exports.resolveTargetInstanceId = resolveTargetInstanceId;
|
|
45
|
+
exports.getHookSettingsPath = getHookSettingsPath;
|
|
46
|
+
exports.buildAgentEventUrl = buildAgentEventUrl;
|
|
47
|
+
exports.buildPermissionRequestUrl = buildPermissionRequestUrl;
|
|
48
|
+
exports.resolveRelayScriptPath = resolveRelayScriptPath;
|
|
49
|
+
exports.shellQuote = shellQuote;
|
|
50
|
+
exports.buildSessionStartCommand = buildSessionStartCommand;
|
|
51
|
+
exports.buildAgentHookSettings = buildAgentHookSettings;
|
|
52
|
+
exports.writeAgentHookSettings = writeAgentHookSettings;
|
|
53
|
+
exports.buildClaudeLaunchCommand = buildClaudeLaunchCommand;
|
|
54
|
+
const crypto_1 = require("crypto");
|
|
55
|
+
const fs_1 = require("fs");
|
|
56
|
+
const os_1 = require("os");
|
|
57
|
+
const path_1 = require("path");
|
|
58
|
+
const env_1 = require("../../lib/env");
|
|
59
|
+
const types_1 = require("../../lib/cli-tools/types");
|
|
60
|
+
const permission_request_payload_1 = require("../../lib/hooks/permission-request-payload");
|
|
61
|
+
const logger_1 = require("../../lib/logger");
|
|
62
|
+
const logger = (0, logger_1.createLogger)('lib/hooks/hook-settings-generator');
|
|
63
|
+
/** Loopback: the agent runs on the machine the server runs on, whatever CM_BIND says. */
|
|
64
|
+
const HOOK_HOST = '127.0.0.1';
|
|
65
|
+
/** Receiver path. Mirrors `src/app/api/hooks/agent-event/route.ts`. */
|
|
66
|
+
exports.AGENT_EVENT_PATH = '/api/hooks/agent-event';
|
|
67
|
+
/**
|
|
68
|
+
* Auto-Yes v2 receiver (Issue #1724). Mirrors
|
|
69
|
+
* `src/app/api/hooks/permission-request/route.ts`.
|
|
70
|
+
*
|
|
71
|
+
* Separate from {@link AGENT_EVENT_PATH} because the two have opposite
|
|
72
|
+
* contracts: that one is fire-and-forget, this one blocks the agent until it
|
|
73
|
+
* answers and its body is obeyed.
|
|
74
|
+
*/
|
|
75
|
+
exports.PERMISSION_REQUEST_PATH = '/api/hooks/permission-request';
|
|
76
|
+
/**
|
|
77
|
+
* Seconds a hook may block the agent.
|
|
78
|
+
*
|
|
79
|
+
* The receiver answers 202 without doing any work of its own, so this only ever
|
|
80
|
+
* matters when the server is wedged or gone. It is well under the 30 s Claude
|
|
81
|
+
* defaults to for `UserPromptSubmit`, which is the one event whose hook the
|
|
82
|
+
* human is sitting and waiting for.
|
|
83
|
+
*/
|
|
84
|
+
exports.HOOK_TIMEOUT_SECONDS = 5;
|
|
85
|
+
/**
|
|
86
|
+
* Seconds `PermissionRequest` may block the agent (Issue #1724).
|
|
87
|
+
*
|
|
88
|
+
* Claude's default for an `http` hook is 600 s, and there is no `async` for
|
|
89
|
+
* http (D4/§5.3.6), so this number is how long a wedged server delays every
|
|
90
|
+
* approval dialog on the machine. The receiver decides from in-memory Auto-Yes
|
|
91
|
+
* state and a TTL-cached policy, so the budget is generous by orders of
|
|
92
|
+
* magnitude; it is small because the failure mode it bounds is the server being
|
|
93
|
+
* gone, and a hook failure is fail-open — the dialog appears, five seconds late.
|
|
94
|
+
*/
|
|
95
|
+
exports.PERMISSION_REQUEST_TIMEOUT_SECONDS = 5;
|
|
96
|
+
/**
|
|
97
|
+
* Environment variable carrying the bearer token, per
|
|
98
|
+
* `docs/user-guide/agent-event-hooks.md`. Must appear in `allowedEnvVars` for
|
|
99
|
+
* the `$`-reference in `headers` to expand at all (D7).
|
|
100
|
+
*/
|
|
101
|
+
exports.AUTH_TOKEN_ENV_VAR = 'CM_AUTH_TOKEN';
|
|
102
|
+
/**
|
|
103
|
+
* `Notification` matcher.
|
|
104
|
+
*
|
|
105
|
+
* Matched against the payload's `notification_type`, not its human-facing
|
|
106
|
+
* `message` (D3). A matcher that names nothing is not an error — it simply
|
|
107
|
+
* fires zero times — so a typo here is another silent failure.
|
|
108
|
+
*/
|
|
109
|
+
exports.NOTIFICATION_MATCHER = 'permission_prompt|idle_prompt';
|
|
110
|
+
/**
|
|
111
|
+
* `PreToolUse` / `PostToolUse` matcher (Issue #1726).
|
|
112
|
+
*
|
|
113
|
+
* Matched against `tool_name`. Deliberately the single tool whose input this
|
|
114
|
+
* server has a use for: `AskUserQuestion` is the only call whose arguments *are*
|
|
115
|
+
* the thing the human has to answer, and a matcher covering every tool would
|
|
116
|
+
* post two payloads per tool call for nothing — on a hot loop that is two
|
|
117
|
+
* requests per `Read`, each of which blocks the agent for as long as the
|
|
118
|
+
* receiver takes.
|
|
119
|
+
*/
|
|
120
|
+
exports.TOOL_USE_MATCHER = permission_request_payload_1.ASK_USER_QUESTION_TOOL;
|
|
121
|
+
/**
|
|
122
|
+
* Bash spellings this server refuses to let an agent run (Issue #1739).
|
|
123
|
+
*
|
|
124
|
+
* On 2026-08-06 a delegated worker restarted its own isolated server with
|
|
125
|
+
* `pkill -f "node dist/server/server.js"`. `-f` matches the whole command line,
|
|
126
|
+
* so it also hit the operator's production server on port 3000 and the global
|
|
127
|
+
* instance on 60301 — two processes the worker did not know existed and could
|
|
128
|
+
* not see. Nothing was recovered until a human rebuilt and restarted by hand.
|
|
129
|
+
*
|
|
130
|
+
* Three earlier layers were in place and none of them stopped it:
|
|
131
|
+
*
|
|
132
|
+
* - The delegation contract said "do not touch port 3000". That is a rule about
|
|
133
|
+
* the *target*, and the worker's subjective target was its own server; the
|
|
134
|
+
* blast radius is exactly what a pattern kill hides from its caller.
|
|
135
|
+
* - A permission dialog did appear — and Auto-Yes approved it. Auto-Yes v2
|
|
136
|
+
* answers the `PermissionRequest` hook (#1724), so anything that reaches a
|
|
137
|
+
* dialog reaches its verdict.
|
|
138
|
+
* - The contract's `autoYes.denyPatterns` would have escalated to a human, but
|
|
139
|
+
* escalation is only as good as the pattern somebody remembered to write.
|
|
140
|
+
*
|
|
141
|
+
* `permissions.deny` sits *underneath* all three: a denied rule is refused
|
|
142
|
+
* before a dialog exists, so there is no `PermissionRequest` for Auto-Yes to
|
|
143
|
+
* answer and no wording in a contract for a worker to reinterpret. Verified
|
|
144
|
+
* live in `docs/design/agent-hooks-permission-deny-verification.md`.
|
|
145
|
+
*
|
|
146
|
+
* The list is deliberately about the *means*, not the target: every entry names
|
|
147
|
+
* a way of selecting processes by pattern rather than by identity. Stopping a
|
|
148
|
+
* process you started yourself stays available through its pid — `kill
|
|
149
|
+
* "$(cat pidfile)"` matches nothing here — which is the idiom
|
|
150
|
+
* `docs/user-guide/agent-event-hooks.md` §0.7 tells operators to use.
|
|
151
|
+
*
|
|
152
|
+
* `kill -9` is on the list even though it takes a pid, because `kill -9 -1`
|
|
153
|
+
* signals every process the user owns and `kill -9 -<pgid>` a whole group; the
|
|
154
|
+
* default `kill` (SIGTERM) is untouched, so the graceful spelling of the same
|
|
155
|
+
* intent is the one that survives.
|
|
156
|
+
*/
|
|
157
|
+
exports.PERMISSION_DENY_RULES = [
|
|
158
|
+
'Bash(pkill:*)',
|
|
159
|
+
'Bash(killall:*)',
|
|
160
|
+
'Bash(kill -9:*)',
|
|
161
|
+
];
|
|
162
|
+
/** Relay script shipped with the package (`files: ["scripts/hooks/"]`). */
|
|
163
|
+
const RELAY_SCRIPT_RELATIVE_PATH = (0, path_1.join)('scripts', 'hooks', 'cmate-agent-event.sh');
|
|
164
|
+
/**
|
|
165
|
+
* Whether to inject at all. `CM_AGENT_HOOKS_INJECT=0` is the rollback switch:
|
|
166
|
+
* sessions start exactly as they did before this Issue.
|
|
167
|
+
*/
|
|
168
|
+
function isHookInjectionEnabled() {
|
|
169
|
+
return process.env.CM_AGENT_HOOKS_INJECT !== '0';
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether the agent's environment is expected to carry a bearer token.
|
|
173
|
+
*
|
|
174
|
+
* The server only ever sees `CM_AUTH_TOKEN_HASH`, so it cannot read the token
|
|
175
|
+
* itself — but a configured hash means every request to this receiver needs one,
|
|
176
|
+
* and the agent inherits the server's environment through tmux.
|
|
177
|
+
*/
|
|
178
|
+
function isAuthTokenExpected() {
|
|
179
|
+
return Boolean(process.env[exports.AUTH_TOKEN_ENV_VAR] || process.env.CM_AUTH_TOKEN_HASH);
|
|
180
|
+
}
|
|
181
|
+
/** Directory the generated settings files live in. */
|
|
182
|
+
function getHookSettingsDirectory(options = {}) {
|
|
183
|
+
if (options.directory)
|
|
184
|
+
return options.directory;
|
|
185
|
+
const override = process.env.CM_AGENT_HOOKS_DIR;
|
|
186
|
+
if (override)
|
|
187
|
+
return override;
|
|
188
|
+
return (0, path_1.join)((0, os_1.homedir)(), '.commandmate', 'hooks');
|
|
189
|
+
}
|
|
190
|
+
/** The instance this settings file speaks for; primary when unspecified. */
|
|
191
|
+
function resolveTargetInstanceId(target) {
|
|
192
|
+
const cliToolId = target.cliToolId ?? 'claude';
|
|
193
|
+
const instanceId = target.instanceId ?? cliToolId;
|
|
194
|
+
return instanceId;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Absolute path of the settings file for one (worktreeId, instanceId).
|
|
198
|
+
*
|
|
199
|
+
* The readable part is sanitised because it becomes a filename; the hash of the
|
|
200
|
+
* raw pair is appended so sanitisation cannot collapse two distinct instances
|
|
201
|
+
* onto one file. Deterministic: the same pair always names the same file, so a
|
|
202
|
+
* restart overwrites rather than accumulates.
|
|
203
|
+
*/
|
|
204
|
+
function getHookSettingsPath(target, options = {}) {
|
|
205
|
+
const cliToolId = target.cliToolId ?? 'claude';
|
|
206
|
+
const instanceId = resolveTargetInstanceId(target);
|
|
207
|
+
const slug = `${cliToolId}-${target.worktreeId}-${instanceId}`.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
208
|
+
const digest = (0, crypto_1.createHash)('sha256')
|
|
209
|
+
.update(JSON.stringify([cliToolId, target.worktreeId, instanceId]))
|
|
210
|
+
.digest('hex')
|
|
211
|
+
.slice(0, 12);
|
|
212
|
+
return (0, path_1.join)(getHookSettingsDirectory(options), `${slug.slice(0, 80)}-${digest}.json`);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Receiver URL with the correlation keys baked in.
|
|
216
|
+
*
|
|
217
|
+
* This is the whole of the instance correlation. `cwd` cannot do the job —
|
|
218
|
+
* `claude` and `claude-2` in the same worktree report the identical directory,
|
|
219
|
+
* which is why `route.ts` had to hard-code the primary instance — and
|
|
220
|
+
* `session_id` cannot either, because `/clear` issues a new one mid-session
|
|
221
|
+
* while the instance stays the same (D7 §1.1). The URL is fixed at injection
|
|
222
|
+
* time and outlives both.
|
|
223
|
+
*/
|
|
224
|
+
function buildAgentEventUrl(target, options = {}) {
|
|
225
|
+
return buildReceiverUrl(exports.AGENT_EVENT_PATH, target, options);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Auto-Yes v2 receiver URL, with the same correlation keys baked in
|
|
229
|
+
* (Issue #1724).
|
|
230
|
+
*
|
|
231
|
+
* They matter more here than on the event path: a verdict applied to the wrong
|
|
232
|
+
* instance is an approval the operator never asked for, and `cwd` cannot tell
|
|
233
|
+
* `claude` from `claude-2`.
|
|
234
|
+
*/
|
|
235
|
+
function buildPermissionRequestUrl(target, options = {}) {
|
|
236
|
+
return buildReceiverUrl(exports.PERMISSION_REQUEST_PATH, target, options);
|
|
237
|
+
}
|
|
238
|
+
function buildReceiverUrl(path, target, options) {
|
|
239
|
+
const cliToolId = target.cliToolId ?? 'claude';
|
|
240
|
+
const port = options.port ?? (0, env_1.getServerPort)();
|
|
241
|
+
const params = new URLSearchParams({
|
|
242
|
+
tool: cliToolId,
|
|
243
|
+
worktreeId: target.worktreeId,
|
|
244
|
+
instanceId: resolveTargetInstanceId(target),
|
|
245
|
+
});
|
|
246
|
+
return `http://${HOOK_HOST}:${port}${path}?${params.toString()}`;
|
|
247
|
+
}
|
|
248
|
+
/** Absolute path of the shipped relay script, or null when it is not on disk. */
|
|
249
|
+
function resolveRelayScriptPath() {
|
|
250
|
+
const candidate = (0, path_1.resolve)(process.cwd(), RELAY_SCRIPT_RELATIVE_PATH);
|
|
251
|
+
return (0, fs_1.existsSync)(candidate) ? candidate : null;
|
|
252
|
+
}
|
|
253
|
+
/** Wrap a value so a POSIX shell reproduces it byte-for-byte. */
|
|
254
|
+
function shellQuote(value) {
|
|
255
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
256
|
+
}
|
|
257
|
+
function buildHttpHandler(url, withAuthHeader, timeout = exports.HOOK_TIMEOUT_SECONDS) {
|
|
258
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
259
|
+
const handler = {
|
|
260
|
+
type: 'http',
|
|
261
|
+
url,
|
|
262
|
+
headers,
|
|
263
|
+
timeout,
|
|
264
|
+
};
|
|
265
|
+
if (withAuthHeader) {
|
|
266
|
+
headers.Authorization = `Bearer $${exports.AUTH_TOKEN_ENV_VAR}`;
|
|
267
|
+
// D7: without this the header is sent as the literal `$CM_AUTH_TOKEN`.
|
|
268
|
+
handler.allowedEnvVars = [exports.AUTH_TOKEN_ENV_VAR];
|
|
269
|
+
}
|
|
270
|
+
return handler;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* The `SessionStart` relay command (D1: http is skipped in silence there).
|
|
274
|
+
*
|
|
275
|
+
* Prefers the shipped script, which already knows how to read Claude's stdin
|
|
276
|
+
* payload and how to fail open. When the package layout puts it out of reach,
|
|
277
|
+
* an inline `curl` posts the same payload to the same URL — the receiver reads
|
|
278
|
+
* Claude's native shape as well as the script's.
|
|
279
|
+
*/
|
|
280
|
+
function buildSessionStartCommand(target, options = {}) {
|
|
281
|
+
const url = buildAgentEventUrl(target, options);
|
|
282
|
+
const withAuthHeader = options.withAuthHeader ?? isAuthTokenExpected();
|
|
283
|
+
const relay = options.relayScriptPath === undefined ? resolveRelayScriptPath() : options.relayScriptPath;
|
|
284
|
+
if (relay) {
|
|
285
|
+
return [
|
|
286
|
+
shellQuote(relay),
|
|
287
|
+
'--tool',
|
|
288
|
+
shellQuote(target.cliToolId ?? 'claude'),
|
|
289
|
+
'--event',
|
|
290
|
+
'session_start',
|
|
291
|
+
'--worktree-id',
|
|
292
|
+
shellQuote(target.worktreeId),
|
|
293
|
+
'--instance-id',
|
|
294
|
+
shellQuote(resolveTargetInstanceId(target)),
|
|
295
|
+
'--url',
|
|
296
|
+
shellQuote(url),
|
|
297
|
+
'--stdin-json',
|
|
298
|
+
].join(' ');
|
|
299
|
+
}
|
|
300
|
+
const auth = withAuthHeader ? ` -H "Authorization: Bearer $${exports.AUTH_TOKEN_ENV_VAR}"` : '';
|
|
301
|
+
return (`curl -sS -m ${exports.HOOK_TIMEOUT_SECONDS} -X POST ` +
|
|
302
|
+
`-H 'Content-Type: application/json'${auth} ` +
|
|
303
|
+
`--data-binary @- ${shellQuote(url)} >/dev/null 2>&1 || true`);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* The settings object handed to `claude --settings`.
|
|
307
|
+
*
|
|
308
|
+
* Deterministic for a given (worktreeId, instanceId, port): callers rely on
|
|
309
|
+
* regenerating it producing the same file.
|
|
310
|
+
*
|
|
311
|
+
* `PermissionRequest` is registered unconditionally (Issue #1724) — it is *not*
|
|
312
|
+
* gated on Auto-Yes being enabled. The receiver answers no-decision whenever
|
|
313
|
+
* Auto-Yes is off, and no-decision is measured to be indistinguishable from
|
|
314
|
+
* having no hook at all (#1721 D5), so a toggle here would only add a second
|
|
315
|
+
* place for the feature to be silently off. It also has to be: Auto-Yes is
|
|
316
|
+
* enabled mid-session, and a hook registered at launch is the only kind this
|
|
317
|
+
* session will have.
|
|
318
|
+
*
|
|
319
|
+
* `PreToolUse` / `PostToolUse` are registered for `AskUserQuestion` alone (Issue
|
|
320
|
+
* #1726), and they post to the *event* receiver rather than the permission one:
|
|
321
|
+
* they are observations, not verdicts. The distinction is not academic — a
|
|
322
|
+
* `PreToolUse` response body can block or redirect a tool call, and answering
|
|
323
|
+
* one for a question the human has not seen yet is the last thing this feature
|
|
324
|
+
* wants to be able to do. The event route answers 202 with a fixed body and
|
|
325
|
+
* cannot decide anything.
|
|
326
|
+
*
|
|
327
|
+
* `permissions.deny` rides along in the same file (Issue #1739). It is not a
|
|
328
|
+
* hook and nothing here delivers it — Claude enforces it itself, before any
|
|
329
|
+
* `PermissionRequest` exists — which is precisely why it belongs next to the
|
|
330
|
+
* hook that Auto-Yes answers rather than in the contract layer above it.
|
|
331
|
+
*/
|
|
332
|
+
function buildAgentHookSettings(target, options = {}) {
|
|
333
|
+
const url = buildAgentEventUrl(target, options);
|
|
334
|
+
const withAuthHeader = options.withAuthHeader ?? isAuthTokenExpected();
|
|
335
|
+
const http = () => buildHttpHandler(url, withAuthHeader);
|
|
336
|
+
const permissionHttp = () => buildHttpHandler(buildPermissionRequestUrl(target, options), withAuthHeader, exports.PERMISSION_REQUEST_TIMEOUT_SECONDS);
|
|
337
|
+
return {
|
|
338
|
+
hooks: {
|
|
339
|
+
SessionStart: [
|
|
340
|
+
{
|
|
341
|
+
hooks: [
|
|
342
|
+
{
|
|
343
|
+
type: 'command',
|
|
344
|
+
command: buildSessionStartCommand(target, options),
|
|
345
|
+
timeout: exports.HOOK_TIMEOUT_SECONDS,
|
|
346
|
+
},
|
|
347
|
+
],
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
UserPromptSubmit: [{ hooks: [http()] }],
|
|
351
|
+
Stop: [{ hooks: [http()] }],
|
|
352
|
+
Notification: [{ matcher: exports.NOTIFICATION_MATCHER, hooks: [http()] }],
|
|
353
|
+
SessionEnd: [{ hooks: [http()] }],
|
|
354
|
+
// Issue #1726. The event receiver, not the permission one: observation.
|
|
355
|
+
PreToolUse: [{ matcher: exports.TOOL_USE_MATCHER, hooks: [http()] }],
|
|
356
|
+
PostToolUse: [{ matcher: exports.TOOL_USE_MATCHER, hooks: [http()] }],
|
|
357
|
+
// Issue #1724. Points at its own receiver, not the event one.
|
|
358
|
+
PermissionRequest: [{ hooks: [permissionHttp()] }],
|
|
359
|
+
},
|
|
360
|
+
// Issue #1739. Enforced by Claude below the hook layer: no dialog, so no
|
|
361
|
+
// PermissionRequest, so nothing for Auto-Yes to approve.
|
|
362
|
+
permissions: { deny: [...exports.PERMISSION_DENY_RULES] },
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Write the settings file and return its absolute path.
|
|
367
|
+
*
|
|
368
|
+
* The directory is created 0700 and the file 0600: it names the endpoint and
|
|
369
|
+
* the instance of every session on the machine, which is nobody else's business
|
|
370
|
+
* even though it holds no secret.
|
|
371
|
+
*/
|
|
372
|
+
function writeAgentHookSettings(target, options = {}) {
|
|
373
|
+
const settingsPath = getHookSettingsPath(target, options);
|
|
374
|
+
(0, fs_1.mkdirSync)(getHookSettingsDirectory(options), { recursive: true, mode: 0o700 });
|
|
375
|
+
(0, fs_1.writeFileSync)(settingsPath, `${JSON.stringify(buildAgentHookSettings(target, options), null, 2)}\n`, { mode: 0o600 });
|
|
376
|
+
return settingsPath;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* The command that launches Claude for this instance.
|
|
380
|
+
*
|
|
381
|
+
* Never throws. Injection is an enhancement to a session that has to start
|
|
382
|
+
* regardless, so a directory that cannot be written costs the structured
|
|
383
|
+
* events and nothing else — the same fail-open posture the hooks themselves
|
|
384
|
+
* have (§1.1 of the verification report).
|
|
385
|
+
*
|
|
386
|
+
* @param claudePath - Resolved Claude CLI path
|
|
387
|
+
* @returns `<claude> --settings <file>`, or bare `<claude>` when injection is
|
|
388
|
+
* off or could not be prepared
|
|
389
|
+
*/
|
|
390
|
+
function buildClaudeLaunchCommand(claudePath, target, options = {}) {
|
|
391
|
+
if (!isHookInjectionEnabled()) {
|
|
392
|
+
return claudePath;
|
|
393
|
+
}
|
|
394
|
+
if (!(0, types_1.isValidInstanceId)(resolveTargetInstanceId(target))) {
|
|
395
|
+
// The instance id is about to be a URL parameter the receiver re-validates;
|
|
396
|
+
// a value that would be rejected there is not worth injecting.
|
|
397
|
+
logger.warn('hook-settings-invalid-instance-id', { worktreeId: target.worktreeId });
|
|
398
|
+
return claudePath;
|
|
399
|
+
}
|
|
400
|
+
try {
|
|
401
|
+
const settingsPath = writeAgentHookSettings(target, options);
|
|
402
|
+
return `${shellQuote(claudePath)} --settings ${shellQuote(settingsPath)}`;
|
|
403
|
+
}
|
|
404
|
+
catch (error) {
|
|
405
|
+
logger.warn('hook-settings-write-failed', {
|
|
406
|
+
worktreeId: target.worktreeId,
|
|
407
|
+
error: error instanceof Error ? error.message : String(error),
|
|
408
|
+
});
|
|
409
|
+
return claudePath;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Reading Claude Code's `PermissionRequest` payload (Issue #1724).
|
|
4
|
+
*
|
|
5
|
+
* The shape here is taken from a real session, not from the documentation:
|
|
6
|
+
* `tests/fixtures/hooks/claude/permission-request.json` and
|
|
7
|
+
* `permission-request-ask-user-question.json`, captured by the Issue #1721
|
|
8
|
+
* spike. Two documented fields do not exist in practice (D2 of
|
|
9
|
+
* `docs/design/agent-hooks-live-verification.md`):
|
|
10
|
+
*
|
|
11
|
+
* - **`tool_use_id` is absent.** Nothing here may key off it. Correlation with
|
|
12
|
+
* `PreToolUse` is `prompt_id` + `tool_name` + `tool_input`.
|
|
13
|
+
* - **`permission_requirements` is absent**; `permission_suggestions`
|
|
14
|
+
* (`addRules` candidates) appears instead. It is carried through for the
|
|
15
|
+
* audit trail and is never a decision input — it is Claude's *suggestion*,
|
|
16
|
+
* which is exactly the thing the adjudicator is supposed to judge.
|
|
17
|
+
*
|
|
18
|
+
* Parsing is strict on purpose. Anything this module cannot vouch for becomes
|
|
19
|
+
* `null`, and the caller turns `null` into a no-decision — the fail-safe side,
|
|
20
|
+
* because the alternative to a dialog is executing a command.
|
|
21
|
+
*
|
|
22
|
+
* @module lib/hooks/permission-request-payload
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.MAX_TOOL_NAME_LENGTH = exports.ASK_USER_QUESTION_TOOL = exports.PERMISSION_REQUEST_EVENT_NAME = void 0;
|
|
26
|
+
exports.parsePermissionRequestPayload = parsePermissionRequestPayload;
|
|
27
|
+
exports.collectToolInputMatchTexts = collectToolInputMatchTexts;
|
|
28
|
+
/** `hook_event_name` this receiver accepts. Anything else is not ours to judge. */
|
|
29
|
+
exports.PERMISSION_REQUEST_EVENT_NAME = 'PermissionRequest';
|
|
30
|
+
/**
|
|
31
|
+
* The tool whose permission request is never adjudicated (Issue #1726 owns it).
|
|
32
|
+
*
|
|
33
|
+
* `AskUserQuestion` raises a `PermissionRequest` like any other tool, but the
|
|
34
|
+
* spike measured that **returning `allow` still shows the picker** (§5.6). So an
|
|
35
|
+
* allow here buys nothing and an allow is not an answer to a question — the two
|
|
36
|
+
* reasons point the same way.
|
|
37
|
+
*/
|
|
38
|
+
exports.ASK_USER_QUESTION_TOOL = 'AskUserQuestion';
|
|
39
|
+
/** Bound on `tool_name`; it is a Claude-side identifier, logged and stored. */
|
|
40
|
+
exports.MAX_TOOL_NAME_LENGTH = 128;
|
|
41
|
+
function readString(source, key) {
|
|
42
|
+
const value = source[key];
|
|
43
|
+
return typeof value === 'string' && value !== '' ? value : null;
|
|
44
|
+
}
|
|
45
|
+
function isPlainObject(value) {
|
|
46
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse a `PermissionRequest` body.
|
|
50
|
+
*
|
|
51
|
+
* @param body - Whatever was posted to the receiver
|
|
52
|
+
* @returns The payload, or null when it is not a `PermissionRequest` this
|
|
53
|
+
* server recognises — which the caller must treat as "no decision".
|
|
54
|
+
*/
|
|
55
|
+
function parsePermissionRequestPayload(body) {
|
|
56
|
+
if (!isPlainObject(body))
|
|
57
|
+
return null;
|
|
58
|
+
if (body.hook_event_name !== exports.PERMISSION_REQUEST_EVENT_NAME)
|
|
59
|
+
return null;
|
|
60
|
+
const toolName = readString(body, 'tool_name');
|
|
61
|
+
if (!toolName || toolName.length > exports.MAX_TOOL_NAME_LENGTH)
|
|
62
|
+
return null;
|
|
63
|
+
// An absent or non-object `tool_input` means there is nothing to judge the
|
|
64
|
+
// deny patterns against, so the request cannot be adjudicated safely.
|
|
65
|
+
if (!isPlainObject(body.tool_input))
|
|
66
|
+
return null;
|
|
67
|
+
return {
|
|
68
|
+
toolName,
|
|
69
|
+
toolInput: body.tool_input,
|
|
70
|
+
promptId: readString(body, 'prompt_id'),
|
|
71
|
+
sessionId: readString(body, 'session_id'),
|
|
72
|
+
permissionMode: readString(body, 'permission_mode'),
|
|
73
|
+
permissionSuggestions: Array.isArray(body.permission_suggestions)
|
|
74
|
+
? body.permission_suggestions
|
|
75
|
+
: null,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The arguments of each tool that carry what is actually being asked for.
|
|
80
|
+
*
|
|
81
|
+
* "Primary arguments" per the Issue: `Bash` is judged on its command line, a
|
|
82
|
+
* file tool on its path. Bulk payloads (`Write.content`, `Edit.new_string`) are
|
|
83
|
+
* deliberately excluded — a deny pattern is a statement about the *action*, and
|
|
84
|
+
* matching it against a file body would suppress an edit for quoting the very
|
|
85
|
+
* string the contract is trying to keep out of the shell.
|
|
86
|
+
*
|
|
87
|
+
* `Bash.description` is included: it is model-authored prose about the same
|
|
88
|
+
* command, so including it can only ever suppress more, never less.
|
|
89
|
+
*/
|
|
90
|
+
const PRIMARY_TOOL_INPUT_KEYS = {
|
|
91
|
+
Bash: ['command', 'description'],
|
|
92
|
+
BashOutput: ['bash_id'],
|
|
93
|
+
KillShell: ['shell_id'],
|
|
94
|
+
Read: ['file_path'],
|
|
95
|
+
Write: ['file_path'],
|
|
96
|
+
Edit: ['file_path'],
|
|
97
|
+
NotebookEdit: ['notebook_path'],
|
|
98
|
+
Glob: ['pattern', 'path'],
|
|
99
|
+
Grep: ['pattern', 'path'],
|
|
100
|
+
WebFetch: ['url', 'prompt'],
|
|
101
|
+
WebSearch: ['query'],
|
|
102
|
+
SlashCommand: ['command'],
|
|
103
|
+
Task: ['description', 'subagent_type', 'prompt'],
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Every string a deny pattern is matched against for one request.
|
|
107
|
+
*
|
|
108
|
+
* **This is the whole of the matching surface, and it comes from a single
|
|
109
|
+
* request's `tool_input`.** Issue #1699 is the reason that sentence is worth
|
|
110
|
+
* writing down: the screen-based path used to match deny patterns against
|
|
111
|
+
* `instructionText`, a scrollback window, so an `rm -rf` a human had approved
|
|
112
|
+
* several turns earlier stayed on the pane and went on matching — suppressing
|
|
113
|
+
* every later approval, including edits with nothing to do with it, until the
|
|
114
|
+
* line scrolled off. A worker sat silent for an hour. Nothing on the pane, and
|
|
115
|
+
* nothing from any earlier request, can reach this function.
|
|
116
|
+
*
|
|
117
|
+
* Unknown tools fall back to the serialised input rather than to nothing:
|
|
118
|
+
* over-matching costs a dialog, under-matching costs the protection a contract
|
|
119
|
+
* asked for. The same fallback covers a known tool whose primary arguments are
|
|
120
|
+
* missing or non-string, so a Claude-side shape change cannot silently empty
|
|
121
|
+
* the surface.
|
|
122
|
+
*
|
|
123
|
+
* @param toolName - `tool_name` from the payload
|
|
124
|
+
* @param toolInput - `tool_input` from the payload
|
|
125
|
+
* @returns Texts to match, never empty for a non-empty input
|
|
126
|
+
*/
|
|
127
|
+
function collectToolInputMatchTexts(toolName, toolInput) {
|
|
128
|
+
const keys = PRIMARY_TOOL_INPUT_KEYS[toolName];
|
|
129
|
+
if (keys) {
|
|
130
|
+
const texts = keys
|
|
131
|
+
.map(key => toolInput[key])
|
|
132
|
+
.filter((value) => typeof value === 'string' && value !== '');
|
|
133
|
+
if (texts.length > 0)
|
|
134
|
+
return texts;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
return [JSON.stringify(toolInput) ?? ''];
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Circular or otherwise unserialisable input: judged on its keys alone, so
|
|
141
|
+
// the caller still gets a non-empty surface instead of a silent allow.
|
|
142
|
+
return [Object.keys(toolInput).join(' ')];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
22
|
exports.MAX_DENY_MATCH_TEXT_LENGTH = exports.MAX_DENY_PATTERN_LENGTH = void 0;
|
|
23
|
+
exports.evaluatePolicyAgainstTexts = evaluatePolicyAgainstTexts;
|
|
23
24
|
exports.resolveAutoAnswerWithPolicy = resolveAutoAnswerWithPolicy;
|
|
24
25
|
exports.resolveAutoAnswer = resolveAutoAnswer;
|
|
25
26
|
const auto_yes_config_1 = require("../../config/auto-yes-config");
|
|
@@ -85,7 +86,7 @@ function collectDenyMatchTexts(promptData) {
|
|
|
85
86
|
else {
|
|
86
87
|
texts.push(...promptData.options);
|
|
87
88
|
}
|
|
88
|
-
return texts
|
|
89
|
+
return texts;
|
|
89
90
|
}
|
|
90
91
|
/**
|
|
91
92
|
* Test the prompt against every deny pattern.
|
|
@@ -95,11 +96,11 @@ function collectDenyMatchTexts(promptData) {
|
|
|
95
96
|
* same ReDoS defence the stop-pattern path uses. A pattern that fails screening
|
|
96
97
|
* — or whose execution throws — is reported as `unusable`, not skipped.
|
|
97
98
|
*/
|
|
98
|
-
function evaluateDenyPatterns(
|
|
99
|
+
function evaluateDenyPatterns(rawTexts, patterns) {
|
|
99
100
|
if (patterns.length === 0) {
|
|
100
101
|
return { outcome: 'no-match' };
|
|
101
102
|
}
|
|
102
|
-
const texts =
|
|
103
|
+
const texts = rawTexts.map(text => text.length > exports.MAX_DENY_MATCH_TEXT_LENGTH ? text.slice(0, exports.MAX_DENY_MATCH_TEXT_LENGTH) : text);
|
|
103
104
|
for (const pattern of patterns) {
|
|
104
105
|
if (pattern.length > exports.MAX_DENY_PATTERN_LENGTH || !(0, auto_yes_config_1.validateStopPattern)(pattern).valid) {
|
|
105
106
|
return { outcome: 'unusable', pattern };
|
|
@@ -118,21 +119,33 @@ function evaluateDenyPatterns(promptData, patterns) {
|
|
|
118
119
|
return { outcome: 'no-match' };
|
|
119
120
|
}
|
|
120
121
|
/**
|
|
121
|
-
* Decide whether the policy forbids answering
|
|
122
|
+
* Decide whether the policy forbids answering, given the prompt type and the
|
|
123
|
+
* exact texts the deny patterns are to be judged against.
|
|
124
|
+
*
|
|
125
|
+
* Split out of {@link evaluatePolicy} for Issue #1724: the `PermissionRequest`
|
|
126
|
+
* hook adjudicates a structured tool call rather than a screen-scraped prompt,
|
|
127
|
+
* so it has no {@link PromptData} to pass — but it must reach *the same verdict*
|
|
128
|
+
* the screen path would. Two implementations of this ordering would be two
|
|
129
|
+
* chances for the hook to be quietly more permissive than the poller, and the
|
|
130
|
+
* hook's verdict is executed without a dialog.
|
|
122
131
|
*
|
|
123
132
|
* Deny patterns are honoured even when `mode` is null: a contract that lists
|
|
124
133
|
* them has stated a policy, and a listed pattern that quietly did nothing is the
|
|
125
134
|
* worst failure a contract can have. `mode` null with no deny patterns — what
|
|
126
135
|
* the parser produces for a contract with no `autoYes` block — reaches none of
|
|
127
136
|
* these branches and leaves behaviour identical.
|
|
137
|
+
*
|
|
138
|
+
* @param promptType - How the prompt would be classified on screen
|
|
139
|
+
* @param denyMatchTexts - The only strings deny patterns are matched against
|
|
140
|
+
* @param policy - Contract policy; null/undefined permits everything
|
|
128
141
|
*/
|
|
129
|
-
function
|
|
142
|
+
function evaluatePolicyAgainstTexts(promptType, denyMatchTexts, policy) {
|
|
130
143
|
if (!policy)
|
|
131
144
|
return null;
|
|
132
145
|
if (policy.mode === 'off') {
|
|
133
146
|
return { reason: 'mode-off' };
|
|
134
147
|
}
|
|
135
|
-
const deny = evaluateDenyPatterns(
|
|
148
|
+
const deny = evaluateDenyPatterns(denyMatchTexts, policy.denyPatterns);
|
|
136
149
|
if (deny.outcome === 'match') {
|
|
137
150
|
return { reason: 'deny-pattern', pattern: deny.pattern };
|
|
138
151
|
}
|
|
@@ -140,15 +153,17 @@ function evaluatePolicy(promptData, policy) {
|
|
|
140
153
|
return { reason: 'deny-pattern-unusable', pattern: deny.pattern };
|
|
141
154
|
}
|
|
142
155
|
if (policy.mode === 'safe') {
|
|
143
|
-
return
|
|
156
|
+
return promptType === 'yes_no' ? null : { reason: 'type-not-allowed' };
|
|
144
157
|
}
|
|
145
158
|
if (policy.mode === 'allow-listed') {
|
|
146
|
-
return policy.allowPromptTypes.includes(
|
|
147
|
-
? null
|
|
148
|
-
: { reason: 'type-not-allowed' };
|
|
159
|
+
return policy.allowPromptTypes.includes(promptType) ? null : { reason: 'type-not-allowed' };
|
|
149
160
|
}
|
|
150
161
|
return null;
|
|
151
162
|
}
|
|
163
|
+
/** {@link evaluatePolicyAgainstTexts} over a detected on-screen prompt. */
|
|
164
|
+
function evaluatePolicy(promptData, policy) {
|
|
165
|
+
return evaluatePolicyAgainstTexts(promptData.type, collectDenyMatchTexts(promptData), policy);
|
|
166
|
+
}
|
|
152
167
|
/**
|
|
153
168
|
* Resolve the automatic answer, reporting whether a policy withheld it.
|
|
154
169
|
*
|
|
@@ -28,7 +28,8 @@ exports.getLastPolicySuppression = getLastPolicySuppression;
|
|
|
28
28
|
exports.clearPolicySuppressions = clearPolicySuppressions;
|
|
29
29
|
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
30
30
|
/** compositeKey -> the most recent policy suppression for that session. */
|
|
31
|
-
const lastPolicySuppressions =
|
|
31
|
+
const lastPolicySuppressions = globalThis.__autoYesPolicySuppressions ??
|
|
32
|
+
(globalThis.__autoYesPolicySuppressions = new Map());
|
|
32
33
|
/**
|
|
33
34
|
* Record that the policy withheld an answer for `instanceId`'s current prompt.
|
|
34
35
|
*
|