commandmate 0.33.2 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +160 -160
- package/.next/app-path-routes-manifest.json +28 -28
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- 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.js.nft.json +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.js.nft.json +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.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.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.js +1 -1
- package/.next/server/app/api/skills/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route.js +1 -1
- package/.next/server/app/api/skills/installations/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_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.js.nft.json +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_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.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +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.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js.nft.json +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 +10 -10
- 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 +28 -28
- package/.next/server/chunks/1049.js +1 -0
- package/.next/server/chunks/1501.js +6 -2
- package/.next/server/chunks/1886.js +3 -3
- 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/3123.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/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 +2 -2
- package/.next/server/chunks/6130.js +1 -0
- 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/6661.js +1 -1
- package/.next/server/chunks/6677.js +25 -0
- package/.next/server/chunks/6781.js +1 -1
- 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/8918.js +7 -5
- package/.next/server/chunks/9080.js +1 -0
- package/.next/server/chunks/9627.js +1 -1
- 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/static/chunks/2053-9ac860ab4e92ac89.js +1 -0
- package/.next/static/chunks/2652-18b8fea64413467e.js +1 -0
- package/.next/static/chunks/{4718-441a2af91f0374e9.js → 4718-2d9f0397a8f931c4.js} +1 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +1 -0
- 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-a39ec2a0732d11a6.js +1 -0
- package/.next/static/css/b09bede85744e1cf.css +1 -0
- package/.next/trace +13 -13
- package/dist/cli/commands/ask.d.ts.map +1 -1
- package/dist/cli/commands/ask.js +11 -2
- 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/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 +30 -4
- package/dist/server/locales/ja/worktree.json +30 -4
- 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/cli-tools/vibe-local.js +10 -0
- package/dist/server/src/lib/cmate-parser.js +8 -1
- 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/hook-settings-generator.js +61 -1
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +302 -27
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +103 -0
- 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/polling/auto-yes-dialog-gate.js +114 -11
- package/dist/server/src/lib/polling/response-checker.js +82 -3
- package/dist/server/src/lib/polling/structured-history-gate.js +68 -4
- package/dist/server/src/lib/schedule-manager.js +178 -19
- package/dist/server/src/lib/session/agent-session-lifecycle.js +31 -1
- 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/session/session-generation-archive.js +194 -0
- package/dist/server/src/lib/tasks/contract-message.js +83 -9
- package/dist/server/src/lib/tasks/contract-parser.js +2 -0
- package/dist/server/src/lib/verification/env-clean-gate.js +81 -4
- 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/153.js +0 -1
- package/.next/server/chunks/4299.js +0 -1
- package/.next/server/chunks/6808.js +0 -1
- package/.next/server/chunks/6838.js +0 -1
- package/.next/server/chunks/7366.js +0 -5
- package/.next/server/chunks/7875.js +0 -25
- package/.next/static/chunks/2053-3f299a7a2c7d6767.js +0 -1
- package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.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-38edcd53e51f53b0.js +0 -1
- package/.next/static/css/acd46e25427a2080.css +0 -1
- /package/.next/static/{0a4qrU8WdUwQrlO4mfLMu → gniPBCKoXtbIOQey8kNcx}/_buildManifest.js +0 -0
- /package/.next/static/{0a4qrU8WdUwQrlO4mfLMu → gniPBCKoXtbIOQey8kNcx}/_ssgManifest.js +0 -0
|
@@ -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']);
|
|
@@ -20,6 +20,7 @@ const db_1 = require("../db");
|
|
|
20
20
|
const logger_1 = require("../../lib/logger");
|
|
21
21
|
const cli_tool_timing_config_1 = require("../../config/cli-tool-timing-config");
|
|
22
22
|
const install_hints_1 = require("./install-hints");
|
|
23
|
+
const agent_session_lifecycle_1 = require("../../lib/session/agent-session-lifecycle");
|
|
23
24
|
const logger = (0, logger_1.createLogger)('cli-tools/vibe-local');
|
|
24
25
|
/**
|
|
25
26
|
* Extract error message from unknown error type (DRY)
|
|
@@ -75,6 +76,15 @@ class VibeLocalTool extends base_1.BaseCLITool {
|
|
|
75
76
|
}
|
|
76
77
|
logger.warn('vibe-local-session-relaunch', { sessionName });
|
|
77
78
|
}
|
|
79
|
+
// Issue #1759 / #2444: the one line every tool's creation path owes the
|
|
80
|
+
// rest of the system. vibe-local emits no structured events, so the
|
|
81
|
+
// generation fence itself is inert here — but `beginAgentSession` is also
|
|
82
|
+
// where a superseded session's chat rows are retired, and vibe-local was
|
|
83
|
+
// the only tool that never called it. Placed after the healthy-reuse
|
|
84
|
+
// `return` above and before the pane is touched, exactly as codex places
|
|
85
|
+
// its call: a reuse is the same process and must archive nothing, a
|
|
86
|
+
// relaunch into this same pane is a new one and must.
|
|
87
|
+
(0, agent_session_lifecycle_1.beginAgentSession)({ worktreeId, cliToolId: this.id, instanceId });
|
|
78
88
|
try {
|
|
79
89
|
// Issue #2070: creation only. On the relaunch path the pane already
|
|
80
90
|
// exists and holds the transcript of the process that died in it; the
|
|
@@ -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':
|