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
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* @module lib/hooks/sources/opencode/client
|
|
43
43
|
*/
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.MAX_OPENCODE_SSE_FRAME_CHARS = exports.MAX_OPENCODE_SESSION_STATUSES = exports.OPENCODE_EVENT_CONTENT_TYPE = exports.OPENCODE_JSON_CONTENT_TYPE = exports.OPENCODE_FETCH_REDIRECT = exports.OPENCODE_REQUEST_TIMEOUT_MS = exports.OPENCODE_SERVER_HOST = void 0;
|
|
45
|
+
exports.OPENCODE_SHARE_REQUEST_TIMEOUT_MS = exports.MAX_OPENCODE_DIFF_PATCH_CHARS = exports.MAX_OPENCODE_DIFF_FILES = exports.OPENCODE_CONTEXT_MESSAGE_WINDOW = exports.MAX_OPENCODE_SESSION_MESSAGES = exports.MAX_OPENCODE_SSE_FRAME_CHARS = exports.MAX_OPENCODE_SESSION_STATUSES = exports.OPENCODE_EVENT_CONTENT_TYPE = exports.OPENCODE_JSON_CONTENT_TYPE = exports.OPENCODE_FETCH_REDIRECT = exports.OPENCODE_REQUEST_TIMEOUT_MS = exports.OPENCODE_SERVER_HOST = void 0;
|
|
46
46
|
exports.opencodeBaseUrl = opencodeBaseUrl;
|
|
47
47
|
exports.probeOpencodeHealth = probeOpencodeHealth;
|
|
48
48
|
exports.fetchOpencodeHealth = fetchOpencodeHealth;
|
|
@@ -50,11 +50,37 @@ exports.fetchOpencodePendingPermissions = fetchOpencodePendingPermissions;
|
|
|
50
50
|
exports.fetchOpencodePendingQuestions = fetchOpencodePendingQuestions;
|
|
51
51
|
exports.fetchOpencodeSessionStatuses = fetchOpencodeSessionStatuses;
|
|
52
52
|
exports.fetchOpencodeActivity = fetchOpencodeActivity;
|
|
53
|
+
exports.abortOpencodeSession = abortOpencodeSession;
|
|
54
|
+
exports.opencodeFileUrl = opencodeFileUrl;
|
|
55
|
+
exports.newOpencodeMessageId = newOpencodeMessageId;
|
|
56
|
+
exports.promptSelectionBody = promptSelectionBody;
|
|
57
|
+
exports.sendOpencodePrompt = sendOpencodePrompt;
|
|
58
|
+
exports.readOpencodeUserMessage = readOpencodeUserMessage;
|
|
53
59
|
exports.replyOpencodePermission = replyOpencodePermission;
|
|
54
60
|
exports.replyOpencodeQuestion = replyOpencodeQuestion;
|
|
55
61
|
exports.createSseParser = createSseParser;
|
|
56
62
|
exports.openOpencodeEventStream = openOpencodeEventStream;
|
|
63
|
+
exports.fetchOpencodeSessionMessages = fetchOpencodeSessionMessages;
|
|
64
|
+
exports.fetchOpencodeModelContextLimit = fetchOpencodeModelContextLimit;
|
|
65
|
+
exports.readOpencodeModelContextLimit = readOpencodeModelContextLimit;
|
|
66
|
+
exports.fetchOpencodeProviderCatalog = fetchOpencodeProviderCatalog;
|
|
67
|
+
exports.readOpencodeProviderCatalog = readOpencodeProviderCatalog;
|
|
68
|
+
exports.fetchOpencodeAgents = fetchOpencodeAgents;
|
|
69
|
+
exports.readOpencodeAgents = readOpencodeAgents;
|
|
70
|
+
exports.isOpencodeLaunchableAgent = isOpencodeLaunchableAgent;
|
|
71
|
+
exports.fetchOpencodeContextTokens = fetchOpencodeContextTokens;
|
|
72
|
+
exports.readOpencodeFileDiffs = readOpencodeFileDiffs;
|
|
73
|
+
exports.fetchOpencodeMessageDiff = fetchOpencodeMessageDiff;
|
|
74
|
+
exports.revertOpencodeMessage = revertOpencodeMessage;
|
|
75
|
+
exports.unrevertOpencodeSession = unrevertOpencodeSession;
|
|
76
|
+
exports.fetchOpencodeShareMode = fetchOpencodeShareMode;
|
|
77
|
+
exports.shareOpencodeSession = shareOpencodeSession;
|
|
78
|
+
exports.unshareOpencodeSession = unshareOpencodeSession;
|
|
79
|
+
exports.fetchOpencodeSessionShareUrl = fetchOpencodeSessionShareUrl;
|
|
80
|
+
const crypto_1 = require("crypto");
|
|
81
|
+
const url_1 = require("url");
|
|
57
82
|
const logger_1 = require("../../../../lib/logger");
|
|
83
|
+
const opencode_share_1 = require("../../../../types/opencode-share");
|
|
58
84
|
const logger = (0, logger_1.createLogger)('lib/hooks/sources/opencode/client');
|
|
59
85
|
/**
|
|
60
86
|
* The only host an opencode server is ever addressed on.
|
|
@@ -308,6 +334,238 @@ async function fetchOpencodeActivity(port) {
|
|
|
308
334
|
return null;
|
|
309
335
|
return Object.values(statuses).includes('busy') ? 'busy' : 'idle';
|
|
310
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Stop the turn one session is running (Issue #2034).
|
|
339
|
+
*
|
|
340
|
+
* `POST /session/:id/abort`. Measured live on **1.18.22** — isolated HOME, an
|
|
341
|
+
* `opencode serve` on 127.0.0.1:4298, LM Studio as the provider, a generation
|
|
342
|
+
* aborted 6 s in:
|
|
343
|
+
*
|
|
344
|
+
* ```
|
|
345
|
+
* HTTP/1.1 200 OK
|
|
346
|
+
* Content-Type: application/json
|
|
347
|
+
* Content-Length: 4
|
|
348
|
+
*
|
|
349
|
+
* true
|
|
350
|
+
* ```
|
|
351
|
+
*
|
|
352
|
+
* and on the event stream, in the same millisecond as the reply:
|
|
353
|
+
*
|
|
354
|
+
* ```
|
|
355
|
+
* 10:17:25.946 session.error MessageAbortedError
|
|
356
|
+
* 10:17:25.946 session.status idle
|
|
357
|
+
* 10:17:25.946 session.idle <- 1st
|
|
358
|
+
* 10:17:25.969 session.idle <- 2nd, 23 ms later
|
|
359
|
+
* ```
|
|
360
|
+
*
|
|
361
|
+
* Two consequences for the caller, and neither is visible from the status code:
|
|
362
|
+
*
|
|
363
|
+
* - **`true` is "accepted", not "a turn was stopped".** Aborting the SAME
|
|
364
|
+
* session again once it was already idle answered `200 true` as well, and
|
|
365
|
+
* emitted one more `session.idle`. So the reply cannot confirm the turn
|
|
366
|
+
* ended; only the event can — see `./subscription`'s idle watch.
|
|
367
|
+
* - **The idle can arrive before this promise resolves.** It did here: the
|
|
368
|
+
* frame is emitted while the request is still in flight. A caller that
|
|
369
|
+
* starts watching *after* awaiting this call can miss its own completion.
|
|
370
|
+
*
|
|
371
|
+
* `true` is required rather than "not null" because the route's own schema
|
|
372
|
+
* (`GET /doc`, `operationId: session.abort`) declares a bare boolean body: a
|
|
373
|
+
* `false` is the server saying it did not take the request, and `requestJson`
|
|
374
|
+
* would hand that back as a perfectly good parsed body.
|
|
375
|
+
*
|
|
376
|
+
* @param port - The instance's server
|
|
377
|
+
* @param sessionId - `ses_…`, the session whose turn should stop
|
|
378
|
+
* @returns Whether the server accepted the abort
|
|
379
|
+
*/
|
|
380
|
+
async function abortOpencodeSession(port, sessionId) {
|
|
381
|
+
const result = await requestJson(`${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/abort`, { method: 'POST' });
|
|
382
|
+
return result === true;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* The `file://` URL for a local file, which is the only form the route takes.
|
|
386
|
+
*
|
|
387
|
+
* Measured on 1.18.22 (Issue #2035). A bare absolute path in `FilePartInput.url`
|
|
388
|
+
* is **accepted with `204` and then silently discarded** — the server answers
|
|
389
|
+
* before it resolves the part, and the resolution failure arrives on the event
|
|
390
|
+
* stream instead:
|
|
391
|
+
*
|
|
392
|
+
* ```
|
|
393
|
+
* session.error UnknownError
|
|
394
|
+
* TypeError: "/…/probe.png" cannot be parsed as a URL.
|
|
395
|
+
* at SessionPrompt.resolveUserPart …
|
|
396
|
+
* ```
|
|
397
|
+
*
|
|
398
|
+
* and the **whole message is dropped, its text part included** — a read-back of
|
|
399
|
+
* the message id answers `404`. So this is not a nicety: a path handed over
|
|
400
|
+
* unencoded loses the operator's message with a success status code on the wire.
|
|
401
|
+
*
|
|
402
|
+
* `pathToFileURL` rather than `'file://' + path` because the difference is
|
|
403
|
+
* exactly the paths people have: a space or a `#` in a worktree name makes the
|
|
404
|
+
* concatenated string a different URL, and non-ASCII makes it an invalid one.
|
|
405
|
+
*
|
|
406
|
+
* @param absolutePath - Absolute path to a local file
|
|
407
|
+
* @returns `file:///…`, percent-encoded
|
|
408
|
+
*/
|
|
409
|
+
function opencodeFileUrl(absolutePath) {
|
|
410
|
+
return (0, url_1.pathToFileURL)(absolutePath).href;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* A message id for a prompt CommandMate is about to post.
|
|
414
|
+
*
|
|
415
|
+
* The route accepts a caller-chosen `messageID` (schema: `pattern: "^msg"`), and
|
|
416
|
+
* that is what makes the send verifiable: the id is known *before* the request,
|
|
417
|
+
* so {@link readOpencodeUserMessage} can ask for that exact message afterwards
|
|
418
|
+
* rather than guessing which of the session's messages was this one. Measured on
|
|
419
|
+
* 1.18.22 — `msg_cmate2035probe0001` was accepted and read back verbatim.
|
|
420
|
+
*
|
|
421
|
+
* The `cmate` infix is deliberate: opencode's own ids are
|
|
422
|
+
* `msg_037794348001Ajss6k50nWrocp`, so a CommandMate-originated message stays
|
|
423
|
+
* identifiable in `opencode.db` afterwards, and the two generators cannot
|
|
424
|
+
* collide.
|
|
425
|
+
*/
|
|
426
|
+
function newOpencodeMessageId() {
|
|
427
|
+
return `msg_cmate${(0, crypto_1.randomBytes)(12).toString('hex')}`;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* The `prompt_async` body keys a selection contributes, or nothing.
|
|
431
|
+
*
|
|
432
|
+
* Keys are omitted rather than nulled so a request from an instance with no
|
|
433
|
+
* settings is byte-identical to the pre-#2048 one.
|
|
434
|
+
*/
|
|
435
|
+
function promptSelectionBody(selection) {
|
|
436
|
+
if (!selection)
|
|
437
|
+
return {};
|
|
438
|
+
const body = {};
|
|
439
|
+
if (selection.agent)
|
|
440
|
+
body.agent = selection.agent;
|
|
441
|
+
if (selection.model?.providerID && selection.model.modelID) {
|
|
442
|
+
body.model = {
|
|
443
|
+
providerID: selection.model.providerID,
|
|
444
|
+
modelID: selection.model.modelID,
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
if (selection.variant)
|
|
448
|
+
body.variant = selection.variant;
|
|
449
|
+
return body;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Post one prompt to a session without waiting for the reply (Issue #2035).
|
|
453
|
+
*
|
|
454
|
+
* `POST /session/:id/prompt_async`. This is the route the send path takes when
|
|
455
|
+
* the instance has a server, and it was chosen over `/tui/append-prompt` +
|
|
456
|
+
* `/tui/submit-prompt` on a measurement, not a preference — see
|
|
457
|
+
* `docs/design/opencode-server-live-verification.md` §11.4. The short version:
|
|
458
|
+
* the `/tui/*` pair drives the TUI's **composer**, so it inherits the composer's
|
|
459
|
+
* state, and a body whose first token matches a slash command opens the command
|
|
460
|
+
* palette and the palette then eats the submit. `/exit` as a message body
|
|
461
|
+
* answered `200 true` on all three calls and produced no message at all. This
|
|
462
|
+
* route does not go through the composer, and the same body arrived verbatim.
|
|
463
|
+
*
|
|
464
|
+
* **`204` means accepted, not delivered.** Three measured ways that gap opens:
|
|
465
|
+
*
|
|
466
|
+
* - a file part whose `url` is not a URL is dropped along with its whole
|
|
467
|
+
* message ({@link opencodeFileUrl});
|
|
468
|
+
* - a server that shares `HOME` + project with this one answers `204` for a
|
|
469
|
+
* session it can reach through `opencode.db` — and the message then appears
|
|
470
|
+
* on **neither** this server's event stream nor this pane's screen;
|
|
471
|
+
* - an unknown route on a real opencode answers `200 text/html` (#1931), which
|
|
472
|
+
* is why the status is compared exactly rather than through `response.ok`.
|
|
473
|
+
*
|
|
474
|
+
* {@link readOpencodeUserMessage} is the other half, and callers are expected to
|
|
475
|
+
* use it. Nothing here throws.
|
|
476
|
+
*
|
|
477
|
+
* @param port - The instance's server
|
|
478
|
+
* @param sessionId - `ses_…`, the session the message belongs to
|
|
479
|
+
* @param messageId - `msg_…`, from {@link newOpencodeMessageId}
|
|
480
|
+
* @param parts - The message body; at least one part
|
|
481
|
+
* @returns Whether the server answered `204`
|
|
482
|
+
*/
|
|
483
|
+
async function sendOpencodePrompt(port, sessionId, messageId, parts, selection) {
|
|
484
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/prompt_async`;
|
|
485
|
+
try {
|
|
486
|
+
const response = await loopbackFetch(url, {
|
|
487
|
+
method: 'POST',
|
|
488
|
+
headers: { 'Content-Type': exports.OPENCODE_JSON_CONTENT_TYPE },
|
|
489
|
+
body: JSON.stringify({
|
|
490
|
+
messageID: messageId,
|
|
491
|
+
...promptSelectionBody(selection),
|
|
492
|
+
parts,
|
|
493
|
+
}),
|
|
494
|
+
signal: AbortSignal.timeout(exports.OPENCODE_REQUEST_TIMEOUT_MS),
|
|
495
|
+
});
|
|
496
|
+
if (response.status !== 204) {
|
|
497
|
+
logger.warn('opencode-prompt-rejected', { port, sessionId, status: response.status });
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
logger.debug('opencode-request-failed', {
|
|
504
|
+
url,
|
|
505
|
+
error: error instanceof Error ? error.message : String(error),
|
|
506
|
+
});
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Read back one message by the id it was posted under (Issue #2035).
|
|
512
|
+
*
|
|
513
|
+
* `GET /session/:id/message/:messageID`. The positive evidence for a send, in
|
|
514
|
+
* the same sense `session.idle` is the positive evidence for an abort (#2034):
|
|
515
|
+
* the status code on the way in says the request was taken, and only this says
|
|
516
|
+
* the message exists.
|
|
517
|
+
*
|
|
518
|
+
* Measured on 1.18.22 across five runs: the message was readable on the **first**
|
|
519
|
+
* attempt, 8-23 ms after the POST began — `prompt_async` answers `204` after the
|
|
520
|
+
* message is created, not before. The falsification ran too: a message posted
|
|
521
|
+
* with a malformed file part answered `204` and then `404` here, which is the
|
|
522
|
+
* case the whole ladder is for.
|
|
523
|
+
*
|
|
524
|
+
* `info.role` is checked because the id space is shared with the assistant's
|
|
525
|
+
* messages: a `messageID` that collided with one would otherwise read back as a
|
|
526
|
+
* perfectly good delivery of somebody else's text.
|
|
527
|
+
*
|
|
528
|
+
* @param port - The instance's server
|
|
529
|
+
* @param sessionId - `ses_…`
|
|
530
|
+
* @param messageId - `msg_…`, the id the prompt was posted under
|
|
531
|
+
*/
|
|
532
|
+
async function readOpencodeUserMessage(port, sessionId, messageId) {
|
|
533
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}` +
|
|
534
|
+
`/message/${encodeURIComponent(messageId)}`;
|
|
535
|
+
let response;
|
|
536
|
+
try {
|
|
537
|
+
response = await loopbackFetch(url, {
|
|
538
|
+
signal: AbortSignal.timeout(exports.OPENCODE_REQUEST_TIMEOUT_MS),
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
return { kind: 'unknown', reason: error instanceof Error ? error.message : String(error) };
|
|
543
|
+
}
|
|
544
|
+
if (response.status === 404)
|
|
545
|
+
return { kind: 'missing' };
|
|
546
|
+
if (!response.ok)
|
|
547
|
+
return { kind: 'unknown', reason: `status ${response.status}` };
|
|
548
|
+
if (!hasContentType(response, exports.OPENCODE_JSON_CONTENT_TYPE)) {
|
|
549
|
+
return { kind: 'unknown', reason: 'content-type' };
|
|
550
|
+
}
|
|
551
|
+
let body;
|
|
552
|
+
try {
|
|
553
|
+
body = (await response.json());
|
|
554
|
+
}
|
|
555
|
+
catch {
|
|
556
|
+
return { kind: 'unknown', reason: 'body' };
|
|
557
|
+
}
|
|
558
|
+
if (!isPlainObject(body))
|
|
559
|
+
return { kind: 'unknown', reason: 'body' };
|
|
560
|
+
const info = isPlainObject(body.info) ? body.info : null;
|
|
561
|
+
if (info === null || info.role !== 'user')
|
|
562
|
+
return { kind: 'unknown', reason: 'role' };
|
|
563
|
+
const texts = (Array.isArray(body.parts) ? body.parts : [])
|
|
564
|
+
.filter(isPlainObject)
|
|
565
|
+
.filter((part) => part.type === 'text' && typeof part.text === 'string')
|
|
566
|
+
.map((part) => part.text);
|
|
567
|
+
return { kind: 'found', texts };
|
|
568
|
+
}
|
|
311
569
|
/**
|
|
312
570
|
* Answer one approval.
|
|
313
571
|
*
|
|
@@ -333,8 +591,17 @@ async function replyOpencodePermission(port, requestId, reply, message) {
|
|
|
333
591
|
/**
|
|
334
592
|
* Answer one question.
|
|
335
593
|
*
|
|
594
|
+
* Reachable from production since Issue #2039. It was written with #1763's
|
|
595
|
+
* source and then had no caller for a year of Issues: `decideOpencode` routes
|
|
596
|
+
* `{ kind: 'answer' }` here, and nothing in `src/` built that verdict, so a
|
|
597
|
+
* `question.asked` could be displayed and never answered except with arrow
|
|
598
|
+
* keys. What #2039 added is the two mappings above it —
|
|
599
|
+
* `resolveStructuredQuestionAnswer` and the `kind === 'question'` branch of
|
|
600
|
+
* `respondByDecisionId` — not a line of this function.
|
|
601
|
+
*
|
|
336
602
|
* @param answers - One array of selected labels per question, in the order the
|
|
337
|
-
* `question.asked` frame listed them
|
|
603
|
+
* `question.asked` frame listed them. Measured shape: `{"answers":[["Blue"]]}`
|
|
604
|
+
* for the one-question call (#1758 §5.2.4)
|
|
338
605
|
*/
|
|
339
606
|
async function replyOpencodeQuestion(port, questionId, answers) {
|
|
340
607
|
const result = await requestJson(`${opencodeBaseUrl(port)}/question/${encodeURIComponent(questionId)}/reply`, {
|
|
@@ -560,3 +827,641 @@ function safeParseFrame(raw) {
|
|
|
560
827
|
return null;
|
|
561
828
|
}
|
|
562
829
|
}
|
|
830
|
+
/**
|
|
831
|
+
* Cap on messages read back from one `GET /session/:id/message` (Issue #2041).
|
|
832
|
+
*
|
|
833
|
+
* Same argument as {@link MAX_OPENCODE_SESSION_STATUSES}: the document comes off
|
|
834
|
+
* a process CommandMate did not start, one server's `opencode.db` is shared by
|
|
835
|
+
* every TUI with the same HOME and project (#1758 §5.6.3), and a session that
|
|
836
|
+
* has been going for a week is not bounded by this instance's behaviour. Two
|
|
837
|
+
* messages per turn measured on 1.18.22 (one user, one or two assistant), so
|
|
838
|
+
* this is roughly 250 turns.
|
|
839
|
+
*/
|
|
840
|
+
exports.MAX_OPENCODE_SESSION_MESSAGES = 500;
|
|
841
|
+
/**
|
|
842
|
+
* Every message in one session, with its parts (Issue #2041).
|
|
843
|
+
*
|
|
844
|
+
* `GET /session/:id/message`. The only route to a reply CommandMate did not see
|
|
845
|
+
* arrive: a fresh subscription to `/event` replays **nothing** — measured on
|
|
846
|
+
* 1.18.22, a second SSE connection opened after three completed turns received
|
|
847
|
+
* one `server.connected` frame and then silence — so a turn that ran while this
|
|
848
|
+
* server was down exists only here.
|
|
849
|
+
*
|
|
850
|
+
* The body is an array of `{ info, parts }`. Returned raw rather than parsed
|
|
851
|
+
* because the parsing lives in `./transcript`, which has to read the *same*
|
|
852
|
+
* shape off the event stream and must not have two readers of it.
|
|
853
|
+
*
|
|
854
|
+
* Answers null for every failure, including the ordinary "nothing is listening
|
|
855
|
+
* because the pane exited" — a caller cannot act on the difference and the
|
|
856
|
+
* distinction {@link OpencodeMessageReadback} draws is not available here (a
|
|
857
|
+
* missing session is a 404 that means the same as an unreachable one for a
|
|
858
|
+
* backfill: there is nothing to recover).
|
|
859
|
+
*
|
|
860
|
+
* @param port - The instance's server
|
|
861
|
+
* @param sessionId - `ses_…`
|
|
862
|
+
* @returns The array, bounded to the newest {@link MAX_OPENCODE_SESSION_MESSAGES}, or null
|
|
863
|
+
*/
|
|
864
|
+
async function fetchOpencodeSessionMessages(port, sessionId) {
|
|
865
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/message`;
|
|
866
|
+
const body = await requestJson(url);
|
|
867
|
+
if (!Array.isArray(body))
|
|
868
|
+
return null;
|
|
869
|
+
const entries = body.filter(isPlainObject);
|
|
870
|
+
// Newest kept, and the array stays in the server's own order so `parentID`
|
|
871
|
+
// grouping still sees a turn's messages together.
|
|
872
|
+
return entries.length > exports.MAX_OPENCODE_SESSION_MESSAGES
|
|
873
|
+
? entries.slice(entries.length - exports.MAX_OPENCODE_SESSION_MESSAGES)
|
|
874
|
+
: entries;
|
|
875
|
+
}
|
|
876
|
+
// ============================================================================
|
|
877
|
+
// Context occupancy (Issue #2042). Appended at the end of the file on purpose:
|
|
878
|
+
// #2041 is rewriting this module's neighbours in parallel, and everything below
|
|
879
|
+
// is additive — no export above it is touched.
|
|
880
|
+
// ============================================================================
|
|
881
|
+
/**
|
|
882
|
+
* How many trailing messages are read back to find the last assistant turn.
|
|
883
|
+
*
|
|
884
|
+
* `GET /session/:id/message?limit=N` answers the **last** N messages in
|
|
885
|
+
* chronological order — measured on 1.18.22, see
|
|
886
|
+
* `docs/design/opencode-server-live-verification.md` §14.3. Four is two
|
|
887
|
+
* user/assistant pairs: enough that a turn still streaming (its assistant
|
|
888
|
+
* message exists but has `output === 0`) falls back to the previous completed
|
|
889
|
+
* one, and small enough that the read stays a few KB rather than the whole
|
|
890
|
+
* conversation. A session whose last four messages contain no finished
|
|
891
|
+
* assistant turn answers null, which is the honest answer — it has not spent a
|
|
892
|
+
* turn yet.
|
|
893
|
+
*/
|
|
894
|
+
exports.OPENCODE_CONTEXT_MESSAGE_WINDOW = 4;
|
|
895
|
+
/**
|
|
896
|
+
* What one model declares it can hold, as `GET /config/providers` states it.
|
|
897
|
+
*
|
|
898
|
+
* Only `context` is read. `limit.input` is also published and is **not** the
|
|
899
|
+
* denominator: on `github-copilot/claude-sonnet-4.6` it is 936,000 against a
|
|
900
|
+
* `context` of 1,000,000, and opencode's own readout divides by `context`
|
|
901
|
+
* (§14.2 quotes the 1.18.22 bundle).
|
|
902
|
+
*/
|
|
903
|
+
async function fetchOpencodeModelContextLimit(port, providerId, modelId) {
|
|
904
|
+
const body = await fetchOpencodeProvidersDocument(port);
|
|
905
|
+
return readOpencodeModelContextLimit(body, providerId, modelId);
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* `GET /config/providers`, unparsed — the one reader of that route (#2048).
|
|
909
|
+
*
|
|
910
|
+
* Issue #2042 read this route for `limit.context` and Issue #2048 needs the
|
|
911
|
+
* same document for the *model and variant catalogue* the settings pane offers.
|
|
912
|
+
* Two independent readers of one endpoint is how the two come to disagree about
|
|
913
|
+
* its shape, so both go through here and each takes what it needs from the
|
|
914
|
+
* body. Nothing is cached: the call is a loopback round trip on a route that
|
|
915
|
+
* answers from memory, and the alternative is a cache that has to be invalidated
|
|
916
|
+
* when the operator adds a provider.
|
|
917
|
+
*/
|
|
918
|
+
async function fetchOpencodeProvidersDocument(port) {
|
|
919
|
+
return requestJson(`${opencodeBaseUrl(port)}/config/providers`);
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* `limit.context` for one model, out of a `GET /config/providers` body.
|
|
923
|
+
*
|
|
924
|
+
* Split from the fetch so the arithmetic is testable against a recorded body
|
|
925
|
+
* rather than a live server. Behaviour is #2042's, unchanged: `context` only,
|
|
926
|
+
* and a non-positive value is "no percentage" rather than a divisor.
|
|
927
|
+
*/
|
|
928
|
+
function readOpencodeModelContextLimit(body, providerId, modelId) {
|
|
929
|
+
if (!isPlainObject(body))
|
|
930
|
+
return null;
|
|
931
|
+
const providers = Array.isArray(body.providers) ? body.providers : [];
|
|
932
|
+
for (const provider of providers) {
|
|
933
|
+
if (!isPlainObject(provider) || provider.id !== providerId)
|
|
934
|
+
continue;
|
|
935
|
+
const models = isPlainObject(provider.models) ? provider.models : null;
|
|
936
|
+
if (!models)
|
|
937
|
+
return null;
|
|
938
|
+
const model = models[modelId];
|
|
939
|
+
if (!isPlainObject(model))
|
|
940
|
+
return null;
|
|
941
|
+
const limit = isPlainObject(model.limit) ? model.limit : null;
|
|
942
|
+
if (!limit)
|
|
943
|
+
return null;
|
|
944
|
+
const context = limit.context;
|
|
945
|
+
// A zero or a negative would divide into a percentage nobody can read, and
|
|
946
|
+
// opencode itself treats a falsy `limit.context` as "no percentage".
|
|
947
|
+
if (typeof context !== 'number' || !Number.isFinite(context) || context <= 0)
|
|
948
|
+
return null;
|
|
949
|
+
return context;
|
|
950
|
+
}
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* The provider / model / variant catalogue the settings pane offers (#2048).
|
|
955
|
+
*
|
|
956
|
+
* Three shapes measured on 1.18.22 (§20.1), each of which is easy to guess
|
|
957
|
+
* wrong:
|
|
958
|
+
*
|
|
959
|
+
* - **`providers` is an array, `models` is an object.** The models are keyed by
|
|
960
|
+
* model id, not listed — `providers[].models["claude-sonnet-4.6"]` — so an
|
|
961
|
+
* `Array.isArray` guard on it drops every model there is.
|
|
962
|
+
* - **`variants` is an object too**, keyed by variant name (`low` / `medium` /
|
|
963
|
+
* `high` / `max` / `minimal` / `none` / `xhigh` across the measured
|
|
964
|
+
* catalogue), whose values carry `effort` or `reasoningEffort`. Only the keys
|
|
965
|
+
* are kept: the name is what `prompt_async` takes, and the effort inside it
|
|
966
|
+
* is opencode's own restatement of the same word.
|
|
967
|
+
* - **`variants: {}` is a real answer**, not a missing field — `kimi-k2.7-code`
|
|
968
|
+
* publishes it — and it is how the pane knows to offer no variant at all.
|
|
969
|
+
*
|
|
970
|
+
* Entries that do not parse are dropped rather than represented: this feeds a
|
|
971
|
+
* `<select>`, and an option with no id is an option that cannot be chosen.
|
|
972
|
+
*
|
|
973
|
+
* @param port - The instance's server
|
|
974
|
+
* @returns The catalogue, or an empty array when the server could not be asked
|
|
975
|
+
*/
|
|
976
|
+
async function fetchOpencodeProviderCatalog(port) {
|
|
977
|
+
return readOpencodeProviderCatalog(await fetchOpencodeProvidersDocument(port));
|
|
978
|
+
}
|
|
979
|
+
/** {@link fetchOpencodeProviderCatalog}'s parser, over an already-read body. */
|
|
980
|
+
function readOpencodeProviderCatalog(body) {
|
|
981
|
+
if (!isPlainObject(body))
|
|
982
|
+
return [];
|
|
983
|
+
const providers = Array.isArray(body.providers) ? body.providers : [];
|
|
984
|
+
const catalog = [];
|
|
985
|
+
for (const provider of providers) {
|
|
986
|
+
if (!isPlainObject(provider))
|
|
987
|
+
continue;
|
|
988
|
+
const id = typeof provider.id === 'string' ? provider.id : null;
|
|
989
|
+
if (!id)
|
|
990
|
+
continue;
|
|
991
|
+
const models = [];
|
|
992
|
+
const rawModels = isPlainObject(provider.models) ? provider.models : {};
|
|
993
|
+
for (const [modelId, rawModel] of Object.entries(rawModels)) {
|
|
994
|
+
if (!isPlainObject(rawModel))
|
|
995
|
+
continue;
|
|
996
|
+
const variants = isPlainObject(rawModel.variants) ? Object.keys(rawModel.variants) : [];
|
|
997
|
+
models.push({
|
|
998
|
+
id: modelId,
|
|
999
|
+
name: typeof rawModel.name === 'string' && rawModel.name.length > 0
|
|
1000
|
+
? rawModel.name
|
|
1001
|
+
: modelId,
|
|
1002
|
+
variants: variants.sort(),
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
models.sort((a, b) => a.id.localeCompare(b.id));
|
|
1006
|
+
catalog.push({
|
|
1007
|
+
id,
|
|
1008
|
+
name: typeof provider.name === 'string' && provider.name.length > 0 ? provider.name : id,
|
|
1009
|
+
models,
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
catalog.sort((a, b) => a.id.localeCompare(b.id));
|
|
1013
|
+
return catalog;
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* The personas this server will start a session as — `GET /agent` (#2048).
|
|
1017
|
+
*
|
|
1018
|
+
* An **array**, unlike `/config/providers`'s object-of-models, and its entries
|
|
1019
|
+
* carry two fields that decide what the pane may offer (§20.1): `mode` is
|
|
1020
|
+
* `primary` or `subagent`, and `hidden` is `true` on the three internal
|
|
1021
|
+
* personas (`compaction`, `summary`, `title`). A stock 1.18.22 install answered
|
|
1022
|
+
* seven agents of which exactly two — `build` and `plan` — are primary and
|
|
1023
|
+
* visible, which is the pair Issue #2048's acceptance condition names.
|
|
1024
|
+
*
|
|
1025
|
+
* Both fields are kept rather than filtered here: this is the reader, and which
|
|
1026
|
+
* agents a *launch* may name is a policy the caller states —
|
|
1027
|
+
* {@link isOpencodeLaunchableAgent}.
|
|
1028
|
+
*
|
|
1029
|
+
* @param port - The instance's server
|
|
1030
|
+
* @returns Every agent the server declared, or an empty array when it could not
|
|
1031
|
+
* be asked
|
|
1032
|
+
*/
|
|
1033
|
+
async function fetchOpencodeAgents(port) {
|
|
1034
|
+
return readOpencodeAgents(await requestJson(`${opencodeBaseUrl(port)}/agent`));
|
|
1035
|
+
}
|
|
1036
|
+
/** {@link fetchOpencodeAgents}'s parser, over an already-read body. */
|
|
1037
|
+
function readOpencodeAgents(body) {
|
|
1038
|
+
if (!Array.isArray(body))
|
|
1039
|
+
return [];
|
|
1040
|
+
const agents = [];
|
|
1041
|
+
for (const entry of body) {
|
|
1042
|
+
if (!isPlainObject(entry))
|
|
1043
|
+
continue;
|
|
1044
|
+
const name = typeof entry.name === 'string' ? entry.name : null;
|
|
1045
|
+
if (!name)
|
|
1046
|
+
continue;
|
|
1047
|
+
// `hidden` is absent on the visible ones rather than `false`, so the test is
|
|
1048
|
+
// truthiness of the key and not a comparison against `false`.
|
|
1049
|
+
if (entry.hidden === true)
|
|
1050
|
+
continue;
|
|
1051
|
+
agents.push({
|
|
1052
|
+
name,
|
|
1053
|
+
mode: typeof entry.mode === 'string' ? entry.mode : '',
|
|
1054
|
+
description: typeof entry.description === 'string' ? entry.description : null,
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
return agents;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Whether an agent may be named on a launch line or a prompt.
|
|
1061
|
+
*
|
|
1062
|
+
* `primary` only. A `subagent` (`explore`, `general`) is something a running
|
|
1063
|
+
* session spawns for a `task` tool call; naming one as the session's own persona
|
|
1064
|
+
* is not a thing opencode's UI offers and not something measured to work.
|
|
1065
|
+
*/
|
|
1066
|
+
function isOpencodeLaunchableAgent(agent) {
|
|
1067
|
+
return agent.mode === 'primary';
|
|
1068
|
+
}
|
|
1069
|
+
/** A finite, non-negative token count, or 0 — the shape `tokens.*` arrives in. */
|
|
1070
|
+
function readTokenCount(source, key) {
|
|
1071
|
+
const value = source[key];
|
|
1072
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0;
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* How full this session's context is, in tokens (Issue #2042).
|
|
1076
|
+
*
|
|
1077
|
+
* **This is not `Session.tokens` and the difference is the whole point.**
|
|
1078
|
+
* `session.updated` reports a *cumulative* count — after two turns the measured
|
|
1079
|
+
* session read `input 6 / output 11 / cache.read 8482 / cache.write 8500`, which
|
|
1080
|
+
* is what `opencode stats` prints and what `AgentSessionRecord` carries.
|
|
1081
|
+
* What opencode's own TUI shows as `8.5K (1%)` is a different quantity: the
|
|
1082
|
+
* token footprint of the **last assistant message**, which is what the next
|
|
1083
|
+
* request actually has to fit into a context window. Summing the session's
|
|
1084
|
+
* counts would have said 16,999 where opencode says 8,508, and the gap widens
|
|
1085
|
+
* with every turn (§14.2).
|
|
1086
|
+
*
|
|
1087
|
+
* The rule is opencode's own, transcribed from the 1.18.22 bundle rather than
|
|
1088
|
+
* inferred: take the last message with `role === 'assistant'` **and**
|
|
1089
|
+
* `tokens.output > 0`, and add `input + output + reasoning + cache.read +
|
|
1090
|
+
* cache.write`. The `output > 0` clause is what skips the assistant message a
|
|
1091
|
+
* turn opens with, whose counts are all zero until the turn finishes.
|
|
1092
|
+
*
|
|
1093
|
+
* `tokens.total` on that message is opencode's own sum of exactly those five
|
|
1094
|
+
* and was measured equal to it (8491, then 8508) — it is not read here because
|
|
1095
|
+
* it is absent until the turn completes, and the five are the definition.
|
|
1096
|
+
*
|
|
1097
|
+
* @param port - The instance's server
|
|
1098
|
+
* @param sessionId - `ses_…`
|
|
1099
|
+
* @returns The occupancy in tokens, or null when no finished assistant turn is
|
|
1100
|
+
* in the window (a fresh session, or one whose last four messages are all
|
|
1101
|
+
* user prompts) and on every transport failure
|
|
1102
|
+
*/
|
|
1103
|
+
async function fetchOpencodeContextTokens(port, sessionId) {
|
|
1104
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/message` +
|
|
1105
|
+
`?limit=${exports.OPENCODE_CONTEXT_MESSAGE_WINDOW}`;
|
|
1106
|
+
const body = await requestJson(url);
|
|
1107
|
+
if (!Array.isArray(body))
|
|
1108
|
+
return null;
|
|
1109
|
+
for (let index = body.length - 1; index >= 0; index -= 1) {
|
|
1110
|
+
const entry = body[index];
|
|
1111
|
+
if (!isPlainObject(entry))
|
|
1112
|
+
continue;
|
|
1113
|
+
// `{ info, parts }`; only `info` carries the counts.
|
|
1114
|
+
const info = isPlainObject(entry.info) ? entry.info : null;
|
|
1115
|
+
if (!info || info.role !== 'assistant')
|
|
1116
|
+
continue;
|
|
1117
|
+
const tokens = isPlainObject(info.tokens) ? info.tokens : null;
|
|
1118
|
+
if (!tokens)
|
|
1119
|
+
continue;
|
|
1120
|
+
const output = readTokenCount(tokens, 'output');
|
|
1121
|
+
if (output <= 0)
|
|
1122
|
+
continue;
|
|
1123
|
+
const cache = isPlainObject(tokens.cache) ? tokens.cache : {};
|
|
1124
|
+
return (readTokenCount(tokens, 'input') +
|
|
1125
|
+
output +
|
|
1126
|
+
readTokenCount(tokens, 'reasoning') +
|
|
1127
|
+
readTokenCount(cache, 'read') +
|
|
1128
|
+
readTokenCount(cache, 'write'));
|
|
1129
|
+
}
|
|
1130
|
+
return null;
|
|
1131
|
+
}
|
|
1132
|
+
const OPENCODE_FILE_DIFF_STATUSES = ['added', 'deleted', 'modified'];
|
|
1133
|
+
/**
|
|
1134
|
+
* Cap on files kept from one diff.
|
|
1135
|
+
*
|
|
1136
|
+
* A diff is carried on the status poll's payload, and `patch` is unbounded — a
|
|
1137
|
+
* generated lockfile is megabytes of it. The cap is on *files* rather than
|
|
1138
|
+
* bytes so the panel never shows half a file's name; {@link MAX_OPENCODE_DIFF_PATCH_CHARS}
|
|
1139
|
+
* is the byte-side companion.
|
|
1140
|
+
*/
|
|
1141
|
+
exports.MAX_OPENCODE_DIFF_FILES = 200;
|
|
1142
|
+
/** Cap on one file's `patch`. Truncated patches still render; huge ones do not. */
|
|
1143
|
+
exports.MAX_OPENCODE_DIFF_PATCH_CHARS = 64 * 1024;
|
|
1144
|
+
/**
|
|
1145
|
+
* Read an array of `SnapshotFileDiff` off any opencode payload.
|
|
1146
|
+
*
|
|
1147
|
+
* Shared by the event reader and the REST reader on purpose: `session.diff`'s
|
|
1148
|
+
* `properties.diff` and `GET /session/:id/diff`'s body are the *same* schema,
|
|
1149
|
+
* and two readers of one shape is how they come apart.
|
|
1150
|
+
*
|
|
1151
|
+
* Entries that are not objects are dropped rather than represented, and a
|
|
1152
|
+
* non-array answers the empty array — "the server said nothing readable" and
|
|
1153
|
+
* "the server said no files" are the same instruction to a panel that hides
|
|
1154
|
+
* itself when empty.
|
|
1155
|
+
*/
|
|
1156
|
+
function readOpencodeFileDiffs(value) {
|
|
1157
|
+
if (!Array.isArray(value))
|
|
1158
|
+
return [];
|
|
1159
|
+
const files = [];
|
|
1160
|
+
for (const entry of value) {
|
|
1161
|
+
if (!isPlainObject(entry))
|
|
1162
|
+
continue;
|
|
1163
|
+
const patch = typeof entry.patch === 'string' ? entry.patch : null;
|
|
1164
|
+
files.push({
|
|
1165
|
+
file: typeof entry.file === 'string' && entry.file.length > 0 ? entry.file : null,
|
|
1166
|
+
patch: patch === null ? null : patch.slice(0, exports.MAX_OPENCODE_DIFF_PATCH_CHARS),
|
|
1167
|
+
additions: typeof entry.additions === 'number' && Number.isFinite(entry.additions)
|
|
1168
|
+
? entry.additions
|
|
1169
|
+
: 0,
|
|
1170
|
+
deletions: typeof entry.deletions === 'number' && Number.isFinite(entry.deletions)
|
|
1171
|
+
? entry.deletions
|
|
1172
|
+
: 0,
|
|
1173
|
+
status: typeof entry.status === 'string' && OPENCODE_FILE_DIFF_STATUSES.includes(entry.status)
|
|
1174
|
+
? entry.status
|
|
1175
|
+
: null,
|
|
1176
|
+
});
|
|
1177
|
+
if (files.length >= exports.MAX_OPENCODE_DIFF_FILES)
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
1180
|
+
return files;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* The files one user message's turn changed (Issue #2043).
|
|
1184
|
+
*
|
|
1185
|
+
* `GET /session/:id/diff?messageID=<msg…>`. **The `messageID` is not optional in
|
|
1186
|
+
* practice**: measured on 1.18.22, the same route without it answered `[]` both
|
|
1187
|
+
* before and after a turn that changed two files, while the same call *with* it
|
|
1188
|
+
* answered both files and their patches.
|
|
1189
|
+
*
|
|
1190
|
+
* The answer is a historical record rather than live state — measured: it still
|
|
1191
|
+
* returned the turn's two files after that turn had been reverted — so a caller
|
|
1192
|
+
* showing "what this turn changed" is reading the right thing, and a caller
|
|
1193
|
+
* asking "is this still applied" is not.
|
|
1194
|
+
*
|
|
1195
|
+
* A malformed `messageID` (one not starting with `msg`) is a **400** from the
|
|
1196
|
+
* server, which collapses to null here like every other failure.
|
|
1197
|
+
*
|
|
1198
|
+
* @param port - The instance's server
|
|
1199
|
+
* @param sessionId - `ses_…`
|
|
1200
|
+
* @param messageId - `msg_…`, the *user* message that opened the turn
|
|
1201
|
+
* @returns The files, or null when the server could not be asked
|
|
1202
|
+
*/
|
|
1203
|
+
async function fetchOpencodeMessageDiff(port, sessionId, messageId) {
|
|
1204
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/diff` +
|
|
1205
|
+
`?messageID=${encodeURIComponent(messageId)}`;
|
|
1206
|
+
const body = await requestJson(url);
|
|
1207
|
+
if (!Array.isArray(body))
|
|
1208
|
+
return null;
|
|
1209
|
+
return readOpencodeFileDiffs(body);
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* `Session.revert.messageID`, or null when the session holds nothing back.
|
|
1213
|
+
*
|
|
1214
|
+
* The one field that distinguishes a revert that took from one that did not,
|
|
1215
|
+
* for both routes: `POST /revert` sets it, `POST /unrevert` clears it, and a
|
|
1216
|
+
* no-op leaves it as it was.
|
|
1217
|
+
*/
|
|
1218
|
+
function readSessionRevertMessageId(body) {
|
|
1219
|
+
if (!isPlainObject(body))
|
|
1220
|
+
return null;
|
|
1221
|
+
const revert = isPlainObject(body.revert) ? body.revert : null;
|
|
1222
|
+
if (!revert)
|
|
1223
|
+
return null;
|
|
1224
|
+
return typeof revert.messageID === 'string' && revert.messageID.length > 0
|
|
1225
|
+
? revert.messageID
|
|
1226
|
+
: null;
|
|
1227
|
+
}
|
|
1228
|
+
/** One POST to a revert route, with the three measured statuses kept apart. */
|
|
1229
|
+
async function postOpencodeRevertRoute(url, body) {
|
|
1230
|
+
let response;
|
|
1231
|
+
try {
|
|
1232
|
+
response = await loopbackFetch(url, {
|
|
1233
|
+
method: 'POST',
|
|
1234
|
+
headers: { 'Content-Type': exports.OPENCODE_JSON_CONTENT_TYPE },
|
|
1235
|
+
body: JSON.stringify(body),
|
|
1236
|
+
signal: AbortSignal.timeout(exports.OPENCODE_REQUEST_TIMEOUT_MS),
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
catch (error) {
|
|
1240
|
+
logger.debug('opencode-request-failed', {
|
|
1241
|
+
url,
|
|
1242
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1243
|
+
});
|
|
1244
|
+
return { outcome: { kind: 'unreachable' } };
|
|
1245
|
+
}
|
|
1246
|
+
if (response.status === 409)
|
|
1247
|
+
return { outcome: { kind: 'busy' } };
|
|
1248
|
+
if (!response.ok) {
|
|
1249
|
+
logger.warn('opencode-revert-rejected', { url, status: response.status });
|
|
1250
|
+
return { outcome: { kind: 'rejected', status: response.status } };
|
|
1251
|
+
}
|
|
1252
|
+
// #1931: an unknown route on a real opencode answers `200 text/html`, so a
|
|
1253
|
+
// 200 alone does not mean this route exists on the server that answered.
|
|
1254
|
+
if (!hasContentType(response, exports.OPENCODE_JSON_CONTENT_TYPE)) {
|
|
1255
|
+
return { outcome: { kind: 'unreachable' } };
|
|
1256
|
+
}
|
|
1257
|
+
try {
|
|
1258
|
+
return { revertedTo: readSessionRevertMessageId(await response.json()) };
|
|
1259
|
+
}
|
|
1260
|
+
catch {
|
|
1261
|
+
return { outcome: { kind: 'unreachable' } };
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Undo one turn's file changes (Issue #2043).
|
|
1266
|
+
*
|
|
1267
|
+
* `POST /session/:id/revert` with `{ messageID }`. **Destructive and measured to
|
|
1268
|
+
* be so**: reverting to the first turn of a two-turn session restored
|
|
1269
|
+
* `sample.txt` to its pre-session contents *and deleted* the `added.txt` the
|
|
1270
|
+
* agent had created. It rewrites the working tree from opencode's own git
|
|
1271
|
+
* snapshot ledger, so it can also undo work that was already committed — the
|
|
1272
|
+
* measurement in §16.5 left a clean tree reading ` D added.txt` / ` M
|
|
1273
|
+
* sample.txt` afterwards.
|
|
1274
|
+
*
|
|
1275
|
+
* That is why the caller is expected to confirm first, and why a `no_op` is
|
|
1276
|
+
* reported rather than swallowed.
|
|
1277
|
+
*
|
|
1278
|
+
* @param port - The instance's server
|
|
1279
|
+
* @param sessionId - `ses_…`
|
|
1280
|
+
* @param messageId - `msg_…`, the user message whose turn is being undone
|
|
1281
|
+
*/
|
|
1282
|
+
async function revertOpencodeMessage(port, sessionId, messageId) {
|
|
1283
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/revert`;
|
|
1284
|
+
const result = await postOpencodeRevertRoute(url, { messageID: messageId });
|
|
1285
|
+
if ('outcome' in result)
|
|
1286
|
+
return result.outcome;
|
|
1287
|
+
// Measured twice, and the second measurement is why this compares ids rather
|
|
1288
|
+
// than testing for null. From a session with nothing reverted, an unknown
|
|
1289
|
+
// `messageID` answers `200` with `revert: null`. From a session that is
|
|
1290
|
+
// **already** holding a revert, the same request answers `200` with the
|
|
1291
|
+
// *existing* `revert` untouched — so a null check alone reported success, and
|
|
1292
|
+
// reported it under the previous revert's message id. A revert that took
|
|
1293
|
+
// echoes the id that was asked for; anything else did nothing.
|
|
1294
|
+
return result.revertedTo === messageId
|
|
1295
|
+
? { kind: 'reverted', messageId }
|
|
1296
|
+
: { kind: 'no_op' };
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Put back everything a revert is holding (Issue #2043).
|
|
1300
|
+
*
|
|
1301
|
+
* `POST /session/:id/unrevert`. Takes no arguments — it restores *all*
|
|
1302
|
+
* previously reverted messages, per the server's own summary — and answers
|
|
1303
|
+
* **200 on a session with nothing reverted**, which is why "restored" here means
|
|
1304
|
+
* "nothing is held back now" rather than "something moved".
|
|
1305
|
+
*
|
|
1306
|
+
* Measured asymmetry worth knowing: a successful unrevert emits **no
|
|
1307
|
+
* `session.diff` frame at all**, only `session.updated` with `revert: null`. A
|
|
1308
|
+
* reader that waited for `session.diff` to go empty would wait forever, which is
|
|
1309
|
+
* why {@link readOpencodeRevertState} reads the session frame too.
|
|
1310
|
+
*/
|
|
1311
|
+
async function unrevertOpencodeSession(port, sessionId) {
|
|
1312
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/unrevert`;
|
|
1313
|
+
const result = await postOpencodeRevertRoute(url, {});
|
|
1314
|
+
if ('outcome' in result)
|
|
1315
|
+
return result.outcome;
|
|
1316
|
+
// Here the null check *is* the right test: unrevert takes no argument, so
|
|
1317
|
+
// "nothing is held back any more" is the whole success condition. A session
|
|
1318
|
+
// that still reports a revert refused to let go of it.
|
|
1319
|
+
return result.revertedTo === null
|
|
1320
|
+
? { kind: 'restored' }
|
|
1321
|
+
: { kind: 'no_op' };
|
|
1322
|
+
}
|
|
1323
|
+
// =============================================================================
|
|
1324
|
+
// Session sharing (Issue #2051)
|
|
1325
|
+
// =============================================================================
|
|
1326
|
+
/**
|
|
1327
|
+
* Timeout for the two share routes.
|
|
1328
|
+
*
|
|
1329
|
+
* Longer than {@link OPENCODE_REQUEST_TIMEOUT_MS}, which bounds loopback calls
|
|
1330
|
+
* that opencode answers out of its own process. These two do not stay on the
|
|
1331
|
+
* loopback: opencode uploads the session to its hosting and waits for the reply,
|
|
1332
|
+
* so the round trip includes somebody else's network. 20s rather than 5s, and
|
|
1333
|
+
* still bounded, because the operator is watching a spinner.
|
|
1334
|
+
*/
|
|
1335
|
+
exports.OPENCODE_SHARE_REQUEST_TIMEOUT_MS = 20_000;
|
|
1336
|
+
/**
|
|
1337
|
+
* The `share` setting this server is running with.
|
|
1338
|
+
*
|
|
1339
|
+
* A whole `GET /config` fetch for one key, because that is the only place the
|
|
1340
|
+
* setting is exposed: there is no `/config/share`, and the value is not on the
|
|
1341
|
+
* session. Cheap enough — the measured body is under 200 bytes.
|
|
1342
|
+
*
|
|
1343
|
+
* @param port - The instance's server
|
|
1344
|
+
* @returns The mode, or null when the key is unset, unknown to this build, or
|
|
1345
|
+
* the server could not be asked. `null` must not be read as `'disabled'`;
|
|
1346
|
+
* see `src/types/opencode-share.ts`
|
|
1347
|
+
*/
|
|
1348
|
+
async function fetchOpencodeShareMode(port) {
|
|
1349
|
+
const body = await requestJson(`${opencodeBaseUrl(port)}/config`);
|
|
1350
|
+
return (0, opencode_share_1.readOpencodeShareMode)(body);
|
|
1351
|
+
}
|
|
1352
|
+
/**
|
|
1353
|
+
* Publish one session to opencode's hosting.
|
|
1354
|
+
*
|
|
1355
|
+
* **This makes the conversation readable by anyone with the link**, under the
|
|
1356
|
+
* operator's own credentials. Measured on 1.18.22: the published page carries
|
|
1357
|
+
* the session *unredacted* — the prompts, the replies and the absolute
|
|
1358
|
+
* `directory` path were all present in the HTML. It is the exact opposite of
|
|
1359
|
+
* `opencode export --sanitize`, and nothing between here and the operator
|
|
1360
|
+
* removes anything. Every caller must have taken an explicit confirmation
|
|
1361
|
+
* first.
|
|
1362
|
+
*
|
|
1363
|
+
* Written against `requestJson`'s siblings rather than through it because the
|
|
1364
|
+
* status code is load-bearing here: `requestJson` collapses every non-2xx to
|
|
1365
|
+
* null, and a 404 (no such session) needs telling apart from a 500 (refused).
|
|
1366
|
+
*
|
|
1367
|
+
* @param port - The instance's server
|
|
1368
|
+
* @param sessionId - `ses_…`
|
|
1369
|
+
* @returns The outcome; on success, the URL opencode minted
|
|
1370
|
+
*/
|
|
1371
|
+
async function shareOpencodeSession(port, sessionId) {
|
|
1372
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/share`;
|
|
1373
|
+
try {
|
|
1374
|
+
// Measured: the route takes no request body at all (`requestBody: null` in
|
|
1375
|
+
// opencode's own OpenAPI), so none is sent.
|
|
1376
|
+
const response = await loopbackFetch(url, {
|
|
1377
|
+
method: 'POST',
|
|
1378
|
+
signal: AbortSignal.timeout(exports.OPENCODE_SHARE_REQUEST_TIMEOUT_MS),
|
|
1379
|
+
});
|
|
1380
|
+
if (response.status === 404)
|
|
1381
|
+
return { kind: 'not-found' };
|
|
1382
|
+
if (!response.ok) {
|
|
1383
|
+
logger.warn('opencode-share-refused', { port, sessionId, status: response.status });
|
|
1384
|
+
return { kind: 'refused', status: response.status };
|
|
1385
|
+
}
|
|
1386
|
+
if (!hasContentType(response, exports.OPENCODE_JSON_CONTENT_TYPE)) {
|
|
1387
|
+
return { kind: 'failed', reason: 'response was not JSON' };
|
|
1388
|
+
}
|
|
1389
|
+
const body = (await response.json());
|
|
1390
|
+
const shareUrl = (0, opencode_share_1.readOpencodeShareUrl)(body);
|
|
1391
|
+
if (shareUrl === null) {
|
|
1392
|
+
// A 200 with no usable URL is the one case that must not read as success:
|
|
1393
|
+
// the session may well be published, and the operator would be told it is
|
|
1394
|
+
// not. Reported as a failure so the UI keeps the revoke path visible.
|
|
1395
|
+
logger.warn('opencode-share-no-url', { port, sessionId });
|
|
1396
|
+
return { kind: 'failed', reason: 'server returned no share URL' };
|
|
1397
|
+
}
|
|
1398
|
+
logger.info('opencode-share-created', { port, sessionId });
|
|
1399
|
+
return { kind: 'shared', url: shareUrl };
|
|
1400
|
+
}
|
|
1401
|
+
catch (error) {
|
|
1402
|
+
return {
|
|
1403
|
+
kind: 'failed',
|
|
1404
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
/**
|
|
1409
|
+
* Take one session's published page down.
|
|
1410
|
+
*
|
|
1411
|
+
* Measured on 1.18.22, and both halves matter:
|
|
1412
|
+
*
|
|
1413
|
+
* - It **works**: the public URL stops serving the conversation and renders
|
|
1414
|
+
* opencode's own "Not Found" view instead. Note that the HTTP status stays
|
|
1415
|
+
* **200** — the not-found view is client-rendered — so a caller must not
|
|
1416
|
+
* verify revocation by fetching the URL and testing for 404.
|
|
1417
|
+
* - The session **keeps its `share: { url }`** afterwards, in the response to
|
|
1418
|
+
* this very call and in `GET /session/:id`, and it survives a server restart.
|
|
1419
|
+
* So there is no server-side flag saying "currently shared", and this
|
|
1420
|
+
* function's boolean is the only signal a caller gets.
|
|
1421
|
+
*
|
|
1422
|
+
* @param port - The instance's server
|
|
1423
|
+
* @param sessionId - `ses_…`
|
|
1424
|
+
* @returns Whether opencode accepted the revocation
|
|
1425
|
+
*/
|
|
1426
|
+
async function unshareOpencodeSession(port, sessionId) {
|
|
1427
|
+
const url = `${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}/share`;
|
|
1428
|
+
try {
|
|
1429
|
+
const response = await loopbackFetch(url, {
|
|
1430
|
+
method: 'DELETE',
|
|
1431
|
+
signal: AbortSignal.timeout(exports.OPENCODE_SHARE_REQUEST_TIMEOUT_MS),
|
|
1432
|
+
});
|
|
1433
|
+
if (!response.ok) {
|
|
1434
|
+
logger.warn('opencode-unshare-refused', { port, sessionId, status: response.status });
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
logger.info('opencode-share-removed', { port, sessionId });
|
|
1438
|
+
return true;
|
|
1439
|
+
}
|
|
1440
|
+
catch (error) {
|
|
1441
|
+
logger.warn('opencode-unshare-failed', {
|
|
1442
|
+
port,
|
|
1443
|
+
sessionId,
|
|
1444
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1445
|
+
});
|
|
1446
|
+
return false;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* The share URL opencode currently records against one session.
|
|
1451
|
+
*
|
|
1452
|
+
* A raw `GET /session/:id` rather than `fetchOpencodeSession()`, which projects
|
|
1453
|
+
* the body down to `{ id, title, directory, parentId }` and drops `share`
|
|
1454
|
+
* along with it.
|
|
1455
|
+
*
|
|
1456
|
+
* Read what this returns as **"a page was published for this session at some
|
|
1457
|
+
* point"**, never as "a page is up now": the field survives
|
|
1458
|
+
* {@link unshareOpencodeSession} and a server restart. See that function.
|
|
1459
|
+
*
|
|
1460
|
+
* @param port - The instance's server
|
|
1461
|
+
* @param sessionId - `ses_…`
|
|
1462
|
+
* @returns The recorded `https:` URL, or null when there is none
|
|
1463
|
+
*/
|
|
1464
|
+
async function fetchOpencodeSessionShareUrl(port, sessionId) {
|
|
1465
|
+
const body = await requestJson(`${opencodeBaseUrl(port)}/session/${encodeURIComponent(sessionId)}`);
|
|
1466
|
+
return (0, opencode_share_1.readOpencodeShareUrl)(body);
|
|
1467
|
+
}
|