commandmate 0.27.1 → 0.29.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 +441 -404
- package/.next/app-path-routes-manifest.json +34 -29
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +9 -9
- package/.next/react-loadable-manifest.json +0 -6
- 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.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.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.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/remote/pair/route.js +2 -0
- package/.next/server/app/api/remote/pair/route.js.nft.json +1 -0
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -0
- 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.js +2 -2
- 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 +34 -29
- package/.next/server/chunks/1058.js +1 -0
- package/.next/server/chunks/1068.js +1 -3
- package/.next/server/chunks/1162.js +1 -1
- 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 +1 -1
- 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/3440.js +1 -1
- package/.next/server/chunks/3480.js +17 -1
- package/.next/server/chunks/3543.js +1 -1
- package/.next/server/chunks/3558.js +1 -0
- package/.next/server/chunks/3945.js +1 -1
- 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 +6 -6
- package/.next/server/chunks/8807.js +84 -18
- package/.next/server/chunks/9123.js +2 -2
- 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/functions-config-manifest.json +3 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/server/src/middleware.js +1 -1
- package/.next/server/src/middleware.js.map +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/5229-580b581fce5aeb52.js +1 -0
- package/.next/static/chunks/6381-c8d93ec301dbc380.js +1 -0
- package/.next/static/chunks/app/api/app/update/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/app/update-check/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/conversation/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/current-output/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/messages/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/session/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/start/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/terminal/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/assistant/tools/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/capabilities/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/status/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/external-apps/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/fs/browse/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/fs/recent-paths/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/hooks/agent-event/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/hooks/claude-done/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/hooks/permission-request/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/metrics/vibe/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/ollama/models/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/push/escalation/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/push/subscriptions/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/push/vapid/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/remote/pair/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/excluded/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/restore/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/scan/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/sync/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/repositories/validate-path/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/sidebar/group-order/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/skills/[id]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/skills/installations/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/skills/operations/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/skills/reindex/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/skills/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/slash-commands/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/templates/[id]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/templates/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/todos/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/login/page-03659dded846ef1d.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/more/page-03867ab635d197c7.js +1 -0
- package/.next/static/chunks/app/proxy/[...path]/route-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/review/page-9a6d18ddcccbb63c.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/layout-e3626364434d521b.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-c07b23b6ca58091c.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-00ad5d9a62a71cab.js +1 -0
- package/.next/static/chunks/webpack-7e79064bfce988d7.js +1 -0
- package/.next/static/css/b6990f889f4f9515.css +1 -0
- package/.next/static/uulKcSOgyxChTo4SipUSF/_buildManifest.js +1 -0
- package/.next/trace +13 -13
- package/.next/types/app/api/remote/pair/route.ts +347 -0
- 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 +6 -1
- package/.next/types/validator.ts +45 -0
- package/README.md +24 -4
- 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/remote.d.ts +248 -0
- package/dist/cli/commands/remote.d.ts.map +1 -0
- package/dist/cli/commands/remote.js +849 -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/config/security-messages.d.ts +25 -0
- package/dist/cli/config/security-messages.d.ts.map +1 -1
- package/dist/cli/config/security-messages.js +43 -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 +12 -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 +83 -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/qr-terminal.d.ts +54 -0
- package/dist/cli/utils/qr-terminal.d.ts.map +1 -0
- package/dist/cli/utils/qr-terminal.js +181 -0
- package/dist/cli/utils/remote-state.d.ts +123 -0
- package/dist/cli/utils/remote-state.d.ts.map +1 -0
- package/dist/cli/utils/remote-state.js +193 -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/config/auth-config.d.ts +1 -1
- package/dist/config/auth-config.d.ts.map +1 -1
- package/dist/config/auth-config.js +5 -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/remote/cloudflare.d.ts +285 -0
- package/dist/lib/remote/cloudflare.d.ts.map +1 -0
- package/dist/lib/remote/cloudflare.js +619 -0
- package/dist/lib/remote/index.d.ts +17 -0
- package/dist/lib/remote/index.d.ts.map +1 -0
- package/dist/lib/remote/index.js +64 -0
- package/dist/lib/remote/provider-registry.d.ts +29 -0
- package/dist/lib/remote/provider-registry.d.ts.map +1 -0
- package/dist/lib/remote/provider-registry.js +73 -0
- package/dist/lib/remote/tailscale.d.ts +268 -0
- package/dist/lib/remote/tailscale.d.ts.map +1 -0
- package/dist/lib/remote/tailscale.js +546 -0
- package/dist/lib/remote/types.d.ts +127 -0
- package/dist/lib/remote/types.d.ts.map +1 -0
- package/dist/lib/remote/types.js +53 -0
- package/dist/lib/security/pairing-code.d.ts +182 -0
- package/dist/lib/security/pairing-code.d.ts.map +1 -0
- package/dist/lib/security/pairing-code.js +265 -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/auth-config.js +5 -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 +2 -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/9IXgWfBUtnEnRqnbmErTp/_buildManifest.js +0 -1
- package/.next/static/chunks/3361-5d6e93fba8a92bc1.js +0 -1
- package/.next/static/chunks/5229-1f5f19740a8d6c11.js +0 -1
- package/.next/static/chunks/6271.295ced91b6335f18.js +0 -1
- package/.next/static/chunks/6381-8cfe50a5ca5425b1.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/login/page-adc51f0f7cbb7ac6.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-f7b3dfbe757dc6b8.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-a75fe180a7233b2b.js +0 -1
- package/.next/static/chunks/webpack-6a9668cf54a26eba.js +0 -1
- package/.next/static/css/928e5a8830fbf997.css +0 -1
- /package/.next/static/{9IXgWfBUtnEnRqnbmErTp → uulKcSOgyxChTo4SipUSF}/_ssgManifest.js +0 -0
|
@@ -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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localhost-self-check.d.ts","sourceRoot":"","sources":["../../../src/lib/server/localhost-self-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAA0B,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,MAAM,CAAC;AAUzF,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD;;;GAGG;AACH,eAAO,MAAM,eAAe,qBAAqB,CAAC;AAElD,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC;IAC1G,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC;CAC1G;AAED,iDAAiD;AACjD,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,MAAM,EAAE,eAAe,CAAC;IACxB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,qBAAqB,CAAC,CAkGhC;AAUD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7F;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,EAAE,CASxF;AAED,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAa/E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAWlF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CASzD;AAgBD,gDAAgD;AAChD,MAAM,WAAW,4BAA4B;IAC3C,6BAA6B;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,uDAAuD;IACvD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,wCAAwC;IACxC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC5E;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAyCvC"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Startup self-check: does the URL we tell users to open actually reach US?
|
|
4
|
+
* Issue #2113
|
|
5
|
+
*
|
|
6
|
+
* CommandMate binds IPv4 `127.0.0.1` by default (server.ts, `CM_BIND`), but every
|
|
7
|
+
* setup guide sends the user to `http://localhost:<port>`. On macOS `localhost`
|
|
8
|
+
* resolves `::1` (IPv6) BEFORE `127.0.0.1`, and a `0.0.0.0`/`::` bind of ours never
|
|
9
|
+
* covers `::1` either — so an unrelated process holding `::1:<port>` silently owns
|
|
10
|
+
* the address the docs advertise. The browser then talks to that process while
|
|
11
|
+
* CommandMate keeps reporting a healthy `> Ready on http://127.0.0.1:<port>`.
|
|
12
|
+
*
|
|
13
|
+
* Measured 2026-08-27 on develop 54e122a9: `127.0.0.1:3000` answered in 14ms while
|
|
14
|
+
* `localhost:3000` and `[::1]:3000` both timed out after 10s against a stray Next.js
|
|
15
|
+
* dev server. Because the squatter was also Next.js, the browser pulled chunks from
|
|
16
|
+
* the WRONG app and rendered CommandMate's own `error.chunkReload.title`
|
|
17
|
+
* ("Updating to the latest version") — an error screen that looks like ours while
|
|
18
|
+
* not being served by us at all.
|
|
19
|
+
*
|
|
20
|
+
* HOW IDENTITY IS DECIDED (the part that has to be exact):
|
|
21
|
+
*
|
|
22
|
+
* The probe sends a GET to `<protocol>://localhost:<port>/api/auth/status` carrying a
|
|
23
|
+
* one-shot random nonce in `x-cm-self-check`, and our own HTTP server carries a
|
|
24
|
+
* temporary `prependListener('request')` that watches for that nonce. The verdict comes
|
|
25
|
+
* from OUR OWN OBSERVATION of the request, never from trusting the response body:
|
|
26
|
+
*
|
|
27
|
+
* observed the nonce -> 'self' (the advertised URL reaches us)
|
|
28
|
+
* got an HTTP response, no nonce-> 'foreign' (something else answered) <- WARN
|
|
29
|
+
* connection error / timeout -> 'unreachable' (nothing there; browsers fall
|
|
30
|
+
* through to 127.0.0.1) <- silent
|
|
31
|
+
*
|
|
32
|
+
* `/api/auth/status` is deliberately an EXISTING endpoint (it is in
|
|
33
|
+
* AUTH_EXCLUDED_PATHS, touches no DB and mutates nothing), so no diagnostic route had
|
|
34
|
+
* to be added. Nothing in the verdict depends on what it returns, which is why the
|
|
35
|
+
* check still works with auth on, with an IP ACL that would 403 us, and against an
|
|
36
|
+
* HTTPS server with a self-signed certificate.
|
|
37
|
+
*
|
|
38
|
+
* FAIL-OPEN IS THE CONTRACT. Nothing here throws, nothing here blocks `listen`, and
|
|
39
|
+
* only the 'foreign' verdict produces output. 'unreachable' is deliberately silent:
|
|
40
|
+
* an empty `::1` is the NORMAL case on a machine where nothing squats the port, and
|
|
41
|
+
* Node's Happy Eyeballs (and every browser) then falls through to `127.0.0.1`.
|
|
42
|
+
*
|
|
43
|
+
* @module lib/server/localhost-self-check
|
|
44
|
+
*/
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.SELF_CHECK_FILE_PREFIX = exports.SELF_CHECK_DIR_NAME = exports.SELF_CHECK_TIMEOUT_MS = exports.SELF_CHECK_HOSTNAME = exports.SELF_CHECK_PATH = exports.SELF_CHECK_HEADER = void 0;
|
|
47
|
+
exports.probeLocalhostIdentity = probeLocalhostIdentity;
|
|
48
|
+
exports.formatBoundUrl = formatBoundUrl;
|
|
49
|
+
exports.formatLocalhostConflictWarning = formatLocalhostConflictWarning;
|
|
50
|
+
exports.getSelfCheckDir = getSelfCheckDir;
|
|
51
|
+
exports.getSelfCheckStatePath = getSelfCheckStatePath;
|
|
52
|
+
exports.writeLocalhostConflict = writeLocalhostConflict;
|
|
53
|
+
exports.readLocalhostConflict = readLocalhostConflict;
|
|
54
|
+
exports.clearLocalhostConflict = clearLocalhostConflict;
|
|
55
|
+
exports.runLocalhostSelfCheck = runLocalhostSelfCheck;
|
|
56
|
+
const http_1 = require("http");
|
|
57
|
+
const https_1 = require("https");
|
|
58
|
+
const crypto_1 = require("crypto");
|
|
59
|
+
const fs_1 = require("fs");
|
|
60
|
+
const path_1 = require("path");
|
|
61
|
+
// Relative, NOT `@/cli/utils/...`: this module is pulled into the CLI program by
|
|
62
|
+
// src/cli/commands/status.ts, and tsconfig.cli.json resets `paths` to {} — an alias
|
|
63
|
+
// import here would break `npm run build:cli`. Same reason as version-probes.ts.
|
|
64
|
+
const install_context_1 = require("../../cli/utils/install-context");
|
|
65
|
+
/** Header the probe request carries its nonce in */
|
|
66
|
+
exports.SELF_CHECK_HEADER = 'x-cm-self-check';
|
|
67
|
+
/**
|
|
68
|
+
* Endpoint the probe targets. Existing route, in AUTH_EXCLUDED_PATHS
|
|
69
|
+
* (src/config/auth-config.ts), no DB access, no side effects.
|
|
70
|
+
*/
|
|
71
|
+
exports.SELF_CHECK_PATH = '/api/auth/status';
|
|
72
|
+
/** Hostname the docs advertise, and therefore the one under test */
|
|
73
|
+
exports.SELF_CHECK_HOSTNAME = 'localhost';
|
|
74
|
+
/** How long to wait for either the nonce observation or a response */
|
|
75
|
+
exports.SELF_CHECK_TIMEOUT_MS = 3000;
|
|
76
|
+
/**
|
|
77
|
+
* Directory (under the config dir) the conflict records live in.
|
|
78
|
+
*
|
|
79
|
+
* `logs/` and not a dedicated `self-check/`: in a local install `getConfigDir()` is the
|
|
80
|
+
* repository checkout itself, and `.gitignore` already ignores `logs/` there (it does
|
|
81
|
+
* the same for `data/`, `skills/`, `temp/` — "service-owned runtime state lands at the
|
|
82
|
+
* repo root"). A new top-level directory would show up as an untracked change in the
|
|
83
|
+
* user's own repository, which for a worktree manager means dirtying a repo it also
|
|
84
|
+
* displays. The record is diagnostic output keyed by port, so `logs/` fits it anyway.
|
|
85
|
+
*/
|
|
86
|
+
exports.SELF_CHECK_DIR_NAME = 'logs';
|
|
87
|
+
/** Filename prefix of a conflict record inside {@link SELF_CHECK_DIR_NAME} */
|
|
88
|
+
exports.SELF_CHECK_FILE_PREFIX = 'self-check-';
|
|
89
|
+
/**
|
|
90
|
+
* Ask "if a user opens the URL we advertise, do they reach this process?".
|
|
91
|
+
*
|
|
92
|
+
* Resolves as soon as the answer is known — the nonce observation fires on our
|
|
93
|
+
* server's `request` event, i.e. when headers arrive, so a 'self' verdict does not
|
|
94
|
+
* wait for Next.js to render or compile the route.
|
|
95
|
+
*
|
|
96
|
+
* Never rejects.
|
|
97
|
+
*/
|
|
98
|
+
async function probeLocalhostIdentity(options) {
|
|
99
|
+
const { server, port, protocol = 'http', host = exports.SELF_CHECK_HOSTNAME, path = exports.SELF_CHECK_PATH, timeoutMs = exports.SELF_CHECK_TIMEOUT_MS, } = options;
|
|
100
|
+
const nonce = options.nonce ?? (0, crypto_1.randomBytes)(16).toString('hex');
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
let settled = false;
|
|
103
|
+
let observed = false;
|
|
104
|
+
let timer = null;
|
|
105
|
+
// Prepended so we read the header before server.ts's own request handler can
|
|
106
|
+
// rewrite anything on it.
|
|
107
|
+
const listener = (req) => {
|
|
108
|
+
const seen = req?.headers?.[exports.SELF_CHECK_HEADER];
|
|
109
|
+
const value = Array.isArray(seen) ? seen[0] : seen;
|
|
110
|
+
if (value === nonce) {
|
|
111
|
+
observed = true;
|
|
112
|
+
settle('self');
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const settle = (verdict) => {
|
|
116
|
+
if (settled)
|
|
117
|
+
return;
|
|
118
|
+
settled = true;
|
|
119
|
+
if (timer !== null)
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
try {
|
|
122
|
+
server.removeListener('request', listener);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// A server that cannot detach a listener is still not a reason to fail startup.
|
|
126
|
+
}
|
|
127
|
+
resolve(verdict);
|
|
128
|
+
};
|
|
129
|
+
try {
|
|
130
|
+
server.prependListener('request', listener);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Without the observer there is no way to tell 'self' from 'foreign'; declaring
|
|
134
|
+
// 'foreign' here would warn on a perfectly healthy machine.
|
|
135
|
+
resolve('unreachable');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
timer = setTimeout(() => settle(observed ? 'self' : 'unreachable'), timeoutMs);
|
|
139
|
+
let req;
|
|
140
|
+
try {
|
|
141
|
+
const send = protocol === 'https' ? https_1.request : http_1.request;
|
|
142
|
+
req = send({
|
|
143
|
+
host,
|
|
144
|
+
port,
|
|
145
|
+
path,
|
|
146
|
+
method: 'GET',
|
|
147
|
+
headers: {
|
|
148
|
+
[exports.SELF_CHECK_HEADER]: nonce,
|
|
149
|
+
'user-agent': 'commandmate-self-check',
|
|
150
|
+
},
|
|
151
|
+
// A self-signed certificate is the documented local HTTPS setup
|
|
152
|
+
// (`mkcert localhost`, see `commandmate start --cert`), so verifying here
|
|
153
|
+
// would turn every such install's check into a silent 'unreachable'.
|
|
154
|
+
// Skipping verification is safe HERE and only here: the verdict comes from
|
|
155
|
+
// our own in-process observation rather than from trusting the peer, the
|
|
156
|
+
// request carries no credentials, and its only payload is a random nonce
|
|
157
|
+
// that means nothing to anyone else. NODE_TLS_REJECT_UNAUTHORIZED is never
|
|
158
|
+
// touched — this is scoped to this one request.
|
|
159
|
+
...(protocol === 'https' ? { rejectUnauthorized: false } : {}),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
settle(observed ? 'self' : 'unreachable');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
req.setTimeout(timeoutMs, () => {
|
|
167
|
+
req.destroy();
|
|
168
|
+
});
|
|
169
|
+
req.on('response', (res) => {
|
|
170
|
+
// Drain so the socket can close; the body is never inspected.
|
|
171
|
+
res.resume();
|
|
172
|
+
settle(observed ? 'self' : 'foreign');
|
|
173
|
+
});
|
|
174
|
+
req.on('error', () => {
|
|
175
|
+
settle(observed ? 'self' : 'unreachable');
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
req.end();
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
settle(observed ? 'self' : 'unreachable');
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Bracket a bare IPv6 literal so the result is a URL a user can paste. `localhost` and
|
|
187
|
+
* dotted-quad hosts pass through untouched.
|
|
188
|
+
*/
|
|
189
|
+
function formatHostForUrl(host) {
|
|
190
|
+
return host.includes(':') && !host.startsWith('[') ? `[${host}]` : host;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Build the dialable URL for a bind address, matching resolveServerEndpoint()'s rule
|
|
194
|
+
* that a wildcard bind is reported as 127.0.0.1.
|
|
195
|
+
*/
|
|
196
|
+
function formatBoundUrl(protocol, bind, port) {
|
|
197
|
+
const host = bind === '0.0.0.0' ? '127.0.0.1' : bind;
|
|
198
|
+
return `${protocol}://${formatHostForUrl(host)}:${port}`;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* The warning, as lines, shared by the startup log and `commandmate status` so the two
|
|
202
|
+
* can never drift apart.
|
|
203
|
+
*/
|
|
204
|
+
function formatLocalhostConflictWarning(record) {
|
|
205
|
+
return [
|
|
206
|
+
`Another process is answering on ${record.probedUrl} — it is NOT this CommandMate server.`,
|
|
207
|
+
` CommandMate is listening on ${record.boundUrl} (CM_BIND=${record.bind}).`,
|
|
208
|
+
` "localhost" can resolve to ::1 (IPv6) first, and ${record.bind} does not cover ::1,`,
|
|
209
|
+
' so a browser opening the localhost URL reaches the other process instead.',
|
|
210
|
+
` Open ${record.boundUrl} instead, or free the port:`,
|
|
211
|
+
` lsof -nP -iTCP:${record.port} -sTCP:LISTEN`,
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
/** Directory holding the per-port conflict records */
|
|
215
|
+
function getSelfCheckDir() {
|
|
216
|
+
return (0, path_1.join)((0, install_context_1.getConfigDir)(), exports.SELF_CHECK_DIR_NAME);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Path of the record for one port (`<configDir>/logs/self-check-<port>.json`).
|
|
220
|
+
*
|
|
221
|
+
* @throws Error when the port is not a plausible TCP port — the value becomes a
|
|
222
|
+
* filename, so it is validated rather than interpolated blindly.
|
|
223
|
+
*/
|
|
224
|
+
function getSelfCheckStatePath(port) {
|
|
225
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
226
|
+
throw new Error(`Invalid port for self-check state path: ${String(port)}`);
|
|
227
|
+
}
|
|
228
|
+
return (0, path_1.join)(getSelfCheckDir(), `${exports.SELF_CHECK_FILE_PREFIX}${port}.json`);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Persist a conflict for `commandmate status` to read.
|
|
232
|
+
*
|
|
233
|
+
* @returns true when the record was written
|
|
234
|
+
*/
|
|
235
|
+
function writeLocalhostConflict(record) {
|
|
236
|
+
try {
|
|
237
|
+
const dir = getSelfCheckDir();
|
|
238
|
+
if (!(0, fs_1.existsSync)(dir)) {
|
|
239
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
|
|
240
|
+
}
|
|
241
|
+
(0, fs_1.writeFileSync)(getSelfCheckStatePath(record.port), `${JSON.stringify(record)}\n`, {
|
|
242
|
+
mode: 0o600,
|
|
243
|
+
});
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Read the conflict recorded for a port.
|
|
252
|
+
*
|
|
253
|
+
* Never throws: `status` must keep working on an unreadable, truncated or
|
|
254
|
+
* hand-edited record, and on a machine where the config dir cannot be resolved at all.
|
|
255
|
+
*
|
|
256
|
+
* @returns The record, or null when there is none (or it is unusable)
|
|
257
|
+
*/
|
|
258
|
+
function readLocalhostConflict(port) {
|
|
259
|
+
try {
|
|
260
|
+
const statePath = getSelfCheckStatePath(port);
|
|
261
|
+
if (!(0, fs_1.existsSync)(statePath)) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const parsed = JSON.parse((0, fs_1.readFileSync)(statePath, 'utf-8'));
|
|
265
|
+
return isConflictRecord(parsed) && parsed.port === port ? parsed : null;
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Drop the record for a port. Called on every clean self-check and on shutdown, so a
|
|
273
|
+
* fixed environment stops warning on the next start rather than needing a manual sweep.
|
|
274
|
+
*/
|
|
275
|
+
function clearLocalhostConflict(port) {
|
|
276
|
+
try {
|
|
277
|
+
const statePath = getSelfCheckStatePath(port);
|
|
278
|
+
if ((0, fs_1.existsSync)(statePath)) {
|
|
279
|
+
(0, fs_1.unlinkSync)(statePath);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// Best effort: a stale record is guarded by the PID comparison in `status`.
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/** Structural check for a record read back off disk */
|
|
287
|
+
function isConflictRecord(value) {
|
|
288
|
+
if (typeof value !== 'object' || value === null)
|
|
289
|
+
return false;
|
|
290
|
+
const r = value;
|
|
291
|
+
return (typeof r.port === 'number' &&
|
|
292
|
+
typeof r.pid === 'number' &&
|
|
293
|
+
typeof r.bind === 'string' &&
|
|
294
|
+
typeof r.boundUrl === 'string' &&
|
|
295
|
+
typeof r.probedUrl === 'string' &&
|
|
296
|
+
typeof r.detectedAt === 'string');
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Run the startup self-check and route its verdict to the log and the status file.
|
|
300
|
+
*
|
|
301
|
+
* Fail-open by construction: every path is wrapped, the function never rejects, and the
|
|
302
|
+
* caller in server.ts does not await it. A `null` return means the check could not be
|
|
303
|
+
* carried out at all — which is reported as nothing, exactly like 'unreachable'.
|
|
304
|
+
*
|
|
305
|
+
* @returns The verdict, or null when the check itself failed
|
|
306
|
+
*/
|
|
307
|
+
async function runLocalhostSelfCheck(options) {
|
|
308
|
+
const { server, port, bind, protocol = 'http', host = exports.SELF_CHECK_HOSTNAME, timeoutMs = exports.SELF_CHECK_TIMEOUT_MS, pid = process.pid, now = () => new Date(), warn = (message) => console.warn(message), probe = probeLocalhostIdentity, } = options;
|
|
309
|
+
try {
|
|
310
|
+
const verdict = await probe({ server, port, protocol, host, timeoutMs });
|
|
311
|
+
if (verdict !== 'foreign') {
|
|
312
|
+
clearLocalhostConflict(port);
|
|
313
|
+
return verdict;
|
|
314
|
+
}
|
|
315
|
+
const record = {
|
|
316
|
+
port,
|
|
317
|
+
pid,
|
|
318
|
+
bind,
|
|
319
|
+
boundUrl: formatBoundUrl(protocol, bind, port),
|
|
320
|
+
probedUrl: `${protocol}://${formatHostForUrl(host)}:${port}`,
|
|
321
|
+
detectedAt: now().toISOString(),
|
|
322
|
+
};
|
|
323
|
+
writeLocalhostConflict(record);
|
|
324
|
+
for (const line of formatLocalhostConflictWarning(record)) {
|
|
325
|
+
warn(line);
|
|
326
|
+
}
|
|
327
|
+
return verdict;
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
// A diagnostic must never be the reason a server is considered unhealthy.
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
@@ -12,9 +12,28 @@
|
|
|
12
12
|
"completion": "Also tell me about completions (optional)",
|
|
13
13
|
"completionDesc": "Ordinary completions that need nothing from you. Off by default on newly registered devices (change it for this device here)"
|
|
14
14
|
},
|
|
15
|
+
"defaultsNotice": {
|
|
16
|
+
"heading": "What changed in notifications",
|
|
17
|
+
"completionChanged": "Ordinary completions that need nothing from you are now off by default on newly registered devices. This device is still on, so they keep arriving.",
|
|
18
|
+
"failuresAdded": "\"When you need to act\" now also covers a failed verification gate, an upstream API fault, and a session that could not start. This device receives those too.",
|
|
19
|
+
"adopt": "Use the new default (turn completions off)",
|
|
20
|
+
"keep": "Keep this device as it is",
|
|
21
|
+
"adopted": "Completions turned off on this device",
|
|
22
|
+
"kept": "Left this device's settings unchanged"
|
|
23
|
+
},
|
|
15
24
|
"permission": {
|
|
16
25
|
"denied": "Notifications are blocked in your browser settings. Allow them for this site to receive push notifications."
|
|
17
26
|
},
|
|
27
|
+
"delivery": {
|
|
28
|
+
"headingFailing": "This device is not receiving notifications",
|
|
29
|
+
"headingRemoved": "This device was dropped by the push service",
|
|
30
|
+
"failing": "The push service has rejected the last {count} notification(s) for this device (HTTP {status}). Your subscription is intact — nothing was deleted.",
|
|
31
|
+
"failingUnknownStatus": "The push service has rejected the last {count} notification(s) for this device. Your subscription is intact — nothing was deleted.",
|
|
32
|
+
"removed": "The push service reported this subscription as gone (HTTP {status}), so the server stopped sending to it. Turn notifications on again below to re-subscribe.",
|
|
33
|
+
"removedUnknownStatus": "The push service reported this subscription as gone, so the server stopped sending to it. Turn notifications on again below to re-subscribe.",
|
|
34
|
+
"apnsHint": "On iPhone/iPad an HTTP 403 usually means the server's CM_VAPID_SUBJECT is not a contact Apple accepts. See docs/user-guide/webapp-guide.md.",
|
|
35
|
+
"since": "First failure: {timestamp}"
|
|
36
|
+
},
|
|
18
37
|
"unsupported": "This browser does not support push notifications.",
|
|
19
38
|
"notConfigured": "Push notifications are not configured on this server. Set the VAPID keys to enable them.",
|
|
20
39
|
"ios": {
|
|
@@ -45,7 +64,10 @@
|
|
|
45
64
|
"failureSessionUnavailable": "Could not start the session: the CLI tool is not installed",
|
|
46
65
|
"failureWithExcerpt": "Failed: {excerpt}",
|
|
47
66
|
"failure": "Failed",
|
|
48
|
-
"
|
|
67
|
+
"failureAgentSessionWithExcerpt": "The agent stopped with an error: {excerpt}",
|
|
68
|
+
"failureAgentSession": "The agent stopped with an error",
|
|
69
|
+
"promptResolved": "Handled — answered on another device",
|
|
70
|
+
"updateAvailable": "An update for {agent} is available: {version}"
|
|
49
71
|
},
|
|
50
72
|
"escalation": {
|
|
51
73
|
"heading": "Reminder",
|
|
@@ -12,9 +12,28 @@
|
|
|
12
12
|
"completion": "完了も知らせる(任意)",
|
|
13
13
|
"completionDesc": "対応の要らない正常完了。新しく登録した端末では既定でオフです(この端末の設定はここで変えられます)"
|
|
14
14
|
},
|
|
15
|
+
"defaultsNotice": {
|
|
16
|
+
"heading": "通知の既定が変わりました",
|
|
17
|
+
"completionChanged": "対応の要らない正常完了は、新しく登録した端末では既定でオフになりました。この端末はオンのままなので、これまでどおり届きます。",
|
|
18
|
+
"failuresAdded": "「対応が必要なとき」に、検証ゲートの不合格・上流APIの障害・セッションの起動失敗の3種が加わりました。この端末はこれらも受け取ります。",
|
|
19
|
+
"adopt": "新しい既定にする(完了通知をオフ)",
|
|
20
|
+
"keep": "この端末の設定を保つ",
|
|
21
|
+
"adopted": "完了通知をこの端末でオフにしました",
|
|
22
|
+
"kept": "この端末の設定はそのままにしました"
|
|
23
|
+
},
|
|
15
24
|
"permission": {
|
|
16
25
|
"denied": "ブラウザの設定で通知がブロックされています。このサイトの通知を許可してください。"
|
|
17
26
|
},
|
|
27
|
+
"delivery": {
|
|
28
|
+
"headingFailing": "この端末には通知が届いていません",
|
|
29
|
+
"headingRemoved": "この端末の購読はプッシュサービス側で失効しました",
|
|
30
|
+
"failing": "直近 {count} 件の通知がプッシュサービスに拒否されました(HTTP {status})。購読は削除されていません。",
|
|
31
|
+
"failingUnknownStatus": "直近 {count} 件の通知がプッシュサービスに拒否されました。購読は削除されていません。",
|
|
32
|
+
"removed": "プッシュサービスがこの購読を失効と報告したため(HTTP {status})、送信を停止しました。下のボタンで通知を有効にし直すと再購読できます。",
|
|
33
|
+
"removedUnknownStatus": "プッシュサービスがこの購読を失効と報告したため、送信を停止しました。下のボタンで通知を有効にし直すと再購読できます。",
|
|
34
|
+
"apnsHint": "iPhone / iPad で HTTP 403 が出る場合、サーバーの CM_VAPID_SUBJECT が Apple の受け付けない値になっていることがほとんどです。docs/user-guide/webapp-guide.md を参照してください。",
|
|
35
|
+
"since": "最初の失敗: {timestamp}"
|
|
36
|
+
},
|
|
18
37
|
"unsupported": "このブラウザはプッシュ通知に対応していません。",
|
|
19
38
|
"notConfigured": "このサーバーではプッシュ通知が設定されていません。VAPID鍵を設定すると有効になります。",
|
|
20
39
|
"ios": {
|
|
@@ -45,7 +64,10 @@
|
|
|
45
64
|
"failureSessionUnavailable": "セッションを起動できませんでした: CLI ツールがインストールされていません",
|
|
46
65
|
"failureWithExcerpt": "失敗しました: {excerpt}",
|
|
47
66
|
"failure": "失敗しました",
|
|
48
|
-
"
|
|
67
|
+
"failureAgentSessionWithExcerpt": "エージェントがエラーで停止しました: {excerpt}",
|
|
68
|
+
"failureAgentSession": "エージェントがエラーで停止しました",
|
|
69
|
+
"promptResolved": "対応済みです(他の端末で応答されました)",
|
|
70
|
+
"updateAvailable": "{agent} の更新が利用できます: {version}"
|
|
49
71
|
},
|
|
50
72
|
"escalation": {
|
|
51
73
|
"heading": "再通知",
|