commandmate 0.33.3 → 0.34.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 +146 -146
- package/.next/app-path-routes-manifest.json +26 -26
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +15 -15
- 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 +2 -2
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +3 -3
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/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 +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_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/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/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_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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_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_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/notes/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.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 +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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +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_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_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.js +2 -2
- 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 +2 -2
- 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.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.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.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_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +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_client-reference-manifest.js +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_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_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +8 -8
- 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 +26 -26
- package/.next/server/chunks/1501.js +4 -4
- package/.next/server/chunks/1886.js +2 -2
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/3077.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3323.js +1 -1
- package/.next/server/chunks/3480.js +2 -2
- package/.next/server/chunks/434.js +1 -0
- package/.next/server/chunks/4443.js +1 -1
- package/.next/server/chunks/4802.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/5571.js +1 -1
- package/.next/server/chunks/595.js +3 -3
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6285.js +1 -1
- package/.next/server/chunks/6286.js +7 -7
- package/.next/server/chunks/6337.js +1 -1
- package/.next/server/chunks/650.js +1 -1
- package/.next/server/chunks/663.js +1 -1
- package/.next/server/chunks/6677.js +25 -0
- package/.next/server/chunks/7075.js +1 -0
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8583.js +1 -0
- package/.next/server/chunks/8807.js +10 -10
- package/.next/server/chunks/8918.js +4 -2
- package/.next/server/chunks/9080.js +1 -0
- package/.next/server/chunks/964.js +1 -0
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/server/src/middleware.js +1 -1
- package/.next/server/src/middleware.js.map +1 -1
- package/.next/static/chunks/2053-9ac860ab4e92ac89.js +1 -0
- package/.next/static/chunks/2652-18b8fea64413467e.js +1 -0
- package/.next/static/chunks/{4718-814f4ecfd7fcc513.js → 4718-29cfcfb806724d9a.js} +1 -1
- package/.next/static/chunks/{8361-9bb887203c456edb.js → 8361-0142beb59be2abf3.js} +1 -1
- package/.next/static/chunks/app/{page-022090bf6f932818.js → page-26a42881c8648cd3.js} +1 -1
- package/.next/static/chunks/app/sessions/page-a3ab6f122ec60d5a.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-60eab4e24c37cb77.js +1 -0
- package/.next/static/css/b09bede85744e1cf.css +1 -0
- package/.next/trace +13 -13
- package/README.md +141 -24
- package/dist/cli/commands/ask.d.ts.map +1 -1
- package/dist/cli/commands/ask.js +11 -2
- package/dist/cli/commands/remote.d.ts +93 -3
- package/dist/cli/commands/remote.d.ts.map +1 -1
- package/dist/cli/commands/remote.js +232 -9
- package/dist/cli/commands/respond.d.ts.map +1 -1
- package/dist/cli/commands/respond.js +8 -4
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +18 -0
- package/dist/cli/commands/wait.d.ts +18 -3
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +137 -2
- package/dist/cli/docs/agent-operations.d.ts +2 -2
- package/dist/cli/docs/agent-operations.d.ts.map +1 -1
- package/dist/cli/docs/agent-operations.js +41 -1
- package/dist/cli/types/index.d.ts +9 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/utils/api-client.d.ts.map +1 -1
- package/dist/cli/utils/api-client.js +11 -1
- package/dist/cli/utils/remote-state.d.ts +32 -0
- package/dist/cli/utils/remote-state.d.ts.map +1 -1
- package/dist/cli/utils/remote-state.js +12 -0
- package/dist/cli/utils/session-target.d.ts +23 -6
- package/dist/cli/utils/session-target.d.ts.map +1 -1
- package/dist/cli/utils/session-target.js +33 -5
- package/dist/server/locales/en/worktree.json +21 -2
- package/dist/server/locales/ja/worktree.json +21 -2
- package/dist/server/server.js +204 -16
- package/dist/server/src/config/schedule-config.js +45 -3
- package/dist/server/src/lib/cli-tools/antigravity.js +95 -10
- package/dist/server/src/lib/cli-tools/submit-verified-sender.js +377 -16
- package/dist/server/src/lib/cmate-parser.js +8 -1
- package/dist/server/src/lib/db/agent-instances-db.js +11 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +140 -19
- package/dist/server/src/lib/detection/tools/claude/detect.js +13 -2
- package/dist/server/src/lib/detection/tools/claude/picker-chrome.js +239 -0
- package/dist/server/src/lib/detection/tools/claude/prompt.js +74 -6
- package/dist/server/src/lib/hooks/sources/claude/history.js +391 -34
- package/dist/server/src/lib/hooks/sources/claude/transcript.js +91 -0
- package/dist/server/src/lib/hooks/sources/opencode/ports.js +6 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +114 -11
- package/dist/server/src/lib/polling/response-checker.js +82 -3
- package/dist/server/src/lib/relay/relay-session-ref.js +15 -8
- package/dist/server/src/lib/schedule-manager.js +178 -19
- package/dist/server/src/lib/session/ask-user-question-prompt.js +4 -2
- package/dist/server/src/lib/session/claude-executor.js +33 -2
- package/dist/server/src/lib/session/resolve-session-target.js +37 -9
- package/dist/server/src/lib/verification/env-clean-gate.js +81 -4
- package/dist/server/src/lib/ws-server.js +74 -5
- package/dist/server/src/types/agent-transcript.js +143 -1
- package/package.json +1 -1
- package/.next/server/chunks/1068.js +0 -1
- package/.next/server/chunks/6808.js +0 -1
- package/.next/server/chunks/7875.js +0 -25
- package/.next/server/chunks/9553.js +0 -1
- package/.next/static/chunks/2053-3f299a7a2c7d6767.js +0 -1
- package/.next/static/chunks/8772-9be53a530950d804.js +0 -1
- package/.next/static/chunks/app/sessions/page-584adf11ae51df10.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-3af707e74a75172b.js +0 -1
- package/.next/static/css/acd46e25427a2080.css +0 -1
- /package/.next/static/{9x6U1h52hH_r6pOsGwI_p → oDWX0JcwfhUYrMnnqDWVC}/_buildManifest.js +0 -0
- /package/.next/static/{9x6U1h52hH_r6pOsGwI_p → oDWX0JcwfhUYrMnnqDWVC}/_ssgManifest.js +0 -0
|
@@ -8,14 +8,19 @@
|
|
|
8
8
|
* conversation area (grows downward) | bare "> " input box | status bar
|
|
9
9
|
* The status bar reads "? for shortcuts ... <model>" when idle and
|
|
10
10
|
* "esc to cancel ..." while generating. Patterns confirmed on a real machine.
|
|
11
|
+
* agy 1.2.1 leaves the idle half of that bar blank after a turn that used a
|
|
12
|
+
* tool (Issue #2478), so readiness is read off the input box — see
|
|
13
|
+
* {@link isAntigravityReady}.
|
|
11
14
|
*/
|
|
12
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
16
|
exports.AntigravityTool = void 0;
|
|
17
|
+
exports.isAntigravityReady = isAntigravityReady;
|
|
14
18
|
const base_1 = require("./base");
|
|
15
19
|
const tmux_1 = require("../tmux/tmux");
|
|
16
20
|
const submit_verified_sender_1 = require("./submit-verified-sender");
|
|
17
21
|
const tmux_capture_cache_1 = require("../tmux/tmux-capture-cache");
|
|
18
22
|
const cli_patterns_1 = require("../detection/cli-patterns");
|
|
23
|
+
const frame_1 = require("../detection/tools/frame");
|
|
19
24
|
const sources_1 = require("../../lib/hooks/sources");
|
|
20
25
|
const agent_session_lifecycle_1 = require("../../lib/session/agent-session-lifecycle");
|
|
21
26
|
const logger_1 = require("../../lib/logger");
|
|
@@ -51,10 +56,14 @@ const ANTIGRAVITY_INIT_MAX_ATTEMPTS = 30;
|
|
|
51
56
|
/** Timeout for waiting for the prompt before sending a message. */
|
|
52
57
|
const ANTIGRAVITY_PROMPT_WAIT_TIMEOUT_MS = 15000;
|
|
53
58
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
59
|
+
* agy's own word for "idle", drawn on the status row under the input box
|
|
60
|
+
* ("? for shortcuts … <model>"). While generating the same row reads "esc to
|
|
61
|
+
* cancel"; the trust screen and the dialogs draw their own footers instead.
|
|
62
|
+
*
|
|
63
|
+
* Issue #2478: sufficient, no longer required. agy 1.2.1 does not redraw it
|
|
64
|
+
* after a turn that used a tool — the row keeps only the right-aligned model
|
|
65
|
+
* label (`tests/fixtures/antigravity-live-2478/after-tool-turn.txt`) — and a
|
|
66
|
+
* send that waited for it timed out on every later turn of that session.
|
|
58
67
|
*/
|
|
59
68
|
const ANTIGRAVITY_READY_FOOTER_PATTERN = /\?\s+for\s+shortcuts/;
|
|
60
69
|
/**
|
|
@@ -69,12 +78,88 @@ const ANTIGRAVITY_READY_FOOTER_PATTERN = /\?\s+for\s+shortcuts/;
|
|
|
69
78
|
*/
|
|
70
79
|
const ANTIGRAVITY_TRUST_DIALOG_PATTERN = /Do you trust the contents of this project\?/;
|
|
71
80
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
81
|
+
* Read agy's input box off the bottom of a frame (Issue #2478).
|
|
82
|
+
*
|
|
83
|
+
* agy draws the box — a bare `>` between two rules, its status row under the
|
|
84
|
+
* lower one — as the last thing on the screen, and everything else it can show
|
|
85
|
+
* either replaces the box (the permission dialogs, the trust screen, the
|
|
86
|
+
* post-answer survey) or is drawn below it (the `/model` picker, the slash
|
|
87
|
+
* command popup, `/feedback`'s category menu). So a frame that ENDS in the box
|
|
88
|
+
* is one whose input box is live, and a `>` row with more than the status row
|
|
89
|
+
* under it is not a box anyone can type into.
|
|
90
|
+
*
|
|
91
|
+
* This is stricter than the status detector's `promptPattern.test(lastLines)`
|
|
92
|
+
* (`detection/tools/antigravity/detect.ts`), which accepts the `>` anywhere in
|
|
93
|
+
* the 15-row tail: the detector tells `/feedback`'s menu apart only in the
|
|
94
|
+
* shared generic prompt step that runs before it, and this check does not run
|
|
95
|
+
* that step. The rows between the `>` and the lower rule may be blank — agy
|
|
96
|
+
* 1.2.1 leaves the box three rows tall after a tool turn.
|
|
97
|
+
*
|
|
98
|
+
* @param contentLines - ANSI-stripped rows, trailing blank rows dropped
|
|
99
|
+
* @returns The status row under the box ('' when agy drew none), or null when
|
|
100
|
+
* the frame does not end in the box
|
|
101
|
+
*/
|
|
102
|
+
function readInputBoxStatusRow(contentLines) {
|
|
103
|
+
const rows = contentLines.map((row) => row.trim());
|
|
104
|
+
const isRule = (i) => i >= 0 && cli_patterns_1.ANTIGRAVITY_SEPARATOR_PATTERN.test(rows[i]);
|
|
105
|
+
const skipBlank = (from) => {
|
|
106
|
+
let i = from;
|
|
107
|
+
while (i >= 0 && rows[i] === '')
|
|
108
|
+
i--;
|
|
109
|
+
return i;
|
|
110
|
+
};
|
|
111
|
+
let i = rows.length - 1;
|
|
112
|
+
let statusRow = '';
|
|
113
|
+
if (i >= 0 && !isRule(i)) {
|
|
114
|
+
statusRow = rows[i];
|
|
115
|
+
i = skipBlank(i - 1);
|
|
116
|
+
}
|
|
117
|
+
if (!isRule(i))
|
|
118
|
+
return null;
|
|
119
|
+
i = skipBlank(i - 1);
|
|
120
|
+
if (i < 0 || !cli_patterns_1.ANTIGRAVITY_PROMPT_PATTERN.test(rows[i]))
|
|
121
|
+
return null;
|
|
122
|
+
return isRule(skipBlank(i - 1)) ? statusRow : null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Decide whether a typed message would land in agy's input box (Issue #2478).
|
|
126
|
+
*
|
|
127
|
+
* Read on the status detector's evidence (`detection/tools/antigravity/detect.ts`)
|
|
128
|
+
* over the status detector's frame (`normalizeFrame`: ANSI stripped, padding
|
|
129
|
+
* dropped, the same 15-row tail):
|
|
130
|
+
*
|
|
131
|
+
* 1. No agy screen is up: the `Switch Model` / `↑/↓ Navigate` test its
|
|
132
|
+
* `beforePrompt` makes (every branch after that test answers `waiting` or
|
|
133
|
+
* `running`, so it covers the numbered dialogs too), and the trust
|
|
134
|
+
* question. Both over the tail — with the pane 1000 rows tall the whole
|
|
135
|
+
* transcript is in the capture, and a quoted question anywhere in it used
|
|
136
|
+
* to block every send.
|
|
137
|
+
* 2. The frame ends in the input box ({@link readInputBoxStatusRow}).
|
|
138
|
+
* 3. agy is not generating. `? for shortcuts` on the status row settles it —
|
|
139
|
+
* kept as a sufficient signal so a thought summary such as "Generating the
|
|
140
|
+
* specified file" left in the tail cannot block a send the pre-#2478 rule
|
|
141
|
+
* allowed. Without it, `afterThinking`'s reading: no spinner, `Generating`
|
|
142
|
+
* or `esc to cancel` in the tail. The box stays on screen while agy
|
|
143
|
+
* generates, so 2 alone would not do.
|
|
144
|
+
*
|
|
145
|
+
* Before #2478 the footer was required and the detector never read it, so the
|
|
146
|
+
* two disagreed on every frame agy 1.2.1 draws after a tool turn.
|
|
147
|
+
*
|
|
148
|
+
* @param output - A captured pane, raw or ANSI-stripped
|
|
149
|
+
* @returns True when the input box is live and agy is idle
|
|
74
150
|
*/
|
|
75
151
|
function isAntigravityReady(output) {
|
|
76
|
-
|
|
77
|
-
|
|
152
|
+
const frame = (0, frame_1.normalizeFrame)(output);
|
|
153
|
+
if (cli_patterns_1.ANTIGRAVITY_SELECTION_LIST_PATTERN.test(frame.lastLines))
|
|
154
|
+
return false;
|
|
155
|
+
if (ANTIGRAVITY_TRUST_DIALOG_PATTERN.test(frame.lastLines))
|
|
156
|
+
return false;
|
|
157
|
+
const statusRow = readInputBoxStatusRow(frame.contentLines);
|
|
158
|
+
if (statusRow === null)
|
|
159
|
+
return false;
|
|
160
|
+
if (ANTIGRAVITY_READY_FOOTER_PATTERN.test(statusRow))
|
|
161
|
+
return true;
|
|
162
|
+
return !(0, cli_patterns_1.detectThinking)('antigravity', frame.lastLines);
|
|
78
163
|
}
|
|
79
164
|
/**
|
|
80
165
|
* Antigravity CLI tool implementation.
|
|
@@ -185,7 +270,7 @@ class AntigravityTool extends base_1.BaseCLITool {
|
|
|
185
270
|
* Wait for agy to become ready (input prompt live).
|
|
186
271
|
* Handles the first-run trust dialog ("Do you trust the contents of this
|
|
187
272
|
* project?") by sending Enter to confirm the default "Yes, I trust this folder"
|
|
188
|
-
* selection. Polls until
|
|
273
|
+
* selection. Polls until {@link isAntigravityReady} or max attempts reached.
|
|
189
274
|
*/
|
|
190
275
|
async waitForReady(sessionName) {
|
|
191
276
|
// One-shot guard: capturePane keeps the dismissed dialog in scrollback, so
|
|
@@ -195,7 +280,7 @@ class AntigravityTool extends base_1.BaseCLITool {
|
|
|
195
280
|
try {
|
|
196
281
|
const rawOutput = await (0, tmux_1.capturePane)(sessionName, 50);
|
|
197
282
|
const output = (0, cli_patterns_1.stripAnsi)(rawOutput);
|
|
198
|
-
// Ready:
|
|
283
|
+
// Ready: the input box is live and no agy screen covers it.
|
|
199
284
|
if (isAntigravityReady(output)) {
|
|
200
285
|
logger.info('antigravity-prompt-detected');
|
|
201
286
|
return;
|
|
@@ -53,12 +53,62 @@
|
|
|
53
53
|
* indistinguishable from a clean send by every signal a caller has. The
|
|
54
54
|
* composer is therefore emptied and read back BEFORE the body is typed — see
|
|
55
55
|
* {@link clearComposerBeforeSend}.
|
|
56
|
+
*
|
|
57
|
+
* Issue #2464 is the body itself going missing on the way in. A body longer
|
|
58
|
+
* than one pty read reaches the TUI as several reads — tmux delivers every byte
|
|
59
|
+
* (12,288 of 12,288 measured on a raw pane), but the reader gets them 1,022
|
|
60
|
+
* bytes at a time on macOS — and Claude Code 2.1.268 reassembles unbracketed
|
|
61
|
+
* input read by read and keeps only the LAST one. A 1 KB brief arrived as its
|
|
62
|
+
* final 2 bytes, a 4 KB one as its final 8, and the send still said `Message
|
|
63
|
+
* sent.`: the tail sits in the composer as ordinary text, Enter submits it, and
|
|
64
|
+
* nothing downstream can tell a tail from a message. Neither the #1880 clear nor
|
|
65
|
+
* the Enter timing is involved — both were switched off in controls and the
|
|
66
|
+
* loss was unchanged. So a long body is now PASTED ({@link pasteBody}: one
|
|
67
|
+
* bracketed paste, which the TUI reads as a unit), and Enter is withheld until
|
|
68
|
+
* the composer shows the whole of it ({@link classifyPasteLanded}). The
|
|
69
|
+
* measurements are in `docs/design/2464-long-body-repro-matrix.md`.
|
|
56
70
|
*/
|
|
71
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
72
|
+
if (k2 === undefined) k2 = k;
|
|
73
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
74
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
75
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
76
|
+
}
|
|
77
|
+
Object.defineProperty(o, k2, desc);
|
|
78
|
+
}) : (function(o, m, k, k2) {
|
|
79
|
+
if (k2 === undefined) k2 = k;
|
|
80
|
+
o[k2] = m[k];
|
|
81
|
+
}));
|
|
82
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
83
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
84
|
+
}) : function(o, v) {
|
|
85
|
+
o["default"] = v;
|
|
86
|
+
});
|
|
87
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
88
|
+
var ownKeys = function(o) {
|
|
89
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
90
|
+
var ar = [];
|
|
91
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
92
|
+
return ar;
|
|
93
|
+
};
|
|
94
|
+
return ownKeys(o);
|
|
95
|
+
};
|
|
96
|
+
return function (mod) {
|
|
97
|
+
if (mod && mod.__esModule) return mod;
|
|
98
|
+
var result = {};
|
|
99
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
100
|
+
__setModuleDefault(result, mod);
|
|
101
|
+
return result;
|
|
102
|
+
};
|
|
103
|
+
})();
|
|
57
104
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
105
|
+
exports.LITERAL_SEND_MAX_BYTES = void 0;
|
|
58
106
|
exports.classifySubmit = classifySubmit;
|
|
59
107
|
exports.isSubmitted = isSubmitted;
|
|
108
|
+
exports.classifyPasteLanded = classifyPasteLanded;
|
|
60
109
|
exports.clearComposerBeforeSend = clearComposerBeforeSend;
|
|
61
110
|
exports.sendMessageWithSubmitVerification = sendMessageWithSubmitVerification;
|
|
111
|
+
const childProcess = __importStar(require("child_process"));
|
|
62
112
|
const tmux_1 = require("../tmux/tmux");
|
|
63
113
|
const tmux_capture_cache_1 = require("../tmux/tmux-capture-cache");
|
|
64
114
|
const composer_spec_1 = require("./composer-spec");
|
|
@@ -77,6 +127,32 @@ const logger = (0, logger_1.createLogger)('cli-tools/submit-verified-sender');
|
|
|
77
127
|
* a tool that never renders it simply never matches.
|
|
78
128
|
*/
|
|
79
129
|
const PASTE_PLACEHOLDER_PATTERN = /\[Pasted text[\s#]/;
|
|
130
|
+
/**
|
|
131
|
+
* Largest body typed as keystrokes (`send-keys -l`); anything longer is pasted
|
|
132
|
+
* (Issue #2464).
|
|
133
|
+
*
|
|
134
|
+
* The limit is the pty's, not tmux's. tmux hands the pane the whole argv —
|
|
135
|
+
* 16,320 bytes arrived intact on tmux 3.5a, and past ~16.3 KB `send-keys`
|
|
136
|
+
* refuses with `command too long`, loudly — but the TUI reads it back in
|
|
137
|
+
* pty-sized pieces, 1,022 bytes each on macOS. Claude Code keeps only the last
|
|
138
|
+
* piece of unbracketed input (`12288 mod 1022` = the 24 bytes that arrived of a
|
|
139
|
+
* 12 KB brief), so a body is only safe as keystrokes while it fits in a single
|
|
140
|
+
* read. Half the smallest read measured leaves room for multi-byte text and for
|
|
141
|
+
* a platform whose reads are shorter.
|
|
142
|
+
*/
|
|
143
|
+
exports.LITERAL_SEND_MAX_BYTES = 512;
|
|
144
|
+
/**
|
|
145
|
+
* How often the composer is read while a pasted body is expected to appear in
|
|
146
|
+
* it. Claude, codex, Command Code and agy all drew the pasted body within
|
|
147
|
+
* 60 ms of `paste-buffer` on a 12 KB brief.
|
|
148
|
+
*/
|
|
149
|
+
const PASTE_LANDED_POLL_MS = 100;
|
|
150
|
+
/** Composer reads before a paste that has not fully appeared is abandoned (2 s). */
|
|
151
|
+
const DEFAULT_PASTE_LANDED_ATTEMPTS = 20;
|
|
152
|
+
/** Per-command timeout for `load-buffer` / `paste-buffer`, as for every other tmux call. */
|
|
153
|
+
const PASTE_COMMAND_TIMEOUT_MS = 5000;
|
|
154
|
+
/** Makes each send's tmux paste buffer name unique within this process. */
|
|
155
|
+
let pasteBufferSeq = 0;
|
|
80
156
|
/**
|
|
81
157
|
* A slash-command sitting on the input line (Issue #1501).
|
|
82
158
|
*
|
|
@@ -107,6 +183,12 @@ const INPUT_LINE_MARKER = /^\s*(?:ctx:\d+%\s*)?[>❯›]/;
|
|
|
107
183
|
* bottom of the pane, so it is read from a short tail even when the capture
|
|
108
184
|
* itself is opencode's whole 200-row frame. Widening it to that frame would
|
|
109
185
|
* match `esc interrupt` printed inside a reply.
|
|
186
|
+
*
|
|
187
|
+
* "The bottom" is the last row that holds anything (Issue #2464). codex,
|
|
188
|
+
* Command Code and agy draw inline from the TOP of the 1000-row pane, so the
|
|
189
|
+
* last twelve rows of the capture are blank padding — measured at rows 306,
|
|
190
|
+
* 297 and 286 of 1,002 — and reading them found no composer on any send to
|
|
191
|
+
* those three tools. See {@link withoutTrailingBlankRows}.
|
|
110
192
|
*/
|
|
111
193
|
const VERIFY_WINDOW_LINES = 12;
|
|
112
194
|
/**
|
|
@@ -161,6 +243,25 @@ function readComposer(reader, lines, windowLines) {
|
|
|
161
243
|
return { kind: 'empty' };
|
|
162
244
|
return { kind: 'text', text: stripped, rows: [inputLine] };
|
|
163
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* The captured rows without the blank rows under the last drawn one
|
|
248
|
+
* (Issue #2464).
|
|
249
|
+
*
|
|
250
|
+
* `capture-pane` returns every row of the pane, and a TUI that renders inline
|
|
251
|
+
* from the top (codex, Command Code, agy) fills only the first few hundred of
|
|
252
|
+
* the 1000 rows the session is created with. The composer is the last thing
|
|
253
|
+
* such a TUI draws, so "the tail of the pane" has to mean "the tail of what is
|
|
254
|
+
* drawn" — otherwise the tail window is all padding, no composer is ever found,
|
|
255
|
+
* and every send to those tools classifies as `submitted` whatever the
|
|
256
|
+
* composer actually holds. A bottom-anchored TUI (claude) has no trailing blank
|
|
257
|
+
* rows, so for it this is the identity.
|
|
258
|
+
*/
|
|
259
|
+
function withoutTrailingBlankRows(lines) {
|
|
260
|
+
let end = lines.length;
|
|
261
|
+
while (end > 0 && lines[end - 1].trim() === '')
|
|
262
|
+
end--;
|
|
263
|
+
return lines.slice(0, end);
|
|
264
|
+
}
|
|
164
265
|
/** Default bounded read-back attempts before giving up (throwing). */
|
|
165
266
|
const DEFAULT_VERIFY_ATTEMPTS = 4;
|
|
166
267
|
/**
|
|
@@ -213,6 +314,76 @@ function inputMatchesBody(strippedInput, message) {
|
|
|
213
314
|
return false;
|
|
214
315
|
return bodyFirstLine.startsWith(strippedInput);
|
|
215
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* Collapsed-paste placeholders, as measured at the production 200x1000
|
|
319
|
+
* geometry (Issue #2464, `tests/fixtures/long-body-2464/`):
|
|
320
|
+
*
|
|
321
|
+
* claude 2.1.268 `[Pasted text #86 +59 lines]` for 60 lines, `[Pasted text #87]` for one
|
|
322
|
+
* agy 1.2.0 `[Pasted text #5 +60 lines]` for 60 lines, `[Pasted text #6 12288 chars]` for one
|
|
323
|
+
* codex 0.154.0 `[Pasted Content 12288 chars]`
|
|
324
|
+
* Command Code 1.53.0 `[PROBE P12k… +60L]` — the first ten characters, then the line count
|
|
325
|
+
*
|
|
326
|
+
* The `#N` stays optional for #1469's version drift (`[Pasted text +46 lines]`).
|
|
327
|
+
*/
|
|
328
|
+
const PASTE_TOKEN_PATTERNS = [
|
|
329
|
+
{
|
|
330
|
+
pattern: /\[Pasted text(?: #\d+)?(?: \+(\d+) lines?| (\d+) chars?)?\]/g,
|
|
331
|
+
read: (m) => m[1] !== undefined ? { lines: Number(m[1]) } : m[2] !== undefined ? { chars: Number(m[2]) } : {},
|
|
332
|
+
},
|
|
333
|
+
{ pattern: /\[Pasted Content (\d+) chars?\]/g, read: (m) => ({ chars: Number(m[1]) }) },
|
|
334
|
+
{ pattern: /\[([^\]\n]*?)… \+(\d+)L\]/g, read: (m) => ({ head: m[1], lineTotal: Number(m[2]) }) },
|
|
335
|
+
];
|
|
336
|
+
/** Every paste placeholder on a composer row, and the text left around them. */
|
|
337
|
+
function findPasteTokens(text) {
|
|
338
|
+
const tokens = [];
|
|
339
|
+
let rest = text;
|
|
340
|
+
for (const { pattern, read } of PASTE_TOKEN_PATTERNS) {
|
|
341
|
+
for (const match of text.matchAll(pattern)) {
|
|
342
|
+
tokens.push(read(match));
|
|
343
|
+
rest = rest.replace(match[0], '');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return { tokens, rest: rest.trim() };
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Does one placeholder account for the whole body?
|
|
350
|
+
*
|
|
351
|
+
* Counts below the body's mean the paste is still arriving; counts above it mean
|
|
352
|
+
* the composer holds more than the body. The two units that differ between
|
|
353
|
+
* tools for the same `+M lines` wording (claude: 59 for a 60-line body, agy: 60)
|
|
354
|
+
* are both accepted — a bracketed paste arrives as one unit, so the failure this
|
|
355
|
+
* guards against is a count that is wildly short (the 24-byte tail of #2464),
|
|
356
|
+
* not one that is off by one line.
|
|
357
|
+
*/
|
|
358
|
+
function comparePasteToken(token, message) {
|
|
359
|
+
const newlines = (message.match(/\n/g) ?? []).length;
|
|
360
|
+
if (token.head !== undefined) {
|
|
361
|
+
const normalizedHead = token.head.replace(/\s+/g, ' ').trim();
|
|
362
|
+
if (!message.replace(/\s+/g, ' ').startsWith(normalizedHead))
|
|
363
|
+
return 'mismatch';
|
|
364
|
+
}
|
|
365
|
+
let observed;
|
|
366
|
+
let accepted;
|
|
367
|
+
if (token.chars !== undefined) {
|
|
368
|
+
observed = token.chars;
|
|
369
|
+
accepted = [[...message].length, message.length];
|
|
370
|
+
}
|
|
371
|
+
else if (token.lineTotal !== undefined) {
|
|
372
|
+
observed = token.lineTotal;
|
|
373
|
+
accepted = [newlines + 1];
|
|
374
|
+
}
|
|
375
|
+
else if (token.lines !== undefined) {
|
|
376
|
+
observed = token.lines;
|
|
377
|
+
accepted = [newlines, newlines + 1];
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
// claude's bare `[Pasted text #N]` is what it draws for a single line.
|
|
381
|
+
return newlines === 0 ? 'landed' : 'pasting';
|
|
382
|
+
}
|
|
383
|
+
if (accepted.includes(observed))
|
|
384
|
+
return 'landed';
|
|
385
|
+
return observed < Math.min(...accepted) ? 'pasting' : 'mismatch';
|
|
386
|
+
}
|
|
216
387
|
/**
|
|
217
388
|
* Classify a captured pane into submitted / pending / replaced (Issue #1501).
|
|
218
389
|
*
|
|
@@ -234,6 +405,10 @@ function inputMatchesBody(strippedInput, message) {
|
|
|
234
405
|
* no marker — that read was unreachable, so every send reached F (in fact B) and
|
|
235
406
|
* this function has never returned anything but `submitted` for it.
|
|
236
407
|
*
|
|
408
|
+
* Issue #2464: the tail window starts at the last drawn row, not at the last row
|
|
409
|
+
* of the pane ({@link withoutTrailingBlankRows}), and C recognises every tool's
|
|
410
|
+
* paste placeholder ({@link findPasteTokens}), not only claude's.
|
|
411
|
+
*
|
|
237
412
|
* @param output - Captured pane, ANSI intact. For opencode this must be the
|
|
238
413
|
* whole pane; {@link ComposerSpec.verifyCaptureLines} is what asks tmux for it.
|
|
239
414
|
* @param cliToolId - CLI tool id, for the "generating" detector
|
|
@@ -243,7 +418,7 @@ function inputMatchesBody(strippedInput, message) {
|
|
|
243
418
|
*/
|
|
244
419
|
function classifySubmit(output, cliToolId, message, composerSpec = (0, composer_spec_1.resolveComposerSpec)(cliToolId)) {
|
|
245
420
|
const clean = (0, cli_patterns_1.stripAnsi)(output);
|
|
246
|
-
const lines = clean.split('\n');
|
|
421
|
+
const lines = withoutTrailingBlankRows(clean.split('\n'));
|
|
247
422
|
const windowLines = lines.slice(-VERIFY_WINDOW_LINES);
|
|
248
423
|
const windowStr = windowLines.join('\n');
|
|
249
424
|
// A. Actively generating a response => the message was accepted. Read from the
|
|
@@ -260,7 +435,7 @@ function classifySubmit(output, cliToolId, message, composerSpec = (0, composer_
|
|
|
260
435
|
return 'submitted';
|
|
261
436
|
}
|
|
262
437
|
// C. A paste placeholder is still folded into the composer => body is there.
|
|
263
|
-
if (composer.rows.some((row) => PASTE_PLACEHOLDER_PATTERN.test(row))) {
|
|
438
|
+
if (composer.rows.some((row) => PASTE_PLACEHOLDER_PATTERN.test(row) || findPasteTokens(row).tokens.length > 0)) {
|
|
264
439
|
return 'pending';
|
|
265
440
|
}
|
|
266
441
|
// D. The typed body is still sitting in the composer => resend Enter.
|
|
@@ -284,6 +459,172 @@ function classifySubmit(output, cliToolId, message, composerSpec = (0, composer_
|
|
|
284
459
|
function isSubmitted(output, cliToolId, message, composerSpec = (0, composer_spec_1.resolveComposerSpec)(cliToolId)) {
|
|
285
460
|
return classifySubmit(output, cliToolId, message, composerSpec) === 'submitted';
|
|
286
461
|
}
|
|
462
|
+
/**
|
|
463
|
+
* How much of a pasted body the composer shows, read BEFORE Enter (Issue #2464).
|
|
464
|
+
*
|
|
465
|
+
* The question #2464 needs answered is not "did Enter work" but "is what Enter
|
|
466
|
+
* would submit the message we sent". Claude kept the last 24 bytes of a 12 KB
|
|
467
|
+
* brief as ordinary composer text; every check that runs after Enter saw an
|
|
468
|
+
* empty box and a generating model, i.e. a perfect send. So the composer is
|
|
469
|
+
* judged here, while pressing Enter can still be withheld:
|
|
470
|
+
*
|
|
471
|
+
* 1. A collapsed placeholder is compared by the count the TUI prints — lines
|
|
472
|
+
* for claude, agy and Command Code, characters for codex and agy's
|
|
473
|
+
* single-line form ({@link comparePasteToken}).
|
|
474
|
+
* 2. Plain text is the body only if it is the body's BEGINNING. Text that
|
|
475
|
+
* occurs in the body but not at its start is exactly the #2464 tail, and is
|
|
476
|
+
* a mismatch rather than "not drawn yet".
|
|
477
|
+
* 3. Anything else — the idle placeholder, a ghost suggestion, no composer —
|
|
478
|
+
* shows nothing of the body. `unseen`, which the caller decides about.
|
|
479
|
+
*
|
|
480
|
+
* Reads the same tail window as {@link classifySubmit}, so a history echo of an
|
|
481
|
+
* earlier message above the composer is never mistaken for this one.
|
|
482
|
+
*/
|
|
483
|
+
function classifyPasteLanded(output, cliToolId, message, composerSpec = (0, composer_spec_1.resolveComposerSpec)(cliToolId)) {
|
|
484
|
+
const lines = withoutTrailingBlankRows((0, cli_patterns_1.stripAnsi)(output).split('\n'));
|
|
485
|
+
const composer = readComposer(composerSpec.reader, lines, lines.slice(-VERIFY_WINDOW_LINES));
|
|
486
|
+
if (composer.kind !== 'text')
|
|
487
|
+
return 'unseen';
|
|
488
|
+
const { tokens, rest } = findPasteTokens(composer.text);
|
|
489
|
+
if (tokens.length === 0) {
|
|
490
|
+
if (inputMatchesBody(composer.text, message))
|
|
491
|
+
return 'landed';
|
|
492
|
+
if (message.includes(composer.text))
|
|
493
|
+
return 'mismatch';
|
|
494
|
+
return 'unseen';
|
|
495
|
+
}
|
|
496
|
+
if (tokens.length > 1 || rest !== '')
|
|
497
|
+
return 'mismatch';
|
|
498
|
+
return comparePasteToken(tokens[0], message);
|
|
499
|
+
}
|
|
500
|
+
/** Run one tmux command, optionally feeding it `input` on stdin. */
|
|
501
|
+
function runTmux(args, input) {
|
|
502
|
+
return new Promise((resolve, reject) => {
|
|
503
|
+
const child = childProcess.execFile('tmux', args, { timeout: PASTE_COMMAND_TIMEOUT_MS }, (error) => {
|
|
504
|
+
if (error) {
|
|
505
|
+
reject(error);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
resolve();
|
|
509
|
+
});
|
|
510
|
+
if (input !== undefined)
|
|
511
|
+
child.stdin?.end(input);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Put a body into the pane as ONE bracketed paste (Issue #2464).
|
|
516
|
+
*
|
|
517
|
+
* `load-buffer -` takes the body on stdin, so there is no argv ceiling (20 KB
|
|
518
|
+
* went through where `send-keys` refuses past ~16.3 KB). `paste-buffer -p`
|
|
519
|
+
* wraps it in `ESC[200~ … ESC[201~` when — and only when — the application
|
|
520
|
+
* has asked for bracketed paste; a TUI that has not receives exactly the bytes
|
|
521
|
+
* `send-keys -l` would have typed (both measured byte-for-byte on a raw pane).
|
|
522
|
+
* `-r` keeps LF as LF instead of tmux's default LF→CR, which would be an Enter
|
|
523
|
+
* per line for a TUI that did not ask for brackets. `-d` drops the buffer on
|
|
524
|
+
* success; a failure drops it here, so no body is left behind in the server.
|
|
525
|
+
*
|
|
526
|
+
* @throws Error when either tmux command fails
|
|
527
|
+
*/
|
|
528
|
+
async function pasteBody(sessionName, message) {
|
|
529
|
+
const bufferName = `cm-send-${process.pid}-${++pasteBufferSeq}`;
|
|
530
|
+
try {
|
|
531
|
+
await runTmux(['load-buffer', '-b', bufferName, '-'], message);
|
|
532
|
+
await runTmux(['paste-buffer', '-p', '-r', '-d', '-b', bufferName, '-t', (0, tmux_1.exactTarget)(sessionName)]);
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
await runTmux(['delete-buffer', '-b', bufferName]).catch(() => undefined);
|
|
536
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
537
|
+
throw new Error(`Failed to paste message into tmux session: ${errorMessage}`);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/** The composer's first row, for an error message a person has to act on. */
|
|
541
|
+
function describeComposer(output, composerSpec) {
|
|
542
|
+
const lines = withoutTrailingBlankRows((0, cli_patterns_1.stripAnsi)(output).split('\n'));
|
|
543
|
+
const composer = readComposer(composerSpec.reader, lines, lines.slice(-VERIFY_WINDOW_LINES));
|
|
544
|
+
if (composer.kind === 'absent')
|
|
545
|
+
return 'no composer on screen';
|
|
546
|
+
if (composer.kind === 'empty')
|
|
547
|
+
return 'an empty composer';
|
|
548
|
+
const text = composer.text.length > 80 ? `${composer.text.slice(0, 80)}…` : composer.text;
|
|
549
|
+
return JSON.stringify(text);
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Take a body that did not arrive intact back out of the composer, best effort.
|
|
553
|
+
*
|
|
554
|
+
* Leaving it would put the fragment in front of the next message. claude and
|
|
555
|
+
* codex go through the verified #1879 loop (a paste can span rows); the rest
|
|
556
|
+
* get the single `C-u` the #1501 path already sends to them.
|
|
557
|
+
*/
|
|
558
|
+
async function withdrawUnsentBody(sessionName, cliToolId, composerSpec) {
|
|
559
|
+
try {
|
|
560
|
+
if (composerSpec.clearBeforeSend) {
|
|
561
|
+
await (0, composer_clear_1.clearComposer)(sessionName, cliToolId);
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
await (0, tmux_1.clearInputLine)(sessionName);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
catch (clearError) {
|
|
568
|
+
logger.error('paste-withdraw-failed', {
|
|
569
|
+
sessionName,
|
|
570
|
+
cliToolId,
|
|
571
|
+
error: clearError instanceof Error ? clearError.message : String(clearError),
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Wait until the composer shows the whole pasted body; decide whether Enter
|
|
577
|
+
* may be pressed (Issue #2464).
|
|
578
|
+
*
|
|
579
|
+
* `pasting` keeps waiting — this is the "a placeholder is not a stuck body"
|
|
580
|
+
* branch: `[Pasted text #3 +20 lines]` for a 60-line brief is a paste still
|
|
581
|
+
* coming in, and Enter pressed now would submit twenty lines. `landed` returns.
|
|
582
|
+
* Everything else ends in a throw WITHOUT Enter, after taking the body back out:
|
|
583
|
+
*
|
|
584
|
+
* - `mismatch`, at once — no amount of waiting turns a tail into a message;
|
|
585
|
+
* - `pasting` that never completes within the attempts;
|
|
586
|
+
* - `unseen` for a tool whose composer this module has measured
|
|
587
|
+
* (`clearBeforeSend`: claude, codex). There, a composer that never shows
|
|
588
|
+
* the body means it did not arrive, and Enter would submit nothing while
|
|
589
|
+
* the caller printed `Message sent.`.
|
|
590
|
+
*
|
|
591
|
+
* `unseen` on any other tool proceeds, with a warning: those composers are
|
|
592
|
+
* drawn in ways this module has not measured, and refusing on them would turn
|
|
593
|
+
* "cannot see it" into "did not send it" for every long message they get.
|
|
594
|
+
*
|
|
595
|
+
* @throws Error when the body cannot be confirmed in the composer
|
|
596
|
+
*/
|
|
597
|
+
async function confirmPasteLanded(params) {
|
|
598
|
+
const { sessionName, message, cliToolId, composer, attempts } = params;
|
|
599
|
+
let state = 'unseen';
|
|
600
|
+
let output = '';
|
|
601
|
+
for (let attempt = 0; attempt < Math.max(1, attempts); attempt++) {
|
|
602
|
+
await new Promise((resolve) => setTimeout(resolve, PASTE_LANDED_POLL_MS));
|
|
603
|
+
output = await (0, tmux_1.capturePane)(sessionName, { startLine: -composer.verifyCaptureLines });
|
|
604
|
+
state = classifyPasteLanded(output, cliToolId, message, composer);
|
|
605
|
+
if (state === 'landed' || state === 'mismatch')
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
if (state === 'landed')
|
|
609
|
+
return;
|
|
610
|
+
if (state === 'unseen' && !composer.clearBeforeSend) {
|
|
611
|
+
logger.warn('paste-landed-unverified', { sessionName, cliToolId, bytes: Buffer.byteLength(message, 'utf8') });
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
const bytes = Buffer.byteLength(message, 'utf8');
|
|
615
|
+
const lineCount = message.split('\n').length;
|
|
616
|
+
const shown = describeComposer(output, composer);
|
|
617
|
+
await withdrawUnsentBody(sessionName, cliToolId, composer);
|
|
618
|
+
(0, tmux_capture_cache_1.invalidateCache)(sessionName);
|
|
619
|
+
logger.error('paste-not-landed', { sessionName, cliToolId, state, bytes, lines: lineCount, shown });
|
|
620
|
+
const what = state === 'mismatch'
|
|
621
|
+
? `the composer does not hold the message as sent (it shows ${shown})`
|
|
622
|
+
: state === 'pasting'
|
|
623
|
+
? `the paste had not finished arriving after ${attempts * PASTE_LANDED_POLL_MS}ms (the composer shows ${shown})`
|
|
624
|
+
: `the message never appeared in the composer (${shown})`;
|
|
625
|
+
throw new Error(`Message body did not arrive intact for session ${sessionName}: ${what}; the message is ${bytes} bytes / ${lineCount} lines. ` +
|
|
626
|
+
'Enter was not pressed, so nothing was submitted (Issue #2464).');
|
|
627
|
+
}
|
|
287
628
|
/**
|
|
288
629
|
* Empty the composer before the body is typed into it (Issue #1880).
|
|
289
630
|
*
|
|
@@ -370,27 +711,47 @@ async function clearComposerBeforeSend(sessionName, cliToolId, composerSpec = (0
|
|
|
370
711
|
* the function THROWS — callers must surface that as a failure, never as
|
|
371
712
|
* success (Issues #1469/#1470/#1471).
|
|
372
713
|
*
|
|
373
|
-
*
|
|
714
|
+
* A body longer than {@link LITERAL_SEND_MAX_BYTES} is pasted instead of typed,
|
|
715
|
+
* and Enter waits until the composer shows all of it (Issue #2464); a body that
|
|
716
|
+
* does not arrive intact THROWS before Enter, with nothing submitted.
|
|
717
|
+
*
|
|
718
|
+
* @throws Error when the body does not arrive intact, or submit cannot be
|
|
719
|
+
* confirmed within the bounded attempts.
|
|
374
720
|
*/
|
|
375
721
|
async function sendMessageWithSubmitVerification(params) {
|
|
376
|
-
const { sessionName, message, cliToolId, composer = (0, composer_spec_1.resolveComposerSpec)(cliToolId), textInputWaitMs = cli_tool_timing_config_1.TUI_TEXT_INPUT_WAIT_MS, interEnterWaitMs = cli_tool_timing_config_1.TUI_TEXT_INPUT_WAIT_MS, verifyAttempts = DEFAULT_VERIFY_ATTEMPTS, verifyDelayMs = cli_tool_timing_config_1.TUI_MESSAGE_PROCESSED_WAIT_MS, } = params;
|
|
722
|
+
const { sessionName, message, cliToolId, composer = (0, composer_spec_1.resolveComposerSpec)(cliToolId), textInputWaitMs = cli_tool_timing_config_1.TUI_TEXT_INPUT_WAIT_MS, interEnterWaitMs = cli_tool_timing_config_1.TUI_TEXT_INPUT_WAIT_MS, verifyAttempts = DEFAULT_VERIFY_ATTEMPTS, verifyDelayMs = cli_tool_timing_config_1.TUI_MESSAGE_PROCESSED_WAIT_MS, pasteLandedAttempts = DEFAULT_PASTE_LANDED_ATTEMPTS, } = params;
|
|
377
723
|
const submitEnterCount = params.submitEnterCount ?? composer.submitEnterCount;
|
|
378
724
|
// 0. Empty the composer first (Issue #1880). The body below is typed at the
|
|
379
725
|
// TUI's current cursor position, so anything already in the box would be
|
|
380
726
|
// spliced into it. Throws for a claude composer that could not be emptied.
|
|
381
727
|
await clearComposerBeforeSend(sessionName, cliToolId, composer);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
728
|
+
if (Buffer.byteLength(message, 'utf8') > exports.LITERAL_SEND_MAX_BYTES) {
|
|
729
|
+
// 1'. A body that would reach the TUI as more than one pty read is pasted
|
|
730
|
+
// as ONE bracketed paste, and Enter waits until the composer shows all
|
|
731
|
+
// of it (Issue #2464). Typed, Claude Code would keep only its last read.
|
|
732
|
+
const pastedAt = Date.now();
|
|
733
|
+
await pasteBody(sessionName, message);
|
|
734
|
+
await confirmPasteLanded({ sessionName, message, cliToolId, composer, attempts: pasteLandedAttempts });
|
|
735
|
+
// 2'. Keep the tool's own registration delay as a floor.
|
|
736
|
+
const remaining = textInputWaitMs - (Date.now() - pastedAt);
|
|
737
|
+
if (remaining > 0) {
|
|
738
|
+
await new Promise((resolve) => setTimeout(resolve, remaining));
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
// 1. Type the body only — never send Enter in the same tmux command.
|
|
743
|
+
//
|
|
744
|
+
// `{ literal: true }` is Issue #1933 受入条件 S9 and it is not decoration.
|
|
745
|
+
// `tmux send-keys` resolves its argument against the key table first, so
|
|
746
|
+
// until this flag existed a message body of exactly `Escape` interrupted
|
|
747
|
+
// the agent (`1b`), `Enter` submitted an empty composer (`0d`) and `C-c`
|
|
748
|
+
// sent SIGINT — and a body starting with `-` was eaten by getopt and sent
|
|
749
|
+
// nowhere at all, with `rc 0`. All four measured on tmux 3.5a; the argv is
|
|
750
|
+
// built in `lib/tmux/key-sequence.ts`, which carries the table.
|
|
751
|
+
await (0, tmux_1.sendKeys)(sessionName, message, false, { literal: true });
|
|
752
|
+
// 2. Let the TUI register the input before pressing Enter.
|
|
753
|
+
await new Promise((resolve) => setTimeout(resolve, textInputWaitMs));
|
|
754
|
+
}
|
|
394
755
|
// 3. Submit as a separate command (double Enter for vibe-local's IME mode).
|
|
395
756
|
for (let i = 0; i < Math.max(1, submitEnterCount); i++) {
|
|
396
757
|
await (0, tmux_1.sendSpecialKeys)(sessionName, ['Enter']);
|
|
@@ -227,8 +227,15 @@ function parseSchedulesSection(rows) {
|
|
|
227
227
|
// Issue #2250: its own case, not a fall-through. #1914's rule is that a
|
|
228
228
|
// tool with a permission vocabulary names itself here; inheriting the
|
|
229
229
|
// no-flag branch would silently blank a valid `plan` / `auto-accept` cell.
|
|
230
|
+
//
|
|
231
|
+
// Issue #2454: the column vocabulary is the six-value
|
|
232
|
+
// COMMAND_CODE_SCHEDULE_PERMISSIONS, not the five `--permission-mode`
|
|
233
|
+
// choices. An empty cell therefore resolves to `yolo` through
|
|
234
|
+
// `defaultPermission` above, which is the only value that lets
|
|
235
|
+
// `commandcode -p` write anything -- the five modes all leave print mode
|
|
236
|
+
// read-only while still reporting success.
|
|
230
237
|
case 'command-code':
|
|
231
|
-
allowedValues = schedule_config_1.
|
|
238
|
+
allowedValues = schedule_config_1.COMMAND_CODE_SCHEDULE_PERMISSIONS;
|
|
232
239
|
break;
|
|
233
240
|
case 'gemini':
|
|
234
241
|
case 'vibe-local':
|
|
@@ -136,6 +136,17 @@ function getAgentInstance(db, worktreeId, instanceId) {
|
|
|
136
136
|
* conflict rather than silently overriding it: the roster is user-maintained
|
|
137
137
|
* and a mismatch means one of the two is wrong. Callers surface it as an error.
|
|
138
138
|
*
|
|
139
|
+
* @deprecated Issue #1925 made `resolveSessionTarget`
|
|
140
|
+
* (`src/lib/session/resolve-session-target.ts`) the one authority, and Issue
|
|
141
|
+
* #2491 moved the last two callers — `POST /send` and `resolveRelaySession` —
|
|
142
|
+
* onto it. **Do not give this function a new caller.** Step 2 above is exactly
|
|
143
|
+
* what #2487 corrected: with no roster row it takes `requestedCliTool` even
|
|
144
|
+
* when `instanceId` itself names a different tool, so a caller wired here gets
|
|
145
|
+
* `mcbd-<requested>-<wt>-<tool-named-id>` back instead of a conflict. It is
|
|
146
|
+
* kept only because its #1629 unit test
|
|
147
|
+
* (`tests/unit/db/agent-instances-resolve-cli-tool.test.ts`) still pins that
|
|
148
|
+
* behaviour; removing both is a separate change.
|
|
149
|
+
*
|
|
139
150
|
* @param db - Database instance
|
|
140
151
|
* @param worktreeId - Worktree ID
|
|
141
152
|
* @param instanceId - Targeted agent instance ID (omitted for the primary instance)
|