commandmate 0.22.1 → 0.23.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 +86 -86
- package/.next/app-path-routes-manifest.json +17 -17
- 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/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 +3 -3
- 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.js +1 -1
- package/.next/server/app/api/daily-summary/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/daily-summary/status/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/external-apps/route.js.nft.json +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 +1 -1
- 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.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route.js.nft.json +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 -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.js +1 -1
- package/.next/server/app/api/metrics/vibe/route.js.nft.json +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/subscriptions/route.js +1 -1
- package/.next/server/app/api/push/subscriptions/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/[id]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/excluded/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/skills/installations/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route.js +1 -1
- package/.next/server/app/api/skills/operations/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route.js +1 -1
- package/.next/server/app/api/skills/reindex/route.js.nft.json +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.js +1 -4
- package/.next/server/app/api/tasks/[taskId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route.js +1 -4
- package/.next/server/app/api/tasks/[taskId]/route.js.nft.json +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route.js +1 -1
- package/.next/server/app/api/templates/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route.js +1 -1
- package/.next/server/app/api/templates/route.js.nft.json +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/todos/route.js +1 -1
- package/.next/server/app/api/todos/route.js.nft.json +1 -1
- package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route.js.nft.json +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route.js +1 -1
- package/.next/server/app/api/verification/runs/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +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 +2 -2
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/marp-render/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +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.js +2 -2
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +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.js +3 -3
- package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +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 -2
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +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 -4
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +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.js +1 -1
- package/.next/server/app/proxy/[...path]/route.js.nft.json +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.js +1 -1
- 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 +2 -2
- 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.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +17 -17
- package/.next/server/chunks/1029.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2546.js +1 -1
- package/.next/server/chunks/3241.js +1 -0
- package/.next/server/chunks/3417.js +1 -1
- package/.next/server/chunks/406.js +10 -6
- package/.next/server/chunks/4444.js +1 -1
- package/.next/server/chunks/5959.js +4 -5
- package/.next/server/chunks/5998.js +1 -12
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6274.js +3 -3
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6781.js +1 -0
- package/.next/server/chunks/7458.js +6 -0
- package/.next/server/chunks/{3753.js → 7970.js} +57 -32
- package/.next/server/chunks/8536.js +1 -1
- package/.next/server/chunks/8807.js +180 -127
- package/.next/server/chunks/9058.js +1 -1
- package/.next/server/chunks/9067.js +1 -1
- package/.next/server/chunks/9360.js +1 -1
- 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/chunks/{6488-63dacfbab082ca8d.js → 6488-95ba9d24a76f0cc5.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/{page-c1be93f2595d0803.js → page-966a451ae7b0903a.js} +1 -1
- package/.next/trace +12 -12
- 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 +5 -1
- package/dist/cli/utils/api-client.d.ts.map +1 -1
- package/dist/cli/utils/api-client.js +9 -2
- package/dist/cli/utils/server-url.d.ts +23 -0
- package/dist/cli/utils/server-url.d.ts.map +1 -1
- package/dist/cli/utils/server-url.js +33 -0
- package/dist/server/src/config/log-config.js +10 -1
- package/dist/server/src/config/safe-directory.js +103 -0
- package/dist/server/src/config/system-directories.js +74 -9
- package/dist/server/src/lib/cli-tools/antigravity.js +19 -2
- package/dist/server/src/lib/cli-tools/codex.js +95 -1
- package/dist/server/src/lib/cli-tools/copilot.js +30 -1
- package/dist/server/src/lib/cli-tools/gemini.js +28 -2
- package/dist/server/src/lib/cli-tools/opencode.js +51 -2
- package/dist/server/src/lib/git/git-default-branch.js +59 -0
- package/dist/server/src/lib/hooks/agent-event-service.js +205 -0
- package/dist/server/src/lib/hooks/agent-event-types.js +7 -86
- package/dist/server/src/lib/hooks/hook-settings-generator.js +26 -11
- package/dist/server/src/lib/hooks/permission-decision-service.js +269 -0
- package/dist/server/src/lib/hooks/sources/abstain.js +78 -0
- package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +372 -0
- package/dist/server/src/lib/hooks/sources/antigravity/source.js +225 -0
- package/dist/server/src/lib/hooks/sources/antigravity/tool-id.js +16 -0
- package/dist/server/src/lib/hooks/sources/claude/source.js +143 -0
- package/dist/server/src/lib/hooks/sources/claude/tool-id.js +18 -0
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +465 -0
- package/dist/server/src/lib/hooks/sources/codex/source.js +138 -0
- package/dist/server/src/lib/hooks/sources/codex/tool-id.js +15 -0
- package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +473 -0
- package/dist/server/src/lib/hooks/sources/copilot/source.js +210 -0
- package/dist/server/src/lib/hooks/sources/copilot/tool-id.js +15 -0
- package/dist/server/src/lib/hooks/sources/define-source.js +169 -0
- package/dist/server/src/lib/hooks/sources/event-mapper.js +157 -0
- package/dist/server/src/lib/hooks/sources/gemini/event-vocabulary.js +102 -0
- package/dist/server/src/lib/hooks/sources/gemini/settings-generator.js +315 -0
- package/dist/server/src/lib/hooks/sources/gemini/shared-config-tree.js +103 -0
- package/dist/server/src/lib/hooks/sources/gemini/source.js +151 -0
- package/dist/server/src/lib/hooks/sources/gemini/tool-id.js +17 -0
- package/dist/server/src/lib/hooks/sources/hook-event-vocabulary.js +111 -0
- package/dist/server/src/lib/hooks/sources/index.js +62 -0
- package/dist/server/src/lib/hooks/sources/legacy-relay.js +84 -0
- package/dist/server/src/lib/hooks/sources/opencode/client.js +299 -0
- package/dist/server/src/lib/hooks/sources/opencode/ingest.js +261 -0
- package/dist/server/src/lib/hooks/sources/opencode/mappers.js +154 -0
- package/dist/server/src/lib/hooks/sources/opencode/payloads.js +189 -0
- package/dist/server/src/lib/hooks/sources/opencode/ports.js +295 -0
- package/dist/server/src/lib/hooks/sources/opencode/runtime.js +159 -0
- package/dist/server/src/lib/hooks/sources/opencode/source.js +250 -0
- package/dist/server/src/lib/hooks/sources/opencode/subscription.js +422 -0
- package/dist/server/src/lib/hooks/sources/opencode/tool-id.js +14 -0
- package/dist/server/src/lib/hooks/sources/opencode/turn-gate.js +193 -0
- package/dist/server/src/lib/hooks/sources/pending-decisions.js +127 -0
- package/dist/server/src/lib/hooks/sources/registry.js +111 -0
- package/dist/server/src/lib/hooks/sources/types.js +46 -0
- package/dist/server/src/lib/session/agent-session-lifecycle.js +82 -0
- package/dist/server/src/lib/session/claude-session.js +10 -3
- package/dist/server/src/lib/tasks/contract-message.js +175 -0
- package/dist/server/src/lib/verification/env-clean-gate.js +320 -0
- package/dist/server/src/lib/verification/env-snapshot.js +474 -0
- package/dist/server/src/lib/verification/gate-runner.js +802 -0
- package/dist/server/src/lib/verification/scope-gate.js +402 -0
- package/dist/server/src/lib/verification/verify-config.js +281 -0
- package/package.json +1 -1
- package/scripts/hooks/cmate-agent-event.sh +73 -3
- package/.next/server/chunks/8856.js +0 -4
- /package/.next/static/{d4vh4O18WEhXs4WbdShIs → wH6K6QNPHSdATFkVoIcy3}/_buildManifest.js +0 -0
- /package/.next/static/{d4vh4O18WEhXs4WbdShIs → wH6K6QNPHSdATFkVoIcy3}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The hooks CommandMate writes into `<worktree>/.gemini/settings.json`, and the
|
|
4
|
+
* command that launches gemini against them (Issue #1762).
|
|
5
|
+
*
|
|
6
|
+
* gemini is the one tool of the five whose hook config is naturally scoped to a
|
|
7
|
+
* worktree: `settings.setValue("Workspace", "hooks", …)` — which is what
|
|
8
|
+
* `gemini hooks migrate` calls — writes the workspace file, and the user's
|
|
9
|
+
* `~/.gemini/settings.json` is never opened (#1757 §5.3.2). So this generator
|
|
10
|
+
* touches nothing global, and the *shared* `~/.gemini` tree that antigravity
|
|
11
|
+
* lives in (`./shared-config-tree`) is out of reach by construction.
|
|
12
|
+
*
|
|
13
|
+
* What it does touch is a file inside the user's repository. Three consequences
|
|
14
|
+
* shaped the code:
|
|
15
|
+
*
|
|
16
|
+
* - **It merges, never replaces.** A checked-in `.gemini/settings.json` with
|
|
17
|
+
* the team's model, tool allowlist and their own hooks keeps every key; only
|
|
18
|
+
* CommandMate's own handlers are rewritten. `mergeGeminiHookSettings` is
|
|
19
|
+
* pure, so this is testable without a filesystem.
|
|
20
|
+
* - **The written command is deterministic.** gemini persists the exact command
|
|
21
|
+
* strings it has been trusted with in `trusted_hooks.json` and re-shows the
|
|
22
|
+
* disclosure banner when they change (#1757 §5.3.3), so a command that
|
|
23
|
+
* varied per launch would nag on every start. It also makes the merge
|
|
24
|
+
* idempotent: relaunching rewrites byte-identical entries.
|
|
25
|
+
* - **It does not carry the instance id.** One file serves `gemini` and
|
|
26
|
+
* `gemini-2` in the same worktree, so an instance baked into it would label
|
|
27
|
+
* both sessions with whichever started last. The instance rides in
|
|
28
|
+
* `CM_HOOK_URL` instead — see {@link buildGeminiLaunchCommand}.
|
|
29
|
+
*
|
|
30
|
+
* ## Which events are registered, and which are not
|
|
31
|
+
*
|
|
32
|
+
* `SessionStart` / `BeforeAgent` / `AfterAgent` / `Notification` / `SessionEnd`.
|
|
33
|
+
* That is every gemini event with a consumer:
|
|
34
|
+
* `user_prompt_submit` → `running`, `stop` → `ready`,
|
|
35
|
+
* `notification(permission_prompt)` → `waiting`, `session_start` → generation
|
|
36
|
+
* fence, `session_end` → recorded.
|
|
37
|
+
*
|
|
38
|
+
* `BeforeTool` / `AfterTool` are deliberately absent. gemini runs hooks
|
|
39
|
+
* synchronously, so registering them buys two blocking round trips per tool call
|
|
40
|
+
* — on a hot `read_file` loop that is the agent waiting on CommandMate, all day
|
|
41
|
+
* — and buys nothing back: `pre_tool_use`/`post_tool_use` answer `running`,
|
|
42
|
+
* which `user_prompt_submit` has already established and only `stop` clears, and
|
|
43
|
+
* the one payload they are otherwise read for is `AskUserQuestion`, a tool
|
|
44
|
+
* gemini does not have. The source still *maps* both spellings, because a user
|
|
45
|
+
* may register them by hand in the same file.
|
|
46
|
+
*
|
|
47
|
+
* @module lib/hooks/sources/gemini/settings-generator
|
|
48
|
+
*/
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.GEMINI_REGISTERED_HOOKS = exports.GEMINI_SETTINGS_FILENAME = exports.GEMINI_HOOK_TIMEOUT_MS = exports.GEMINI_CONFIG_DIRNAME = void 0;
|
|
51
|
+
exports.getGeminiSettingsPath = getGeminiSettingsPath;
|
|
52
|
+
exports.buildGeminiHookCommand = buildGeminiHookCommand;
|
|
53
|
+
exports.isCommandMateHookCommand = isCommandMateHookCommand;
|
|
54
|
+
exports.buildGeminiHookGroups = buildGeminiHookGroups;
|
|
55
|
+
exports.mergeGeminiHookSettings = mergeGeminiHookSettings;
|
|
56
|
+
exports.writeGeminiHookSettings = writeGeminiHookSettings;
|
|
57
|
+
exports.buildGeminiLaunchCommand = buildGeminiLaunchCommand;
|
|
58
|
+
const path_1 = require("path");
|
|
59
|
+
const types_1 = require("../../../../lib/cli-tools/types");
|
|
60
|
+
const hook_settings_generator_1 = require("../../../../lib/hooks/hook-settings-generator");
|
|
61
|
+
const logger_1 = require("../../../../lib/logger");
|
|
62
|
+
const event_mapper_1 = require("../event-mapper");
|
|
63
|
+
const shared_config_tree_1 = require("./shared-config-tree");
|
|
64
|
+
const tool_id_1 = require("./tool-id");
|
|
65
|
+
const logger = (0, logger_1.createLogger)('lib/hooks/sources/gemini/settings-generator');
|
|
66
|
+
/** Directory gemini reads workspace configuration from, relative to the worktree. */
|
|
67
|
+
exports.GEMINI_CONFIG_DIRNAME = '.gemini';
|
|
68
|
+
/**
|
|
69
|
+
* Handler timeout, **in milliseconds** — gemini is the one tool that does not
|
|
70
|
+
* count this in seconds.
|
|
71
|
+
*
|
|
72
|
+
* Measured, and measured the hard way. `timeout: 5` — the seconds figure every
|
|
73
|
+
* other tool takes, and what #1757 §8.2 R13 recorded as "the unit is seconds
|
|
74
|
+
* everywhere" — produced this on a live v0.55.1 session:
|
|
75
|
+
*
|
|
76
|
+
* ```
|
|
77
|
+
* Hook execution error: Hook timed out after 5ms
|
|
78
|
+
* Hook execution for SessionStart: 0 succeeded, 1 failed …, total duration: 8ms
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* The hook was registered, was disclosed in the banner, and ran — and was killed
|
|
82
|
+
* before `curl` could open a socket, so **every event was lost while everything
|
|
83
|
+
* looked correctly configured**. The bundle confirms it:
|
|
84
|
+
* `DEFAULT_HOOK_TIMEOUT = 6e4` and the message is `Hook timed out after
|
|
85
|
+
* ${timeout}ms`. gemini's default is therefore 60s where Claude's is 600s and
|
|
86
|
+
* copilot's is ~10s.
|
|
87
|
+
*
|
|
88
|
+
* The value is {@link HOOK_TIMEOUT_SECONDS} converted, so the budget stays the
|
|
89
|
+
* one number the rest of the codebase reasons about.
|
|
90
|
+
*/
|
|
91
|
+
exports.GEMINI_HOOK_TIMEOUT_MS = hook_settings_generator_1.HOOK_TIMEOUT_SECONDS * 1000;
|
|
92
|
+
/** Workspace settings file, relative to {@link GEMINI_CONFIG_DIRNAME}. */
|
|
93
|
+
exports.GEMINI_SETTINGS_FILENAME = 'settings.json';
|
|
94
|
+
/**
|
|
95
|
+
* The gemini events CommandMate registers, and the word each relay call reports.
|
|
96
|
+
*
|
|
97
|
+
* Ordered as the file is written, so a diff of two generated files reads in one
|
|
98
|
+
* direction. See the module comment for why `BeforeTool` / `AfterTool` are not
|
|
99
|
+
* here.
|
|
100
|
+
*/
|
|
101
|
+
exports.GEMINI_REGISTERED_HOOKS = [
|
|
102
|
+
['SessionStart', 'session_start'],
|
|
103
|
+
['BeforeAgent', 'user_prompt_submit'],
|
|
104
|
+
['AfterAgent', 'stop'],
|
|
105
|
+
['Notification', 'notification'],
|
|
106
|
+
['SessionEnd', 'session_end'],
|
|
107
|
+
];
|
|
108
|
+
/** Absolute path of the workspace settings file for one worktree. */
|
|
109
|
+
function getGeminiSettingsPath(worktreePath) {
|
|
110
|
+
return (0, path_1.join)(worktreePath, exports.GEMINI_CONFIG_DIRNAME, exports.GEMINI_SETTINGS_FILENAME);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The relay invocation for one event.
|
|
114
|
+
*
|
|
115
|
+
* `type: "http"` is not an option here, or anywhere outside Claude: #1757 R7
|
|
116
|
+
* measured all four new tools rejecting it, so `scripts/hooks/cmate-agent-event.sh`
|
|
117
|
+
* is the only delivery mechanism gemini has.
|
|
118
|
+
*
|
|
119
|
+
* No `--url`. The endpoint comes from `CM_HOOK_URL`, which
|
|
120
|
+
* {@link buildGeminiLaunchCommand} puts in the session's environment with the
|
|
121
|
+
* instance baked in; passing `--url` here would override it from a file that
|
|
122
|
+
* cannot know which instance it is serving. `--worktree-id` *is* baked in,
|
|
123
|
+
* because the file already is per-worktree and a body that names the worktree
|
|
124
|
+
* keeps working when the environment does not reach the hook.
|
|
125
|
+
*
|
|
126
|
+
* @param relayPath - Absolute path to the relay script
|
|
127
|
+
* @param event - The word to report
|
|
128
|
+
* @param worktreeId - CommandMate's worktree id
|
|
129
|
+
*/
|
|
130
|
+
function buildGeminiHookCommand(relayPath, event, worktreeId) {
|
|
131
|
+
return [
|
|
132
|
+
(0, hook_settings_generator_1.shellQuote)(relayPath),
|
|
133
|
+
'--tool',
|
|
134
|
+
tool_id_1.GEMINI_CLI_TOOL_ID,
|
|
135
|
+
'--event',
|
|
136
|
+
event,
|
|
137
|
+
'--worktree-id',
|
|
138
|
+
(0, hook_settings_generator_1.shellQuote)(worktreeId),
|
|
139
|
+
'--stdin-json',
|
|
140
|
+
].join(' ');
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Whether a command string is one CommandMate wrote for this worktree.
|
|
144
|
+
*
|
|
145
|
+
* Used to replace our own entries on rewrite instead of appending a duplicate
|
|
146
|
+
* set at every launch. Three tokens have to be present together — the relay's
|
|
147
|
+
* name, this tool, and this worktree id — so a hook the operator wrote for a
|
|
148
|
+
* *different* worktree, or for another tool, or with their own script, is left
|
|
149
|
+
* alone.
|
|
150
|
+
*
|
|
151
|
+
* A hand-configured hook from the #1549 guide that happens to match all three is
|
|
152
|
+
* replaced, and that is the right outcome: it posts the same event for the same
|
|
153
|
+
* instance to the same receiver, so the only thing lost is the duplicate.
|
|
154
|
+
*/
|
|
155
|
+
function isCommandMateHookCommand(command, worktreeId) {
|
|
156
|
+
return (command.includes('cmate-agent-event.sh') &&
|
|
157
|
+
command.includes(`--tool ${tool_id_1.GEMINI_CLI_TOOL_ID}`) &&
|
|
158
|
+
command.includes(`--worktree-id ${(0, hook_settings_generator_1.shellQuote)(worktreeId)}`));
|
|
159
|
+
}
|
|
160
|
+
/** Whether one entry of a `hooks[<Event>]` array is CommandMate's. */
|
|
161
|
+
function isCommandMateGroup(group, worktreeId) {
|
|
162
|
+
if (!(0, event_mapper_1.isPlainObject)(group))
|
|
163
|
+
return false;
|
|
164
|
+
// The grouped shape gemini documents.
|
|
165
|
+
const handlers = group.hooks;
|
|
166
|
+
if (Array.isArray(handlers)) {
|
|
167
|
+
return (handlers.length > 0 &&
|
|
168
|
+
handlers.every((handler) => (0, event_mapper_1.isPlainObject)(handler) &&
|
|
169
|
+
typeof handler.command === 'string' &&
|
|
170
|
+
isCommandMateHookCommand(handler.command, worktreeId)));
|
|
171
|
+
}
|
|
172
|
+
// A flat handler. Not what this generator emits, but cheap to recognise so an
|
|
173
|
+
// older or hand-flattened entry of ours is replaced rather than duplicated.
|
|
174
|
+
return typeof group.command === 'string' && isCommandMateHookCommand(group.command, worktreeId);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The `hooks` entries CommandMate contributes, keyed by gemini's event name.
|
|
178
|
+
*
|
|
179
|
+
* @param relayPath - Absolute path to the relay script
|
|
180
|
+
* @param target - The instance being started; only its worktree reaches the file
|
|
181
|
+
* @returns One matcher group per registered event
|
|
182
|
+
*/
|
|
183
|
+
function buildGeminiHookGroups(relayPath, target) {
|
|
184
|
+
const groups = {};
|
|
185
|
+
for (const [nativeName, event] of exports.GEMINI_REGISTERED_HOOKS) {
|
|
186
|
+
groups[nativeName] = [
|
|
187
|
+
{
|
|
188
|
+
hooks: [
|
|
189
|
+
{
|
|
190
|
+
type: 'command',
|
|
191
|
+
command: buildGeminiHookCommand(relayPath, event, target.worktreeId),
|
|
192
|
+
// Milliseconds. See GEMINI_HOOK_TIMEOUT_MS — this is the one field
|
|
193
|
+
// whose unit differs from every other tool's, and getting it wrong
|
|
194
|
+
// loses every event without an error anywhere the operator looks.
|
|
195
|
+
timeout: exports.GEMINI_HOOK_TIMEOUT_MS,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
}
|
|
201
|
+
return groups;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Put CommandMate's hooks into an existing settings object without disturbing
|
|
205
|
+
* anything else in it.
|
|
206
|
+
*
|
|
207
|
+
* Pure, so the guarantee this module exists for is checked without a
|
|
208
|
+
* filesystem. The rules:
|
|
209
|
+
*
|
|
210
|
+
* - every top-level key other than `hooks` is passed through by identity, in
|
|
211
|
+
* its original position;
|
|
212
|
+
* - inside `hooks`, an event CommandMate does not register is passed through
|
|
213
|
+
* **by identity** — including values that are not arrays, which a
|
|
214
|
+
* hand-edited file can contain;
|
|
215
|
+
* - inside an event CommandMate does register, the user's groups are kept and
|
|
216
|
+
* ours are replaced.
|
|
217
|
+
*
|
|
218
|
+
* @param existing - The parsed settings file, or null when there is none
|
|
219
|
+
* @param groups - What {@link buildGeminiHookGroups} produced
|
|
220
|
+
* @param worktreeId - Identifies our own previous entries
|
|
221
|
+
* @returns The object to serialise
|
|
222
|
+
*/
|
|
223
|
+
function mergeGeminiHookSettings(existing, groups, worktreeId) {
|
|
224
|
+
const existingHooks = (0, event_mapper_1.isPlainObject)(existing?.hooks) ? existing.hooks : {};
|
|
225
|
+
const merged = {};
|
|
226
|
+
for (const [nativeName, value] of Object.entries(existingHooks)) {
|
|
227
|
+
if (!Array.isArray(value)) {
|
|
228
|
+
merged[nativeName] = value;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const kept = value.filter((group) => !isCommandMateGroup(group, worktreeId));
|
|
232
|
+
// Identity when nothing of ours was in there, so an untouched event is
|
|
233
|
+
// untouched down to the array instance.
|
|
234
|
+
merged[nativeName] = kept.length === value.length ? value : kept;
|
|
235
|
+
}
|
|
236
|
+
for (const [nativeName, ours] of Object.entries(groups)) {
|
|
237
|
+
const kept = merged[nativeName];
|
|
238
|
+
merged[nativeName] = Array.isArray(kept) ? [...kept, ...ours] : [...ours];
|
|
239
|
+
}
|
|
240
|
+
return { ...existing, hooks: merged };
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Write `<worktree>/.gemini/settings.json`.
|
|
244
|
+
*
|
|
245
|
+
* @param worktreePath - Absolute path of the worktree gemini will run in
|
|
246
|
+
* @param target - The instance being started
|
|
247
|
+
* @returns The path written, or null when injection is off or not possible
|
|
248
|
+
*/
|
|
249
|
+
function writeGeminiHookSettings(worktreePath, target) {
|
|
250
|
+
if (!(0, hook_settings_generator_1.isHookInjectionEnabled)())
|
|
251
|
+
return null;
|
|
252
|
+
const relayPath = (0, hook_settings_generator_1.resolveRelayScriptPath)();
|
|
253
|
+
if (!relayPath) {
|
|
254
|
+
// No inline-curl fallback, unlike Claude's `SessionStart`: that fallback
|
|
255
|
+
// posts the agent's payload verbatim and relies on the URL to say which
|
|
256
|
+
// tool sent it, and the URL here lives in an environment variable a
|
|
257
|
+
// settings file cannot read. A gemini session with no hooks is the
|
|
258
|
+
// pre-#1762 status quo; a gemini session posting events nothing can
|
|
259
|
+
// attribute is worse.
|
|
260
|
+
logger.warn('gemini-hook-relay-missing', { worktreeId: target.worktreeId });
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
const settingsPath = getGeminiSettingsPath(worktreePath);
|
|
264
|
+
try {
|
|
265
|
+
const existing = (0, shared_config_tree_1.readJsonObjectFile)(settingsPath);
|
|
266
|
+
const groups = buildGeminiHookGroups(relayPath, target);
|
|
267
|
+
(0, shared_config_tree_1.writeJsonObjectFile)(settingsPath, mergeGeminiHookSettings(existing, groups, target.worktreeId));
|
|
268
|
+
return settingsPath;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
// Fail-open, like every other part of this path: the events are an
|
|
272
|
+
// enhancement to a session that has to start regardless.
|
|
273
|
+
logger.warn('gemini-hook-settings-write-failed', {
|
|
274
|
+
worktreeId: target.worktreeId,
|
|
275
|
+
error: error instanceof Error ? error.message : String(error),
|
|
276
|
+
});
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The command that launches gemini for one instance.
|
|
282
|
+
*
|
|
283
|
+
* `CM_HOOK_URL` is the whole of the instance correlation, and it is an
|
|
284
|
+
* environment variable rather than a flag in the settings file for a reason the
|
|
285
|
+
* file cannot get around: `.gemini/settings.json` is per *worktree*, and
|
|
286
|
+
* `gemini` and `gemini-2` share it. The relay reads `CM_HOOK_URL` itself — no
|
|
287
|
+
* shell expansion inside the hook command is involved — and the receiver reads
|
|
288
|
+
* `tool`, `worktreeId` and `instanceId` out of the query string, which is
|
|
289
|
+
* exactly how Claude's injected `--settings` correlates.
|
|
290
|
+
*
|
|
291
|
+
* When the variable does not reach the hook, the relay falls back to its default
|
|
292
|
+
* endpoint and the body's `--worktree-id` still resolves the worktree; the event
|
|
293
|
+
* lands on the primary instance. That is a degradation, not a
|
|
294
|
+
* misattribution.
|
|
295
|
+
*
|
|
296
|
+
* Never throws, and returns the executable unchanged when injection is off, so
|
|
297
|
+
* `CM_AGENT_HOOKS_INJECT=0` produces the byte-identical command line this tool
|
|
298
|
+
* used before #1762.
|
|
299
|
+
*
|
|
300
|
+
* @param executablePath - `gemini`, or a resolved path to it
|
|
301
|
+
* @param target - The instance being started
|
|
302
|
+
* @returns The command line to type into the pane
|
|
303
|
+
*/
|
|
304
|
+
function buildGeminiLaunchCommand(executablePath, target, options = {}) {
|
|
305
|
+
if (!(0, hook_settings_generator_1.isHookInjectionEnabled)())
|
|
306
|
+
return executablePath;
|
|
307
|
+
if (!(0, types_1.isValidInstanceId)((0, hook_settings_generator_1.resolveTargetInstanceId)(target))) {
|
|
308
|
+
// About to become a URL parameter the receiver re-validates; a value that
|
|
309
|
+
// would be rejected there is not worth injecting.
|
|
310
|
+
logger.warn('gemini-hook-invalid-instance-id', { worktreeId: target.worktreeId });
|
|
311
|
+
return executablePath;
|
|
312
|
+
}
|
|
313
|
+
const url = (0, hook_settings_generator_1.buildAgentEventUrl)({ ...target, cliToolId: tool_id_1.GEMINI_CLI_TOOL_ID }, options);
|
|
314
|
+
return `CM_HOOK_URL=${(0, hook_settings_generator_1.shellQuote)(url)} ${(0, hook_settings_generator_1.shellQuote)(executablePath)}`;
|
|
315
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Non-destructive JSON config writing for the `~/.gemini` tree that gemini and
|
|
4
|
+
* antigravity share (Issue #1762).
|
|
5
|
+
*
|
|
6
|
+
* ## Why this is one module rather than two
|
|
7
|
+
*
|
|
8
|
+
* `~/.gemini/` is gemini's directory, and antigravity squats in it. On a machine
|
|
9
|
+
* with both installed it holds, at once:
|
|
10
|
+
*
|
|
11
|
+
* ```
|
|
12
|
+
* ~/.gemini/settings.json gemini, user scope
|
|
13
|
+
* ~/.gemini/oauth_creds.json gemini, the credentials a session needs
|
|
14
|
+
* ~/.gemini/config/hooks.json antigravity, the ONLY file it reads (#1757 P8)
|
|
15
|
+
* ~/.gemini/antigravity/ antigravity 2.0 state
|
|
16
|
+
* ~/.gemini/antigravity-cli/ agy state, incl. its own settings.json
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* So "write the config file" is a sentence with a blast radius here that it does
|
|
20
|
+
* not have for Claude or codex: a generator that rewrites a file wholesale takes
|
|
21
|
+
* out the *other* tool's configuration, and a generator that redirects the tree
|
|
22
|
+
* (a `HOME` or `GEMINI_CLI_HOME` swap) takes out gemini's OAuth credentials and
|
|
23
|
+
* leaves the user staring at a login screen. Both failures are silent at the
|
|
24
|
+
* moment they happen.
|
|
25
|
+
*
|
|
26
|
+
* Everything in this module therefore does exactly one thing: **read what is
|
|
27
|
+
* there, put CommandMate's own key back, and write the rest through untouched.**
|
|
28
|
+
* A file CommandMate has never seen keeps every byte it had except the one key
|
|
29
|
+
* that is ours. Both directions are pinned by
|
|
30
|
+
* `tests/unit/hooks/sources/shared-config-tree-1762.test.ts`.
|
|
31
|
+
*
|
|
32
|
+
* It lives under `gemini/` because the tree is gemini's; `antigravity/` imports
|
|
33
|
+
* it rather than growing a second copy, which is the point — one merge
|
|
34
|
+
* implementation means "we do not clobber" is one thing to get right and one
|
|
35
|
+
* thing to test, instead of two that can drift.
|
|
36
|
+
*
|
|
37
|
+
* @module lib/hooks/sources/gemini/shared-config-tree
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.readJsonObjectFile = readJsonObjectFile;
|
|
41
|
+
exports.writeJsonObjectFile = writeJsonObjectFile;
|
|
42
|
+
const fs_1 = require("fs");
|
|
43
|
+
const path_1 = require("path");
|
|
44
|
+
const system_directories_1 = require("../../../../config/system-directories");
|
|
45
|
+
const event_mapper_1 = require("../event-mapper");
|
|
46
|
+
/**
|
|
47
|
+
* Read a JSON object from disk, or null when there is nothing usable there.
|
|
48
|
+
*
|
|
49
|
+
* Null covers three different situations on purpose — absent, unreadable, and
|
|
50
|
+
* "parsed fine but is not an object" — because the caller's response to all
|
|
51
|
+
* three is the same: treat the file as empty and write a config that has only
|
|
52
|
+
* CommandMate's key in it.
|
|
53
|
+
*
|
|
54
|
+
* It deliberately does **not** cover "parsed fine and is an object we do not
|
|
55
|
+
* recognise". That case returns the object, and the merge preserves it. A user's
|
|
56
|
+
* `settings.json` is full of keys this codebase has never heard of.
|
|
57
|
+
*
|
|
58
|
+
* @param path - Absolute path to the file
|
|
59
|
+
* @returns The parsed object, or null
|
|
60
|
+
*/
|
|
61
|
+
function readJsonObjectFile(path) {
|
|
62
|
+
if (!(0, fs_1.existsSync)(path))
|
|
63
|
+
return null;
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse((0, fs_1.readFileSync)(path, 'utf8'));
|
|
66
|
+
return (0, event_mapper_1.isPlainObject)(parsed) ? parsed : null;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// A hand-edited file with a trailing comma is not something to fail a
|
|
70
|
+
// session over. Injection is an enhancement; the session starts either way.
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Write a JSON object, creating the directory when it is missing.
|
|
76
|
+
*
|
|
77
|
+
* The mode arguments apply only when the entry is *created*: an existing file
|
|
78
|
+
* keeps the permissions the user gave it, which matters because these files are
|
|
79
|
+
* theirs and not CommandMate's. A new one is 0600 and a new directory 0700 — the
|
|
80
|
+
* same posture `hook-settings-generator` takes, and for the same reason (the
|
|
81
|
+
* contents name every worktree and instance on the machine).
|
|
82
|
+
*
|
|
83
|
+
* Issue #1774: unlike its siblings this takes the path as an argument rather
|
|
84
|
+
* than resolving an environment variable, so there is no default to fall back
|
|
85
|
+
* to — the caller asked for one specific file. It therefore *refuses* rather
|
|
86
|
+
* than redirects. Throwing is the fail-open signal both callers already handle
|
|
87
|
+
* (`writeGeminiHookSettings` and `writeAntigravityHooksConfig` catch, warn and
|
|
88
|
+
* return null), and it has to happen before the mkdir: a recursive mkdir under
|
|
89
|
+
* `/proc` does not throw, it spins the event loop until the process is killed.
|
|
90
|
+
*
|
|
91
|
+
* @param path - Absolute path to the file
|
|
92
|
+
* @param value - The object to serialise
|
|
93
|
+
* @throws If the path is inside a virtual filesystem. Callers treat a throw as
|
|
94
|
+
* "launch without hooks"
|
|
95
|
+
*/
|
|
96
|
+
function writeJsonObjectFile(path, value) {
|
|
97
|
+
if ((0, system_directories_1.isVirtualFilesystemPath)(path)) {
|
|
98
|
+
throw new Error(`Refusing to write inside a virtual filesystem: ${path} ` +
|
|
99
|
+
`(a recursive mkdir under /proc, /sys or /dev never returns on Linux; Issue #1774)`);
|
|
100
|
+
}
|
|
101
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(path), { recursive: true, mode: 0o700 });
|
|
102
|
+
(0, fs_1.writeFileSync)(path, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
|
|
103
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini CLI's {@link AgentEventSource} (Issue #1762, Phase 4-4 of Epic #1720).
|
|
4
|
+
*
|
|
5
|
+
* ## Why the values below are what they are
|
|
6
|
+
*
|
|
7
|
+
* - **`noDecision: 'proceeds'`.** #1757 could not measure this: the account
|
|
8
|
+
* available to the spike was refused by the server with `IneligibleTierError`
|
|
9
|
+
* before any tool call happened, so §5.3.6 lists items 6 and 7 as unmeasured.
|
|
10
|
+
* It is not guessed either. gemini v0.55.1's shipped bundle decides whether a
|
|
11
|
+
* hook blocked a tool in `DefaultHookOutput`:
|
|
12
|
+
*
|
|
13
|
+
* ```js
|
|
14
|
+
* isBlockingDecision() { return this.decision === "block" || this.decision === "deny"; }
|
|
15
|
+
* isAskDecision() { return this.decision === "ask"; }
|
|
16
|
+
* shouldStopExecution(){ return this.continue === false; }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* All three read fields that an empty or absent reply does not have, so
|
|
20
|
+
* silence cannot block, cannot escalate and cannot stop. Fail-open is a
|
|
21
|
+
* property of the parser rather than of a measurement — which is the stronger
|
|
22
|
+
* statement of the two, and the opposite of antigravity, where the same
|
|
23
|
+
* question has the opposite answer (`../antigravity/source`).
|
|
24
|
+
*
|
|
25
|
+
* - **`encodeVerdict` returns `{}` for every verdict, and this source
|
|
26
|
+
* adjudicates nothing.** Not a gap — gemini's hook protocol has no way to
|
|
27
|
+
* approve anything. Reading the scheduler in the same bundle:
|
|
28
|
+
*
|
|
29
|
+
* ```js
|
|
30
|
+
* const hookResult = await evaluateBeforeToolHook(…); // 1. the hook runs
|
|
31
|
+
* …
|
|
32
|
+
* const { decision: policyDecision } = await checkPolicy(…); // 2. the Policy Engine
|
|
33
|
+
* let decision = policyDecision;
|
|
34
|
+
* if (hookDecision === "ask") decision = ASK_USER; // 3. hook may only escalate
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* A hook can *deny* (step 1 returns an error outright), it can *escalate* an
|
|
38
|
+
* allow into a dialog (step 3), and it can do nothing. There is no branch in
|
|
39
|
+
* which a hook turns a `checkPolicy` verdict into an approval. So **on gemini,
|
|
40
|
+
* approval is the Policy Engine's job and only the Policy Engine's job**
|
|
41
|
+
* (`--approval-mode` / `--policy` / `-y, --yolo`), and Auto-Yes keeps exactly
|
|
42
|
+
* the one meaning it has today for this tool: the TUI path — detect the
|
|
43
|
+
* dialog, answer it. There is no second, hook-shaped approval channel for it
|
|
44
|
+
* to compete with, which is what Issue #1720 asked to be established before
|
|
45
|
+
* this Issue shipped. CommandMate passes none of those flags, so injecting
|
|
46
|
+
* hooks does not widen what a gemini session may do.
|
|
47
|
+
*
|
|
48
|
+
* - **`configScope: 'per-worktree'`.** `<worktree>/.gemini/settings.json`
|
|
49
|
+
* (#1757 §5.3.2). The user's `~/.gemini/settings.json` is never opened, which
|
|
50
|
+
* also keeps this source out of the tree antigravity occupies.
|
|
51
|
+
*
|
|
52
|
+
* - **`decisionTimeoutSeconds: 0`.** Not `null`. `null` means "waits forever",
|
|
53
|
+
* which is opencode's situation and would be a lie here: no gemini event ever
|
|
54
|
+
* waits on a CommandMate verdict, because none is ever asked for.
|
|
55
|
+
*
|
|
56
|
+
* @module lib/hooks/sources/gemini/source
|
|
57
|
+
*/
|
|
58
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
|
+
exports.geminiAgentEventSource = void 0;
|
|
60
|
+
exports.injectGeminiHookSettings = injectGeminiHookSettings;
|
|
61
|
+
const types_1 = require("../../../../lib/cli-tools/types");
|
|
62
|
+
const define_source_1 = require("../define-source");
|
|
63
|
+
const event_mapper_1 = require("../event-mapper");
|
|
64
|
+
const hook_event_vocabulary_1 = require("../hook-event-vocabulary");
|
|
65
|
+
const event_vocabulary_1 = require("./event-vocabulary");
|
|
66
|
+
const settings_generator_1 = require("./settings-generator");
|
|
67
|
+
const tool_id_1 = require("./tool-id");
|
|
68
|
+
/**
|
|
69
|
+
* Write this worktree's `.gemini/settings.json`, on the session-creation path.
|
|
70
|
+
*
|
|
71
|
+
* **This is the one thing about gemini that {@link AgentEventSource} cannot
|
|
72
|
+
* express.** `prepareLaunch` receives an {@link AgentInstanceRef}, which is
|
|
73
|
+
* `(worktreeId, cliToolId, instanceId)` and carries no filesystem path — the
|
|
74
|
+
* right shape for the four tools whose config is global or per-instance, and one
|
|
75
|
+
* field short for the only tool whose config is per-*worktree*. Rather than
|
|
76
|
+
* widen the interface for one tool, or resolve the path by pulling the database
|
|
77
|
+
* into the module every receiver imports, the caller that already holds the path
|
|
78
|
+
* passes it here and `prepareLaunch` builds the command line.
|
|
79
|
+
*
|
|
80
|
+
* Reported rather than worked around: see the Issue #1762 entry in `CHANGELOG.md`.
|
|
81
|
+
*
|
|
82
|
+
* @param worktreePath - Absolute path of the worktree the session runs in
|
|
83
|
+
* @param target - The instance being created
|
|
84
|
+
* @returns The settings file written, or null when nothing was written
|
|
85
|
+
*/
|
|
86
|
+
function injectGeminiHookSettings(worktreePath, target) {
|
|
87
|
+
const settingsTarget = {
|
|
88
|
+
worktreeId: target.worktreeId,
|
|
89
|
+
instanceId: target.instanceId,
|
|
90
|
+
cliToolId: tool_id_1.GEMINI_CLI_TOOL_ID,
|
|
91
|
+
};
|
|
92
|
+
if (!(0, types_1.isValidInstanceId)(target.instanceId ?? tool_id_1.GEMINI_CLI_TOOL_ID))
|
|
93
|
+
return null;
|
|
94
|
+
return (0, settings_generator_1.writeGeminiHookSettings)(worktreePath, settingsTarget);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Gemini CLI as an event source.
|
|
98
|
+
*
|
|
99
|
+
* Registered in `../registry`. Nothing outside this directory imports it by
|
|
100
|
+
* name; callers ask the registry for the tool they are holding.
|
|
101
|
+
*/
|
|
102
|
+
exports.geminiAgentEventSource = (0, define_source_1.definePushHookSource)({
|
|
103
|
+
cliToolId: tool_id_1.GEMINI_CLI_TOOL_ID,
|
|
104
|
+
// Silence cannot block: `decision` and `continue` are both absent from an
|
|
105
|
+
// empty reply, and both parsers test for a present value. See the module
|
|
106
|
+
// comment for the three lines of gemini's own code this rests on.
|
|
107
|
+
noDecision: { kind: 'proceeds' },
|
|
108
|
+
capabilities: {
|
|
109
|
+
// What CommandMate's injected config makes gemini emit. `pre_tool_use` and
|
|
110
|
+
// `post_tool_use` are absent on purpose — the spellings are mapped, but the
|
|
111
|
+
// hooks are not registered (see `./settings-generator`), so a caller waiting
|
|
112
|
+
// for one from a CommandMate-started gemini session would wait for good.
|
|
113
|
+
supportedEvents: ['session_start', 'user_prompt_submit', 'stop', 'notification', 'session_end'],
|
|
114
|
+
configScope: 'per-worktree',
|
|
115
|
+
// No gemini event waits on a verdict from CommandMate. See the module comment.
|
|
116
|
+
decisionTimeoutSeconds: 0,
|
|
117
|
+
},
|
|
118
|
+
// gemini's own table, kept in gemini's own module: four of the seven are
|
|
119
|
+
// spelled differently, and merging them into the shared CamelCase table would
|
|
120
|
+
// teach Claude, codex and copilot to accept spellings none of them sends
|
|
121
|
+
// (`docs/design/agent-event-source-interface.md` §5).
|
|
122
|
+
mappers: (0, event_mapper_1.fromNameTable)(event_vocabulary_1.GEMINI_HOOK_EVENT_NAMES),
|
|
123
|
+
nativeEventNameFields: ['hook_event_name'],
|
|
124
|
+
conversationIdFields: hook_event_vocabulary_1.SESSION_ID_FIELDS,
|
|
125
|
+
// gemini publishes no per-tool-call correlation id: its `BeforeTool` payload
|
|
126
|
+
// carries `tool_name` and `tool_input` and nothing resembling `tool_use_id`.
|
|
127
|
+
toolCallIdFields: [],
|
|
128
|
+
extractDetail: event_vocabulary_1.extractGeminiEventDetail,
|
|
129
|
+
// gemini has no `PermissionRequest` event and no `AskUserQuestion` tool
|
|
130
|
+
// (#1757 §8.1), so there is no payload of either kind to read. Null is the
|
|
131
|
+
// honest answer and degrades to the behaviour of a machine without hooks.
|
|
132
|
+
parsePermissionRequest: () => null,
|
|
133
|
+
parseQuestion: () => null,
|
|
134
|
+
// gemini hooks cannot approve — only deny, escalate to a dialog, or stop the
|
|
135
|
+
// agent outright. CommandMate emits none of those: a denial from Auto-Yes
|
|
136
|
+
// takes the choice away in the direction waiting cannot undo, and an
|
|
137
|
+
// escalation would add dialogs the Policy Engine had already settled. So every
|
|
138
|
+
// verdict encodes to the empty body, which the bundle reads as no opinion.
|
|
139
|
+
encodeVerdict: () => ({}),
|
|
140
|
+
// The settings file is written by `injectGeminiHookSettings`, which the
|
|
141
|
+
// session module calls with the worktree path this interface cannot carry.
|
|
142
|
+
// `settingsPath` is therefore null here rather than wrong.
|
|
143
|
+
prepareLaunch: (target, executablePath) => ({
|
|
144
|
+
command: (0, settings_generator_1.buildGeminiLaunchCommand)(executablePath, {
|
|
145
|
+
worktreeId: target.worktreeId,
|
|
146
|
+
instanceId: target.instanceId,
|
|
147
|
+
cliToolId: tool_id_1.GEMINI_CLI_TOOL_ID,
|
|
148
|
+
}),
|
|
149
|
+
settingsPath: null,
|
|
150
|
+
}),
|
|
151
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini CLI's {@link CLIToolType} id, as a constant.
|
|
4
|
+
*
|
|
5
|
+
* The same one-line module Claude has, for the same reason: the literal
|
|
6
|
+
* `'gemini'` appears once under `src/lib/hooks/`, and the modules that write
|
|
7
|
+
* gemini's config import the constant rather than restating it.
|
|
8
|
+
*
|
|
9
|
+
* Separate from `./source` because the settings generator needs the id and the
|
|
10
|
+
* source imports the generator; importing it back out of `./source` would close
|
|
11
|
+
* a cycle.
|
|
12
|
+
*
|
|
13
|
+
* @module lib/hooks/sources/gemini/tool-id
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.GEMINI_CLI_TOOL_ID = void 0;
|
|
17
|
+
exports.GEMINI_CLI_TOOL_ID = 'gemini';
|