commandmate 0.27.0 → 0.28.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/.env.example +28 -0
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +286 -256
- package/.next/app-path-routes-manifest.json +36 -32
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +32 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route.js +1 -1
- package/.next/server/app/api/app/update/route.js.nft.json +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 +32 -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 +34 -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/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route.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 +2 -2
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route.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/escalation/route.js +1 -1
- package/.next/server/app/api/push/escalation/route.js.nft.json +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route.js +7 -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.js.nft.json +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.js.nft.json +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route.js.nft.json +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 -1
- 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 -1
- 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 +2 -2
- 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 +2 -2
- 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]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-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 +2 -2
- 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]/env/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.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]/instances/opencode/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -0
- 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 +2 -2
- 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 +4 -4
- 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]/opencode/diff/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -0
- 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]/resolve-target/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +5 -1
- 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 +6 -2
- 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 +7 -3
- 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 +1 -1
- 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 -3
- 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 -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.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.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.js +1 -1
- package/.next/server/app/review/page.js.nft.json +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 +15 -10
- 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 +2 -2
- 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 +36 -32
- package/.next/server/chunks/1058.js +1 -0
- package/.next/server/chunks/1068.js +1 -3
- package/.next/server/chunks/1191.js +13 -0
- package/.next/server/chunks/1296.js +1 -1
- package/.next/server/chunks/1601.js +2 -2
- package/.next/server/chunks/1714.js +7 -0
- package/.next/server/chunks/1886.js +5 -0
- package/.next/server/chunks/1944.js +1 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/221.js +19 -0
- package/.next/server/chunks/222.js +1 -0
- package/.next/server/chunks/2328.js +1 -1
- package/.next/server/chunks/2366.js +1 -0
- package/.next/server/chunks/2404.js +2 -2
- package/.next/server/chunks/243.js +1 -0
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2759.js +1 -1
- package/.next/server/chunks/3346.js +1 -1
- package/.next/server/chunks/3480.js +17 -1
- package/.next/server/chunks/3558.js +1 -0
- package/.next/server/chunks/4299.js +1 -0
- package/.next/server/chunks/4393.js +1 -1
- package/.next/server/chunks/5017.js +1 -1
- package/.next/server/chunks/5089.js +1 -1
- package/.next/server/chunks/5354.js +1 -1
- package/.next/server/chunks/5571.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6274.js +11 -10
- package/.next/server/chunks/6285.js +1 -1
- package/.next/server/chunks/6337.js +1 -0
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/663.js +78 -0
- package/.next/server/chunks/7472.js +1 -1
- package/.next/server/chunks/7824.js +1 -0
- package/.next/server/chunks/7905.js +1 -0
- package/.next/server/chunks/880.js +1 -1
- package/.next/server/chunks/8807.js +84 -18
- package/.next/server/chunks/9130.js +5 -0
- package/.next/server/chunks/9328.js +1 -1
- package/.next/server/chunks/9358.js +1 -1
- package/.next/server/chunks/9508.js +1 -1
- package/.next/server/chunks/9584.js +1 -0
- package/.next/server/chunks/9627.js +274 -0
- package/.next/server/chunks/9798.js +2 -0
- package/.next/server/chunks/9938.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1188-8567ee5ecfef02ee.js +1 -0
- package/.next/static/chunks/3361-aa1b6e7c1d7eeeb4.js +1 -0
- package/.next/static/chunks/3968-8d8ca15657748bfb.js +1 -0
- package/.next/static/chunks/6381-d921ab728eda1191.js +1 -0
- package/.next/static/chunks/app/api/app/update/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/app/update-check/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/conversation/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/current-output/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/messages/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/session/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/start/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/terminal/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/assistant/tools/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/capabilities/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/status/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/external-apps/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/fs/browse/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/fs/recent-paths/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/hooks/agent-event/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/hooks/claude-done/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/hooks/permission-request/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/metrics/vibe/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/ollama/models/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/push/escalation/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/push/subscriptions/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/push/vapid/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/excluded/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/restore/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/scan/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/sync/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/repositories/validate-path/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/sidebar/group-order/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/skills/[id]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/skills/installations/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/skills/operations/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/skills/reindex/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/skills/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/slash-commands/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/templates/[id]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/templates/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/todos/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/more/page-03867ab635d197c7.js +1 -0
- package/.next/static/chunks/app/proxy/[...path]/route-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/review/page-9a6d18ddcccbb63c.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/layout-9247d6b9d647f750.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-27b7cb2e77099eec.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-00ad5d9a62a71cab.js +1 -0
- package/.next/static/css/98722bc4152cedcc.css +1 -0
- package/.next/trace +13 -13
- package/.next/types/app/api/worktrees/[id]/instances/opencode/route.ts +347 -0
- package/.next/types/app/api/worktrees/[id]/opencode/diff/route.ts +347 -0
- package/.next/types/app/api/worktrees/[id]/opencode/session/route.ts +347 -0
- package/.next/types/app/api/worktrees/[id]/opencode/share/route.ts +347 -0
- package/.next/types/routes.d.ts +5 -1
- package/.next/types/validator.ts +36 -0
- package/README.md +9 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +66 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +46 -1
- package/dist/cli/commands/interrupt.d.ts +25 -0
- package/dist/cli/commands/interrupt.d.ts.map +1 -0
- package/dist/cli/commands/interrupt.js +146 -0
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +11 -4
- package/dist/cli/commands/respond.d.ts.map +1 -1
- package/dist/cli/commands/respond.js +146 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +104 -0
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +39 -1
- package/dist/cli/config/agent-target-options.d.ts +12 -0
- package/dist/cli/config/agent-target-options.d.ts.map +1 -1
- package/dist/cli/config/agent-target-options.js +15 -1
- 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 +34 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +6 -0
- package/dist/cli/types/api-responses.d.ts +375 -0
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/types/index.d.ts +63 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/types/index.js +31 -1
- package/dist/cli/utils/daemon.d.ts.map +1 -1
- package/dist/cli/utils/daemon.js +3 -0
- package/dist/cli/utils/env-setup.d.ts +24 -0
- package/dist/cli/utils/env-setup.d.ts.map +1 -1
- package/dist/cli/utils/env-setup.js +70 -0
- package/dist/cli/utils/vapid-keygen.d.ts +74 -0
- package/dist/cli/utils/vapid-keygen.d.ts.map +1 -0
- package/dist/cli/utils/vapid-keygen.js +111 -0
- package/dist/lib/cli-tools/types.d.ts +11 -1
- package/dist/lib/cli-tools/types.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.d.ts +14 -3
- package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.js +14 -3
- package/dist/lib/push/vapid.d.ts +178 -0
- package/dist/lib/push/vapid.d.ts.map +1 -0
- package/dist/lib/push/vapid.js +293 -0
- package/dist/lib/server/localhost-self-check.d.ts +203 -0
- package/dist/lib/server/localhost-self-check.d.ts.map +1 -0
- package/dist/lib/server/localhost-self-check.js +333 -0
- package/dist/server/locales/en/notifications.json +23 -1
- package/dist/server/locales/ja/notifications.json +23 -1
- package/dist/server/server.js +103 -0
- package/dist/server/src/config/image-extensions.js +244 -0
- package/dist/server/src/config/opencode-constants.js +69 -0
- package/dist/server/src/config/tmux-pane-config.js +100 -1
- package/dist/server/src/lib/cli-tools/base.js +33 -48
- package/dist/server/src/lib/cli-tools/opencode-config.js +12 -0
- package/dist/server/src/lib/cli-tools/opencode.js +435 -7
- package/dist/server/src/lib/cli-tools/start-availability.js +160 -0
- package/dist/server/src/lib/cmate-cli-tool-parser.js +328 -7
- package/dist/server/src/lib/cmate-parser.js +12 -0
- package/dist/server/src/lib/db/agent-instances-db.js +129 -0
- package/dist/server/src/lib/db/agent-session-cost-db.js +204 -0
- package/dist/server/src/lib/db/agent-session-cost-sampler.js +194 -0
- package/dist/server/src/lib/db/chat-db.js +33 -0
- package/dist/server/src/lib/db/db-instance.js +11 -0
- package/dist/server/src/lib/db/db.js +8 -3
- package/dist/server/src/lib/db/migrations/index.js +6 -0
- package/dist/server/src/lib/db/migrations/runner.js +1 -1
- package/dist/server/src/lib/db/migrations/v57-push-subscription-defaults-notice.js +54 -0
- package/dist/server/src/lib/db/migrations/v58-agent-session-costs.js +100 -0
- package/dist/server/src/lib/db/migrations/v59-opencode-instance-settings.js +71 -0
- package/dist/server/src/lib/db/push-subscriptions-db.js +56 -5
- package/dist/server/src/lib/detection/cli-patterns.js +17 -6
- package/dist/server/src/lib/detection/excerpt.js +48 -0
- package/dist/server/src/lib/detection/model-info-extractor.js +26 -3
- package/dist/server/src/lib/detection/opencode-modal-overlay.js +400 -0
- package/dist/server/src/lib/detection/opencode-pane-obstruction.js +181 -0
- package/dist/server/src/lib/detection/status-detector.js +7 -0
- package/dist/server/src/lib/detection/status-reason.js +20 -0
- package/dist/server/src/lib/detection/terminal-columns.js +94 -0
- package/dist/server/src/lib/detection/tools/opencode/detect.js +43 -0
- package/dist/server/src/lib/detection/tools/opencode/prompt.js +20 -0
- package/dist/server/src/lib/detection/tools/verified-against.js +14 -3
- package/dist/server/src/lib/detection/upstream-faults.js +7 -22
- package/dist/server/src/lib/hooks/agent-session-telemetry.js +324 -0
- package/dist/server/src/lib/hooks/pending-decision-kind.js +72 -0
- package/dist/server/src/lib/hooks/sources/define-source.js +88 -0
- package/dist/server/src/lib/hooks/sources/opencode/client.js +907 -2
- package/dist/server/src/lib/hooks/sources/opencode/diff.js +336 -0
- package/dist/server/src/lib/hooks/sources/opencode/history.js +480 -0
- package/dist/server/src/lib/hooks/sources/opencode/ingest.js +76 -7
- package/dist/server/src/lib/hooks/sources/opencode/launch-settings.js +222 -0
- package/dist/server/src/lib/hooks/sources/opencode/mappers.js +31 -0
- package/dist/server/src/lib/hooks/sources/opencode/payloads.js +45 -0
- package/dist/server/src/lib/hooks/sources/opencode/ports.js +16 -0
- package/dist/server/src/lib/hooks/sources/opencode/push.js +307 -0
- package/dist/server/src/lib/hooks/sources/opencode/reattach.js +284 -0
- package/dist/server/src/lib/hooks/sources/opencode/runtime.js +165 -2
- package/dist/server/src/lib/hooks/sources/opencode/source.js +46 -2
- package/dist/server/src/lib/hooks/sources/opencode/subscription.js +407 -4
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +383 -0
- package/dist/server/src/lib/hooks/structured-decision-response.js +460 -0
- package/dist/server/src/lib/job-executor.js +43 -20
- package/dist/server/src/lib/polling/response-checker.js +43 -16
- package/dist/server/src/lib/polling/structured-history-gate.js +75 -0
- package/dist/server/src/lib/prompt-answer-sender.js +153 -2
- package/dist/server/src/lib/push/delivery-health.js +237 -0
- package/dist/server/src/lib/push/failure-push-notifier.js +109 -7
- package/dist/server/src/lib/push/index.js +25 -1
- package/dist/server/src/lib/push/prompt-card-state.js +254 -14
- package/dist/server/src/lib/push/push-sender.js +63 -12
- package/dist/server/src/lib/push/resolution-push-notifier.js +15 -3
- package/dist/server/src/lib/push/vapid.js +264 -5
- package/dist/server/src/lib/push/waiting-push-notifier.js +7 -0
- package/dist/server/src/lib/server/localhost-self-check.js +333 -0
- package/dist/server/src/lib/session/agent-event-state.js +169 -4
- package/dist/server/src/lib/session/claude-executor.js +152 -15
- package/dist/server/src/lib/session/current-output-builder.js +182 -15
- package/dist/server/src/lib/session/opencode-session-api.js +214 -0
- package/dist/server/src/lib/session/opencode-session-recall.js +168 -0
- package/dist/server/src/lib/session/opencode-session-store.js +274 -0
- package/dist/server/src/lib/session/provisional-turn.js +54 -1
- package/dist/server/src/lib/session/send-user-message.js +6 -5
- package/dist/server/src/lib/session/structured-prompt.js +53 -2
- package/dist/server/src/lib/skills/compatibility-matrix.js +50 -1
- package/dist/server/src/lib/tmux/tmux.js +74 -4
- package/dist/server/src/lib/verification/gate-runner.js +71 -8
- package/dist/server/src/types/agent-session.js +63 -0
- package/dist/server/src/types/agent-transcript.js +80 -0
- package/dist/server/src/types/opencode-export.js +228 -0
- package/dist/server/src/types/opencode-instance-settings.js +140 -0
- package/dist/server/src/types/opencode-share.js +111 -0
- package/dist/server/src/types/terminal-keys.js +69 -1
- package/dist/types/cli-tool-contracts.d.ts +48 -0
- package/dist/types/cli-tool-contracts.d.ts.map +1 -1
- package/dist/types/terminal-keys.d.ts +89 -0
- package/dist/types/terminal-keys.d.ts.map +1 -0
- package/dist/types/terminal-keys.js +105 -0
- package/package.json +1 -1
- package/.next/server/chunks/1029.js +0 -1
- package/.next/server/chunks/1239.js +0 -1
- package/.next/server/chunks/1538.js +0 -7
- package/.next/server/chunks/2546.js +0 -1
- package/.next/server/chunks/2689.js +0 -13
- package/.next/server/chunks/3292.js +0 -1
- package/.next/server/chunks/3417.js +0 -1
- package/.next/server/chunks/3736.js +0 -1
- package/.next/server/chunks/4423.js +0 -1
- package/.next/server/chunks/4444.js +0 -32
- package/.next/server/chunks/4565.js +0 -3
- package/.next/server/chunks/467.js +0 -1
- package/.next/server/chunks/4905.js +0 -5
- package/.next/server/chunks/552.js +0 -19
- package/.next/server/chunks/5998.js +0 -74
- package/.next/server/chunks/6919.js +0 -1
- package/.next/server/chunks/7970.js +0 -229
- package/.next/server/chunks/8536.js +0 -1
- package/.next/server/chunks/9284.js +0 -1
- package/.next/static/chunks/3361-5d6e93fba8a92bc1.js +0 -1
- package/.next/static/chunks/6381-b7250e8ca7a44c6c.js +0 -1
- package/.next/static/chunks/8521-c43994fb58501d13.js +0 -1
- package/.next/static/chunks/app/api/app/update/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/app/update-check/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/conversation/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/current-output/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/messages/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/session/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/start/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/terminal/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/assistant/tools/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/auth/login/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/auth/status/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/capabilities/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/status/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/external-apps/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/fs/browse/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/fs/recent-paths/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/hooks/agent-event/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/hooks/claude-done/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/hooks/permission-request/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/metrics/vibe/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/ollama/models/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/push/escalation/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/push/subscriptions/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/push/vapid/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/excluded/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/restore/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/scan/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/sync/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/repositories/validate-path/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/sidebar/group-order/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/skills/[id]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/skills/installations/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/skills/operations/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/skills/reindex/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/skills/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/slash-commands/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/templates/[id]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/templates/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/todos/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/more/page-3266dfa945972649.js +0 -1
- package/.next/static/chunks/app/proxy/[...path]/route-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/review/page-8f63aff862fee421.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/layout-6add0d88e2828c23.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-e4f28966b4fc0ce1.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-a75fe180a7233b2b.js +0 -1
- package/.next/static/css/928e5a8830fbf997.css +0 -1
- /package/.next/static/{t0BoV4H46ZgKmTjSi7GIz → 0GHE2JGlFzqvSBZAcBFSt}/_buildManifest.js +0 -0
- /package/.next/static/{t0BoV4H46ZgKmTjSi7GIz → 0GHE2JGlFzqvSBZAcBFSt}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VAPID configuration for Web Push, and the one startup check that reports on it
|
|
3
|
+
* (Issue #1125; the check and the subject rules are Issues #2123 / #2124).
|
|
4
|
+
*
|
|
5
|
+
* Keys are supplied via environment variables and read lazily so tests can vary
|
|
6
|
+
* them and so an unconfigured deployment simply disables push (never crashes).
|
|
7
|
+
* The private key and subject are secrets — never log the returned config.
|
|
8
|
+
*
|
|
9
|
+
* ## Why the default subject is an https: URL (Issue #2124)
|
|
10
|
+
*
|
|
11
|
+
* The VAPID `sub` claim is the sender's contact, and **Apple validates it**. The
|
|
12
|
+
* original default, `mailto:commandmate@localhost`, names a domain that cannot
|
|
13
|
+
* exist, so APNs answered 403 and iOS/iPadOS received nothing while Android kept
|
|
14
|
+
* working — FCM is permissive about `sub`, so testing on Android alone cannot
|
|
15
|
+
* see it. Measured by the orchestrator during the Epic #2002 device UAT
|
|
16
|
+
* (2026-08-27, develop e8d09989), fanning ONE waiting notification to two
|
|
17
|
+
* devices:
|
|
18
|
+
*
|
|
19
|
+
* Android 10 / Chrome 151 -> FCM default subject: delivered
|
|
20
|
+
* iPad / iPadOS 18.7 -> APNs default subject: 403, push-send-failed
|
|
21
|
+
* https://github.com/Kewton/CommandMate: delivered
|
|
22
|
+
*
|
|
23
|
+
* This file's author did NOT reproduce that on hardware; the APNs/FCM behaviour
|
|
24
|
+
* above is quoted from that UAT and is not re-measured here. What IS pinned by
|
|
25
|
+
* the unit suite is the pure part: which subjects this module accepts and which
|
|
26
|
+
* it flags, and that the default is one of the accepted ones.
|
|
27
|
+
*
|
|
28
|
+
* RFC 8292 §2.1 allows both `mailto:` and `https:` for `sub`, so a project URL
|
|
29
|
+
* is a conforming default that needs no per-install mailbox.
|
|
30
|
+
*
|
|
31
|
+
* ## Why an invalid subject is reported and NOT replaced
|
|
32
|
+
*
|
|
33
|
+
* {@link inspectVapidConfig} flags a bad `CM_VAPID_SUBJECT`; {@link getVapidConfig}
|
|
34
|
+
* still returns it verbatim. Silently substituting the default would make the
|
|
35
|
+
* warning describe a value the server does not actually send, and would make
|
|
36
|
+
* `commandmate status` disagree with the wire. The operator set it; they are told
|
|
37
|
+
* it will be rejected, and startup is never blocked (fail-open, exactly as
|
|
38
|
+
* `lib/server/localhost-self-check` is).
|
|
39
|
+
*
|
|
40
|
+
* ## No `@/` imports here, ever
|
|
41
|
+
*
|
|
42
|
+
* `src/cli/commands/status.ts` imports this module so the CLI and the server run
|
|
43
|
+
* the SAME check, and `tsconfig.cli.json` resets `paths` to `{}` — an alias
|
|
44
|
+
* import here would break `npm run build:cli`. Same constraint as
|
|
45
|
+
* `lib/server/localhost-self-check.ts` and `lib/detection/version-probes.ts`.
|
|
46
|
+
* This module must also stay dependency-free for that reason.
|
|
47
|
+
*
|
|
48
|
+
* @module lib/push/vapid
|
|
49
|
+
*/
|
|
50
|
+
export interface VapidConfig {
|
|
51
|
+
publicKey: string;
|
|
52
|
+
privateKey: string;
|
|
53
|
+
subject: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Default `sub` claim when `CM_VAPID_SUBJECT` is unset.
|
|
57
|
+
*
|
|
58
|
+
* A real, resolvable https: URL — see the module header for the APNs measurement
|
|
59
|
+
* that made `mailto:commandmate@localhost` the wrong answer (Issue #2124).
|
|
60
|
+
*/
|
|
61
|
+
export declare const VAPID_DEFAULT_SUBJECT = "https://github.com/Kewton/CommandMate";
|
|
62
|
+
/** The three environment variables that configure Web Push. */
|
|
63
|
+
export declare const VAPID_ENV_KEYS: {
|
|
64
|
+
readonly publicKey: "CM_VAPID_PUBLIC_KEY";
|
|
65
|
+
readonly privateKey: "CM_VAPID_PRIVATE_KEY";
|
|
66
|
+
readonly subject: "CM_VAPID_SUBJECT";
|
|
67
|
+
};
|
|
68
|
+
/** What is wrong with a `CM_VAPID_SUBJECT`, or `null` when nothing is. */
|
|
69
|
+
export type VapidSubjectIssue =
|
|
70
|
+
/** Neither `mailto:` nor `https:` — RFC 8292 §2.1 allows only those two. */
|
|
71
|
+
'unsupported-scheme'
|
|
72
|
+
/** Parsed as a supported scheme but carries no host at all. */
|
|
73
|
+
| 'missing-host'
|
|
74
|
+
/** A host no push service can resolve: `localhost`, a bare name, a reserved TLD, a loopback literal. */
|
|
75
|
+
| 'non-routable-host';
|
|
76
|
+
/**
|
|
77
|
+
* The host a subject names, lowercased, or `null` when it names none.
|
|
78
|
+
*
|
|
79
|
+
* `mailto:` takes everything after the LAST `@` (a local part may legally contain
|
|
80
|
+
* one when quoted) up to the first `?` (RFC 6068 header separator). `https:` is
|
|
81
|
+
* parsed by `URL`, whose `hostname` already strips the brackets off an IPv6
|
|
82
|
+
* literal.
|
|
83
|
+
*/
|
|
84
|
+
export declare function extractVapidSubjectHost(subject: string): string | null;
|
|
85
|
+
/**
|
|
86
|
+
* Decide whether a `sub` claim is one a push service can be expected to accept.
|
|
87
|
+
*
|
|
88
|
+
* Deliberately conservative: it rejects only hosts that provably cannot resolve.
|
|
89
|
+
* A reachable-but-wrong contact (`mailto:nobody@example.com`) is the operator's
|
|
90
|
+
* business, and a check that guessed at it would warn on healthy installs.
|
|
91
|
+
*
|
|
92
|
+
* @param subject - Raw `CM_VAPID_SUBJECT`, or the default.
|
|
93
|
+
* @returns The problem, or `null` when the subject is usable.
|
|
94
|
+
*/
|
|
95
|
+
export declare function classifyVapidSubject(subject: string): VapidSubjectIssue | null;
|
|
96
|
+
/** How a deployment's Web Push configuration reads right now. */
|
|
97
|
+
export type VapidStatus =
|
|
98
|
+
/** Neither key is set: push is off, and nothing was half-configured. */
|
|
99
|
+
'unconfigured'
|
|
100
|
+
/** Exactly one of the two keys is set — almost always a typo or a half-finished edit. */
|
|
101
|
+
| 'partial'
|
|
102
|
+
/** Both keys present, but `CM_VAPID_SUBJECT` will be rejected by at least APNs. */
|
|
103
|
+
| 'invalid-subject'
|
|
104
|
+
/** Both keys present and the subject is usable. Nothing to report. */
|
|
105
|
+
| 'ok';
|
|
106
|
+
/** The single verdict {@link inspectVapidConfig} produces (Issues #2123 / #2124). */
|
|
107
|
+
export interface VapidInspection {
|
|
108
|
+
status: VapidStatus;
|
|
109
|
+
/** True when both keys are present, i.e. when push can send at all. */
|
|
110
|
+
configured: boolean;
|
|
111
|
+
/** The `sub` claim that will actually be sent. */
|
|
112
|
+
subject: string;
|
|
113
|
+
/** Whether {@link subject} came from the environment or from the built-in default. */
|
|
114
|
+
subjectSource: 'env' | 'default';
|
|
115
|
+
/** What is wrong with {@link subject}, or `null`. */
|
|
116
|
+
subjectIssue: VapidSubjectIssue | null;
|
|
117
|
+
/** Names of the VAPID variables that are set — never their values. */
|
|
118
|
+
presentKeys: readonly string[];
|
|
119
|
+
/** Names of the key variables that are missing. */
|
|
120
|
+
missingKeys: readonly string[];
|
|
121
|
+
}
|
|
122
|
+
/** The slice of the environment this module reads. */
|
|
123
|
+
export type VapidEnv = Readonly<Record<string, string | undefined>>;
|
|
124
|
+
/**
|
|
125
|
+
* Read the three variables and say, in one verdict, everything both Issues need
|
|
126
|
+
* reported: whether push is on at all (#2123) and whether the subject will be
|
|
127
|
+
* accepted (#2124).
|
|
128
|
+
*
|
|
129
|
+
* ONE check, two facts — deliberately not two checks. The startup log, the
|
|
130
|
+
* `commandmate status` output and the unit suite all consume this one function,
|
|
131
|
+
* so the two surfaces cannot drift apart.
|
|
132
|
+
*
|
|
133
|
+
* Pure: no I/O, no logging, never throws.
|
|
134
|
+
*
|
|
135
|
+
* @param env - Environment to read (default: `process.env`). `commandmate status`
|
|
136
|
+
* passes the env the *daemon* runs with, which is not this process's own.
|
|
137
|
+
*/
|
|
138
|
+
export declare function inspectVapidConfig(env?: VapidEnv): VapidInspection;
|
|
139
|
+
/**
|
|
140
|
+
* The startup / `status` report, as lines — shared by both surfaces so they can
|
|
141
|
+
* never drift apart, exactly as `formatLocalhostConflictWarning` is (#2113).
|
|
142
|
+
*
|
|
143
|
+
* **Returns an empty array when the configuration is healthy.** That silence is
|
|
144
|
+
* the negative control both Issues ask for: a correctly configured server prints
|
|
145
|
+
* nothing about push, so the presence of a line is itself the signal.
|
|
146
|
+
*
|
|
147
|
+
* Never includes a key or a private value. `subject` is printed because it is the
|
|
148
|
+
* value the operator has to fix, and it is a contact address rather than a
|
|
149
|
+
* credential — the module header's "never log the config" rule is about the keys.
|
|
150
|
+
*/
|
|
151
|
+
export declare function formatVapidReportLines(inspection: VapidInspection): string[];
|
|
152
|
+
/** Options for {@link runVapidSelfCheck}. */
|
|
153
|
+
export interface RunVapidSelfCheckOptions {
|
|
154
|
+
/** Environment to inspect (default: `process.env`). */
|
|
155
|
+
env?: VapidEnv;
|
|
156
|
+
/** Where the report goes (default: `console.warn`). */
|
|
157
|
+
warn?: (message: string) => void;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Run the startup self-check and print its verdict, or nothing when healthy.
|
|
161
|
+
*
|
|
162
|
+
* Fail-open by construction, the same contract `runLocalhostSelfCheck` carries:
|
|
163
|
+
* it never throws, it never blocks `listen`, and a healthy install is silent.
|
|
164
|
+
*
|
|
165
|
+
* @returns The inspection, or `null` when the check itself could not be carried
|
|
166
|
+
* out (which is reported as nothing at all).
|
|
167
|
+
*/
|
|
168
|
+
export declare function runVapidSelfCheck(options?: RunVapidSelfCheckOptions): VapidInspection | null;
|
|
169
|
+
/**
|
|
170
|
+
* Returns the VAPID config, or null when push is not configured (both public
|
|
171
|
+
* and private keys must be present). Read from env on every call.
|
|
172
|
+
*/
|
|
173
|
+
export declare function getVapidConfig(): VapidConfig | null;
|
|
174
|
+
/** True when both VAPID keys are configured. */
|
|
175
|
+
export declare function isPushConfigured(): boolean;
|
|
176
|
+
/** The public (application server) key clients need to subscribe, or null. */
|
|
177
|
+
export declare function getVapidPublicKey(): string | null;
|
|
178
|
+
//# sourceMappingURL=vapid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vapid.d.ts","sourceRoot":"","sources":["../../../src/lib/push/vapid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,0CAA0C,CAAC;AAE7E,+DAA+D;AAC/D,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAuBX,0EAA0E;AAC1E,MAAM,MAAM,iBAAiB;AAC3B,4EAA4E;AAC1E,oBAAoB;AACtB,+DAA+D;GAC7D,cAAc;AAChB,wGAAwG;GACtG,mBAAmB,CAAC;AAQxB;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAe9E;AAED,iEAAiE;AACjE,MAAM,MAAM,WAAW;AACrB,wEAAwE;AACtE,cAAc;AAChB,yFAAyF;GACvF,SAAS;AACX,mFAAmF;GACjF,iBAAiB;AACnB,sEAAsE;GACpE,IAAI,CAAC;AAET,qFAAqF;AACrF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,uEAAuE;IACvE,UAAU,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,aAAa,EAAE,KAAK,GAAG,SAAS,CAAC;IACjC,qDAAqD;IACrD,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,sEAAsE;IACtE,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,mDAAmD;IACnD,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,sDAAsD;AACtD,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,QAAsB,GAAG,eAAe,CAiC/E;AAcD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,eAAe,GAAG,MAAM,EAAE,CAiC5E;AAED,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,uDAAuD;IACvD,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,uDAAuD;IACvD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,eAAe,GAAG,IAAI,CAahG;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAQnD;AAED,gDAAgD;AAChD,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VAPID configuration for Web Push, and the one startup check that reports on it
|
|
4
|
+
* (Issue #1125; the check and the subject rules are Issues #2123 / #2124).
|
|
5
|
+
*
|
|
6
|
+
* Keys are supplied via environment variables and read lazily so tests can vary
|
|
7
|
+
* them and so an unconfigured deployment simply disables push (never crashes).
|
|
8
|
+
* The private key and subject are secrets — never log the returned config.
|
|
9
|
+
*
|
|
10
|
+
* ## Why the default subject is an https: URL (Issue #2124)
|
|
11
|
+
*
|
|
12
|
+
* The VAPID `sub` claim is the sender's contact, and **Apple validates it**. The
|
|
13
|
+
* original default, `mailto:commandmate@localhost`, names a domain that cannot
|
|
14
|
+
* exist, so APNs answered 403 and iOS/iPadOS received nothing while Android kept
|
|
15
|
+
* working — FCM is permissive about `sub`, so testing on Android alone cannot
|
|
16
|
+
* see it. Measured by the orchestrator during the Epic #2002 device UAT
|
|
17
|
+
* (2026-08-27, develop e8d09989), fanning ONE waiting notification to two
|
|
18
|
+
* devices:
|
|
19
|
+
*
|
|
20
|
+
* Android 10 / Chrome 151 -> FCM default subject: delivered
|
|
21
|
+
* iPad / iPadOS 18.7 -> APNs default subject: 403, push-send-failed
|
|
22
|
+
* https://github.com/Kewton/CommandMate: delivered
|
|
23
|
+
*
|
|
24
|
+
* This file's author did NOT reproduce that on hardware; the APNs/FCM behaviour
|
|
25
|
+
* above is quoted from that UAT and is not re-measured here. What IS pinned by
|
|
26
|
+
* the unit suite is the pure part: which subjects this module accepts and which
|
|
27
|
+
* it flags, and that the default is one of the accepted ones.
|
|
28
|
+
*
|
|
29
|
+
* RFC 8292 §2.1 allows both `mailto:` and `https:` for `sub`, so a project URL
|
|
30
|
+
* is a conforming default that needs no per-install mailbox.
|
|
31
|
+
*
|
|
32
|
+
* ## Why an invalid subject is reported and NOT replaced
|
|
33
|
+
*
|
|
34
|
+
* {@link inspectVapidConfig} flags a bad `CM_VAPID_SUBJECT`; {@link getVapidConfig}
|
|
35
|
+
* still returns it verbatim. Silently substituting the default would make the
|
|
36
|
+
* warning describe a value the server does not actually send, and would make
|
|
37
|
+
* `commandmate status` disagree with the wire. The operator set it; they are told
|
|
38
|
+
* it will be rejected, and startup is never blocked (fail-open, exactly as
|
|
39
|
+
* `lib/server/localhost-self-check` is).
|
|
40
|
+
*
|
|
41
|
+
* ## No `@/` imports here, ever
|
|
42
|
+
*
|
|
43
|
+
* `src/cli/commands/status.ts` imports this module so the CLI and the server run
|
|
44
|
+
* the SAME check, and `tsconfig.cli.json` resets `paths` to `{}` — an alias
|
|
45
|
+
* import here would break `npm run build:cli`. Same constraint as
|
|
46
|
+
* `lib/server/localhost-self-check.ts` and `lib/detection/version-probes.ts`.
|
|
47
|
+
* This module must also stay dependency-free for that reason.
|
|
48
|
+
*
|
|
49
|
+
* @module lib/push/vapid
|
|
50
|
+
*/
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.VAPID_ENV_KEYS = exports.VAPID_DEFAULT_SUBJECT = void 0;
|
|
53
|
+
exports.extractVapidSubjectHost = extractVapidSubjectHost;
|
|
54
|
+
exports.classifyVapidSubject = classifyVapidSubject;
|
|
55
|
+
exports.inspectVapidConfig = inspectVapidConfig;
|
|
56
|
+
exports.formatVapidReportLines = formatVapidReportLines;
|
|
57
|
+
exports.runVapidSelfCheck = runVapidSelfCheck;
|
|
58
|
+
exports.getVapidConfig = getVapidConfig;
|
|
59
|
+
exports.isPushConfigured = isPushConfigured;
|
|
60
|
+
exports.getVapidPublicKey = getVapidPublicKey;
|
|
61
|
+
/**
|
|
62
|
+
* Default `sub` claim when `CM_VAPID_SUBJECT` is unset.
|
|
63
|
+
*
|
|
64
|
+
* A real, resolvable https: URL — see the module header for the APNs measurement
|
|
65
|
+
* that made `mailto:commandmate@localhost` the wrong answer (Issue #2124).
|
|
66
|
+
*/
|
|
67
|
+
exports.VAPID_DEFAULT_SUBJECT = 'https://github.com/Kewton/CommandMate';
|
|
68
|
+
/** The three environment variables that configure Web Push. */
|
|
69
|
+
exports.VAPID_ENV_KEYS = {
|
|
70
|
+
publicKey: 'CM_VAPID_PUBLIC_KEY',
|
|
71
|
+
privateKey: 'CM_VAPID_PRIVATE_KEY',
|
|
72
|
+
subject: 'CM_VAPID_SUBJECT',
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Host suffixes that never resolve on the public internet, so a push service can
|
|
76
|
+
* never verify a `sub` that names one.
|
|
77
|
+
*
|
|
78
|
+
* `.example` is here as a *TLD*; `example.com` is an ordinary resolvable domain
|
|
79
|
+
* and is deliberately NOT rejected (it is the conventional placeholder in every
|
|
80
|
+
* VAPID tutorial and in this repository's own tests).
|
|
81
|
+
*/
|
|
82
|
+
const NON_ROUTABLE_TLDS = [
|
|
83
|
+
'local',
|
|
84
|
+
'localhost',
|
|
85
|
+
'localdomain',
|
|
86
|
+
'internal',
|
|
87
|
+
'intranet',
|
|
88
|
+
'home',
|
|
89
|
+
'lan',
|
|
90
|
+
'test',
|
|
91
|
+
'invalid',
|
|
92
|
+
'example',
|
|
93
|
+
];
|
|
94
|
+
/** Loopback / unspecified literals, which are never a contact anyone can reach. */
|
|
95
|
+
function isLoopbackLiteral(host) {
|
|
96
|
+
if (host === '::1' || host === '0.0.0.0' || host === '::')
|
|
97
|
+
return true;
|
|
98
|
+
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The host a subject names, lowercased, or `null` when it names none.
|
|
102
|
+
*
|
|
103
|
+
* `mailto:` takes everything after the LAST `@` (a local part may legally contain
|
|
104
|
+
* one when quoted) up to the first `?` (RFC 6068 header separator). `https:` is
|
|
105
|
+
* parsed by `URL`, whose `hostname` already strips the brackets off an IPv6
|
|
106
|
+
* literal.
|
|
107
|
+
*/
|
|
108
|
+
function extractVapidSubjectHost(subject) {
|
|
109
|
+
const trimmed = subject.trim();
|
|
110
|
+
if (/^mailto:/i.test(trimmed)) {
|
|
111
|
+
const address = trimmed.slice('mailto:'.length).split('?')[0];
|
|
112
|
+
const at = address.lastIndexOf('@');
|
|
113
|
+
if (at < 0)
|
|
114
|
+
return null;
|
|
115
|
+
const host = address.slice(at + 1).trim().toLowerCase();
|
|
116
|
+
return host.length > 0 ? host : null;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const url = new URL(trimmed);
|
|
120
|
+
return url.hostname.length > 0 ? url.hostname.toLowerCase() : null;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Decide whether a `sub` claim is one a push service can be expected to accept.
|
|
128
|
+
*
|
|
129
|
+
* Deliberately conservative: it rejects only hosts that provably cannot resolve.
|
|
130
|
+
* A reachable-but-wrong contact (`mailto:nobody@example.com`) is the operator's
|
|
131
|
+
* business, and a check that guessed at it would warn on healthy installs.
|
|
132
|
+
*
|
|
133
|
+
* @param subject - Raw `CM_VAPID_SUBJECT`, or the default.
|
|
134
|
+
* @returns The problem, or `null` when the subject is usable.
|
|
135
|
+
*/
|
|
136
|
+
function classifyVapidSubject(subject) {
|
|
137
|
+
const trimmed = subject.trim();
|
|
138
|
+
if (!/^(mailto:|https:\/\/)/i.test(trimmed))
|
|
139
|
+
return 'unsupported-scheme';
|
|
140
|
+
const host = extractVapidSubjectHost(trimmed);
|
|
141
|
+
if (host === null)
|
|
142
|
+
return 'missing-host';
|
|
143
|
+
if (isLoopbackLiteral(host))
|
|
144
|
+
return 'non-routable-host';
|
|
145
|
+
// A bare name (`localhost`, `mac-mini`) has no public resolution path.
|
|
146
|
+
if (!host.includes('.'))
|
|
147
|
+
return 'non-routable-host';
|
|
148
|
+
const tld = host.slice(host.lastIndexOf('.') + 1);
|
|
149
|
+
if (NON_ROUTABLE_TLDS.includes(tld))
|
|
150
|
+
return 'non-routable-host';
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Read the three variables and say, in one verdict, everything both Issues need
|
|
155
|
+
* reported: whether push is on at all (#2123) and whether the subject will be
|
|
156
|
+
* accepted (#2124).
|
|
157
|
+
*
|
|
158
|
+
* ONE check, two facts — deliberately not two checks. The startup log, the
|
|
159
|
+
* `commandmate status` output and the unit suite all consume this one function,
|
|
160
|
+
* so the two surfaces cannot drift apart.
|
|
161
|
+
*
|
|
162
|
+
* Pure: no I/O, no logging, never throws.
|
|
163
|
+
*
|
|
164
|
+
* @param env - Environment to read (default: `process.env`). `commandmate status`
|
|
165
|
+
* passes the env the *daemon* runs with, which is not this process's own.
|
|
166
|
+
*/
|
|
167
|
+
function inspectVapidConfig(env = process.env) {
|
|
168
|
+
const publicKey = env[exports.VAPID_ENV_KEYS.publicKey]?.trim() ?? '';
|
|
169
|
+
const privateKey = env[exports.VAPID_ENV_KEYS.privateKey]?.trim() ?? '';
|
|
170
|
+
const rawSubject = env[exports.VAPID_ENV_KEYS.subject]?.trim() ?? '';
|
|
171
|
+
const presentKeys = [];
|
|
172
|
+
const missingKeys = [];
|
|
173
|
+
(publicKey ? presentKeys : missingKeys).push(exports.VAPID_ENV_KEYS.publicKey);
|
|
174
|
+
(privateKey ? presentKeys : missingKeys).push(exports.VAPID_ENV_KEYS.privateKey);
|
|
175
|
+
const subject = rawSubject || exports.VAPID_DEFAULT_SUBJECT;
|
|
176
|
+
const subjectSource = rawSubject ? 'env' : 'default';
|
|
177
|
+
const subjectIssue = classifyVapidSubject(subject);
|
|
178
|
+
if (rawSubject)
|
|
179
|
+
presentKeys.push(exports.VAPID_ENV_KEYS.subject);
|
|
180
|
+
const configured = publicKey !== '' && privateKey !== '';
|
|
181
|
+
const status = configured
|
|
182
|
+
? subjectIssue === null
|
|
183
|
+
? 'ok'
|
|
184
|
+
: 'invalid-subject'
|
|
185
|
+
: publicKey || privateKey
|
|
186
|
+
? 'partial'
|
|
187
|
+
: 'unconfigured';
|
|
188
|
+
return {
|
|
189
|
+
status,
|
|
190
|
+
configured,
|
|
191
|
+
subject,
|
|
192
|
+
subjectSource,
|
|
193
|
+
subjectIssue,
|
|
194
|
+
presentKeys,
|
|
195
|
+
missingKeys,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** Human-readable reason for a {@link VapidSubjectIssue}. */
|
|
199
|
+
function describeSubjectIssue(issue) {
|
|
200
|
+
switch (issue) {
|
|
201
|
+
case 'unsupported-scheme':
|
|
202
|
+
return 'it is neither a "mailto:" address nor an "https://" URL (RFC 8292 allows only those two)';
|
|
203
|
+
case 'missing-host':
|
|
204
|
+
return 'it names no host at all';
|
|
205
|
+
case 'non-routable-host':
|
|
206
|
+
return 'its host cannot be resolved from the public internet (localhost, a bare name, or a reserved TLD)';
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* The startup / `status` report, as lines — shared by both surfaces so they can
|
|
211
|
+
* never drift apart, exactly as `formatLocalhostConflictWarning` is (#2113).
|
|
212
|
+
*
|
|
213
|
+
* **Returns an empty array when the configuration is healthy.** That silence is
|
|
214
|
+
* the negative control both Issues ask for: a correctly configured server prints
|
|
215
|
+
* nothing about push, so the presence of a line is itself the signal.
|
|
216
|
+
*
|
|
217
|
+
* Never includes a key or a private value. `subject` is printed because it is the
|
|
218
|
+
* value the operator has to fix, and it is a contact address rather than a
|
|
219
|
+
* credential — the module header's "never log the config" rule is about the keys.
|
|
220
|
+
*/
|
|
221
|
+
function formatVapidReportLines(inspection) {
|
|
222
|
+
switch (inspection.status) {
|
|
223
|
+
case 'ok':
|
|
224
|
+
return [];
|
|
225
|
+
case 'unconfigured':
|
|
226
|
+
return [
|
|
227
|
+
'Push notifications are disabled: no VAPID keys are configured.',
|
|
228
|
+
` Set ${exports.VAPID_ENV_KEYS.publicKey} and ${exports.VAPID_ENV_KEYS.privateKey} to enable them.`,
|
|
229
|
+
' "commandmate init" generates a key pair for you.',
|
|
230
|
+
' Setup: docs/user-guide/webapp-guide.md ("Phone notifications")',
|
|
231
|
+
];
|
|
232
|
+
case 'partial':
|
|
233
|
+
return [
|
|
234
|
+
`Push notifications are disabled: ${inspection.missingKeys.join(' and ')} ${inspection.missingKeys.length > 1 ? 'are' : 'is'} not set.`,
|
|
235
|
+
` Both ${exports.VAPID_ENV_KEYS.publicKey} and ${exports.VAPID_ENV_KEYS.privateKey} are required;` +
|
|
236
|
+
' a key pair only works as a pair.',
|
|
237
|
+
' "commandmate init" generates a key pair for you.',
|
|
238
|
+
' Setup: docs/user-guide/webapp-guide.md ("Phone notifications")',
|
|
239
|
+
];
|
|
240
|
+
case 'invalid-subject':
|
|
241
|
+
return [
|
|
242
|
+
`${exports.VAPID_ENV_KEYS.subject}="${inspection.subject}" will be rejected by Apple (APNs):` +
|
|
243
|
+
` ${describeSubjectIssue(inspection.subjectIssue)}.`,
|
|
244
|
+
' iPhone/iPad receive nothing while Android keeps working, because FCM does not check it.',
|
|
245
|
+
` Use a reachable contact, e.g. ${exports.VAPID_DEFAULT_SUBJECT} or mailto:you@your-domain.example.org.`,
|
|
246
|
+
` Unset ${exports.VAPID_ENV_KEYS.subject} to fall back to ${exports.VAPID_DEFAULT_SUBJECT}.`,
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Run the startup self-check and print its verdict, or nothing when healthy.
|
|
252
|
+
*
|
|
253
|
+
* Fail-open by construction, the same contract `runLocalhostSelfCheck` carries:
|
|
254
|
+
* it never throws, it never blocks `listen`, and a healthy install is silent.
|
|
255
|
+
*
|
|
256
|
+
* @returns The inspection, or `null` when the check itself could not be carried
|
|
257
|
+
* out (which is reported as nothing at all).
|
|
258
|
+
*/
|
|
259
|
+
function runVapidSelfCheck(options = {}) {
|
|
260
|
+
const { env = process.env, warn = (message) => console.warn(message) } = options;
|
|
261
|
+
try {
|
|
262
|
+
const inspection = inspectVapidConfig(env);
|
|
263
|
+
for (const line of formatVapidReportLines(inspection)) {
|
|
264
|
+
warn(line);
|
|
265
|
+
}
|
|
266
|
+
return inspection;
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// A diagnostic must never be the reason a server fails to start.
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Returns the VAPID config, or null when push is not configured (both public
|
|
275
|
+
* and private keys must be present). Read from env on every call.
|
|
276
|
+
*/
|
|
277
|
+
function getVapidConfig() {
|
|
278
|
+
const publicKey = process.env[exports.VAPID_ENV_KEYS.publicKey]?.trim();
|
|
279
|
+
const privateKey = process.env[exports.VAPID_ENV_KEYS.privateKey]?.trim();
|
|
280
|
+
if (!publicKey || !privateKey) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
const subject = process.env[exports.VAPID_ENV_KEYS.subject]?.trim() || exports.VAPID_DEFAULT_SUBJECT;
|
|
284
|
+
return { publicKey, privateKey, subject };
|
|
285
|
+
}
|
|
286
|
+
/** True when both VAPID keys are configured. */
|
|
287
|
+
function isPushConfigured() {
|
|
288
|
+
return getVapidConfig() !== null;
|
|
289
|
+
}
|
|
290
|
+
/** The public (application server) key clients need to subscribe, or null. */
|
|
291
|
+
function getVapidPublicKey() {
|
|
292
|
+
return getVapidConfig()?.publicKey ?? null;
|
|
293
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup self-check: does the URL we tell users to open actually reach US?
|
|
3
|
+
* Issue #2113
|
|
4
|
+
*
|
|
5
|
+
* CommandMate binds IPv4 `127.0.0.1` by default (server.ts, `CM_BIND`), but every
|
|
6
|
+
* setup guide sends the user to `http://localhost:<port>`. On macOS `localhost`
|
|
7
|
+
* resolves `::1` (IPv6) BEFORE `127.0.0.1`, and a `0.0.0.0`/`::` bind of ours never
|
|
8
|
+
* covers `::1` either — so an unrelated process holding `::1:<port>` silently owns
|
|
9
|
+
* the address the docs advertise. The browser then talks to that process while
|
|
10
|
+
* CommandMate keeps reporting a healthy `> Ready on http://127.0.0.1:<port>`.
|
|
11
|
+
*
|
|
12
|
+
* Measured 2026-08-27 on develop 54e122a9: `127.0.0.1:3000` answered in 14ms while
|
|
13
|
+
* `localhost:3000` and `[::1]:3000` both timed out after 10s against a stray Next.js
|
|
14
|
+
* dev server. Because the squatter was also Next.js, the browser pulled chunks from
|
|
15
|
+
* the WRONG app and rendered CommandMate's own `error.chunkReload.title`
|
|
16
|
+
* ("Updating to the latest version") — an error screen that looks like ours while
|
|
17
|
+
* not being served by us at all.
|
|
18
|
+
*
|
|
19
|
+
* HOW IDENTITY IS DECIDED (the part that has to be exact):
|
|
20
|
+
*
|
|
21
|
+
* The probe sends a GET to `<protocol>://localhost:<port>/api/auth/status` carrying a
|
|
22
|
+
* one-shot random nonce in `x-cm-self-check`, and our own HTTP server carries a
|
|
23
|
+
* temporary `prependListener('request')` that watches for that nonce. The verdict comes
|
|
24
|
+
* from OUR OWN OBSERVATION of the request, never from trusting the response body:
|
|
25
|
+
*
|
|
26
|
+
* observed the nonce -> 'self' (the advertised URL reaches us)
|
|
27
|
+
* got an HTTP response, no nonce-> 'foreign' (something else answered) <- WARN
|
|
28
|
+
* connection error / timeout -> 'unreachable' (nothing there; browsers fall
|
|
29
|
+
* through to 127.0.0.1) <- silent
|
|
30
|
+
*
|
|
31
|
+
* `/api/auth/status` is deliberately an EXISTING endpoint (it is in
|
|
32
|
+
* AUTH_EXCLUDED_PATHS, touches no DB and mutates nothing), so no diagnostic route had
|
|
33
|
+
* to be added. Nothing in the verdict depends on what it returns, which is why the
|
|
34
|
+
* check still works with auth on, with an IP ACL that would 403 us, and against an
|
|
35
|
+
* HTTPS server with a self-signed certificate.
|
|
36
|
+
*
|
|
37
|
+
* FAIL-OPEN IS THE CONTRACT. Nothing here throws, nothing here blocks `listen`, and
|
|
38
|
+
* only the 'foreign' verdict produces output. 'unreachable' is deliberately silent:
|
|
39
|
+
* an empty `::1` is the NORMAL case on a machine where nothing squats the port, and
|
|
40
|
+
* Node's Happy Eyeballs (and every browser) then falls through to `127.0.0.1`.
|
|
41
|
+
*
|
|
42
|
+
* @module lib/server/localhost-self-check
|
|
43
|
+
*/
|
|
44
|
+
import { type IncomingMessage, type ServerResponse } from 'http';
|
|
45
|
+
/** Header the probe request carries its nonce in */
|
|
46
|
+
export declare const SELF_CHECK_HEADER = "x-cm-self-check";
|
|
47
|
+
/**
|
|
48
|
+
* Endpoint the probe targets. Existing route, in AUTH_EXCLUDED_PATHS
|
|
49
|
+
* (src/config/auth-config.ts), no DB access, no side effects.
|
|
50
|
+
*/
|
|
51
|
+
export declare const SELF_CHECK_PATH = "/api/auth/status";
|
|
52
|
+
/** Hostname the docs advertise, and therefore the one under test */
|
|
53
|
+
export declare const SELF_CHECK_HOSTNAME = "localhost";
|
|
54
|
+
/** How long to wait for either the nonce observation or a response */
|
|
55
|
+
export declare const SELF_CHECK_TIMEOUT_MS = 3000;
|
|
56
|
+
/**
|
|
57
|
+
* Directory (under the config dir) the conflict records live in.
|
|
58
|
+
*
|
|
59
|
+
* `logs/` and not a dedicated `self-check/`: in a local install `getConfigDir()` is the
|
|
60
|
+
* repository checkout itself, and `.gitignore` already ignores `logs/` there (it does
|
|
61
|
+
* the same for `data/`, `skills/`, `temp/` — "service-owned runtime state lands at the
|
|
62
|
+
* repo root"). A new top-level directory would show up as an untracked change in the
|
|
63
|
+
* user's own repository, which for a worktree manager means dirtying a repo it also
|
|
64
|
+
* displays. The record is diagnostic output keyed by port, so `logs/` fits it anyway.
|
|
65
|
+
*/
|
|
66
|
+
export declare const SELF_CHECK_DIR_NAME = "logs";
|
|
67
|
+
/** Filename prefix of a conflict record inside {@link SELF_CHECK_DIR_NAME} */
|
|
68
|
+
export declare const SELF_CHECK_FILE_PREFIX = "self-check-";
|
|
69
|
+
/**
|
|
70
|
+
* What the startup probe concluded.
|
|
71
|
+
*
|
|
72
|
+
* Only `foreign` is actionable; see the module header for why `unreachable` is silent.
|
|
73
|
+
*/
|
|
74
|
+
export type LocalhostProbeVerdict = 'self' | 'foreign' | 'unreachable';
|
|
75
|
+
/**
|
|
76
|
+
* The record a conflicted server leaves behind for `commandmate status`.
|
|
77
|
+
*
|
|
78
|
+
* `pid` is what makes the record trustworthy: `status` only reports it when it matches
|
|
79
|
+
* the PID it just read out of the state file, so a record left by an earlier server on
|
|
80
|
+
* the same port can never be attributed to the current one.
|
|
81
|
+
*/
|
|
82
|
+
export interface LocalhostConflictRecord {
|
|
83
|
+
/** Port the conflict was observed on */
|
|
84
|
+
port: number;
|
|
85
|
+
/** PID of the CommandMate server that observed it */
|
|
86
|
+
pid: number;
|
|
87
|
+
/** CM_BIND as configured */
|
|
88
|
+
bind: string;
|
|
89
|
+
/** URL CommandMate actually listens on */
|
|
90
|
+
boundUrl: string;
|
|
91
|
+
/** URL that was probed, i.e. the one the documentation advertises */
|
|
92
|
+
probedUrl: string;
|
|
93
|
+
/** ISO timestamp of the observation */
|
|
94
|
+
detectedAt: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The slice of `http.Server` the probe needs. Structural on purpose: tests hand it a
|
|
98
|
+
* real `http.Server`, and nothing here should be able to touch the rest of the server.
|
|
99
|
+
*/
|
|
100
|
+
export interface RequestObserver {
|
|
101
|
+
prependListener(event: 'request', listener: (req: IncomingMessage, res: ServerResponse) => void): unknown;
|
|
102
|
+
removeListener(event: 'request', listener: (req: IncomingMessage, res: ServerResponse) => void): unknown;
|
|
103
|
+
}
|
|
104
|
+
/** Options for {@link probeLocalhostIdentity} */
|
|
105
|
+
export interface ProbeLocalhostOptions {
|
|
106
|
+
/** Our own HTTP(S) server, used to observe the probe request landing on us */
|
|
107
|
+
server: RequestObserver;
|
|
108
|
+
/** Port the server listens on */
|
|
109
|
+
port: number;
|
|
110
|
+
/** Protocol the server speaks (default: 'http') */
|
|
111
|
+
protocol?: 'http' | 'https';
|
|
112
|
+
/** Hostname to probe (default: {@link SELF_CHECK_HOSTNAME}); overridden in tests */
|
|
113
|
+
host?: string;
|
|
114
|
+
/** Request path (default: {@link SELF_CHECK_PATH}) */
|
|
115
|
+
path?: string;
|
|
116
|
+
/** Deadline for the whole probe (default: {@link SELF_CHECK_TIMEOUT_MS}) */
|
|
117
|
+
timeoutMs?: number;
|
|
118
|
+
/** Nonce override; generated per call when omitted */
|
|
119
|
+
nonce?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Ask "if a user opens the URL we advertise, do they reach this process?".
|
|
123
|
+
*
|
|
124
|
+
* Resolves as soon as the answer is known — the nonce observation fires on our
|
|
125
|
+
* server's `request` event, i.e. when headers arrive, so a 'self' verdict does not
|
|
126
|
+
* wait for Next.js to render or compile the route.
|
|
127
|
+
*
|
|
128
|
+
* Never rejects.
|
|
129
|
+
*/
|
|
130
|
+
export declare function probeLocalhostIdentity(options: ProbeLocalhostOptions): Promise<LocalhostProbeVerdict>;
|
|
131
|
+
/**
|
|
132
|
+
* Build the dialable URL for a bind address, matching resolveServerEndpoint()'s rule
|
|
133
|
+
* that a wildcard bind is reported as 127.0.0.1.
|
|
134
|
+
*/
|
|
135
|
+
export declare function formatBoundUrl(protocol: 'http' | 'https', bind: string, port: number): string;
|
|
136
|
+
/**
|
|
137
|
+
* The warning, as lines, shared by the startup log and `commandmate status` so the two
|
|
138
|
+
* can never drift apart.
|
|
139
|
+
*/
|
|
140
|
+
export declare function formatLocalhostConflictWarning(record: LocalhostConflictRecord): string[];
|
|
141
|
+
/** Directory holding the per-port conflict records */
|
|
142
|
+
export declare function getSelfCheckDir(): string;
|
|
143
|
+
/**
|
|
144
|
+
* Path of the record for one port (`<configDir>/logs/self-check-<port>.json`).
|
|
145
|
+
*
|
|
146
|
+
* @throws Error when the port is not a plausible TCP port — the value becomes a
|
|
147
|
+
* filename, so it is validated rather than interpolated blindly.
|
|
148
|
+
*/
|
|
149
|
+
export declare function getSelfCheckStatePath(port: number): string;
|
|
150
|
+
/**
|
|
151
|
+
* Persist a conflict for `commandmate status` to read.
|
|
152
|
+
*
|
|
153
|
+
* @returns true when the record was written
|
|
154
|
+
*/
|
|
155
|
+
export declare function writeLocalhostConflict(record: LocalhostConflictRecord): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Read the conflict recorded for a port.
|
|
158
|
+
*
|
|
159
|
+
* Never throws: `status` must keep working on an unreadable, truncated or
|
|
160
|
+
* hand-edited record, and on a machine where the config dir cannot be resolved at all.
|
|
161
|
+
*
|
|
162
|
+
* @returns The record, or null when there is none (or it is unusable)
|
|
163
|
+
*/
|
|
164
|
+
export declare function readLocalhostConflict(port: number): LocalhostConflictRecord | null;
|
|
165
|
+
/**
|
|
166
|
+
* Drop the record for a port. Called on every clean self-check and on shutdown, so a
|
|
167
|
+
* fixed environment stops warning on the next start rather than needing a manual sweep.
|
|
168
|
+
*/
|
|
169
|
+
export declare function clearLocalhostConflict(port: number): void;
|
|
170
|
+
/** Options for {@link runLocalhostSelfCheck} */
|
|
171
|
+
export interface RunLocalhostSelfCheckOptions {
|
|
172
|
+
/** Our own HTTP(S) server */
|
|
173
|
+
server: RequestObserver;
|
|
174
|
+
/** Port the server listens on */
|
|
175
|
+
port: number;
|
|
176
|
+
/** CM_BIND as configured */
|
|
177
|
+
bind: string;
|
|
178
|
+
/** Protocol the server speaks (default: 'http') */
|
|
179
|
+
protocol?: 'http' | 'https';
|
|
180
|
+
/** Hostname to probe (default: {@link SELF_CHECK_HOSTNAME}); overridden in tests */
|
|
181
|
+
host?: string;
|
|
182
|
+
/** Deadline for the probe */
|
|
183
|
+
timeoutMs?: number;
|
|
184
|
+
/** PID to stamp the record with (default: `process.pid`) */
|
|
185
|
+
pid?: number;
|
|
186
|
+
/** Clock, injectable for deterministic tests */
|
|
187
|
+
now?: () => Date;
|
|
188
|
+
/** Where the warning goes (default: `console.warn`) */
|
|
189
|
+
warn?: (message: string) => void;
|
|
190
|
+
/** Probe override, injected by tests */
|
|
191
|
+
probe?: (options: ProbeLocalhostOptions) => Promise<LocalhostProbeVerdict>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Run the startup self-check and route its verdict to the log and the status file.
|
|
195
|
+
*
|
|
196
|
+
* Fail-open by construction: every path is wrapped, the function never rejects, and the
|
|
197
|
+
* caller in server.ts does not await it. A `null` return means the check could not be
|
|
198
|
+
* carried out at all — which is reported as nothing, exactly like 'unreachable'.
|
|
199
|
+
*
|
|
200
|
+
* @returns The verdict, or null when the check itself failed
|
|
201
|
+
*/
|
|
202
|
+
export declare function runLocalhostSelfCheck(options: RunLocalhostSelfCheckOptions): Promise<LocalhostProbeVerdict | null>;
|
|
203
|
+
//# sourceMappingURL=localhost-self-check.d.ts.map
|