commandmate 0.30.2 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +151 -151
- package/.next/app-path-routes-manifest.json +25 -25
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +9 -9
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route.js +1 -1
- package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route.js +3 -3
- 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 +4 -4
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -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_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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route.js +1 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/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-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/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 +4 -3
- 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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +4 -3
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +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]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/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.js +2 -2
- package/.next/server/app/chat/page.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +2 -2
- package/.next/server/app/more/page.js.nft.json +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.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +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.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +2 -2
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +2 -2
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +1 -1
- package/.next/server/app/skills/page.js.nft.json +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +11 -11
- 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_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +25 -25
- package/.next/server/chunks/1058.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1262.js +1 -1
- package/.next/server/chunks/1886.js +3 -3
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2328.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/261.js +1 -1
- package/.next/server/chunks/3123.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3480.js +5 -4
- package/.next/server/chunks/4299.js +1 -1
- package/.next/server/chunks/4393.js +1 -1
- package/.next/server/chunks/4443.js +1 -5
- package/.next/server/chunks/4802.js +1 -0
- package/.next/server/chunks/5017.js +1 -1
- package/.next/server/chunks/5043.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/552.js +2 -2
- package/.next/server/chunks/6072.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/663.js +4 -3
- package/.next/server/chunks/6894.js +2 -2
- package/.next/server/chunks/7187.js +1 -0
- package/.next/server/chunks/7472.js +1 -1
- package/.next/server/chunks/{880.js → 7859.js} +6 -6
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8800.js +2 -2
- package/.next/server/chunks/8918.js +7 -0
- package/.next/server/chunks/9123.js +2 -2
- package/.next/server/chunks/9130.js +4 -4
- package/.next/server/chunks/9627.js +1 -1
- package/.next/server/chunks/9696.js +1 -1
- package/.next/server/chunks/9798.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
- package/.next/static/chunks/4718-46e1d2f07c8423ba.js +1 -0
- package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
- package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
- package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
- package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
- package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
- package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
- package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
- package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
- package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
- package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
- package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
- package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-64d4ec3051971760.js +1 -0
- package/.next/static/css/5c13ea243dfdcb66.css +1 -0
- package/.next/trace +13 -13
- package/README.md +37 -11
- package/dist/cli/commands/attach.d.ts +50 -0
- package/dist/cli/commands/attach.d.ts.map +1 -0
- package/dist/cli/commands/attach.js +204 -0
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +114 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +23 -2
- package/dist/cli/commands/ls.d.ts.map +1 -1
- package/dist/cli/commands/ls.js +41 -1
- package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
- package/dist/cli/config/cli-dependencies.js +34 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +5 -0
- package/dist/cli/types/index.d.ts +36 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/config/tmux-pane-config.d.ts +153 -0
- package/dist/config/tmux-pane-config.d.ts.map +1 -0
- package/dist/config/tmux-pane-config.js +172 -0
- package/dist/lib/cli-tools/session-name.d.ts +44 -0
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
- package/dist/lib/cli-tools/session-name.js +57 -0
- package/dist/lib/cli-tools/types.d.ts +1 -1
- package/dist/lib/cli-tools/types.d.ts.map +1 -1
- package/dist/lib/cli-tools/types.js +6 -1
- package/dist/lib/cli-tools/validation.d.ts +34 -0
- package/dist/lib/cli-tools/validation.d.ts.map +1 -0
- package/dist/lib/cli-tools/validation.js +41 -0
- package/dist/lib/detection/status-reason.d.ts +18 -0
- package/dist/lib/detection/status-reason.d.ts.map +1 -1
- package/dist/lib/detection/status-reason.js +18 -0
- package/dist/lib/detection/tools/verified-against.d.ts +57 -7
- package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.js +59 -8
- package/dist/lib/detection/version-probes.d.ts +26 -5
- package/dist/lib/detection/version-probes.d.ts.map +1 -1
- package/dist/lib/detection/version-probes.js +28 -6
- package/dist/lib/session/tmux-session-surface.d.ts +369 -0
- package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
- package/dist/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/config/cli-tool-timing-config.js +12 -1
- package/dist/server/src/config/detection-evidence-config.js +5 -0
- package/dist/server/src/config/schedule-config.js +28 -1
- package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
- package/dist/server/src/lib/cli-tools/base.js +13 -8
- package/dist/server/src/lib/cli-tools/claude.js +20 -0
- package/dist/server/src/lib/cli-tools/codex.js +205 -61
- package/dist/server/src/lib/cli-tools/command-code.js +349 -0
- package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
- package/dist/server/src/lib/cli-tools/copilot.js +2 -2
- package/dist/server/src/lib/cli-tools/gemini.js +2 -2
- package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
- package/dist/server/src/lib/cli-tools/index.js +4 -1
- package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
- package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
- package/dist/server/src/lib/cli-tools/manager.js +2 -0
- package/dist/server/src/lib/cli-tools/opencode.js +2 -2
- package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
- package/dist/server/src/lib/cli-tools/types.js +6 -1
- package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
- package/dist/server/src/lib/cmate-parser.js +6 -0
- package/dist/server/src/lib/detection/cli-patterns.js +441 -8
- package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
- package/dist/server/src/lib/detection/selection-shape.js +341 -0
- package/dist/server/src/lib/detection/sgr-background.js +210 -0
- package/dist/server/src/lib/detection/status-detector.js +6 -0
- package/dist/server/src/lib/detection/status-reason.js +18 -0
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
- package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
- package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
- package/dist/server/src/lib/detection/tools/registry.js +6 -4
- package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
- package/dist/server/src/lib/detection/version-probes.js +28 -6
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +77 -16
- package/dist/server/src/lib/hooks/sources/claude/history.js +94 -18
- package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
- package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
- package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
- package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
- package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
- package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
- package/dist/server/src/lib/hooks/sources/index.js +3 -1
- package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
- package/dist/server/src/lib/hooks/sources/registry.js +4 -0
- package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
- package/dist/server/src/lib/job-executor.js +12 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
- package/dist/server/src/lib/polling/response-checker.js +112 -7
- package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
- package/dist/server/src/lib/realtime/types.js +15 -5
- package/dist/server/src/lib/response-cleaner.js +24 -1
- package/dist/server/src/lib/response-extractor.js +11 -0
- package/dist/server/src/lib/session/claude-executor.js +223 -4
- package/dist/server/src/lib/session/cli-session.js +52 -0
- package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
- package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
- package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
- package/dist/server/src/lib/tmux/read-mode.js +44 -2
- package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
- package/dist/server/src/lib/tmux/session-hooks.js +122 -0
- package/dist/server/src/lib/tmux/session-status-options.js +213 -0
- package/dist/server/src/lib/tmux/tmux.js +79 -2
- package/dist/server/src/lib/version-checker.js +110 -0
- package/dist/server/src/lib/ws-server.js +16 -10
- package/dist/server/src/types/agent-transcript.js +73 -1
- package/dist/server/src/types/terminal-keys.js +131 -3
- package/dist/types/terminal-keys.d.ts +100 -3
- package/dist/types/terminal-keys.d.ts.map +1 -1
- package/dist/types/terminal-keys.js +131 -3
- package/package.json +1 -1
- package/.next/server/chunks/3099.js +0 -5
- package/.next/server/chunks/7824.js +0 -1
- package/.next/server/chunks/848.js +0 -1
- package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
- package/.next/static/chunks/6381-147dde2a967e9458.js +0 -1
- package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-2f73d69187936627.js +0 -1
- package/.next/static/css/23f9c40ecc458c77.css +0 -1
- /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → 60mm4_QBuFtFTfo5UMyKU}/_buildManifest.js +0 -0
- /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → 60mm4_QBuFtFTfo5UMyKU}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase D of Issue #2317, server side: knowing when a human owns the geometry.
|
|
4
|
+
*
|
|
5
|
+
* `commandmate attach --live` hands a session's window from the pinned
|
|
6
|
+
* 200x1000 canvas to the attached terminal (`window-size latest`) so the agent
|
|
7
|
+
* re-lays-out and the transcript is actually readable, then pins it back on
|
|
8
|
+
* detach. While that handover is in force the session carries `@cm_delegated=1`,
|
|
9
|
+
* and the server has to behave differently in exactly two places:
|
|
10
|
+
*
|
|
11
|
+
* 1. **`reconcileSessionGeometry` must not resize.** Every `send` to a live
|
|
12
|
+
* session reaches `reconcileExistingSession()`, which would snap the window
|
|
13
|
+
* back to 200x1000 mid-read — the #1623 rejection note assumed this happened
|
|
14
|
+
* on every send and it does not, but it does happen on a session restart and
|
|
15
|
+
* on the reuse path, which is enough to break a delegated read.
|
|
16
|
+
* 2. **The poller must not save a scraped reply.** At 44 rows the frame is a
|
|
17
|
+
* fraction of the turn, and every extraction rule in `response-checker` was
|
|
18
|
+
* measured against the 1000-row canvas. claude — the only tool `--live`
|
|
19
|
+
* accepts — writes its History from its own transcript JSONL, so suppressing
|
|
20
|
+
* the scrape loses nothing and prevents a truncated reply being recorded.
|
|
21
|
+
*
|
|
22
|
+
* ## Why the flag is read from tmux rather than held in memory
|
|
23
|
+
*
|
|
24
|
+
* The delegation is performed by the CLI process (`commandmate attach --live`),
|
|
25
|
+
* which is not the server. The tmux session is the only thing both of them can
|
|
26
|
+
* see, and a user option on it is the cheapest shared channel that survives the
|
|
27
|
+
* CLI exiting, the server restarting, and a `client-detached` hook firing when
|
|
28
|
+
* neither is watching.
|
|
29
|
+
*
|
|
30
|
+
* ## Why the read is cached
|
|
31
|
+
*
|
|
32
|
+
* `checkForResponse` runs about every two seconds per active session. A
|
|
33
|
+
* `show-options` per poll would be one extra tmux round-trip per session per
|
|
34
|
+
* poll for a value that changes twice a day, so reads are memoised for
|
|
35
|
+
* {@link DELEGATION_TTL_MS}. The TTL is short enough that the restore edge is
|
|
36
|
+
* observed within one poll of the detach.
|
|
37
|
+
*/
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DELEGATION_TTL_MS = void 0;
|
|
40
|
+
exports.isGeometryDelegated = isGeometryDelegated;
|
|
41
|
+
exports.probeGeometryDelegation = probeGeometryDelegation;
|
|
42
|
+
exports.hasHumanClientAttached = hasHumanClientAttached;
|
|
43
|
+
exports.forgetGeometryDelegation = forgetGeometryDelegation;
|
|
44
|
+
exports.resetGeometryDelegationState = resetGeometryDelegationState;
|
|
45
|
+
const child_process_1 = require("child_process");
|
|
46
|
+
const util_1 = require("util");
|
|
47
|
+
const tmux_session_surface_1 = require("../session/tmux-session-surface");
|
|
48
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
49
|
+
/** tmux calls here are interactive-latency, not long-running. */
|
|
50
|
+
const TMUX_TIMEOUT = 5000;
|
|
51
|
+
/**
|
|
52
|
+
* How long a delegation read is reused.
|
|
53
|
+
*
|
|
54
|
+
* One second, against a ~2s poll: short enough that the poll after a detach sees
|
|
55
|
+
* the restore, long enough that the several readers of one session in one poll
|
|
56
|
+
* (the status helper, the response checker) share a single tmux round-trip.
|
|
57
|
+
*/
|
|
58
|
+
exports.DELEGATION_TTL_MS = 1000;
|
|
59
|
+
const cache = globalThis.__cmGeometryDelegationCache ??
|
|
60
|
+
(globalThis.__cmGeometryDelegationCache = new Map());
|
|
61
|
+
const lastObserved = globalThis.__cmGeometryDelegationEdge ??
|
|
62
|
+
(globalThis.__cmGeometryDelegationEdge = new Map());
|
|
63
|
+
/**
|
|
64
|
+
* Whether `@cm_delegated` is set to `1` on a session.
|
|
65
|
+
*
|
|
66
|
+
* Never throws: a session that has gone away, or a tmux that is not running, is
|
|
67
|
+
* "not delegated" — the answer that leaves every caller on its normal path.
|
|
68
|
+
*
|
|
69
|
+
* @param sessionName - Target session
|
|
70
|
+
* @param now - Epoch ms, injectable for tests
|
|
71
|
+
*/
|
|
72
|
+
async function isGeometryDelegated(sessionName, now = Date.now()) {
|
|
73
|
+
const cached = cache.get(sessionName);
|
|
74
|
+
if (cached && now - cached.readAt < exports.DELEGATION_TTL_MS)
|
|
75
|
+
return cached.delegated;
|
|
76
|
+
let delegated = false;
|
|
77
|
+
try {
|
|
78
|
+
const { stdout } = await execFileAsync('tmux', (0, tmux_session_surface_1.buildShowSessionOptionValueArgs)(sessionName, tmux_session_surface_1.CM_DELEGATED_OPTION), { timeout: TMUX_TIMEOUT });
|
|
79
|
+
delegated = stdout.trim() === '1';
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// THE ORDINARY CASE, not an error path. Measured on tmux 3.5a: asking for a
|
|
83
|
+
// user option a session does not carry exits NON-ZERO with
|
|
84
|
+
// `invalid option: @cm_delegated` — it is not an empty string and it is not
|
|
85
|
+
// exit 0. So "this session has never been delegated" arrives here, and it
|
|
86
|
+
// arrives here on every poll of every session, which is why nothing is
|
|
87
|
+
// logged. A session that is gone, and a tmux that is not running, land in
|
|
88
|
+
// the same place and mean the same thing.
|
|
89
|
+
delegated = false;
|
|
90
|
+
}
|
|
91
|
+
cache.set(sessionName, { delegated, readAt: now });
|
|
92
|
+
return delegated;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Read the delegation flag and report the release edge.
|
|
96
|
+
*
|
|
97
|
+
* The edge is what the poller needs: on restore the pane goes back to 1000 rows,
|
|
98
|
+
* so a `last_captured_line` recorded against a 44-row frame indexes into
|
|
99
|
+
* nothing. Resetting the cursor at that moment is what closes both the
|
|
100
|
+
* double-save window (a cursor too low re-saves) and the never-save window (a
|
|
101
|
+
* cursor too high suppresses forever).
|
|
102
|
+
*
|
|
103
|
+
* @param sessionName - Target session
|
|
104
|
+
* @param now - Epoch ms, injectable for tests
|
|
105
|
+
*/
|
|
106
|
+
async function probeGeometryDelegation(sessionName, now = Date.now()) {
|
|
107
|
+
const delegated = await isGeometryDelegated(sessionName, now);
|
|
108
|
+
const previous = lastObserved.get(sessionName) ?? false;
|
|
109
|
+
lastObserved.set(sessionName, delegated);
|
|
110
|
+
return { delegated, released: previous && !delegated };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Whether any NON-control-mode client is attached to the session.
|
|
114
|
+
*
|
|
115
|
+
* Used by `reconcileSessionGeometry` as the second half of its skip condition:
|
|
116
|
+
* `@cm_delegated` says "a `--live` attach is in force", this says "somebody is
|
|
117
|
+
* looking at it right now". A control-mode client — CommandMate's own transport
|
|
118
|
+
* — never counts, which is what keeps the server from treating its own
|
|
119
|
+
* connection as a reason to stop pinning the canvas.
|
|
120
|
+
*
|
|
121
|
+
* Never throws; an unreadable client list is "nobody is attached".
|
|
122
|
+
*/
|
|
123
|
+
async function hasHumanClientAttached(sessionName) {
|
|
124
|
+
try {
|
|
125
|
+
const { stdout } = await execFileAsync('tmux', (0, tmux_session_surface_1.buildListClientsArgs)(sessionName), {
|
|
126
|
+
timeout: TMUX_TIMEOUT,
|
|
127
|
+
});
|
|
128
|
+
return (0, tmux_session_surface_1.countHumanClients)(stdout) > 0;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/** Drop every memo for a session — call when it is known to be gone. */
|
|
135
|
+
function forgetGeometryDelegation(sessionName) {
|
|
136
|
+
cache.delete(sessionName);
|
|
137
|
+
lastObserved.delete(sessionName);
|
|
138
|
+
}
|
|
139
|
+
/** Test seam: drop every memo, for suites that drive several sessions. */
|
|
140
|
+
function resetGeometryDelegationState() {
|
|
141
|
+
cache.clear();
|
|
142
|
+
lastObserved.clear();
|
|
143
|
+
}
|
|
@@ -112,18 +112,31 @@ exports.PAGER_SCRIPT_FILENAME = 'cm-read-pane.sh';
|
|
|
112
112
|
* stopped.
|
|
113
113
|
*/
|
|
114
114
|
exports.PAGER_SCRIPT = `#!/bin/sh
|
|
115
|
-
# CommandMate reading mode (Issue #1623) — generated file, edits are overwritten.
|
|
115
|
+
# CommandMate reading mode (Issue #1623; --follow added by #2317) — generated file, edits are overwritten.
|
|
116
116
|
#
|
|
117
117
|
# Renders the transcript of a CommandMate tmux session with layout-only blank rows
|
|
118
118
|
# squeezed away, so a pager lands on the composer instead of hundreds of rows of
|
|
119
119
|
# padding. Invoked by \`prefix+g\` through \`display-popup -E\`; also runnable by hand:
|
|
120
120
|
#
|
|
121
121
|
# sh ~/.commandmate/bin/${exports.PAGER_SCRIPT_FILENAME} mcbd-claude-my-worktree
|
|
122
|
+
# sh ~/.commandmate/bin/${exports.PAGER_SCRIPT_FILENAME} --follow mcbd-claude-my-worktree
|
|
122
123
|
#
|
|
123
|
-
#
|
|
124
|
+
# Without --follow the popup is a SNAPSHOT. Press the key again to refresh it.
|
|
125
|
+
# With --follow (Issue #2317 Phase C) it redraws every CM_READ_FOLLOW_INTERVAL
|
|
126
|
+
# seconds and closes on \`q\`. Neither mode alters the pane, the window or the
|
|
127
|
+
# session — the popup is per-client and leaves nothing behind when it closes.
|
|
124
128
|
set -u
|
|
125
129
|
|
|
126
|
-
|
|
130
|
+
FOLLOW=0
|
|
131
|
+
SESSION=""
|
|
132
|
+
for arg in "$@"; do
|
|
133
|
+
case "$arg" in
|
|
134
|
+
--follow|-f) FOLLOW=1 ;;
|
|
135
|
+
-*) ;;
|
|
136
|
+
*) if [ -z "$SESSION" ]; then SESSION="$arg"; fi ;;
|
|
137
|
+
esac
|
|
138
|
+
done
|
|
139
|
+
|
|
127
140
|
if [ -z "$SESSION" ]; then
|
|
128
141
|
SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null) || SESSION=""
|
|
129
142
|
fi
|
|
@@ -137,6 +150,65 @@ case "$LINES_BACK" in
|
|
|
137
150
|
''|*[!0-9]*) LINES_BACK=1000 ;;
|
|
138
151
|
esac
|
|
139
152
|
|
|
153
|
+
# LC_ALL is pinned for awk ONLY (not for less, which still renders UTF-8 box
|
|
154
|
+
# drawing in the user's locale). Under gawk in a UTF-8 locale, sprintf("%c",194)
|
|
155
|
+
# yields U+00C2 rather than the byte 0xC2 and the NBSP fold below silently stops
|
|
156
|
+
# matching. See SQUEEZE_AWK_LOCALE in read-mode-pager.ts.
|
|
157
|
+
cm_read_render() {
|
|
158
|
+
tmux capture-pane -pe -t "=$SESSION:" -S "-$LINES_BACK" -E - \\
|
|
159
|
+
| LC_ALL=${exports.SQUEEZE_AWK_LOCALE} awk '${exports.SQUEEZE_AWK_PROGRAM}'
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if [ "$FOLLOW" = "1" ]; then
|
|
163
|
+
INTERVAL="\${CM_READ_FOLLOW_INTERVAL:-2}"
|
|
164
|
+
case "$INTERVAL" in
|
|
165
|
+
''|*[!0-9]*) INTERVAL=2 ;;
|
|
166
|
+
esac
|
|
167
|
+
if [ "$INTERVAL" -lt 1 ]; then INTERVAL=1; fi
|
|
168
|
+
# The key check below waits 0.2s per tick (stty \`time 2\`), so one tick is a
|
|
169
|
+
# fifth of a second and the key is answered long before the next redraw.
|
|
170
|
+
TICKS=$((INTERVAL * 5))
|
|
171
|
+
|
|
172
|
+
OLD_STTY=$(stty -g 2>/dev/null) || OLD_STTY=""
|
|
173
|
+
cm_read_restore_tty() {
|
|
174
|
+
if [ -n "$OLD_STTY" ]; then stty "$OLD_STTY" 2>/dev/null || true; fi
|
|
175
|
+
printf '\\033[?25h'
|
|
176
|
+
}
|
|
177
|
+
trap 'cm_read_restore_tty' EXIT
|
|
178
|
+
trap 'cm_read_restore_tty; exit 0' INT TERM
|
|
179
|
+
# \`min 0 time 2\` is what makes a single-byte read non-blocking-with-a-deadline:
|
|
180
|
+
# it returns after 0.2s with nothing when no key was pressed. Without it the
|
|
181
|
+
# loop would either block forever on the key or busy-spin between redraws.
|
|
182
|
+
if [ -n "$OLD_STTY" ]; then stty -icanon -echo min 0 time 2 2>/dev/null || true; fi
|
|
183
|
+
printf '\\033[?25l'
|
|
184
|
+
|
|
185
|
+
ROWS=$(tput lines 2>/dev/null) || ROWS=40
|
|
186
|
+
case "$ROWS" in
|
|
187
|
+
''|*[!0-9]*) ROWS=40 ;;
|
|
188
|
+
esac
|
|
189
|
+
BODY_ROWS=$((ROWS - 2))
|
|
190
|
+
if [ "$BODY_ROWS" -lt 1 ]; then BODY_ROWS=1; fi
|
|
191
|
+
|
|
192
|
+
while :; do
|
|
193
|
+
FRAME=$(cm_read_render | tail -n "$BODY_ROWS")
|
|
194
|
+
printf '\\033[H\\033[2J%s\\n' "$FRAME"
|
|
195
|
+
printf '\\033[7m[CommandMate] following %s — press q to close\\033[0m' "$SESSION"
|
|
196
|
+
TICK=0
|
|
197
|
+
while [ "$TICK" -lt "$TICKS" ]; do
|
|
198
|
+
if [ -n "$OLD_STTY" ]; then
|
|
199
|
+
KEY=$(dd bs=1 count=1 2>/dev/null)
|
|
200
|
+
case "$KEY" in
|
|
201
|
+
q|Q) exit 0 ;;
|
|
202
|
+
esac
|
|
203
|
+
else
|
|
204
|
+
sleep 1
|
|
205
|
+
TICK="$TICKS"
|
|
206
|
+
fi
|
|
207
|
+
TICK=$((TICK + 1))
|
|
208
|
+
done
|
|
209
|
+
done
|
|
210
|
+
fi
|
|
211
|
+
|
|
140
212
|
if [ -n "\${CM_READ_PAGER:-}" ]; then
|
|
141
213
|
PAGER_CMD="$CM_READ_PAGER"
|
|
142
214
|
elif command -v less >/dev/null 2>&1; then
|
|
@@ -145,13 +217,7 @@ else
|
|
|
145
217
|
PAGER_CMD="cat"
|
|
146
218
|
fi
|
|
147
219
|
|
|
148
|
-
|
|
149
|
-
# drawing in the user's locale). Under gawk in a UTF-8 locale, sprintf("%c",194)
|
|
150
|
-
# yields U+00C2 rather than the byte 0xC2 and the NBSP fold below silently stops
|
|
151
|
-
# matching. See SQUEEZE_AWK_LOCALE in read-mode-pager.ts.
|
|
152
|
-
tmux capture-pane -pe -t "=$SESSION:" -S "-$LINES_BACK" -E - \\
|
|
153
|
-
| LC_ALL=${exports.SQUEEZE_AWK_LOCALE} awk '${exports.SQUEEZE_AWK_PROGRAM}' \\
|
|
154
|
-
| $PAGER_CMD
|
|
220
|
+
cm_read_render | $PAGER_CMD
|
|
155
221
|
|
|
156
222
|
# Without a pager the popup would close before anything could be read.
|
|
157
223
|
if [ "$PAGER_CMD" = "cat" ]; then
|
|
@@ -45,9 +45,11 @@
|
|
|
45
45
|
* (`CM_READ_MODE=off` + restart), not a shutdown side effect.
|
|
46
46
|
*/
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.DEFAULT_READ_MODE_KEY = exports.MCBD_SESSION_PREFIX = void 0;
|
|
48
|
+
exports.READ_MODE_FOLLOW_ENV = exports.DEFAULT_READ_MODE_KEY = exports.MCBD_SESSION_PREFIX = void 0;
|
|
49
49
|
exports.getPagerScriptPath = getPagerScriptPath;
|
|
50
50
|
exports.isReadModeEnabled = isReadModeEnabled;
|
|
51
|
+
exports.isReadModeFollowEnabled = isReadModeFollowEnabled;
|
|
52
|
+
exports.buildPopupCommand = buildPopupCommand;
|
|
51
53
|
exports.resolveReadModeKey = resolveReadModeKey;
|
|
52
54
|
exports.quoteForTmuxCommand = quoteForTmuxCommand;
|
|
53
55
|
exports.buildBindKeyArgs = buildBindKeyArgs;
|
|
@@ -79,6 +81,26 @@ const TMUX_TIMEOUT = 5000;
|
|
|
79
81
|
exports.MCBD_SESSION_PREFIX = 'mcbd-';
|
|
80
82
|
/** Key bound under the prefix table when `CM_READ_MODE_KEY` is unset. */
|
|
81
83
|
exports.DEFAULT_READ_MODE_KEY = 'g';
|
|
84
|
+
/**
|
|
85
|
+
* Environment variable that makes `prefix + <key>` open the FOLLOWING popup
|
|
86
|
+
* instead of the snapshot one (Issue #2317, Phase C).
|
|
87
|
+
*
|
|
88
|
+
* ## Why one key and an option, rather than a second binding
|
|
89
|
+
*
|
|
90
|
+
* Issue #2317 offers two shapes for the follow mode — a second bound key
|
|
91
|
+
* (`CM_READ_MODE_FOLLOW_KEY`, default `G`) or a switch — and leaves the choice
|
|
92
|
+
* to implementation. This is the switch, for a reason that outlives the choice:
|
|
93
|
+
* a `bind-key` writes the tmux server's GLOBAL prefix table, which every session
|
|
94
|
+
* on the machine inherits including ones CommandMate knows nothing about. #2317
|
|
95
|
+
* 決定事項 2 says the new surface must stay session-scoped; a SECOND global key
|
|
96
|
+
* would have doubled the one global intervention the feature was allowed to
|
|
97
|
+
* keep. An environment variable costs no key table at all.
|
|
98
|
+
*
|
|
99
|
+
* The follow popup remains reachable two other ways with no key at all:
|
|
100
|
+
* `commandmate capture <id> --pane --follow`, and the opt-in
|
|
101
|
+
* `CM_READ_MODE_AUTO_POPUP=on`, which opens it on attach.
|
|
102
|
+
*/
|
|
103
|
+
exports.READ_MODE_FOLLOW_ENV = 'CM_READ_MODE_FOLLOW';
|
|
82
104
|
/**
|
|
83
105
|
* Accepted `CM_READ_MODE_KEY` values: a single alphanumeric, an F-key, either
|
|
84
106
|
* optionally with a `C-` / `M-` / `S-` modifier. Deliberately narrow — a typo
|
|
@@ -104,6 +126,26 @@ function isReadModeEnabled() {
|
|
|
104
126
|
const raw = (process.env.CM_READ_MODE ?? '').trim().toLowerCase();
|
|
105
127
|
return raw !== 'off' && raw !== '0' && raw !== 'false';
|
|
106
128
|
}
|
|
129
|
+
/** True when the operator asked `prefix + <key>` to follow rather than snapshot. */
|
|
130
|
+
function isReadModeFollowEnabled() {
|
|
131
|
+
return (process.env[exports.READ_MODE_FOLLOW_ENV] ?? '').trim().toLowerCase() === 'on';
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The shell command the popup runs: the pager script, plus `--follow` when the
|
|
135
|
+
* operator asked for it.
|
|
136
|
+
*
|
|
137
|
+
* One word per argument and no quoting of its own — {@link quoteForTmuxCommand}
|
|
138
|
+
* wraps the WHOLE line, so tmux hands `/bin/sh` a single command string. That is
|
|
139
|
+
* the same shape the snapshot form has always had; the flag rides inside the
|
|
140
|
+
* quotes rather than after them, because a word after the closing quote would be
|
|
141
|
+
* a second argument to `display-popup`, not to the script.
|
|
142
|
+
*
|
|
143
|
+
* @param scriptPath - Absolute path of the materialized pager script
|
|
144
|
+
* @param follow - Whether to append `--follow`
|
|
145
|
+
*/
|
|
146
|
+
function buildPopupCommand(scriptPath, follow) {
|
|
147
|
+
return follow ? `${scriptPath} --follow` : scriptPath;
|
|
148
|
+
}
|
|
107
149
|
/**
|
|
108
150
|
* Resolve the configured key, or undefined when it is malformed.
|
|
109
151
|
* @returns The key to bind, or undefined if `CM_READ_MODE_KEY` fails validation
|
|
@@ -283,7 +325,7 @@ async function reconcileReadModeBinding() {
|
|
|
283
325
|
detail: 'display-popup requires tmux 3.2+; use `commandmate capture <id> --pane` instead',
|
|
284
326
|
};
|
|
285
327
|
}
|
|
286
|
-
const quoted = quoteForTmuxCommand(scriptPath);
|
|
328
|
+
const quoted = quoteForTmuxCommand(buildPopupCommand(scriptPath, isReadModeFollowEnabled()));
|
|
287
329
|
if (quoted === undefined) {
|
|
288
330
|
return { installed: false, outcome: 'unsafe-script-path', key, scriptPath };
|
|
289
331
|
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The shell scripts session-scoped tmux hooks run (Issue #2317, Phases C and D).
|
|
4
|
+
*
|
|
5
|
+
* ## Why the text is embedded rather than shipped as a file
|
|
6
|
+
*
|
|
7
|
+
* The same reason `read-mode-pager.ts` gives for `cm-read-pane.sh`:
|
|
8
|
+
* `package.json`'s `files` list does not publish `scripts/`, and an `npx`
|
|
9
|
+
* install lives in a cache npm may garbage-collect out from under a hook that
|
|
10
|
+
* outlives the process which installed it. Embedding the text and materializing
|
|
11
|
+
* it into `~/.commandmate/bin/` gives every hook one absolute path that is
|
|
12
|
+
* stable across global / local / npx installs.
|
|
13
|
+
*
|
|
14
|
+
* ## Why the hooks call scripts instead of doing the work inline
|
|
15
|
+
*
|
|
16
|
+
* Measured on tmux 3.5a (Issue #2317 技術検証): a hook body of the shape
|
|
17
|
+
* `if-shell -F '#{…}' '<command>'` is accepted by `set-hook` and then never
|
|
18
|
+
* fires — silently, with no error anywhere. A
|
|
19
|
+
* `run-shell -b '<script> #{session_name} #{client_control_mode}'` DOES fire.
|
|
20
|
+
* So the formats are handed to a script and every branch is taken in `sh`.
|
|
21
|
+
*
|
|
22
|
+
* The hook environment is the tmux SERVER's, which carries `TMUX` — so the bare
|
|
23
|
+
* `tmux` these scripts call reaches the same server that fired the hook, private
|
|
24
|
+
* socket included. That is verified, not assumed: the whole live probe for this
|
|
25
|
+
* Issue ran under `tmux -L cm2317` and the scripts reached that server.
|
|
26
|
+
*
|
|
27
|
+
* ## Both scripts refuse to touch a session that is not CommandMate's
|
|
28
|
+
*
|
|
29
|
+
* A hook is session-scoped, so in principle it can only fire on the session it
|
|
30
|
+
* was installed on. The `mcbd-` guard is still there because these scripts are
|
|
31
|
+
* also runnable by hand and because a session can be renamed.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.AUTO_POPUP_SCRIPT = exports.LIVE_DELEGATE_SCRIPT = exports.LIVE_RESTORE_SCRIPT = exports.AUTO_POPUP_SCRIPT_FILENAME = exports.LIVE_DELEGATE_SCRIPT_FILENAME = exports.LIVE_RESTORE_SCRIPT_FILENAME = void 0;
|
|
35
|
+
exports.getScriptDir = getScriptDir;
|
|
36
|
+
exports.getScriptPath = getScriptPath;
|
|
37
|
+
exports.materializeScript = materializeScript;
|
|
38
|
+
exports.materializeLiveRestoreScript = materializeLiveRestoreScript;
|
|
39
|
+
exports.materializeLiveDelegateScript = materializeLiveDelegateScript;
|
|
40
|
+
exports.materializeAutoPopupScript = materializeAutoPopupScript;
|
|
41
|
+
const fs_1 = require("fs");
|
|
42
|
+
const os_1 = require("os");
|
|
43
|
+
const path_1 = require("path");
|
|
44
|
+
const tmux_pane_config_1 = require("../../config/tmux-pane-config");
|
|
45
|
+
const tmux_session_surface_1 = require("../session/tmux-session-surface");
|
|
46
|
+
const read_mode_pager_1 = require("./read-mode-pager");
|
|
47
|
+
/** Basename of the Phase D geometry-restore script. */
|
|
48
|
+
exports.LIVE_RESTORE_SCRIPT_FILENAME = 'cm-live-restore.sh';
|
|
49
|
+
/** Basename of the Phase D geometry-delegation script. */
|
|
50
|
+
exports.LIVE_DELEGATE_SCRIPT_FILENAME = 'cm-live-delegate.sh';
|
|
51
|
+
/** Basename of the Phase C auto-popup script. */
|
|
52
|
+
exports.AUTO_POPUP_SCRIPT_FILENAME = 'cm-auto-popup.sh';
|
|
53
|
+
/**
|
|
54
|
+
* Restore a session's pinned canvas once no human client is attached.
|
|
55
|
+
*
|
|
56
|
+
* NOT a hook body — tmux 3.5a never fires a session-scoped `client-detached`
|
|
57
|
+
* (see the measurement table in `live-attach.ts`). Two things run this sequence:
|
|
58
|
+
* `commandmate attach --live` when `attach-session` returns, and the server's
|
|
59
|
+
* status poll (`reconcileDelegatedGeometry`) for every case where the CLI never
|
|
60
|
+
* got to — it was killed, the terminal window was closed, or the detach happened
|
|
61
|
+
* from a client this process never saw. This script is the third, manual, path:
|
|
62
|
+
* the escape hatch for a session left delegated while no server is running.
|
|
63
|
+
*
|
|
64
|
+
* The control-mode test is the whole reason the client count is not simply
|
|
65
|
+
* `#{session_attached}`: CommandMate's own transport attaches as a `tmux -C`
|
|
66
|
+
* client and never leaves, so a session with the human gone still reports
|
|
67
|
+
* `session_attached=1`. `client_control_mode` is `1` for those and `0` for a
|
|
68
|
+
* terminal, so the restore waits for the HUMAN count to reach zero
|
|
69
|
+
* (Issue #2317 受入条件 Phase D 4).
|
|
70
|
+
*/
|
|
71
|
+
exports.LIVE_RESTORE_SCRIPT = `#!/bin/sh
|
|
72
|
+
# CommandMate live-attach restore (Issue #2317) — generated file, edits are overwritten.
|
|
73
|
+
#
|
|
74
|
+
# sh ~/.commandmate/bin/${exports.LIVE_RESTORE_SCRIPT_FILENAME} <session> [control_mode] [width] [height]
|
|
75
|
+
#
|
|
76
|
+
# Pins the session's window back to CommandMate's canvas once no human client is
|
|
77
|
+
# attached to it any more. Safe to run when nothing is delegated: it then simply
|
|
78
|
+
# re-applies the geometry the session already has.
|
|
79
|
+
set -u
|
|
80
|
+
|
|
81
|
+
SESSION="\${1:-}"
|
|
82
|
+
CONTROL_MODE="\${2:-0}"
|
|
83
|
+
WIDTH="\${3:-${tmux_pane_config_1.TUI_PANE_WIDTH}}"
|
|
84
|
+
HEIGHT="\${4:-${tmux_pane_config_1.TUI_PANE_HEIGHT}}"
|
|
85
|
+
|
|
86
|
+
case "$SESSION" in
|
|
87
|
+
${tmux_session_surface_1.MCBD_SESSION_PREFIX}*) ;;
|
|
88
|
+
*) exit 0 ;;
|
|
89
|
+
esac
|
|
90
|
+
|
|
91
|
+
# A control-mode client detaching is CommandMate's own transport reconnecting,
|
|
92
|
+
# not the human leaving. Doing the restore here would fight the human's attach.
|
|
93
|
+
if [ "$CONTROL_MODE" = "1" ]; then
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Anyone left who is NOT a control client? Then the geometry is still theirs.
|
|
98
|
+
HUMANS=$(tmux list-clients -t "=$SESSION:" -F '#{client_control_mode}' 2>/dev/null \\
|
|
99
|
+
| grep -c -v '^1$') || HUMANS=0
|
|
100
|
+
if [ "\${HUMANS:-0}" -gt 0 ]; then
|
|
101
|
+
exit 0
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
tmux set-window-option -t "=$SESSION:" window-size manual 2>/dev/null || exit 0
|
|
105
|
+
tmux resize-window -t "=$SESSION:" -x "$WIDTH" -y "$HEIGHT" 2>/dev/null || true
|
|
106
|
+
tmux set-option -u -t "=$SESSION:" @cm_delegated 2>/dev/null || true
|
|
107
|
+
`;
|
|
108
|
+
/**
|
|
109
|
+
* Hand a session's geometry to the terminal that just attached.
|
|
110
|
+
*
|
|
111
|
+
* The opt-in half of Phase D: `commandmate attach --live` performs these two
|
|
112
|
+
* writes itself, and this script is what makes a HAND-ROLLED `tmux attach`
|
|
113
|
+
* behave the same way when the operator asked for it with
|
|
114
|
+
* `CM_LIVE_ATTACH_HOOK=on`.
|
|
115
|
+
*
|
|
116
|
+
* claude-only by session-name prefix, and that is not a shortcut. The session
|
|
117
|
+
* name is `mcbd-<tool>-<worktree>`, no other CLI tool id begins with `claude`,
|
|
118
|
+
* and the script has nothing but the name to go on — a hook fires with tmux
|
|
119
|
+
* formats, not with CommandMate's roster. Widening it means widening
|
|
120
|
+
* `LIVE_ATTACH_TOOLS` too, and that needs the per-tool re-measurement
|
|
121
|
+
* Issue #2317 puts out of scope.
|
|
122
|
+
*/
|
|
123
|
+
exports.LIVE_DELEGATE_SCRIPT = `#!/bin/sh
|
|
124
|
+
# CommandMate live-attach delegate (Issue #2317) — generated file, edits are overwritten.
|
|
125
|
+
#
|
|
126
|
+
# sh ~/.commandmate/bin/${exports.LIVE_DELEGATE_SCRIPT_FILENAME} <session> <control_mode> [client]
|
|
127
|
+
#
|
|
128
|
+
# Hands the session's window from CommandMate's pinned canvas to the terminal
|
|
129
|
+
# that just attached, so an alternate-screen agent re-lays-out and its transcript
|
|
130
|
+
# becomes readable. Installed as a session-scoped \`client-attached[0]\` hook only
|
|
131
|
+
# when CM_LIVE_ATTACH_HOOK=on; \`commandmate attach --live\` does the same two
|
|
132
|
+
# writes itself and needs no hook.
|
|
133
|
+
#
|
|
134
|
+
# The window is put back by whoever notices the human is gone first: the CLI on
|
|
135
|
+
# return from attach-session, or the server's status poll. This script never
|
|
136
|
+
# restores — the attach edge is the only edge tmux 3.5a lets a session-scoped
|
|
137
|
+
# hook see.
|
|
138
|
+
set -u
|
|
139
|
+
|
|
140
|
+
SESSION="\${1:-}"
|
|
141
|
+
CONTROL_MODE="\${2:-0}"
|
|
142
|
+
|
|
143
|
+
case "$SESSION" in
|
|
144
|
+
${tmux_session_surface_1.MCBD_SESSION_PREFIX}claude-*) ;;
|
|
145
|
+
*) exit 0 ;;
|
|
146
|
+
esac
|
|
147
|
+
|
|
148
|
+
# A control-mode client is CommandMate's own transport. Handing it the geometry
|
|
149
|
+
# would resize the canvas to whatever that connection negotiated, which is the
|
|
150
|
+
# #1163 regression this whole feature is built to avoid.
|
|
151
|
+
if [ "$CONTROL_MODE" = "1" ]; then
|
|
152
|
+
exit 0
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
# Raised BEFORE the size change, so a status poll landing between the two sees
|
|
156
|
+
# "delegated, still pinned" rather than "not delegated, 44 rows".
|
|
157
|
+
tmux set-option -t "=$SESSION:" @cm_delegated 1 2>/dev/null || exit 0
|
|
158
|
+
tmux set-window-option -t "=$SESSION:" window-size latest 2>/dev/null || true
|
|
159
|
+
`;
|
|
160
|
+
/**
|
|
161
|
+
* Open the following transcript popup when a human attaches (Phase C, opt-in).
|
|
162
|
+
*
|
|
163
|
+
* Default off, and it has to be: the popup owns the keyboard until `q` is
|
|
164
|
+
* pressed, so opening it unasked would make every attach start by taking input
|
|
165
|
+
* away from the composer. `CM_READ_MODE_AUTO_POPUP=on` is the opt-in, and even
|
|
166
|
+
* then the control-mode test below keeps it from firing for CommandMate's own
|
|
167
|
+
* transport — a popup opened on a control client would be a popup nobody can
|
|
168
|
+
* see and nobody can close.
|
|
169
|
+
*/
|
|
170
|
+
exports.AUTO_POPUP_SCRIPT = `#!/bin/sh
|
|
171
|
+
# CommandMate auto read popup (Issue #2317) — generated file, edits are overwritten.
|
|
172
|
+
#
|
|
173
|
+
# sh ~/.commandmate/bin/${exports.AUTO_POPUP_SCRIPT_FILENAME} <session> <control_mode> <client>
|
|
174
|
+
#
|
|
175
|
+
# Opens the following transcript popup for a human client attaching to a
|
|
176
|
+
# CommandMate session. Never opens for a control-mode client.
|
|
177
|
+
set -u
|
|
178
|
+
|
|
179
|
+
SESSION="\${1:-}"
|
|
180
|
+
CONTROL_MODE="\${2:-0}"
|
|
181
|
+
CLIENT="\${3:-}"
|
|
182
|
+
|
|
183
|
+
case "$SESSION" in
|
|
184
|
+
${tmux_session_surface_1.MCBD_SESSION_PREFIX}*) ;;
|
|
185
|
+
*) exit 0 ;;
|
|
186
|
+
esac
|
|
187
|
+
|
|
188
|
+
if [ "$CONTROL_MODE" = "1" ]; then
|
|
189
|
+
exit 0
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
PAGER_SCRIPT="$HOME/.commandmate/bin/${read_mode_pager_1.PAGER_SCRIPT_FILENAME}"
|
|
193
|
+
[ -x "$PAGER_SCRIPT" ] || exit 0
|
|
194
|
+
|
|
195
|
+
if [ -n "$CLIENT" ]; then
|
|
196
|
+
tmux display-popup -c "$CLIENT" -w 90% -h 85% -E "sh \\"$PAGER_SCRIPT\\" --follow \\"$SESSION\\"" 2>/dev/null || true
|
|
197
|
+
else
|
|
198
|
+
tmux display-popup -w 90% -h 85% -E "sh \\"$PAGER_SCRIPT\\" --follow \\"$SESSION\\"" 2>/dev/null || true
|
|
199
|
+
fi
|
|
200
|
+
`;
|
|
201
|
+
/** Directory every materialized CommandMate script lives in. */
|
|
202
|
+
function getScriptDir() {
|
|
203
|
+
return (0, path_1.join)((0, os_1.homedir)(), '.commandmate', 'bin');
|
|
204
|
+
}
|
|
205
|
+
/** Absolute path of a materialized script. */
|
|
206
|
+
function getScriptPath(filename) {
|
|
207
|
+
return (0, path_1.join)(getScriptDir(), filename);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Write a script to `~/.commandmate/bin/<filename>` if its content changed.
|
|
211
|
+
*
|
|
212
|
+
* Idempotent by content comparison so a restart does not churn the file's mtime,
|
|
213
|
+
* and re-executable after a `chmod` accident because the mode is re-applied —
|
|
214
|
+
* the same contract `materializePagerScript()` has had since #1623.
|
|
215
|
+
*
|
|
216
|
+
* @param filename - Basename to write
|
|
217
|
+
* @param content - Full script text
|
|
218
|
+
* @returns The absolute path written
|
|
219
|
+
*/
|
|
220
|
+
function materializeScript(filename, content) {
|
|
221
|
+
const scriptPath = getScriptPath(filename);
|
|
222
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(scriptPath), { recursive: true });
|
|
223
|
+
let current;
|
|
224
|
+
if ((0, fs_1.existsSync)(scriptPath)) {
|
|
225
|
+
try {
|
|
226
|
+
current = (0, fs_1.readFileSync)(scriptPath, 'utf-8');
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
current = undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (current !== content) {
|
|
233
|
+
(0, fs_1.writeFileSync)(scriptPath, content, { mode: 0o755 });
|
|
234
|
+
}
|
|
235
|
+
(0, fs_1.chmodSync)(scriptPath, 0o755);
|
|
236
|
+
return scriptPath;
|
|
237
|
+
}
|
|
238
|
+
/** Materialize the Phase D restore script and return its absolute path. */
|
|
239
|
+
function materializeLiveRestoreScript() {
|
|
240
|
+
return materializeScript(exports.LIVE_RESTORE_SCRIPT_FILENAME, exports.LIVE_RESTORE_SCRIPT);
|
|
241
|
+
}
|
|
242
|
+
/** Materialize the Phase D delegate script and return its absolute path. */
|
|
243
|
+
function materializeLiveDelegateScript() {
|
|
244
|
+
return materializeScript(exports.LIVE_DELEGATE_SCRIPT_FILENAME, exports.LIVE_DELEGATE_SCRIPT);
|
|
245
|
+
}
|
|
246
|
+
/** Materialize the Phase C auto-popup script and return its absolute path. */
|
|
247
|
+
function materializeAutoPopupScript() {
|
|
248
|
+
return materializeScript(exports.AUTO_POPUP_SCRIPT_FILENAME, exports.AUTO_POPUP_SCRIPT);
|
|
249
|
+
}
|