commandmate 0.23.0 → 0.24.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 +393 -384
- package/.next/app-path-routes-manifest.json +15 -14
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +9 -9
- package/.next/react-loadable-manifest.json +1 -1
- 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/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 +1 -1
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +2 -2
- 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/daily-summary/route.js +1 -1
- package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route.js +1 -1
- package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route.js +1 -0
- package/.next/server/app/api/push/escalation/route.js.nft.json +1 -0
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/push/subscriptions/route.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.js.nft.json +1 -1
- package/.next/server/app/api/push/vapid/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.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.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/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.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.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.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.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]/cli-tool/route.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +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]/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.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.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.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.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.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.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.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.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.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]/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.js +5 -5
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_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]/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 +2 -2
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
- package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_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 +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route.js +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 +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_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.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.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.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.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/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]/route.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.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/chat/page.js +2 -2
- package/.next/server/app/chat/page.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +2 -2
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page.js +1 -1
- package/.next/server/app/review/page.js.nft.json +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +2 -2
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +2 -2
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +1 -1
- package/.next/server/app/skills/page.js.nft.json +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +6 -6
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +15 -14
- package/.next/server/chunks/1029.js +1 -1
- package/.next/server/chunks/1296.js +1 -1
- package/.next/server/chunks/1366.js +1 -1
- package/.next/server/chunks/1601.js +7 -0
- package/.next/server/chunks/1825.js +1 -1
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2546.js +1 -1
- package/.next/server/chunks/3417.js +1 -1
- package/.next/server/chunks/3451.js +1 -1
- package/.next/server/chunks/3480.js +1 -1
- package/.next/server/chunks/3543.js +1 -1
- package/.next/server/chunks/3945.js +1 -1
- package/.next/server/chunks/4393.js +1 -0
- package/.next/server/chunks/4444.js +1 -1
- package/.next/server/chunks/4455.js +1 -0
- package/.next/server/chunks/5164.js +1 -0
- package/.next/server/chunks/5959.js +5 -5
- package/.next/server/chunks/5998.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6159.js +1 -1
- package/.next/server/chunks/6274.js +2 -2
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/7458.js +5 -5
- package/.next/server/chunks/8536.js +1 -1
- package/.next/server/chunks/880.js +21 -0
- package/.next/server/chunks/8807.js +134 -129
- package/.next/server/chunks/9058.js +1 -1
- package/.next/server/chunks/9123.js +8 -8
- package/.next/server/chunks/9358.js +1 -1
- package/.next/server/chunks/9373.js +3 -3
- package/.next/server/chunks/9687.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/4322-dfd5a7119b5ba4fc.js +1 -0
- package/.next/static/chunks/{4974-eaf66770bfa9dea0.js → 4974-35592ec312322124.js} +1 -1
- package/.next/static/chunks/5229-0610b4e3288e777d.js +1 -0
- package/.next/static/chunks/6381-18a6a02a94d00d76.js +1 -0
- package/.next/static/chunks/7229.7f0f5a7032b612b4.js +1 -0
- package/.next/static/chunks/{744-fa8c0ae444c8338c.js → 744-3ad06d8c8ca482fc.js} +1 -1
- package/.next/static/chunks/app/api/app/update/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
- package/.next/static/chunks/app/api/app/update-check/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
- package/.next/static/chunks/app/api/assistant/conversation/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
- package/.next/static/chunks/app/api/assistant/current-output/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
- package/.next/static/chunks/app/api/assistant/messages/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/assistant/session/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/assistant/start/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/assistant/terminal/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/assistant/tools/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/status/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/external-apps/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/fs/browse/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/fs/recent-paths/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/hooks/agent-event/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/hooks/claude-done/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/hooks/permission-request/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/metrics/vibe/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/ollama/models/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/push/escalation/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/push/subscriptions/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/push/vapid/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/excluded/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/restore/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/scan/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/sync/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/repositories/validate-path/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/sidebar/group-order/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/skills/[id]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/skills/installations/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/skills/operations/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/skills/reindex/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/skills/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/slash-commands/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/templates/[id]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/templates/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/todos/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/chat/page-15d13fc024d78f5d.js +1 -0
- package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/more/page-b8ba537baeac8d5b.js +1 -0
- package/.next/static/chunks/app/page-afc64708362f31e5.js +1 -0
- package/.next/static/chunks/app/proxy/[...path]/route-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/repositories/page-3469dacb6be7842f.js +1 -0
- package/.next/static/chunks/app/review/page-2d9cb7e068f8f35a.js +1 -0
- package/.next/static/chunks/app/sessions/page-7470c2bfd89e0df9.js +1 -0
- package/.next/static/chunks/app/skills/[skillId]/page-5e24481162f7ea78.js +1 -0
- package/.next/static/chunks/app/skills/installed/page-efd2d710a27f9735.js +1 -0
- package/.next/static/chunks/app/skills/page-0498adfc6e48684b.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9ddcb224594f620f.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/layout-fae89f8d4cc3ff97.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-e611d30e47989e5d.js +1 -0
- package/.next/static/chunks/{webpack-180bebdee221b6f4.js → webpack-3534d858912a6c92.js} +1 -1
- package/.next/static/css/3ac44cfc082d02ad.css +1 -0
- package/.next/static/smu4mnL7qMf8w38n9dQJE/_buildManifest.js +1 -0
- package/.next/trace +12 -12
- package/.next/types/app/api/push/escalation/route.ts +347 -0
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +6 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +19 -1
- package/dist/cli/commands/task.d.ts.map +1 -1
- package/dist/cli/commands/task.js +6 -0
- package/dist/cli/commands/verify.js +6 -1
- package/dist/cli/types/api-responses.d.ts +46 -0
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +17 -1
- package/dist/server/locales/en/notifications.json +20 -1
- package/dist/server/locales/ja/notifications.json +20 -1
- package/dist/server/server.js +23 -0
- package/dist/server/src/lib/db/db.js +2 -1
- package/dist/server/src/lib/db/migrations/index.js +2 -0
- package/dist/server/src/lib/db/migrations/runner.js +1 -1
- package/dist/server/src/lib/db/migrations/v56-gate-result-source.js +58 -0
- package/dist/server/src/lib/db/verification-db.js +26 -6
- package/dist/server/src/lib/detection/model-info-extractor.js +384 -0
- package/dist/server/src/lib/hooks/sources/antigravity/source.js +4 -0
- package/dist/server/src/lib/hooks/sources/claude/source.js +7 -0
- package/dist/server/src/lib/hooks/sources/codex/source.js +5 -0
- package/dist/server/src/lib/hooks/sources/define-source.js +8 -0
- package/dist/server/src/lib/hooks/sources/event-mapper.js +20 -0
- package/dist/server/src/lib/hooks/sources/opencode/ingest.js +6 -0
- package/dist/server/src/lib/hooks/sources/opencode/mappers.js +22 -0
- package/dist/server/src/lib/hooks/sources/opencode/source.js +3 -0
- package/dist/server/src/lib/polling/response-checker.js +47 -0
- package/dist/server/src/lib/push/escalation-settings.js +114 -0
- package/dist/server/src/lib/push/index.js +21 -1
- package/dist/server/src/lib/push/notification-dedup.js +35 -0
- package/dist/server/src/lib/push/push-sender.js +66 -7
- package/dist/server/src/lib/push/waiting-push-notifier.js +231 -0
- package/dist/server/src/lib/realtime/waiting-broadcast.js +93 -0
- package/dist/server/src/lib/session/agent-event-state.js +260 -0
- package/dist/server/src/lib/session/current-output-builder.js +24 -0
- package/dist/server/src/lib/session/next-action-helper.js +93 -0
- package/dist/server/src/lib/session/prompt-waiting-composition.js +38 -0
- package/dist/server/src/lib/session/waiting-episode-state.js +136 -0
- package/dist/server/src/lib/session/waiting-kind.js +59 -0
- package/dist/server/src/lib/tasks/contract-message.js +64 -21
- package/dist/server/src/lib/tasks/contract-parser.js +58 -12
- package/dist/server/src/lib/verification/gate-runner.js +64 -22
- package/dist/server/src/lib/verification/verify-config.js +84 -51
- package/dist/server/src/lib/ws-server.js +9 -0
- package/dist/server/src/types/sidebar.js +68 -0
- package/package.json +1 -1
- package/.next/server/chunks/6283.js +0 -1
- package/.next/server/chunks/646.js +0 -21
- package/.next/static/chunks/4560-0917ae2e6a0e5400.js +0 -1
- package/.next/static/chunks/6488-95ba9d24a76f0cc5.js +0 -1
- package/.next/static/chunks/7229.edb331fb9fbafa27.js +0 -1
- package/.next/static/chunks/app/api/assistant/messages/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/assistant/session/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/assistant/start/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/assistant/terminal/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/assistant/tools/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/auth/login/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/auth/status/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/status/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/external-apps/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/fs/browse/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/fs/recent-paths/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/hooks/agent-event/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/hooks/claude-done/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/hooks/permission-request/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/metrics/vibe/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/ollama/models/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/push/subscriptions/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/push/vapid/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/excluded/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/restore/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/scan/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/sync/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/repositories/validate-path/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/sidebar/group-order/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/skills/[id]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/skills/installations/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/skills/operations/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/skills/reindex/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/skills/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/slash-commands/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/templates/[id]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/templates/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/todos/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/chat/page-83a2238ab453afaa.js +0 -1
- package/.next/static/chunks/app/layout-86574192bd3c0e6b.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/more/page-1619018cac999bbc.js +0 -1
- package/.next/static/chunks/app/page-a34d26812f085b6c.js +0 -1
- package/.next/static/chunks/app/proxy/[...path]/route-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/repositories/page-202680fe6ec169c8.js +0 -1
- package/.next/static/chunks/app/review/page-b559bfb11c46931b.js +0 -1
- package/.next/static/chunks/app/sessions/page-3fa7e767d0ab3889.js +0 -1
- package/.next/static/chunks/app/skills/[skillId]/page-10d6f983e5f06ffb.js +0 -1
- package/.next/static/chunks/app/skills/installed/page-6641f95e6a6e5f9d.js +0 -1
- package/.next/static/chunks/app/skills/page-184f8e23e31a3667.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-6041d3c3db326317.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/layout-973ec48531555712.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-966a451ae7b0903a.js +0 -1
- package/.next/static/css/d3453a6876553d32.css +0 -1
- package/.next/static/wH6K6QNPHSdATFkVoIcy3/_buildManifest.js +0 -1
- /package/.next/static/{wH6K6QNPHSdATFkVoIcy3 → smu4mnL7qMf8w38n9dQJE}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The "still waiting" reminder setting (Issue #1790).
|
|
4
|
+
*
|
|
5
|
+
* A wait that nobody answers is the case push notifications exist for, and one
|
|
6
|
+
* notification is easy to miss — so after a threshold the server sends exactly
|
|
7
|
+
* one more. How long to wait, and whether to do it at all, is a user decision,
|
|
8
|
+
* and it is a *server-side* one: the check runs in the background with no
|
|
9
|
+
* request and no browser attached, so it cannot read a device's localStorage the
|
|
10
|
+
* way #1788's in-app toggle does. It is therefore stored once for the install
|
|
11
|
+
* and applies to every subscribed device.
|
|
12
|
+
*
|
|
13
|
+
* ## Why the SQL lives here
|
|
14
|
+
*
|
|
15
|
+
* `app_settings` (migration v27) is the generic key-value store this rides on,
|
|
16
|
+
* so no migration is added. Its typed helpers live in `db/app-settings-db`, but
|
|
17
|
+
* both existing ones are `string[]`-shaped and this value is an object with two
|
|
18
|
+
* fields of different types; a third helper there would be a fourth reader of
|
|
19
|
+
* the same table with no shared logic to gain. Keeping the accessor beside its
|
|
20
|
+
* only consumer also keeps the defaults — which the escalation tick applies on
|
|
21
|
+
* every failure path — in one file.
|
|
22
|
+
*
|
|
23
|
+
* Every read is total: a missing row, malformed JSON, an out-of-range threshold
|
|
24
|
+
* or an unopenable database all resolve to {@link DEFAULT_ESCALATION_SETTINGS}
|
|
25
|
+
* rather than throwing. The caller is a background timer whose failure mode
|
|
26
|
+
* must be "no reminder", never "the server logs an exception every minute".
|
|
27
|
+
*
|
|
28
|
+
* @module lib/push/escalation-settings
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.ESCALATION_SETTINGS_KEY = void 0;
|
|
32
|
+
exports.normalizeEscalationSettings = normalizeEscalationSettings;
|
|
33
|
+
exports.getPushEscalationSettings = getPushEscalationSettings;
|
|
34
|
+
exports.setPushEscalationSettings = setPushEscalationSettings;
|
|
35
|
+
const db_instance_1 = require("../../lib/db/db-instance");
|
|
36
|
+
const logger_1 = require("../../lib/logger");
|
|
37
|
+
const logger = (0, logger_1.createLogger)('push/escalation-settings');
|
|
38
|
+
/** `app_settings.key` this setting is stored under. */
|
|
39
|
+
exports.ESCALATION_SETTINGS_KEY = 'push_escalation';
|
|
40
|
+
/**
|
|
41
|
+
* On by default at ten minutes, per the Issue.
|
|
42
|
+
*
|
|
43
|
+
* Defaulting to *on* is the same call #1788 made for the in-app toast: a user
|
|
44
|
+
* who never opened the settings screen is the one most likely to walk away from
|
|
45
|
+
* a waiting agent, and the cost of being wrong is one extra notification per
|
|
46
|
+
* unanswered wait — bounded, because there is only ever one.
|
|
47
|
+
*/
|
|
48
|
+
exports.DEFAULT_ESCALATION_SETTINGS = {
|
|
49
|
+
enabled: true,
|
|
50
|
+
thresholdMinutes: 10,
|
|
51
|
+
};
|
|
52
|
+
/** The thresholds the settings UI offers, in minutes. */
|
|
53
|
+
exports.ESCALATION_THRESHOLD_CHOICES = [5, 10, 30, 60];
|
|
54
|
+
/** Guard rails for a hand-written value: at least a minute, at most a day. */
|
|
55
|
+
exports.MIN_ESCALATION_THRESHOLD_MINUTES = 1;
|
|
56
|
+
exports.MAX_ESCALATION_THRESHOLD_MINUTES = 1440;
|
|
57
|
+
/**
|
|
58
|
+
* Narrow arbitrary input to a usable setting, filling each field independently.
|
|
59
|
+
*
|
|
60
|
+
* Field-by-field rather than all-or-nothing so that a bad threshold does not
|
|
61
|
+
* silently switch the reminder back on (or off): the half the user did set is
|
|
62
|
+
* the half that is honoured.
|
|
63
|
+
*/
|
|
64
|
+
function normalizeEscalationSettings(value) {
|
|
65
|
+
if (typeof value !== 'object' || value === null)
|
|
66
|
+
return { ...exports.DEFAULT_ESCALATION_SETTINGS };
|
|
67
|
+
const record = value;
|
|
68
|
+
const enabled = typeof record.enabled === 'boolean' ? record.enabled : exports.DEFAULT_ESCALATION_SETTINGS.enabled;
|
|
69
|
+
const raw = record.thresholdMinutes;
|
|
70
|
+
const thresholdMinutes = typeof raw === 'number' &&
|
|
71
|
+
Number.isFinite(raw) &&
|
|
72
|
+
raw >= exports.MIN_ESCALATION_THRESHOLD_MINUTES &&
|
|
73
|
+
raw <= exports.MAX_ESCALATION_THRESHOLD_MINUTES
|
|
74
|
+
? Math.round(raw)
|
|
75
|
+
: exports.DEFAULT_ESCALATION_SETTINGS.thresholdMinutes;
|
|
76
|
+
return { enabled, thresholdMinutes };
|
|
77
|
+
}
|
|
78
|
+
/** Read the setting. Never throws — see the module docblock. */
|
|
79
|
+
function getPushEscalationSettings() {
|
|
80
|
+
try {
|
|
81
|
+
const row = (0, db_instance_1.getDbInstance)()
|
|
82
|
+
.prepare('SELECT value FROM app_settings WHERE key = ?')
|
|
83
|
+
.get(exports.ESCALATION_SETTINGS_KEY);
|
|
84
|
+
if (!row)
|
|
85
|
+
return { ...exports.DEFAULT_ESCALATION_SETTINGS };
|
|
86
|
+
return normalizeEscalationSettings(JSON.parse(row.value));
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
logger.warn('escalation-settings-read-failed', {
|
|
90
|
+
error: error instanceof Error ? error.message : String(error),
|
|
91
|
+
});
|
|
92
|
+
return { ...exports.DEFAULT_ESCALATION_SETTINGS };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Persist the setting, normalizing first so a malformed request cannot store a
|
|
97
|
+
* value later reads would have to reject anyway.
|
|
98
|
+
*
|
|
99
|
+
* @returns What was actually written.
|
|
100
|
+
*/
|
|
101
|
+
function setPushEscalationSettings(value) {
|
|
102
|
+
const settings = normalizeEscalationSettings(value);
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
(0, db_instance_1.getDbInstance)()
|
|
105
|
+
.prepare(`
|
|
106
|
+
INSERT INTO app_settings (key, value, created_at, updated_at)
|
|
107
|
+
VALUES (?, ?, ?, ?)
|
|
108
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
109
|
+
value = excluded.value,
|
|
110
|
+
updated_at = excluded.updated_at
|
|
111
|
+
`)
|
|
112
|
+
.run(exports.ESCALATION_SETTINGS_KEY, JSON.stringify(settings), now, now);
|
|
113
|
+
return settings;
|
|
114
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/** Web Push module barrel (Issue #1125). */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
|
|
4
|
+
exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_SETTINGS_KEY = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.normalizeEscalationSettings = exports.setPushEscalationSettings = exports.getPushEscalationSettings = exports.ESCALATION_TICK_MS = exports.pendingEscalationCount = exports.runEscalationTick = exports.handleWaitingTransition = exports.isWaitingPushNotifierActive = exports.stopWaitingPushNotifier = exports.startWaitingPushNotifier = exports.resetWaitingPushDedup = exports.shouldSendWaitingPush = exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
|
|
5
5
|
var vapid_1 = require("./vapid");
|
|
6
6
|
Object.defineProperty(exports, "getVapidConfig", { enumerable: true, get: function () { return vapid_1.getVapidConfig; } });
|
|
7
7
|
Object.defineProperty(exports, "isPushConfigured", { enumerable: true, get: function () { return vapid_1.isPushConfigured; } });
|
|
@@ -15,3 +15,23 @@ var notification_dedup_1 = require("./notification-dedup");
|
|
|
15
15
|
Object.defineProperty(exports, "shouldSendNotification", { enumerable: true, get: function () { return notification_dedup_1.shouldSendNotification; } });
|
|
16
16
|
Object.defineProperty(exports, "resetNotificationDedup", { enumerable: true, get: function () { return notification_dedup_1.resetNotificationDedup; } });
|
|
17
17
|
Object.defineProperty(exports, "DEFAULT_DEDUP_WINDOW_MS", { enumerable: true, get: function () { return notification_dedup_1.DEFAULT_DEDUP_WINDOW_MS; } });
|
|
18
|
+
Object.defineProperty(exports, "shouldSendWaitingPush", { enumerable: true, get: function () { return notification_dedup_1.shouldSendWaitingPush; } });
|
|
19
|
+
Object.defineProperty(exports, "resetWaitingPushDedup", { enumerable: true, get: function () { return notification_dedup_1.resetWaitingPushDedup; } });
|
|
20
|
+
// Waiting-edge driven notifications (Issue #1790).
|
|
21
|
+
var waiting_push_notifier_1 = require("./waiting-push-notifier");
|
|
22
|
+
Object.defineProperty(exports, "startWaitingPushNotifier", { enumerable: true, get: function () { return waiting_push_notifier_1.startWaitingPushNotifier; } });
|
|
23
|
+
Object.defineProperty(exports, "stopWaitingPushNotifier", { enumerable: true, get: function () { return waiting_push_notifier_1.stopWaitingPushNotifier; } });
|
|
24
|
+
Object.defineProperty(exports, "isWaitingPushNotifierActive", { enumerable: true, get: function () { return waiting_push_notifier_1.isWaitingPushNotifierActive; } });
|
|
25
|
+
Object.defineProperty(exports, "handleWaitingTransition", { enumerable: true, get: function () { return waiting_push_notifier_1.handleWaitingTransition; } });
|
|
26
|
+
Object.defineProperty(exports, "runEscalationTick", { enumerable: true, get: function () { return waiting_push_notifier_1.runEscalationTick; } });
|
|
27
|
+
Object.defineProperty(exports, "pendingEscalationCount", { enumerable: true, get: function () { return waiting_push_notifier_1.pendingEscalationCount; } });
|
|
28
|
+
Object.defineProperty(exports, "ESCALATION_TICK_MS", { enumerable: true, get: function () { return waiting_push_notifier_1.ESCALATION_TICK_MS; } });
|
|
29
|
+
var escalation_settings_1 = require("./escalation-settings");
|
|
30
|
+
Object.defineProperty(exports, "getPushEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.getPushEscalationSettings; } });
|
|
31
|
+
Object.defineProperty(exports, "setPushEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.setPushEscalationSettings; } });
|
|
32
|
+
Object.defineProperty(exports, "normalizeEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.normalizeEscalationSettings; } });
|
|
33
|
+
Object.defineProperty(exports, "DEFAULT_ESCALATION_SETTINGS", { enumerable: true, get: function () { return escalation_settings_1.DEFAULT_ESCALATION_SETTINGS; } });
|
|
34
|
+
Object.defineProperty(exports, "ESCALATION_THRESHOLD_CHOICES", { enumerable: true, get: function () { return escalation_settings_1.ESCALATION_THRESHOLD_CHOICES; } });
|
|
35
|
+
Object.defineProperty(exports, "ESCALATION_SETTINGS_KEY", { enumerable: true, get: function () { return escalation_settings_1.ESCALATION_SETTINGS_KEY; } });
|
|
36
|
+
Object.defineProperty(exports, "MIN_ESCALATION_THRESHOLD_MINUTES", { enumerable: true, get: function () { return escalation_settings_1.MIN_ESCALATION_THRESHOLD_MINUTES; } });
|
|
37
|
+
Object.defineProperty(exports, "MAX_ESCALATION_THRESHOLD_MINUTES", { enumerable: true, get: function () { return escalation_settings_1.MAX_ESCALATION_THRESHOLD_MINUTES; } });
|
|
@@ -15,6 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.DEFAULT_DEDUP_WINDOW_MS = void 0;
|
|
16
16
|
exports.shouldSendNotification = shouldSendNotification;
|
|
17
17
|
exports.resetNotificationDedup = resetNotificationDedup;
|
|
18
|
+
exports.shouldSendWaitingPush = shouldSendWaitingPush;
|
|
19
|
+
exports.resetWaitingPushDedup = resetWaitingPushDedup;
|
|
18
20
|
const crypto_1 = require("crypto");
|
|
19
21
|
/** Default suppression window: repeats of identical content within this are dropped. */
|
|
20
22
|
exports.DEFAULT_DEDUP_WINDOW_MS = 30_000;
|
|
@@ -40,3 +42,36 @@ function shouldSendNotification(event, now = Date.now(), windowMs = exports.DEFA
|
|
|
40
42
|
function resetNotificationDedup() {
|
|
41
43
|
lastSent.clear();
|
|
42
44
|
}
|
|
45
|
+
const waitingSent = globalThis.__waitingPushDedup ??
|
|
46
|
+
(globalThis.__waitingPushDedup = new Map());
|
|
47
|
+
/**
|
|
48
|
+
* Whether this waiting notification should be sent, recording it if so.
|
|
49
|
+
*
|
|
50
|
+
* Replaces the content hash for the waiting path (Issue #1790). Content was
|
|
51
|
+
* never the right key here: two identical `Do you want to proceed?` prompts
|
|
52
|
+
* seconds apart are two separate waits a human has to answer twice, and the
|
|
53
|
+
* 30 s window dropped the second one — while a single wait that outlives the
|
|
54
|
+
* window could be notified again for the same question. The episode's `since`
|
|
55
|
+
* is the wait's identity, so "one notification per wait" becomes exact:
|
|
56
|
+
*
|
|
57
|
+
* - first notification of an episode → sent, recorded;
|
|
58
|
+
* - any repeat for the same `since` → suppressed, however it arrived (the
|
|
59
|
+
* poller and the edge listener both report the same wait);
|
|
60
|
+
* - the escalation → allowed exactly once per episode;
|
|
61
|
+
* - a new episode (the wait ended and another began) → sent again, even if the
|
|
62
|
+
* prompt text and the elapsed time are identical.
|
|
63
|
+
*/
|
|
64
|
+
function shouldSendWaitingPush(event) {
|
|
65
|
+
const key = `${event.worktreeId}::${event.instanceId}`;
|
|
66
|
+
const escalated = event.escalated === true;
|
|
67
|
+
const prev = waitingSent.get(key);
|
|
68
|
+
if (prev && prev.since === event.since && (prev.escalated || !escalated)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
waitingSent.set(key, { since: event.since, escalated });
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
/** Clear the episode-scoped state (for tests). */
|
|
75
|
+
function resetWaitingPushDedup() {
|
|
76
|
+
waitingSent.clear();
|
|
77
|
+
}
|
|
@@ -64,6 +64,36 @@ function buildExcerpt(text, maxLength = MAX_EXCERPT_LENGTH) {
|
|
|
64
64
|
return collapsed;
|
|
65
65
|
return collapsed.slice(0, maxLength - 1).trimEnd() + '…';
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Whether this wait can only be dealt with at the terminal (Issue #1790).
|
|
69
|
+
*
|
|
70
|
+
* A `menu` (selection list / pager) and an `unclassified` wait share the one
|
|
71
|
+
* fact the reader acts on: tapping the notification will not present anything
|
|
72
|
+
* to answer. `prompt` — and an absent kind, which is every pre-#1790 caller —
|
|
73
|
+
* keeps the original "waiting for your reply" wording.
|
|
74
|
+
*/
|
|
75
|
+
function needsTerminal(waitingKind) {
|
|
76
|
+
return waitingKind === 'menu' || waitingKind === 'unclassified';
|
|
77
|
+
}
|
|
78
|
+
/** The body for a waiting notification, in the reader's language. */
|
|
79
|
+
function buildWaitingBody(event, messages, excerpt, now) {
|
|
80
|
+
const terminal = needsTerminal(event.waitingKind);
|
|
81
|
+
if (event.escalated) {
|
|
82
|
+
// The excerpt is dropped on purpose: after ten minutes the question is no
|
|
83
|
+
// longer news, the elapsed time is.
|
|
84
|
+
const elapsedMs = now - (event.waitingSince ?? now);
|
|
85
|
+
const minutes = String(Math.max(1, Math.floor(elapsedMs / 60_000)));
|
|
86
|
+
return (terminal ? messages.stillWaitingTerminal : messages.stillWaitingPrompt).replace('{minutes}', minutes);
|
|
87
|
+
}
|
|
88
|
+
if (terminal) {
|
|
89
|
+
return excerpt
|
|
90
|
+
? messages.terminalAttentionWithExcerpt.replace('{excerpt}', excerpt)
|
|
91
|
+
: messages.terminalAttention;
|
|
92
|
+
}
|
|
93
|
+
return excerpt
|
|
94
|
+
? messages.promptWaitingWithExcerpt.replace('{excerpt}', excerpt)
|
|
95
|
+
: messages.promptWaiting;
|
|
96
|
+
}
|
|
67
97
|
/** Build the minimal notification payload for an event, in the reader's language. */
|
|
68
98
|
function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Date.now()) {
|
|
69
99
|
const excerpt = buildExcerpt(event.excerpt);
|
|
@@ -71,9 +101,7 @@ function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Da
|
|
|
71
101
|
const title = `${event.worktreeName}${agentSuffix}`;
|
|
72
102
|
const messages = PUSH_MESSAGES[resolvePushLocale(locale)];
|
|
73
103
|
const body = event.kind === 'prompt'
|
|
74
|
-
? excerpt
|
|
75
|
-
? messages.promptWaitingWithExcerpt.replace('{excerpt}', excerpt)
|
|
76
|
-
: messages.promptWaiting
|
|
104
|
+
? buildWaitingBody(event, messages, excerpt, now)
|
|
77
105
|
: excerpt
|
|
78
106
|
? messages.completionWithExcerpt.replace('{excerpt}', excerpt)
|
|
79
107
|
: messages.completion;
|
|
@@ -83,8 +111,12 @@ function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Da
|
|
|
83
111
|
body,
|
|
84
112
|
worktreeId: event.worktreeId,
|
|
85
113
|
url: `/worktrees/${event.worktreeId}`,
|
|
114
|
+
// Unchanged by #1790, and deliberately: the escalation carries the same tag
|
|
115
|
+
// as the notification it follows up, so the Service Worker replaces the
|
|
116
|
+
// stale one instead of stacking a second card for the same wait.
|
|
86
117
|
tag: `${event.worktreeId}:${event.kind}`,
|
|
87
118
|
timestamp: now,
|
|
119
|
+
...(event.waitingKind ? { waitingKind: event.waitingKind } : {}),
|
|
88
120
|
};
|
|
89
121
|
}
|
|
90
122
|
async function sendToOne(sub, payload) {
|
|
@@ -102,19 +134,46 @@ async function sendToOne(sub, payload) {
|
|
|
102
134
|
logger.warn('push-send-failed', { statusCode: statusCode ?? 'unknown' });
|
|
103
135
|
}
|
|
104
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Which guard applies to this event (Issue #1790).
|
|
139
|
+
*
|
|
140
|
+
* An episode-scoped waiting notification is deduped by the wait it belongs to;
|
|
141
|
+
* everything else — every completion, and any prompt event that predates the
|
|
142
|
+
* episode store — keeps the content hash and its 30 s window. Both record as
|
|
143
|
+
* they decide, so this must be called exactly once per event.
|
|
144
|
+
*/
|
|
145
|
+
function passesDedup(event) {
|
|
146
|
+
if (event.kind === 'prompt' && typeof event.waitingSince === 'number') {
|
|
147
|
+
return (0, notification_dedup_1.shouldSendWaitingPush)({
|
|
148
|
+
worktreeId: event.worktreeId,
|
|
149
|
+
instanceId: event.instanceId ?? event.agentName ?? '',
|
|
150
|
+
since: event.waitingSince,
|
|
151
|
+
escalated: event.escalated,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return (0, notification_dedup_1.shouldSendNotification)({
|
|
155
|
+
worktreeId: event.worktreeId,
|
|
156
|
+
kind: event.kind,
|
|
157
|
+
content: event.excerpt,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
105
160
|
/**
|
|
106
161
|
* Fan out a notification to all subscriptions opted into this event's kind.
|
|
107
162
|
* Never throws — push is advisory and must not disrupt the poller. No-op when
|
|
108
163
|
* push is unconfigured, deduped, or there are no matching subscriptions.
|
|
164
|
+
*
|
|
165
|
+
* `now` is injectable because the escalation body quotes how long the wait has
|
|
166
|
+
* lasted (Issue #1790): the reminder is raised from a periodic check that knows
|
|
167
|
+
* the tick's time, and reading the clock again here would report a different
|
|
168
|
+
* elapsed time from the one that decided to send.
|
|
109
169
|
*/
|
|
110
|
-
async function notifyPushSubscribers(event) {
|
|
170
|
+
async function notifyPushSubscribers(event, now = Date.now()) {
|
|
111
171
|
try {
|
|
112
172
|
const config = (0, vapid_1.getVapidConfig)();
|
|
113
173
|
if (!config)
|
|
114
174
|
return;
|
|
115
|
-
if (!(
|
|
175
|
+
if (!passesDedup(event))
|
|
116
176
|
return;
|
|
117
|
-
}
|
|
118
177
|
const db = (0, db_instance_1.getDbInstance)();
|
|
119
178
|
const subscriptions = (0, push_subscriptions_db_1.getPushSubscriptionsForKind)(db, event.kind);
|
|
120
179
|
if (subscriptions.length === 0)
|
|
@@ -132,7 +191,7 @@ async function notifyPushSubscribers(event) {
|
|
|
132
191
|
byLocale.set(locale, [sub]);
|
|
133
192
|
}
|
|
134
193
|
await Promise.all(Array.from(byLocale, ([locale, subs]) => {
|
|
135
|
-
const payload = JSON.stringify(buildPushPayload(event, locale));
|
|
194
|
+
const payload = JSON.stringify(buildPushPayload(event, locale, now));
|
|
136
195
|
return Promise.all(subs.map((sub) => sendToOne(sub, payload)));
|
|
137
196
|
}));
|
|
138
197
|
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Send a push notification when an agent starts waiting, and one reminder if it
|
|
4
|
+
* is still waiting later (Issue #1790).
|
|
5
|
+
*
|
|
6
|
+
* ## Why this subscribes rather than detects
|
|
7
|
+
*
|
|
8
|
+
* The prompt notification used to be raised from one line inside the response
|
|
9
|
+
* poller, which made it inherit every one of that poller's boundaries: it only
|
|
10
|
+
* runs when a send-family API or Auto-Yes started it, it stops itself on the
|
|
11
|
+
* first prompt of a turn, it gives up after `MAX_POLLING_DURATION`, and it can
|
|
12
|
+
* only see waits the screen scraper classified as `isPrompt`. A wait that began
|
|
13
|
+
* after a `tmux` keystroke, a second prompt in the same turn, a wait that only
|
|
14
|
+
* the agent's own hook events reported, and a selection list were all silently
|
|
15
|
+
* unnotifiable.
|
|
16
|
+
*
|
|
17
|
+
* #1786 made the waiting edge observable exactly once, in
|
|
18
|
+
* `waiting-episode-state`, and #1788 already subscribes to it for the WebSocket
|
|
19
|
+
* frame. This module is the same subscription for push — it captures no pane,
|
|
20
|
+
* runs no detector, and keeps no "was it waiting last time?" of its own.
|
|
21
|
+
*
|
|
22
|
+
* ## The poller still notifies, and that is deliberate
|
|
23
|
+
*
|
|
24
|
+
* Contrary to the Issue's premise, the edge is *not* observed by a background
|
|
25
|
+
* process: `observeWaitingEdge`'s only caller is `worktree-status-helper`, on
|
|
26
|
+
* the worktree list / detail API probe. So the edge fires when a client is
|
|
27
|
+
* looking, and moving push onto it *alone* would have swapped one blind spot
|
|
28
|
+
* (no poller) for a worse one (nobody has the app open — the very situation a
|
|
29
|
+
* phone notification is for). The poller therefore keeps its call, and
|
|
30
|
+
* `response-checker` opens the same episode through `observeWaitingEdge` so both
|
|
31
|
+
* producers name the wait identically; `shouldSendWaitingPush` then collapses
|
|
32
|
+
* them to one notification. See the commit message for the measurement.
|
|
33
|
+
*
|
|
34
|
+
* ## Escalation
|
|
35
|
+
*
|
|
36
|
+
* There is no existing server-side sweep over waiting sessions to ride on, so
|
|
37
|
+
* this keeps a small interval of its own. It exists only while some wait is
|
|
38
|
+
* outstanding — created on the first open episode, cleared when the last one
|
|
39
|
+
* closes — so an install with nothing waiting has no timer, and one that never
|
|
40
|
+
* configured VAPID never even gets that far.
|
|
41
|
+
*
|
|
42
|
+
* Everything here is advisory: a failure must not disturb the status read that
|
|
43
|
+
* observed the edge (`emit` contains listener throws) nor the poller.
|
|
44
|
+
*
|
|
45
|
+
* @module lib/push/waiting-push-notifier
|
|
46
|
+
*/
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.ESCALATION_TICK_MS = void 0;
|
|
49
|
+
exports.handleWaitingTransition = handleWaitingTransition;
|
|
50
|
+
exports.runEscalationTick = runEscalationTick;
|
|
51
|
+
exports.startWaitingPushNotifier = startWaitingPushNotifier;
|
|
52
|
+
exports.stopWaitingPushNotifier = stopWaitingPushNotifier;
|
|
53
|
+
exports.isWaitingPushNotifierActive = isWaitingPushNotifierActive;
|
|
54
|
+
exports.pendingEscalationCount = pendingEscalationCount;
|
|
55
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
56
|
+
const db_instance_1 = require("../../lib/db/db-instance");
|
|
57
|
+
const worktree_db_1 = require("../../lib/db/worktree-db");
|
|
58
|
+
const logger_1 = require("../../lib/logger");
|
|
59
|
+
const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
|
|
60
|
+
const escalation_settings_1 = require("./escalation-settings");
|
|
61
|
+
const push_sender_1 = require("./push-sender");
|
|
62
|
+
const vapid_1 = require("./vapid");
|
|
63
|
+
const logger = (0, logger_1.createLogger)('push/waiting-notifier');
|
|
64
|
+
/** How often outstanding waits are re-checked. Minute granularity is enough. */
|
|
65
|
+
exports.ESCALATION_TICK_MS = 60_000;
|
|
66
|
+
const pending = globalThis.__waitingPushPending ??
|
|
67
|
+
(globalThis.__waitingPushPending = new Map());
|
|
68
|
+
/**
|
|
69
|
+
* The worktree's display name, for the notification title.
|
|
70
|
+
*
|
|
71
|
+
* Falls back to the id rather than dropping the notification: a database that
|
|
72
|
+
* cannot answer is a reason to send a less readable title, not a reason to
|
|
73
|
+
* leave the user waiting in silence.
|
|
74
|
+
*/
|
|
75
|
+
function resolveWorktreeName(worktreeId) {
|
|
76
|
+
try {
|
|
77
|
+
return (0, worktree_db_1.getWorktreeById)((0, db_instance_1.getDbInstance)(), worktreeId)?.name ?? worktreeId;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return worktreeId;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Fan one waiting notification out. Never throws. */
|
|
84
|
+
async function sendWaitingPush(wait, escalated, now) {
|
|
85
|
+
const instanceId = wait.instanceId ?? wait.cliToolId;
|
|
86
|
+
try {
|
|
87
|
+
await (0, push_sender_1.notifyPushSubscribers)({
|
|
88
|
+
worktreeId: wait.worktreeId,
|
|
89
|
+
worktreeName: resolveWorktreeName(wait.worktreeId),
|
|
90
|
+
kind: 'prompt',
|
|
91
|
+
agentName: instanceId,
|
|
92
|
+
instanceId,
|
|
93
|
+
waitingKind: wait.kind,
|
|
94
|
+
waitingSince: wait.since,
|
|
95
|
+
escalated,
|
|
96
|
+
},
|
|
97
|
+
// The deciding tick's clock, not a fresh reading: the reminder's body
|
|
98
|
+
// quotes the elapsed time this call was made on.
|
|
99
|
+
now);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
logger.warn('waiting-push-failed', {
|
|
103
|
+
worktreeId: wait.worktreeId,
|
|
104
|
+
instanceId,
|
|
105
|
+
escalated,
|
|
106
|
+
error: error instanceof Error ? error.message : String(error),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function startEscalationTimer() {
|
|
111
|
+
if (globalThis.__waitingPushEscalationTimer !== undefined)
|
|
112
|
+
return;
|
|
113
|
+
const timer = setInterval(() => {
|
|
114
|
+
runEscalationTick();
|
|
115
|
+
}, exports.ESCALATION_TICK_MS);
|
|
116
|
+
// Never hold the process open for a reminder; the server exiting is a far
|
|
117
|
+
// stronger signal than "someone might still be waiting".
|
|
118
|
+
timer.unref?.();
|
|
119
|
+
globalThis.__waitingPushEscalationTimer = timer;
|
|
120
|
+
}
|
|
121
|
+
function stopEscalationTimerIfIdle() {
|
|
122
|
+
if (pending.size > 0)
|
|
123
|
+
return;
|
|
124
|
+
const timer = globalThis.__waitingPushEscalationTimer;
|
|
125
|
+
if (timer !== undefined) {
|
|
126
|
+
clearInterval(timer);
|
|
127
|
+
globalThis.__waitingPushEscalationTimer = undefined;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Handle one crossing of the waiting edge.
|
|
132
|
+
*
|
|
133
|
+
* Exported for tests, which drive it directly rather than through the
|
|
134
|
+
* subscription so a failure points at this function and not at #1786's store.
|
|
135
|
+
*/
|
|
136
|
+
function handleWaitingTransition(transition) {
|
|
137
|
+
// Nothing downstream can do anything without VAPID keys, so an install
|
|
138
|
+
// without push does not track waits, does not read the database and does not
|
|
139
|
+
// start a timer — it is inert rather than merely quiet.
|
|
140
|
+
if (!(0, vapid_1.isPushConfigured)())
|
|
141
|
+
return;
|
|
142
|
+
const key = (0, auto_yes_state_1.buildCompositeKey)(transition.worktreeId, transition.cliToolId, transition.instanceId);
|
|
143
|
+
if (!transition.waiting || transition.since === null) {
|
|
144
|
+
pending.delete(key);
|
|
145
|
+
stopEscalationTimerIfIdle();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const wait = {
|
|
149
|
+
worktreeId: transition.worktreeId,
|
|
150
|
+
cliToolId: transition.cliToolId,
|
|
151
|
+
instanceId: transition.instanceId,
|
|
152
|
+
since: transition.since,
|
|
153
|
+
kind: transition.kind,
|
|
154
|
+
};
|
|
155
|
+
pending.set(key, wait);
|
|
156
|
+
startEscalationTimer();
|
|
157
|
+
void sendWaitingPush(wait, false, transition.at);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Re-notify every wait that has outlived the threshold, once each.
|
|
161
|
+
*
|
|
162
|
+
* Exported so tests can advance a fake clock instead of a real minute.
|
|
163
|
+
*/
|
|
164
|
+
function runEscalationTick(now = Date.now()) {
|
|
165
|
+
if (pending.size === 0) {
|
|
166
|
+
stopEscalationTimerIfIdle();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const settings = (0, escalation_settings_1.getPushEscalationSettings)();
|
|
170
|
+
const thresholdMs = settings.thresholdMinutes * 60_000;
|
|
171
|
+
for (const [key, wait] of Array.from(pending)) {
|
|
172
|
+
// The episode store, not this map, is the authority on whether the wait is
|
|
173
|
+
// still going: it is written by the status probe, so an answer given in
|
|
174
|
+
// another tab — or a wait whose closing edge this module never saw — is
|
|
175
|
+
// caught here even when `pending` still lists it.
|
|
176
|
+
const episode = (0, waiting_episode_state_1.getWaitingEpisode)(wait.worktreeId, wait.cliToolId, wait.instanceId);
|
|
177
|
+
if (episode === null || episode.since !== wait.since) {
|
|
178
|
+
pending.delete(key);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (!settings.enabled)
|
|
182
|
+
continue;
|
|
183
|
+
if (now - wait.since < thresholdMs)
|
|
184
|
+
continue;
|
|
185
|
+
// Dropped before sending, not after: the reminder is once per episode, and
|
|
186
|
+
// an in-flight fan-out must not be able to earn a second one.
|
|
187
|
+
pending.delete(key);
|
|
188
|
+
void sendWaitingPush({ ...wait, kind: episode.kind ?? wait.kind }, true, now);
|
|
189
|
+
}
|
|
190
|
+
stopEscalationTimerIfIdle();
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Subscribe to the waiting edge.
|
|
194
|
+
*
|
|
195
|
+
* Idempotent by replacement, like #1788's broadcast: calling it again drops the
|
|
196
|
+
* previous subscription rather than adding a second one, so a module evaluated
|
|
197
|
+
* twice cannot double-notify.
|
|
198
|
+
*
|
|
199
|
+
* @returns The unsubscribe function (also reachable as
|
|
200
|
+
* {@link stopWaitingPushNotifier}).
|
|
201
|
+
*/
|
|
202
|
+
function startWaitingPushNotifier() {
|
|
203
|
+
stopWaitingPushNotifier();
|
|
204
|
+
const unsubscribe = (0, waiting_episode_state_1.onWaitingTransition)((transition) => {
|
|
205
|
+
handleWaitingTransition(transition);
|
|
206
|
+
});
|
|
207
|
+
globalThis.__waitingPushUnsubscribe = unsubscribe;
|
|
208
|
+
return unsubscribe;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Drop the subscription, the outstanding waits and the timer. Safe when none is
|
|
212
|
+
* active, and the seam a test uses to leave no interval behind (CI runs the
|
|
213
|
+
* whole suite in one process).
|
|
214
|
+
*/
|
|
215
|
+
function stopWaitingPushNotifier() {
|
|
216
|
+
const existing = globalThis.__waitingPushUnsubscribe;
|
|
217
|
+
if (existing) {
|
|
218
|
+
existing();
|
|
219
|
+
globalThis.__waitingPushUnsubscribe = undefined;
|
|
220
|
+
}
|
|
221
|
+
pending.clear();
|
|
222
|
+
stopEscalationTimerIfIdle();
|
|
223
|
+
}
|
|
224
|
+
/** Whether a subscription is currently active. Test seam. */
|
|
225
|
+
function isWaitingPushNotifierActive() {
|
|
226
|
+
return globalThis.__waitingPushUnsubscribe !== undefined;
|
|
227
|
+
}
|
|
228
|
+
/** How many waits are awaiting their reminder. Test seam. */
|
|
229
|
+
function pendingEscalationCount() {
|
|
230
|
+
return pending.size;
|
|
231
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Push the waiting edge to every subscriber of a worktree room (Issue #1788).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this file exists rather than a detector
|
|
6
|
+
*
|
|
7
|
+
* Issue #1786 made the false→true / true→false crossing observable exactly once,
|
|
8
|
+
* in `waiting-episode-state`, and handed out `onWaitingTransition` for the
|
|
9
|
+
* surfaces that need the instant rather than the level. This module is that
|
|
10
|
+
* subscription and nothing more: it translates a {@link WaitingTransition} into
|
|
11
|
+
* a {@link SessionStatusEvent} and publishes it. It does not capture a pane, does
|
|
12
|
+
* not read the structured events, and does not keep a "was it waiting last
|
|
13
|
+
* time?" of its own — three surfaces each keeping their own answer to that is
|
|
14
|
+
* precisely what #1786 exists to prevent.
|
|
15
|
+
*
|
|
16
|
+
* Because it subscribes to the edge and not to the response poller, a wait that
|
|
17
|
+
* only the agent's own hook events could see (#1725) broadcasts exactly like one
|
|
18
|
+
* the screen scraper read, and a wait that lasts twenty minutes broadcasts once.
|
|
19
|
+
*
|
|
20
|
+
* ## Why `publish` is injected
|
|
21
|
+
*
|
|
22
|
+
* `ws-server` owns the rooms and starts this subscription from
|
|
23
|
+
* `setupWebSocket`, so importing `broadcast` here would close an import cycle
|
|
24
|
+
* (ws-server → waiting-broadcast → ws-server). Taking the publisher as an
|
|
25
|
+
* argument also makes the translation testable without standing up a server.
|
|
26
|
+
*
|
|
27
|
+
* ## Authorization
|
|
28
|
+
*
|
|
29
|
+
* None is bypassed. The publisher is the room broadcaster, and a socket only
|
|
30
|
+
* joins a room through the authenticated `subscribe` path (#331/#332): a client
|
|
31
|
+
* that never subscribed to a worktree still never hears about it.
|
|
32
|
+
*
|
|
33
|
+
* @module lib/realtime/waiting-broadcast
|
|
34
|
+
*/
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildWaitingStatusEvent = buildWaitingStatusEvent;
|
|
37
|
+
exports.startWaitingStatusBroadcast = startWaitingStatusBroadcast;
|
|
38
|
+
exports.stopWaitingStatusBroadcast = stopWaitingStatusBroadcast;
|
|
39
|
+
exports.isWaitingStatusBroadcastActive = isWaitingStatusBroadcastActive;
|
|
40
|
+
const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
|
|
41
|
+
/**
|
|
42
|
+
* Translate a waiting crossing into the frame clients receive.
|
|
43
|
+
*
|
|
44
|
+
* `isRunning` is deliberately omitted — see the field's doc on
|
|
45
|
+
* {@link SessionStatusEvent}. `instance` is normalized to the instance id the
|
|
46
|
+
* per-instance status map is keyed by (the CLI tool id for the primary), so a
|
|
47
|
+
* client can look the entry up without re-deriving the convention.
|
|
48
|
+
*/
|
|
49
|
+
function buildWaitingStatusEvent(transition) {
|
|
50
|
+
return {
|
|
51
|
+
type: 'session_status_changed',
|
|
52
|
+
worktreeId: transition.worktreeId,
|
|
53
|
+
cliTool: transition.cliToolId,
|
|
54
|
+
instance: transition.instanceId ?? transition.cliToolId,
|
|
55
|
+
isWaitingForResponse: transition.waiting,
|
|
56
|
+
waitingKind: transition.kind ?? null,
|
|
57
|
+
waitingSince: transition.since,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Subscribe to the waiting edge and publish it to the worktree's room.
|
|
62
|
+
*
|
|
63
|
+
* Idempotent: calling it again replaces the previous subscription rather than
|
|
64
|
+
* adding a second one, so a re-entered `setupWebSocket` cannot double-send.
|
|
65
|
+
*
|
|
66
|
+
* @param publish - Room broadcaster, normally `ws-server`'s internal one.
|
|
67
|
+
* @returns The unsubscribe function (also reachable as
|
|
68
|
+
* {@link stopWaitingStatusBroadcast}).
|
|
69
|
+
*/
|
|
70
|
+
function startWaitingStatusBroadcast(publish) {
|
|
71
|
+
stopWaitingStatusBroadcast();
|
|
72
|
+
const unsubscribe = (0, waiting_episode_state_1.onWaitingTransition)((transition) => {
|
|
73
|
+
publish(transition.worktreeId, buildWaitingStatusEvent(transition));
|
|
74
|
+
});
|
|
75
|
+
globalThis.__waitingStatusBroadcastUnsubscribe = unsubscribe;
|
|
76
|
+
return unsubscribe;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Drop the subscription, if any. Safe to call when none is active — and called
|
|
80
|
+
* from `closeWebSocket`, so a suite that stands a server up and tears it down
|
|
81
|
+
* does not leave a listener pointed at a dead room map.
|
|
82
|
+
*/
|
|
83
|
+
function stopWaitingStatusBroadcast() {
|
|
84
|
+
const existing = globalThis.__waitingStatusBroadcastUnsubscribe;
|
|
85
|
+
if (existing) {
|
|
86
|
+
existing();
|
|
87
|
+
globalThis.__waitingStatusBroadcastUnsubscribe = undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Whether a subscription is currently active. Test seam. */
|
|
91
|
+
function isWaitingStatusBroadcastActive() {
|
|
92
|
+
return globalThis.__waitingStatusBroadcastUnsubscribe !== undefined;
|
|
93
|
+
}
|