botmux 3.10.0 → 3.11.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/dist/.runtime-build-id +1 -1
- package/dist/adapters/backend/herdr-backend.d.ts +4 -3
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +11 -8
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/pty-backend.d.ts +1 -1
- package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
- package/dist/adapters/backend/pty-backend.js +4 -1
- package/dist/adapters/backend/pty-backend.js.map +1 -1
- package/dist/adapters/backend/riff-backend.d.ts +29 -5
- package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
- package/dist/adapters/backend/riff-backend.js +302 -31
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/backend/sandbox.d.ts +6 -0
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +7 -0
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +4 -1
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +37 -3
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/backend/zellij-backend.d.ts +3 -3
- package/dist/adapters/backend/zellij-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zellij-backend.js +9 -3
- package/dist/adapters/backend/zellij-backend.js.map +1 -1
- package/dist/adapters/backend/zellij-observe-backend.d.ts +3 -3
- package/dist/adapters/backend/zellij-observe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zellij-observe-backend.js +12 -7
- package/dist/adapters/backend/zellij-observe-backend.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app.js +11 -2
- package/dist/adapters/cli/codex-app.js.map +1 -1
- package/dist/adapters/cli/read-isolation.d.ts +35 -2
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +88 -7
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/runner-input.d.ts +15 -14
- package/dist/adapters/cli/runner-input.d.ts.map +1 -1
- package/dist/adapters/cli/runner-input.js +64 -26
- package/dist/adapters/cli/runner-input.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +20 -5
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +24 -0
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +110 -5
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/fleet-shutdown.d.ts +47 -0
- package/dist/cli/fleet-shutdown.d.ts.map +1 -0
- package/dist/cli/fleet-shutdown.js +387 -0
- package/dist/cli/fleet-shutdown.js.map +1 -0
- package/dist/cli/pm2-descriptor-guard.d.ts +19 -0
- package/dist/cli/pm2-descriptor-guard.d.ts.map +1 -0
- package/dist/cli/pm2-descriptor-guard.js +122 -0
- package/dist/cli/pm2-descriptor-guard.js.map +1 -0
- package/dist/cli/pm2-exact-start.d.ts +16 -0
- package/dist/cli/pm2-exact-start.d.ts.map +1 -0
- package/dist/cli/pm2-exact-start.js +63 -0
- package/dist/cli/pm2-exact-start.js.map +1 -0
- package/dist/cli/pm2-god-admission.d.ts +8 -0
- package/dist/cli/pm2-god-admission.d.ts.map +1 -0
- package/dist/cli/pm2-god-admission.js +25 -0
- package/dist/cli/pm2-god-admission.js.map +1 -0
- package/dist/cli/pm2-jlist.d.ts +13 -0
- package/dist/cli/pm2-jlist.d.ts.map +1 -0
- package/dist/cli/pm2-jlist.js +108 -0
- package/dist/cli/pm2-jlist.js.map +1 -0
- package/dist/cli/pm2-preflight.d.ts +10 -0
- package/dist/cli/pm2-preflight.d.ts.map +1 -0
- package/dist/cli/pm2-preflight.js +23 -0
- package/dist/cli/pm2-preflight.js.map +1 -0
- package/dist/cli/pm2-shutdown-capability.d.ts +27 -0
- package/dist/cli/pm2-shutdown-capability.d.ts.map +1 -0
- package/dist/cli/pm2-shutdown-capability.js +161 -0
- package/dist/cli/pm2-shutdown-capability.js.map +1 -0
- package/dist/cli/pm2-start-transaction.d.ts +55 -0
- package/dist/cli/pm2-start-transaction.d.ts.map +1 -0
- package/dist/cli/pm2-start-transaction.js +220 -0
- package/dist/cli/pm2-start-transaction.js.map +1 -0
- package/dist/cli/send-dispatch.d.ts +12 -0
- package/dist/cli/send-dispatch.d.ts.map +1 -1
- package/dist/cli/send-dispatch.js +31 -4
- package/dist/cli/send-dispatch.js.map +1 -1
- package/dist/cli/session-list-liveness.d.ts +1 -0
- package/dist/cli/session-list-liveness.d.ts.map +1 -1
- package/dist/cli/session-list-liveness.js +6 -0
- package/dist/cli/session-list-liveness.js.map +1 -1
- package/dist/cli/session-picker-layout.d.ts +26 -0
- package/dist/cli/session-picker-layout.d.ts.map +1 -0
- package/dist/cli/session-picker-layout.js +123 -0
- package/dist/cli/session-picker-layout.js.map +1 -0
- package/dist/cli/session-picker-viewport.d.ts +49 -0
- package/dist/cli/session-picker-viewport.d.ts.map +1 -0
- package/dist/cli/session-picker-viewport.js +46 -0
- package/dist/cli/session-picker-viewport.js.map +1 -0
- package/dist/cli/supervisor-shutdown-client.d.ts +31 -0
- package/dist/cli/supervisor-shutdown-client.d.ts.map +1 -0
- package/dist/cli/supervisor-shutdown-client.js +146 -0
- package/dist/cli/supervisor-shutdown-client.js.map +1 -0
- package/dist/cli/terminal-width.d.ts +48 -0
- package/dist/cli/terminal-width.d.ts.map +1 -0
- package/dist/cli/terminal-width.js +119 -0
- package/dist/cli/terminal-width.js.map +1 -0
- package/dist/cli/vc-agent.d.ts.map +1 -1
- package/dist/cli/vc-agent.js +1 -1
- package/dist/cli/vc-agent.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2269 -716
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.js +1630 -125
- package/dist/codex-app-runner.js.map +1 -1
- package/dist/core/ask-api.d.ts +8 -1
- package/dist/core/ask-api.d.ts.map +1 -1
- package/dist/core/ask-api.js +18 -0
- package/dist/core/ask-api.js.map +1 -1
- package/dist/core/ask-broker.d.ts +20 -0
- package/dist/core/ask-broker.d.ts.map +1 -1
- package/dist/core/ask-broker.js +467 -47
- package/dist/core/ask-broker.js.map +1 -1
- package/dist/core/ask-persist-store.d.ts +126 -0
- package/dist/core/ask-persist-store.d.ts.map +1 -0
- package/dist/core/ask-persist-store.js +188 -0
- package/dist/core/ask-persist-store.js.map +1 -0
- package/dist/core/ask-types.d.ts +80 -0
- package/dist/core/ask-types.d.ts.map +1 -1
- package/dist/core/ask-types.js +62 -0
- package/dist/core/ask-types.js.map +1 -1
- package/dist/core/cli-session-id-publisher.d.ts +20 -0
- package/dist/core/cli-session-id-publisher.d.ts.map +1 -0
- package/dist/core/cli-session-id-publisher.js +21 -0
- package/dist/core/cli-session-id-publisher.js.map +1 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +427 -255
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/cost-calculator.d.ts +13 -0
- package/dist/core/cost-calculator.d.ts.map +1 -1
- package/dist/core/cost-calculator.js +385 -26
- package/dist/core/cost-calculator.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +9 -0
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +842 -288
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/explicit-session-backing-cleanup.d.ts +49 -0
- package/dist/core/explicit-session-backing-cleanup.d.ts.map +1 -0
- package/dist/core/explicit-session-backing-cleanup.js +76 -0
- package/dist/core/explicit-session-backing-cleanup.js.map +1 -0
- package/dist/core/idle-worker-sweeper.d.ts +20 -0
- package/dist/core/idle-worker-sweeper.d.ts.map +1 -1
- package/dist/core/idle-worker-sweeper.js +18 -0
- package/dist/core/idle-worker-sweeper.js.map +1 -1
- package/dist/core/inflight-input-tracker.d.ts +10 -0
- package/dist/core/inflight-input-tracker.d.ts.map +1 -1
- package/dist/core/inflight-input-tracker.js +7 -0
- package/dist/core/inflight-input-tracker.js.map +1 -1
- package/dist/core/managed-origin-attestation.d.ts +51 -0
- package/dist/core/managed-origin-attestation.d.ts.map +1 -0
- package/dist/core/managed-origin-attestation.js +208 -0
- package/dist/core/managed-origin-attestation.js.map +1 -0
- package/dist/core/managed-origin-capability.d.ts +62 -3
- package/dist/core/managed-origin-capability.d.ts.map +1 -1
- package/dist/core/managed-origin-capability.js +419 -9
- package/dist/core/managed-origin-capability.js.map +1 -1
- package/dist/core/pending-repo-journal.d.ts +6 -0
- package/dist/core/pending-repo-journal.d.ts.map +1 -0
- package/dist/core/pending-repo-journal.js +85 -0
- package/dist/core/pending-repo-journal.js.map +1 -0
- package/dist/core/persistent-backend.d.ts +6 -1
- package/dist/core/persistent-backend.d.ts.map +1 -1
- package/dist/core/persistent-backend.js +12 -6
- package/dist/core/persistent-backend.js.map +1 -1
- package/dist/core/process-start-identity.d.ts +3 -0
- package/dist/core/process-start-identity.d.ts.map +1 -0
- package/dist/core/process-start-identity.js +62 -0
- package/dist/core/process-start-identity.js.map +1 -0
- package/dist/core/raw-command-writer.d.ts +34 -0
- package/dist/core/raw-command-writer.d.ts.map +1 -0
- package/dist/core/raw-command-writer.js +48 -0
- package/dist/core/raw-command-writer.js.map +1 -0
- package/dist/core/reply-target.d.ts +85 -22
- package/dist/core/reply-target.d.ts.map +1 -1
- package/dist/core/reply-target.js +267 -32
- package/dist/core/reply-target.js.map +1 -1
- package/dist/core/resource-monitor/runtime.d.ts.map +1 -1
- package/dist/core/resource-monitor/runtime.js +4 -1
- package/dist/core/resource-monitor/runtime.js.map +1 -1
- package/dist/core/restart-report.d.ts +6 -1
- package/dist/core/restart-report.d.ts.map +1 -1
- package/dist/core/restart-report.js +22 -4
- package/dist/core/restart-report.js.map +1 -1
- package/dist/core/riff-shutdown-detach.d.ts +164 -0
- package/dist/core/riff-shutdown-detach.d.ts.map +1 -0
- package/dist/core/riff-shutdown-detach.js +787 -0
- package/dist/core/riff-shutdown-detach.js.map +1 -0
- package/dist/core/riff-worker-shutdown-readiness.d.ts +17 -0
- package/dist/core/riff-worker-shutdown-readiness.d.ts.map +1 -0
- package/dist/core/riff-worker-shutdown-readiness.js +21 -0
- package/dist/core/riff-worker-shutdown-readiness.js.map +1 -0
- package/dist/core/session-manager.d.ts +6 -6
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +1227 -594
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-marker.d.ts +1 -1
- package/dist/core/session-marker.d.ts.map +1 -1
- package/dist/core/session-marker.js +2 -2
- package/dist/core/session-marker.js.map +1 -1
- package/dist/core/session-mutation-guard.d.ts +17 -0
- package/dist/core/session-mutation-guard.d.ts.map +1 -0
- package/dist/core/session-mutation-guard.js +33 -0
- package/dist/core/session-mutation-guard.js.map +1 -0
- package/dist/core/shutdown-budgets.d.ts +27 -0
- package/dist/core/shutdown-budgets.d.ts.map +1 -0
- package/dist/core/shutdown-budgets.js +47 -0
- package/dist/core/shutdown-budgets.js.map +1 -0
- package/dist/core/supervisor-shutdown-ipc.d.ts +10 -0
- package/dist/core/supervisor-shutdown-ipc.d.ts.map +1 -0
- package/dist/core/supervisor-shutdown-ipc.js +10 -0
- package/dist/core/supervisor-shutdown-ipc.js.map +1 -0
- package/dist/core/supervisor-shutdown-protocol.d.ts +16 -0
- package/dist/core/supervisor-shutdown-protocol.d.ts.map +1 -0
- package/dist/core/supervisor-shutdown-protocol.js +16 -0
- package/dist/core/supervisor-shutdown-protocol.js.map +1 -0
- package/dist/core/trigger-final-suppression.d.ts +4 -0
- package/dist/core/trigger-final-suppression.d.ts.map +1 -1
- package/dist/core/trigger-final-suppression.js +6 -11
- package/dist/core/trigger-final-suppression.js.map +1 -1
- package/dist/core/trigger-session.d.ts +70 -0
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +923 -145
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +94 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +194 -13
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +2597 -547
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +76 -2
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +2255 -773
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +20 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +24 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/feed-groups.d.ts +17 -0
- package/dist/dashboard/feed-groups.d.ts.map +1 -0
- package/dist/dashboard/feed-groups.js +75 -0
- package/dist/dashboard/feed-groups.js.map +1 -0
- package/dist/dashboard/session-card-model.d.ts +1 -1
- package/dist/dashboard/session-card-model.d.ts.map +1 -1
- package/dist/dashboard/session-card-model.js +8 -5
- package/dist/dashboard/session-card-model.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +4 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +139 -46
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +4 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +40 -3
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +95 -2
- package/dist/dashboard/web/groups-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +86 -40
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/kanban-model.js +1 -1
- package/dist/dashboard/web/kanban-model.js.map +1 -1
- package/dist/dashboard/web/overview-page.d.ts.map +1 -1
- package/dist/dashboard/web/overview-page.js +3 -2
- package/dist/dashboard/web/overview-page.js.map +1 -1
- package/dist/dashboard/web/overview.d.ts +3 -0
- package/dist/dashboard/web/overview.d.ts.map +1 -1
- package/dist/dashboard/web/overview.js +2 -0
- package/dist/dashboard/web/overview.js.map +1 -1
- package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-kanban.js +2 -0
- package/dist/dashboard/web/sessions-kanban.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +103 -2
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +3 -2
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/ui.d.ts +8 -0
- package/dist/dashboard/web/ui.d.ts.map +1 -1
- package/dist/dashboard/web/ui.js +15 -0
- package/dist/dashboard/web/ui.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-GED4FEMS.js +10 -0
- package/dist/dashboard-web/chunks/chunk-6J5LS5AU.js +51 -0
- package/dist/dashboard-web/chunks/{chunk-ZU3UUKAR.js → chunk-HK7NIBJG.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-3UE7S77S.js → chunk-KRHWZEXU.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-VBXJOJFH.js +1 -0
- package/dist/dashboard-web/chunks/connectors-page-EELM66G3.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-WKUV6E42.js +8 -0
- package/dist/dashboard-web/chunks/{insights-page-T2ZX2RWL.js → insights-page-54UBPPOC.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-YNVBAGR6.js → monitor-room-PORHVKRH.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-LHM55YWN.js → monitoring-page-XGA7AXNL.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-ATXVP7PW.js → office-page-AO3AFG45.js} +1 -1
- package/dist/dashboard-web/chunks/overview-page-F5BUTYR6.js +1 -0
- package/dist/dashboard-web/chunks/{roles-page-56VWM6CD.js → roles-page-M5GIASJU.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-S5K6U4EO.js → schedules-page-O232WQRR.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-YFRPSTIL.js +6 -0
- package/dist/dashboard-web/chunks/{settings-page-QUZDQARR.js → settings-page-OJAZLZQT.js} +1 -1
- package/dist/dashboard-web/chunks/{skills-page-IFY7AEND.js → skills-page-EFZQPWV4.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-C7FJQPFZ.js → team-federation-page-ZJVAP7HW.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-2LMF3WWR.js → v3-page-GYWTRGO2.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-3XC6QRMY.js → whiteboards-page-MSDAG6P7.js} +1 -1
- package/dist/dashboard-web/style.css +255 -0
- package/dist/dashboard.js +172 -7
- package/dist/dashboard.js.map +1 -1
- package/dist/desktop/renderer/app.js +21 -0
- package/dist/desktop/renderer/app.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +35 -9
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +35 -9
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/ask-card.d.ts +23 -0
- package/dist/im/lark/ask-card.d.ts.map +1 -1
- package/dist/im/lark/ask-card.js +94 -4
- package/dist/im/lark/ask-card.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +6 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +112 -15
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +496 -310
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +7 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +39 -26
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/doc-comment.d.ts +7 -4
- package/dist/im/lark/doc-comment.d.ts.map +1 -1
- package/dist/im/lark/doc-comment.js +19 -6
- package/dist/im/lark/doc-comment.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +16 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +88 -23
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/forward-followup-content.d.ts.map +1 -1
- package/dist/im/lark/forward-followup-content.js +9 -1
- package/dist/im/lark/forward-followup-content.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts.map +1 -1
- package/dist/im/lark/grant-command.js +7 -4
- package/dist/im/lark/grant-command.js.map +1 -1
- package/dist/im/lark/md-card.d.ts +11 -0
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +46 -0
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts +23 -2
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +58 -3
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/overview-card.d.ts.map +1 -1
- package/dist/im/lark/overview-card.js +2 -1
- package/dist/im/lark/overview-card.js.map +1 -1
- package/dist/services/async-trigger-state.d.ts +6 -1
- package/dist/services/async-trigger-state.d.ts.map +1 -1
- package/dist/services/async-trigger-state.js +21 -0
- package/dist/services/async-trigger-state.js.map +1 -1
- package/dist/services/async-trigger-store.d.ts +23 -1
- package/dist/services/async-trigger-store.d.ts.map +1 -1
- package/dist/services/async-trigger-store.js +96 -13
- package/dist/services/async-trigger-store.js.map +1 -1
- package/dist/services/bridge-fallback-gate.d.ts +40 -0
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +124 -24
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/codex-app-runner-protocol.d.ts +8 -0
- package/dist/services/codex-app-runner-protocol.d.ts.map +1 -1
- package/dist/services/codex-app-runner-protocol.js +9 -2
- package/dist/services/codex-app-runner-protocol.js.map +1 -1
- package/dist/services/codex-bridge-queue.d.ts +1 -0
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +1 -0
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-service-tier.d.ts +2 -0
- package/dist/services/codex-service-tier.d.ts.map +1 -1
- package/dist/services/codex-service-tier.js +1 -0
- package/dist/services/codex-service-tier.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +27 -0
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js +340 -2
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/grant-policy.d.ts +3 -0
- package/dist/services/grant-policy.d.ts.map +1 -1
- package/dist/services/grant-policy.js +5 -0
- package/dist/services/grant-policy.js.map +1 -1
- package/dist/services/grant-prefs-store.d.ts +6 -3
- package/dist/services/grant-prefs-store.d.ts.map +1 -1
- package/dist/services/grant-prefs-store.js +42 -12
- package/dist/services/grant-prefs-store.js.map +1 -1
- package/dist/services/hook-runner.d.ts +20 -1
- package/dist/services/hook-runner.d.ts.map +1 -1
- package/dist/services/hook-runner.js +17 -13
- package/dist/services/hook-runner.js.map +1 -1
- package/dist/services/idempotency-store.d.ts +134 -0
- package/dist/services/idempotency-store.d.ts.map +1 -0
- package/dist/services/idempotency-store.js +299 -0
- package/dist/services/idempotency-store.js.map +1 -0
- package/dist/services/jsonl-cursor.d.ts +7 -3
- package/dist/services/jsonl-cursor.d.ts.map +1 -1
- package/dist/services/jsonl-cursor.js +55 -31
- package/dist/services/jsonl-cursor.js.map +1 -1
- package/dist/services/open-platform-rename.d.ts.map +1 -1
- package/dist/services/open-platform-rename.js +1 -108
- package/dist/services/open-platform-rename.js.map +1 -1
- package/dist/services/restart-intent-store.d.ts +22 -2
- package/dist/services/restart-intent-store.d.ts.map +1 -1
- package/dist/services/restart-intent-store.js +160 -18
- package/dist/services/restart-intent-store.js.map +1 -1
- package/dist/services/sandbox-store.d.ts +22 -0
- package/dist/services/sandbox-store.d.ts.map +1 -1
- package/dist/services/sandbox-store.js +37 -8
- package/dist/services/sandbox-store.js.map +1 -1
- package/dist/services/send-policy.d.ts +41 -33
- package/dist/services/send-policy.d.ts.map +1 -1
- package/dist/services/send-policy.js +39 -40
- package/dist/services/send-policy.js.map +1 -1
- package/dist/services/session-store.d.ts +66 -0
- package/dist/services/session-store.d.ts.map +1 -1
- package/dist/services/session-store.js +403 -67
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/submit-notification.d.ts +3 -0
- package/dist/services/submit-notification.d.ts.map +1 -0
- package/dist/services/submit-notification.js +15 -0
- package/dist/services/submit-notification.js.map +1 -0
- package/dist/services/traex-transcript.d.ts +25 -2
- package/dist/services/traex-transcript.d.ts.map +1 -1
- package/dist/services/traex-transcript.js +133 -1
- package/dist/services/traex-transcript.js.map +1 -1
- package/dist/services/trigger-types.d.ts +13 -1
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/trigger-types.js +39 -0
- package/dist/services/trigger-types.js.map +1 -1
- package/dist/services/voice/index.d.ts +3 -2
- package/dist/services/voice/index.d.ts.map +1 -1
- package/dist/services/voice/index.js +5 -5
- package/dist/services/voice/index.js.map +1 -1
- package/dist/services/voice/openai.d.ts +2 -1
- package/dist/services/voice/openai.d.ts.map +1 -1
- package/dist/services/voice/openai.js +2 -1
- package/dist/services/voice/openai.js.map +1 -1
- package/dist/services/voice/sami.d.ts +5 -2
- package/dist/services/voice/sami.d.ts.map +1 -1
- package/dist/services/voice/sami.js +19 -4
- package/dist/services/voice/sami.js.map +1 -1
- package/dist/setup/bots-store.d.ts.map +1 -1
- package/dist/setup/bots-store.js +10 -4
- package/dist/setup/bots-store.js.map +1 -1
- package/dist/setup/lark-scopes.json +2 -0
- package/dist/setup/open-platform-automation.d.ts +9 -1
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +44 -15
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/setup/open-platform-visibility.d.ts +42 -0
- package/dist/setup/open-platform-visibility.d.ts.map +1 -0
- package/dist/setup/open-platform-visibility.js +133 -0
- package/dist/setup/open-platform-visibility.js.map +1 -0
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +6 -0
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/skills/definitions.js +2 -2
- package/dist/types.d.ts +290 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/bot-routing.d.ts +1 -0
- package/dist/utils/bot-routing.d.ts.map +1 -1
- package/dist/utils/bot-routing.js +1 -1
- package/dist/utils/bot-routing.js.map +1 -1
- package/dist/utils/child-env.d.ts +1 -1
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +9 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/codex-app-control.d.ts +438 -0
- package/dist/utils/codex-app-control.d.ts.map +1 -0
- package/dist/utils/codex-app-control.js +2336 -0
- package/dist/utils/codex-app-control.js.map +1 -0
- package/dist/utils/codex-app-dispatch-ledger.d.ts +78 -0
- package/dist/utils/codex-app-dispatch-ledger.d.ts.map +1 -0
- package/dist/utils/codex-app-dispatch-ledger.js +149 -0
- package/dist/utils/codex-app-dispatch-ledger.js.map +1 -0
- package/dist/utils/codex-app-turn-dispatch.d.ts +77 -0
- package/dist/utils/codex-app-turn-dispatch.d.ts.map +1 -0
- package/dist/utils/codex-app-turn-dispatch.js +141 -0
- package/dist/utils/codex-app-turn-dispatch.js.map +1 -0
- package/dist/utils/codex-app-turn-liveness.d.ts +125 -0
- package/dist/utils/codex-app-turn-liveness.d.ts.map +1 -0
- package/dist/utils/codex-app-turn-liveness.js +301 -0
- package/dist/utils/codex-app-turn-liveness.js.map +1 -0
- package/dist/utils/idle-detector.d.ts +12 -0
- package/dist/utils/idle-detector.d.ts.map +1 -1
- package/dist/utils/idle-detector.js +19 -0
- package/dist/utils/idle-detector.js.map +1 -1
- package/dist/utils/input-gate.d.ts +87 -0
- package/dist/utils/input-gate.d.ts.map +1 -1
- package/dist/utils/input-gate.js +86 -0
- package/dist/utils/input-gate.js.map +1 -1
- package/dist/utils/lark-upload.d.ts.map +1 -1
- package/dist/utils/lark-upload.js +52 -1
- package/dist/utils/lark-upload.js.map +1 -1
- package/dist/utils/pending-input-queue.d.ts +15 -0
- package/dist/utils/pending-input-queue.d.ts.map +1 -1
- package/dist/utils/pending-input-queue.js +5 -1
- package/dist/utils/pending-input-queue.js.map +1 -1
- package/dist/utils/user-token.d.ts.map +1 -1
- package/dist/utils/user-token.js +53 -2
- package/dist/utils/user-token.js.map +1 -1
- package/dist/worker-ipc-preload.d.ts +12 -0
- package/dist/worker-ipc-preload.d.ts.map +1 -0
- package/dist/worker-ipc-preload.js +44 -0
- package/dist/worker-ipc-preload.js.map +1 -0
- package/dist/worker.js +2604 -325
- package/dist/worker.js.map +1 -1
- package/dist/workflows/v3/session-relay-client.d.ts +1 -0
- package/dist/workflows/v3/session-relay-client.d.ts.map +1 -1
- package/dist/workflows/v3/session-relay-client.js +12 -3
- package/dist/workflows/v3/session-relay-client.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-LTVOUDIS.js +0 -10
- package/dist/dashboard-web/chunks/chunk-DCS35UMD.js +0 -1
- package/dist/dashboard-web/chunks/chunk-MFQPCVHY.js +0 -51
- package/dist/dashboard-web/chunks/connectors-page-5KWDIMKC.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-FHOKYXMW.js +0 -8
- package/dist/dashboard-web/chunks/overview-page-QYI3KBDD.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-WBP4N7D2.js +0 -6
|
@@ -14,7 +14,7 @@ import * as scheduler from './scheduler.js';
|
|
|
14
14
|
import { scanMultipleProjects, describeProjectDir } from '../services/project-scanner.js';
|
|
15
15
|
import { createRepoWorktree, pushWorktreeBranch } from '../services/git-worktree.js';
|
|
16
16
|
import { worktreeSlugFromContextAI } from '../services/worktree-slug-ai.js';
|
|
17
|
-
import { resolvePairedSpawnBackendType } from './persistent-backend.js';
|
|
17
|
+
import { isRiffBackendSession, resolvePairedSpawnBackendType } from './persistent-backend.js';
|
|
18
18
|
import { buildRepoSelectCard, buildAdoptSelectCard, buildCodexAppThreadSelectCard, buildSlashListCard, getCliDisplayName, buildConfigCard, buildForkPanelCard, buildAdoptBlockedCard } from '../im/lark/card-builder.js';
|
|
19
19
|
import { handleDashboardCommand } from './dashboard-command/index.js';
|
|
20
20
|
import { createCliAdapterSync } from '../adapters/cli/registry.js';
|
|
@@ -24,8 +24,8 @@ import { chatAppLink, threadAppLink, normalizeBrand } from '../im/lark/lark-host
|
|
|
24
24
|
import { claimPairing } from '../services/pairing-store.js';
|
|
25
25
|
import { logger } from '../utils/logger.js';
|
|
26
26
|
import { scheduleTimeZone } from '../utils/timezone.js';
|
|
27
|
-
import {
|
|
28
|
-
import { expandHome, getSessionWorkingDir, getProjectScanDirs, rememberLastCliInput, buildNewTopicCliInput,
|
|
27
|
+
import { killWorker, teardownAuthoritativePersistentBackingBeforeClose, suspendWorker, forkWorker, forkAdoptWorker, adoptSandboxBlocked, getCurrentCliVersion, postFreshStreamingCard, postPrivateSnapshotCard, resolvePrivateCardAudience, deliverEphemeralOrReply, deliverWritableTerminalCardTo, closeSession as closeWorkerPoolSession, withActiveSessionKeyLock, requestSessionRestart, isSessionTransferring } from './worker-pool.js';
|
|
28
|
+
import { expandHome, getSessionWorkingDir, getProjectScanDirs, rememberLastCliInput, buildNewTopicCliInput, getAvailableBots, } from './session-manager.js';
|
|
29
29
|
import { markInitialUserTurnPending } from './initial-user-turn.js';
|
|
30
30
|
import { discoverSlashCommandsForAdapter, listMcpServerNames, supportsFilesystemCommandDiscovery } from './command-discovery.js';
|
|
31
31
|
import { validateWorkingDir } from './working-dir.js';
|
|
@@ -45,7 +45,7 @@ import { CONFIG_FIELDS, findConfigField, settableFieldKeys, parseBooleanValue, a
|
|
|
45
45
|
import { resolveCliId, findInvalidAllowedUserEntries } from '../setup/bot-config-editor.js';
|
|
46
46
|
import { buildClosedSessionCard } from './closed-session-card.js';
|
|
47
47
|
import { ttadkConfigModelChoices } from '../setup/cli-selection.js';
|
|
48
|
-
import { publishAttentionPatch,
|
|
48
|
+
import { publishAttentionPatch, announcePendingRepoSession } from './session-activity.js';
|
|
49
49
|
import { setCardMode } from '../services/card-mode-store.js';
|
|
50
50
|
import { canOperate } from '../im/lark/event-dispatcher.js';
|
|
51
51
|
import { buildSafeInsightReport } from '../services/insight/report.js';
|
|
@@ -53,12 +53,14 @@ import { invalidWorkingDirs } from '../utils/working-dir.js';
|
|
|
53
53
|
import { writeRoleFile, deleteRoleFile, resolveRole, resolveRoleFile, resolveTeamRoleFile, writeTeamRoleFile, deleteTeamRoleFile, MAX_ROLE_BYTES } from './role-resolver.js';
|
|
54
54
|
import { getBotCapability, setBotCapability, clearBotCapability } from '../services/bot-profile-store.js';
|
|
55
55
|
import { deleteRoleProfileEntry, deleteRoleProfileIfEmpty, isValidRoleProfileId, listRoleProfileEntries, listRoleProfiles, MAX_ROLE_PROFILE_ENTRY_BYTES, readRoleProfileEntry, writeRoleProfileEntry, } from '../services/role-profile-store.js';
|
|
56
|
-
import { sessionKey, sessionAnchorId, markRepoCardConsumed
|
|
56
|
+
import { activeSessionKey, sessionKey, sessionAnchorId, markRepoCardConsumed } from './types.js';
|
|
57
57
|
import { t, localeForBot } from '../i18n/index.js';
|
|
58
58
|
import { runSkillsImCommand } from './skills/im-command.js';
|
|
59
59
|
import { fetchDaemonIpc } from './daemon-ipc-auth.js';
|
|
60
60
|
import { updateSessionTitle } from './session-title.js';
|
|
61
61
|
import { requestAgentSessionRename } from './session-rename.js';
|
|
62
|
+
import { hasProtectedSessionMutationOwnership } from './session-mutation-guard.js';
|
|
63
|
+
import { withBotTurnMutation } from './bot-turn-mutation-gate.js';
|
|
62
64
|
import { configuredRuntimeDisplayName, sessionConfiguredRuntimeDisplayName, } from './cli-runtime-display.js';
|
|
63
65
|
// ─── Exported constants ──────────────────────────────────────────────────────
|
|
64
66
|
// DAEMON_COMMANDS / PASSTHROUGH_COMMANDS / normalizePassthroughCommand now live
|
|
@@ -1218,24 +1220,43 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1218
1220
|
switch (cmd) {
|
|
1219
1221
|
case '/close': {
|
|
1220
1222
|
if (ds) {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1223
|
+
const targetSessionId = ds.session.sessionId;
|
|
1224
|
+
const closed = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
1225
|
+
// Re-resolve the exact session after all peer admissions drain. A
|
|
1226
|
+
// relay may have moved it to another key while this command was
|
|
1227
|
+
// admitted; closeSession removes its current identity, never the
|
|
1228
|
+
// stale root key from this message.
|
|
1229
|
+
const current = [...activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId);
|
|
1230
|
+
if (!current)
|
|
1231
|
+
return undefined;
|
|
1232
|
+
// Capture the closed-session card BEFORE closeWorkerPoolSession —
|
|
1233
|
+
// it reads the live session's identity off `current`.
|
|
1234
|
+
const card = buildClosedSessionCard(current, localeForBot(current.larkAppId));
|
|
1235
|
+
try {
|
|
1236
|
+
// closeWorkerPoolSession proves fail-closed backing teardown
|
|
1237
|
+
// before mutating any registry/store state, throwing when it
|
|
1238
|
+
// cannot verify it. Surface that so the active record is kept
|
|
1239
|
+
// for retry instead of being silently dropped.
|
|
1240
|
+
await closeWorkerPoolSession(targetSessionId);
|
|
1241
|
+
}
|
|
1242
|
+
catch (err) {
|
|
1243
|
+
return { status: 'teardown_failed', err };
|
|
1244
|
+
}
|
|
1245
|
+
return { status: 'closed', current, card };
|
|
1246
|
+
});
|
|
1247
|
+
if (!closed) {
|
|
1248
|
+
await sessionReply(rootId, t('cmd.no_active_session', undefined, loc));
|
|
1249
|
+
break;
|
|
1227
1250
|
}
|
|
1228
|
-
|
|
1229
|
-
logger.error(`[${logTag}] Refused /close because backing teardown was not verified: ${err}`);
|
|
1230
|
-
await sessionReply(rootId, `⚠️ 会话关闭失败,已保留 active 记录以便重试:${err instanceof Error ? err.message : String(err)}`);
|
|
1251
|
+
if (closed.status === 'teardown_failed') {
|
|
1252
|
+
logger.error(`[${logTag}] Refused /close because backing teardown was not verified: ${closed.err}`);
|
|
1253
|
+
await sessionReply(rootId, `⚠️ 会话关闭失败,已保留 active 记录以便重试:${closed.err instanceof Error ? closed.err.message : String(closed.err)}`);
|
|
1231
1254
|
break;
|
|
1232
1255
|
}
|
|
1233
|
-
if (activeSessions.get(activeKey) === ds)
|
|
1234
|
-
activeSessions.delete(activeKey);
|
|
1235
1256
|
// 「会话已关闭」卡片优先「仅自己可见」:普通群里走 ephemeral 只发给执行
|
|
1236
1257
|
// /close 的本人;话题群不支持 ephemeral(18053) 时回退为正常的群内可见回复
|
|
1237
1258
|
// ——与流式卡片上「关闭会话」按钮的送达方式保持一致。
|
|
1238
|
-
await deliverEphemeralOrReply(
|
|
1259
|
+
await deliverEphemeralOrReply(closed.current, message.senderId, closed.card, 'interactive', () => sessionReply(rootId, closed.card, 'interactive'));
|
|
1239
1260
|
logger.info(`[${logTag}] Session closed by /close command`);
|
|
1240
1261
|
}
|
|
1241
1262
|
else {
|
|
@@ -1280,10 +1301,17 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1280
1301
|
break;
|
|
1281
1302
|
}
|
|
1282
1303
|
const closedSessionId = ds.session.sessionId;
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1304
|
+
const detached = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
1305
|
+
const current = [...activeSessions.values()].find(candidate => candidate.session.sessionId === closedSessionId);
|
|
1306
|
+
if (!current || !current.adoptedFrom)
|
|
1307
|
+
return false;
|
|
1308
|
+
await closeWorkerPoolSession(closedSessionId);
|
|
1309
|
+
return true;
|
|
1310
|
+
});
|
|
1311
|
+
if (!detached) {
|
|
1312
|
+
await sessionReply(rootId, t('cmd.no_active_session', undefined, loc));
|
|
1313
|
+
break;
|
|
1314
|
+
}
|
|
1287
1315
|
await sessionReply(rootId, t('cmd.detach.success', undefined, loc));
|
|
1288
1316
|
logger.info(`[${logTag}] Detached (adopt) by ${cmd} command`);
|
|
1289
1317
|
break;
|
|
@@ -1294,6 +1322,19 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1294
1322
|
await sessionReply(rootId, t('card.action.adopt_no_restart', undefined, loc));
|
|
1295
1323
|
break;
|
|
1296
1324
|
}
|
|
1325
|
+
if (isRiffBackendSession(ds)) {
|
|
1326
|
+
logger.info(`[${logTag}] Rejected /restart for Riff backend session`);
|
|
1327
|
+
await sessionReply(rootId, t('cmd.restart.riff_unsupported', undefined, loc));
|
|
1328
|
+
break;
|
|
1329
|
+
}
|
|
1330
|
+
// Codex App: an accepted-but-unsettled dispatch still owns the turn
|
|
1331
|
+
// route. requestSessionRestart does not itself gate on dispatch
|
|
1332
|
+
// ownership, so reject here before the coordinator tears the worker
|
|
1333
|
+
// down (mirrors the card-handler restart path).
|
|
1334
|
+
if (hasProtectedSessionMutationOwnership(ds)) {
|
|
1335
|
+
await sessionReply(rootId, '当前 Codex App 仍有未结算消息,暂不能重启;请等待本轮完成或关闭会话。');
|
|
1336
|
+
break;
|
|
1337
|
+
}
|
|
1297
1338
|
if (isSessionTransferring(ds)) {
|
|
1298
1339
|
await sessionReply(rootId, t('cmd.session.transfer_in_progress', undefined, loc));
|
|
1299
1340
|
break;
|
|
@@ -1326,22 +1367,55 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1326
1367
|
await sessionReply(rootId, t('cmd.session.transfer_in_progress', undefined, loc));
|
|
1327
1368
|
break;
|
|
1328
1369
|
}
|
|
1370
|
+
// A live Riff worker owns a remote task rooted in its original cwd.
|
|
1371
|
+
// killWorker/restart deliberately refuse to replace that generation,
|
|
1372
|
+
// so persisting a new cwd here would report success while the remote
|
|
1373
|
+
// task keeps running in the old directory.
|
|
1374
|
+
if (isRiffBackendSession(ds)) {
|
|
1375
|
+
await sessionReply(rootId, t('cmd.cd.riff_unsupported', undefined, loc));
|
|
1376
|
+
break;
|
|
1377
|
+
}
|
|
1378
|
+
// Cheap preflight avoids creating a requested directory when the
|
|
1379
|
+
// current FIFO already makes the switch impossible. The mutation
|
|
1380
|
+
// below repeats this check after draining peer admissions.
|
|
1381
|
+
if (hasProtectedSessionMutationOwnership(ds)) {
|
|
1382
|
+
await sessionReply(rootId, '当前 Codex App 仍有未结算消息,暂不能切换工作目录;请等待本轮完成或关闭会话。');
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1329
1385
|
const validation = validateWorkingDir(targetPath, loc, { autoCreate: true });
|
|
1330
1386
|
if (!validation.ok) {
|
|
1331
1387
|
await sessionReply(rootId, validation.error);
|
|
1332
1388
|
break;
|
|
1333
1389
|
}
|
|
1334
1390
|
const resolvedPath = validation.resolvedPath;
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1391
|
+
const targetSessionId = ds.session.sessionId;
|
|
1392
|
+
const switched = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
1393
|
+
const current = [...activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId
|
|
1394
|
+
&& candidate.session.status === 'active');
|
|
1395
|
+
if (!current)
|
|
1396
|
+
return 'gone';
|
|
1397
|
+
if (hasProtectedSessionMutationOwnership(current)) {
|
|
1398
|
+
return 'pending';
|
|
1399
|
+
}
|
|
1400
|
+
const suspended = !current.adoptedFrom
|
|
1401
|
+
&& suspendWorker(current, 'working_dir_changed');
|
|
1402
|
+
if (!suspended)
|
|
1403
|
+
killWorker(current);
|
|
1404
|
+
repinSessionWorkingDir(current, resolvedPath);
|
|
1405
|
+
// cwd 变了,riff 多仓 stamp(选择卡多选时写入)随之失效——保留会让下次
|
|
1406
|
+
// refork 仍按旧仓库组合推导、无视新目录。
|
|
1407
|
+
current.session.riffRepoDirs = undefined;
|
|
1408
|
+
sessionStore.updateSession(current.session);
|
|
1409
|
+
return 'switched';
|
|
1410
|
+
});
|
|
1411
|
+
if (switched === 'pending') {
|
|
1412
|
+
await sessionReply(rootId, '当前 Codex App 仍有未结算消息,暂不能切换工作目录;请等待本轮完成或关闭会话。');
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
if (switched === 'gone') {
|
|
1416
|
+
await sessionReply(rootId, t('cmd.no_active_session', undefined, loc));
|
|
1417
|
+
break;
|
|
1418
|
+
}
|
|
1345
1419
|
if (validation.created) {
|
|
1346
1420
|
await sessionReply(rootId, t('cmd.cd.created_switched', { path: resolvedPath }, loc));
|
|
1347
1421
|
}
|
|
@@ -1385,148 +1459,156 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1385
1459
|
break;
|
|
1386
1460
|
}
|
|
1387
1461
|
case '/repo': {
|
|
1462
|
+
// A live Riff generation must finish the explicit /close protocol before
|
|
1463
|
+
// its anchor can be reused. The generic repo-switch path closes and
|
|
1464
|
+
// immediately reforks; if remote cancellation fails, that would fall
|
|
1465
|
+
// through to the double-fork kill and orphan the remote task.
|
|
1466
|
+
if (ds && !ds.pendingRepo && isRiffBackendSession(ds)) {
|
|
1467
|
+
await sessionReply(rootId, t('cmd.cd.riff_unsupported', undefined, loc));
|
|
1468
|
+
logger.warn(`[${logTag}] Repo switch refused: Riff session requires explicit close before replacement`);
|
|
1469
|
+
break;
|
|
1470
|
+
}
|
|
1388
1471
|
const repoArg = message.content.replace(/^\/repo\s*/, '').trim();
|
|
1472
|
+
if (ds && !ds.pendingRepo
|
|
1473
|
+
&& hasProtectedSessionMutationOwnership(ds)) {
|
|
1474
|
+
await sessionReply(rootId, '当前 Codex App 仍有未结算消息,暂不能切换仓库;请等待本轮完成或关闭会话。');
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1389
1477
|
// First-spawn fork: consume the buffered prompt/attachments and start the
|
|
1390
1478
|
// CLI in whatever workingDir is currently set on the session. Shared by
|
|
1391
1479
|
// `commitRepoSelection` (a repo was named) and the bare-`/repo` launch
|
|
1392
1480
|
// (use the default workingDir) — both only run while `pendingRepo`.
|
|
1393
|
-
const forkPendingCli = async (replyText,
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1481
|
+
const forkPendingCli = async (replyText, selection) => {
|
|
1482
|
+
const targetSessionId = ds.session.sessionId;
|
|
1483
|
+
const started = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
1484
|
+
const current = [...activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId
|
|
1485
|
+
&& candidate.session.status === 'active');
|
|
1486
|
+
if (!current || current !== ds || !current.pendingRepo)
|
|
1397
1487
|
return false;
|
|
1488
|
+
if (selection) {
|
|
1489
|
+
current.workingDir = selection.path;
|
|
1490
|
+
current.session.workingDir = selection.path;
|
|
1491
|
+
current.session.riffRepoDirs = selection.riffRepoDirs;
|
|
1492
|
+
sessionStore.updateSession(current.session);
|
|
1398
1493
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
(
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
return false;
|
|
1421
|
-
}
|
|
1422
|
-
const pendingPrompt = ds.pendingPrompt ?? '';
|
|
1423
|
-
const pendingRawInput = ds.pendingRawInput;
|
|
1424
|
-
const hasBufferedInput = pendingPrompt.trim().length > 0 ||
|
|
1425
|
-
(ds.pendingAttachments?.length ?? 0) > 0 ||
|
|
1426
|
-
(ds.pendingFollowUps?.length ?? 0) > 0 ||
|
|
1427
|
-
ds.pendingChatContext !== undefined;
|
|
1428
|
-
// Nothing to submit at all (bare `/repo`: the message IS the command).
|
|
1429
|
-
// The CLI boots idle, so the user's NEXT real message is its first
|
|
1430
|
-
// turn and must carry the full new-topic opening — see
|
|
1431
|
-
// markInitialUserTurnPending below.
|
|
1432
|
-
const emptyStart = !pendingRawInput && !hasBufferedInput;
|
|
1433
|
-
if (hasBufferedInput)
|
|
1434
|
-
ensureSessionWhiteboard(ds);
|
|
1435
|
-
const wrappedInput = hasBufferedInput
|
|
1436
|
-
? buildNewTopicCliInput(pendingPrompt, ds.session.sessionId, ds.session.cliId ?? botCfg.cliId, ds.session.cliPathOverride ?? botCfg.cliPathOverride, ds.pendingAttachments, ds.pendingMentions, availableBots, ds.pendingFollowUps, { name: selfBot.botName, openId: selfBot.botOpenId }, loc, ds.pendingSender, {
|
|
1494
|
+
const selfBot = getBot(current.larkAppId);
|
|
1495
|
+
const botCfg = selfBot.config;
|
|
1496
|
+
const pendingPrompt = current.pendingPrompt ?? '';
|
|
1497
|
+
const pendingRawInput = current.pendingRawInput;
|
|
1498
|
+
const hasBufferedInput = pendingPrompt.trim().length > 0
|
|
1499
|
+
|| current.pendingCodexAppText !== undefined
|
|
1500
|
+
|| (current.pendingAttachments?.length ?? 0) > 0
|
|
1501
|
+
|| (current.pendingFollowUps?.length ?? 0) > 0
|
|
1502
|
+
|| current.pendingChatContext !== undefined;
|
|
1503
|
+
let wrappedInput;
|
|
1504
|
+
if (hasBufferedInput) {
|
|
1505
|
+
const { buildNewTopicCliInput: buildInput, ensureSessionWhiteboard, getAvailableBots } = await import('./session-manager.js');
|
|
1506
|
+
ensureSessionWhiteboard(current);
|
|
1507
|
+
const availableBots = await getAvailableBots(current.larkAppId, current.chatId);
|
|
1508
|
+
// Detached lifecycle work can still close/replace while the
|
|
1509
|
+
// roster lookup awaits. Never fork the captured generation.
|
|
1510
|
+
if (current.session.status !== 'active'
|
|
1511
|
+
|| [...activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId) !== current
|
|
1512
|
+
|| !current.pendingRepo)
|
|
1513
|
+
return false;
|
|
1514
|
+
wrappedInput = buildInput(pendingPrompt, current.session.sessionId, current.session.cliId ?? botCfg.cliId, current.session.cliPathOverride ?? botCfg.cliPathOverride, current.pendingAttachments, current.pendingMentions, availableBots, current.pendingFollowUps, { name: selfBot.botName, openId: selfBot.botOpenId }, loc, current.pendingSender, {
|
|
1437
1515
|
larkAppId,
|
|
1438
|
-
chatId:
|
|
1439
|
-
whiteboardId:
|
|
1440
|
-
substituteTrigger:
|
|
1441
|
-
codexAppText:
|
|
1442
|
-
codexAppApplicationContext:
|
|
1443
|
-
codexAppMessageContext:
|
|
1444
|
-
codexAppFollowUps:
|
|
1445
|
-
codexAppFollowUpContexts:
|
|
1446
|
-
chatContext:
|
|
1447
|
-
})
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
? [ds.pendingCodexAppText ?? '', ...(ds.pendingCodexAppFollowUps ?? [])].filter(Boolean).join('\n\n')
|
|
1455
|
-
: pendingPrompt || ds.pendingFollowUps?.join('\n\n') || '',
|
|
1516
|
+
chatId: current.chatId,
|
|
1517
|
+
whiteboardId: current.session.whiteboardId,
|
|
1518
|
+
substituteTrigger: current.pendingSubstituteTrigger,
|
|
1519
|
+
codexAppText: current.pendingCodexAppText,
|
|
1520
|
+
codexAppApplicationContext: current.pendingCodexAppApplicationContext,
|
|
1521
|
+
codexAppMessageContext: current.pendingCodexAppMessageContext,
|
|
1522
|
+
codexAppFollowUps: current.pendingCodexAppFollowUps,
|
|
1523
|
+
codexAppFollowUpContexts: current.pendingCodexAppFollowUpContexts,
|
|
1524
|
+
chatContext: current.pendingChatContext,
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
if (pendingRawInput && hasBufferedInput && wrappedInput) {
|
|
1528
|
+
current.pendingFollowUpInput = {
|
|
1529
|
+
userPrompt: current.pendingCodexAppText !== undefined || current.pendingCodexAppFollowUps
|
|
1530
|
+
? [current.pendingCodexAppText ?? '', ...(current.pendingCodexAppFollowUps ?? [])].filter(Boolean).join('\n\n')
|
|
1531
|
+
: pendingPrompt || current.pendingFollowUps?.join('\n\n') || '',
|
|
1456
1532
|
cliInput: wrappedInput.content,
|
|
1457
|
-
...(
|
|
1458
|
-
|
|
1533
|
+
...((current.pendingFollowUpTurnIds?.at(-1) ?? current.pendingFollowUpTurnId)
|
|
1534
|
+
? { turnId: current.pendingFollowUpTurnIds?.at(-1) ?? current.pendingFollowUpTurnId }
|
|
1535
|
+
: {}),
|
|
1536
|
+
...((current.session.cliId ?? botCfg.cliId) === 'codex-app' && botCfg.codexAppCleanInput === true && wrappedInput.codexAppInput
|
|
1459
1537
|
? { codexAppInput: wrappedInput.codexAppInput }
|
|
1460
1538
|
: {}),
|
|
1461
1539
|
codexAppInputGateFrozen: true,
|
|
1462
1540
|
};
|
|
1463
1541
|
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
//
|
|
1487
|
-
//
|
|
1488
|
-
//
|
|
1542
|
+
if (pendingRawInput)
|
|
1543
|
+
rememberLastCliInput(current, pendingRawInput, pendingRawInput);
|
|
1544
|
+
else if (hasBufferedInput && wrappedInput)
|
|
1545
|
+
rememberLastCliInput(current, pendingPrompt, wrappedInput);
|
|
1546
|
+
// forkWorker performs the synchronous pre-accept/write-ahead work.
|
|
1547
|
+
// Keep the opening reservation and every buffered field intact if
|
|
1548
|
+
// that step throws, so a failed launch cannot silently consume the
|
|
1549
|
+
// first user turn or expose this worker:null owner as scratch.
|
|
1550
|
+
const pendingTurnId = current.pendingTurnId
|
|
1551
|
+
?? current.session.pendingRepoSetup?.turnId;
|
|
1552
|
+
// Nothing to submit at all (bare `/repo`: the message IS the
|
|
1553
|
+
// command). The CLI boots idle, so the user's NEXT real message is
|
|
1554
|
+
// its first turn and must carry the full new-topic opening — see
|
|
1555
|
+
// markInitialUserTurnPending below.
|
|
1556
|
+
const emptyStart = !pendingRawInput && !hasBufferedInput;
|
|
1557
|
+
forkWorker(current, pendingRawInput ? '' : (wrappedInput ?? ''), !pendingRawInput && pendingTurnId ? { turnId: pendingTurnId } : false);
|
|
1558
|
+
current.pendingRepo = false;
|
|
1559
|
+
current.pendingRepoCommitInFlight = true;
|
|
1560
|
+
// Queued activation ownership lasts through adapter submission.
|
|
1561
|
+
// These source buffers were folded into opening N; clear them but
|
|
1562
|
+
// keep the gate so later inbounds enter the exact post-ACK FIFO.
|
|
1563
|
+
current.initialStartPending = current.session.queuedActivationPending === true;
|
|
1564
|
+
// Durable, one-shot: an empty-started CLI has never received a real
|
|
1565
|
+
// user turn, so the next business message must be built as a NEW
|
|
1566
|
+
// TOPIC (routing + built-in skill discovery + identity), not a
|
|
1567
|
+
// follow-up. Set after the fork so a throwing fork leaves it clean.
|
|
1489
1568
|
if (emptyStart)
|
|
1490
|
-
markInitialUserTurnPending(
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1569
|
+
markInitialUserTurnPending(current);
|
|
1570
|
+
publishAttentionPatch(current);
|
|
1571
|
+
current.pendingPrompt = undefined;
|
|
1572
|
+
current.pendingCodexAppText = undefined;
|
|
1573
|
+
current.pendingCodexAppApplicationContext = undefined;
|
|
1574
|
+
current.pendingCodexAppMessageContext = undefined;
|
|
1575
|
+
current.pendingChatContext = undefined;
|
|
1576
|
+
current.pendingAttachments = undefined;
|
|
1577
|
+
current.pendingMentions = undefined;
|
|
1578
|
+
current.pendingSubstituteTrigger = undefined;
|
|
1579
|
+
current.pendingSender = undefined;
|
|
1580
|
+
current.pendingFollowUps = undefined;
|
|
1581
|
+
current.pendingFollowUpTurnId = undefined;
|
|
1582
|
+
current.pendingFollowUpTurnIds = undefined;
|
|
1583
|
+
current.pendingCodexAppFollowUps = undefined;
|
|
1584
|
+
current.pendingCodexAppFollowUpContexts = undefined;
|
|
1585
|
+
current.pendingCodexAppFollowUpGateAccepted = undefined;
|
|
1586
|
+
current.pendingTurnId = undefined;
|
|
1587
|
+
const cardToWithdraw = current.repoCardMessageId;
|
|
1588
|
+
markRepoCardConsumed(current, cardToWithdraw);
|
|
1589
|
+
current.repoCardMessageId = undefined;
|
|
1590
|
+
return { current, cardToWithdraw };
|
|
1591
|
+
});
|
|
1592
|
+
if (!started)
|
|
1593
|
+
return false;
|
|
1594
|
+
try {
|
|
1513
1595
|
try {
|
|
1514
1596
|
await sessionReply(rootId, replyText);
|
|
1515
1597
|
}
|
|
1516
1598
|
catch (e) {
|
|
1517
1599
|
logger.warn(`[${logTag}] Confirm reply after pending repo commit failed: ${e instanceof Error ? e.message : e}`);
|
|
1518
1600
|
}
|
|
1519
|
-
if (cardToWithdraw) {
|
|
1601
|
+
if (started.cardToWithdraw) {
|
|
1520
1602
|
try {
|
|
1521
|
-
await deleteMessage(
|
|
1603
|
+
await deleteMessage(started.current.larkAppId, started.cardToWithdraw);
|
|
1522
1604
|
}
|
|
1523
1605
|
catch { /* best-effort */ }
|
|
1524
1606
|
}
|
|
1525
1607
|
}
|
|
1526
1608
|
finally {
|
|
1527
|
-
|
|
1609
|
+
started.current.pendingRepoCommitInFlight = false;
|
|
1528
1610
|
}
|
|
1529
|
-
return
|
|
1611
|
+
return true;
|
|
1530
1612
|
};
|
|
1531
1613
|
// Shared commit path for an already-resolved repo: update the session's
|
|
1532
1614
|
// working dir, then either fork into the pending CLI (first spawn) or
|
|
@@ -1534,27 +1616,11 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1534
1616
|
// numeric `/repo <N>` form and the `/repo <path|name>` form.
|
|
1535
1617
|
const commitRepoSelection = async (selectedPath, displayName, how) => {
|
|
1536
1618
|
if (ds.pendingRepo) {
|
|
1537
|
-
|
|
1538
|
-
|
|
1619
|
+
// First spawn: the cwd pin and fork are one exclusive commit. Two
|
|
1620
|
+
// simultaneous selections cannot make A reply while forking B's cwd.
|
|
1621
|
+
const started = await forkPendingCli(t('cmd.repo.selected_in_pending', { name: displayName }, loc), { path: selectedPath, riffRepoDirs: undefined });
|
|
1622
|
+
if (!started)
|
|
1539
1623
|
return false;
|
|
1540
|
-
}
|
|
1541
|
-
ds.pendingRepoCommitInFlight = true;
|
|
1542
|
-
try {
|
|
1543
|
-
// Claim before changing cwd so a card selection cannot overwrite
|
|
1544
|
-
// this choice while the pending prompt is prepared.
|
|
1545
|
-
ds.workingDir = selectedPath;
|
|
1546
|
-
ds.session.workingDir = selectedPath;
|
|
1547
|
-
ds.session.riffRepoDirs = undefined;
|
|
1548
|
-
sessionStore.updateSession(ds.session);
|
|
1549
|
-
// forkPendingCli owns claim release + confirm reply + card withdraw.
|
|
1550
|
-
if (!await forkPendingCli(t('cmd.repo.selected_in_pending', { name: displayName }, loc), true)) {
|
|
1551
|
-
return false;
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
catch (e) {
|
|
1555
|
-
ds.pendingRepoCommitInFlight = false;
|
|
1556
|
-
throw e;
|
|
1557
|
-
}
|
|
1558
1624
|
}
|
|
1559
1625
|
else {
|
|
1560
1626
|
// Safety net: a mid-session `/repo` switch closes the running
|
|
@@ -1588,56 +1654,85 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1588
1654
|
// card), so `claude --resume` later would reopen the old context in
|
|
1589
1655
|
// the new repo's cwd. The new repo is pinned onto the fresh session
|
|
1590
1656
|
// below instead.
|
|
1591
|
-
const
|
|
1592
|
-
const
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1657
|
+
const targetSessionId = ds.session.sessionId;
|
|
1658
|
+
const switched = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
1659
|
+
const candidate = [...activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId);
|
|
1660
|
+
if (!candidate || candidate !== ds || candidate.session.status !== 'active') {
|
|
1661
|
+
return { ok: false, error: 'session_replaced' };
|
|
1662
|
+
}
|
|
1663
|
+
const key = activeSessionKey(candidate);
|
|
1664
|
+
return withActiveSessionKeyLock(activeSessions, key, async () => {
|
|
1665
|
+
// Resume/scheduler/dashboard creators use this same key lock
|
|
1666
|
+
// without joining the bot admission gate. Re-resolve after the
|
|
1667
|
+
// lock wait, then keep it across close -> replacement publish.
|
|
1668
|
+
const current = [...activeSessions.values()].find(owner => owner.session.sessionId === targetSessionId);
|
|
1669
|
+
if (!current || current !== candidate
|
|
1670
|
+
|| activeSessions.get(key) !== current
|
|
1671
|
+
|| current.session.status !== 'active') {
|
|
1672
|
+
return { ok: false, error: 'session_replaced' };
|
|
1673
|
+
}
|
|
1674
|
+
if (hasProtectedSessionMutationOwnership(current)) {
|
|
1675
|
+
return { ok: false, error: 'dispatch_pending' };
|
|
1676
|
+
}
|
|
1677
|
+
const closedCard = buildClosedSessionCard(current, loc);
|
|
1678
|
+
const oldSession = current.session;
|
|
1679
|
+
await closeWorkerPoolSession(targetSessionId);
|
|
1680
|
+
// The key lock excludes every sanctioned creator. A direct
|
|
1681
|
+
// lifecycle callback may still have published unexpectedly;
|
|
1682
|
+
// fail closed instead of overwriting that first owner.
|
|
1683
|
+
if (activeSessions.get(key) === current)
|
|
1684
|
+
activeSessions.delete(key);
|
|
1685
|
+
if (activeSessions.has(key)) {
|
|
1686
|
+
return { ok: false, error: 'session_replaced' };
|
|
1687
|
+
}
|
|
1688
|
+
const cardToWithdraw = current.repoCardMessageId;
|
|
1689
|
+
markRepoCardConsumed(current, cardToWithdraw);
|
|
1690
|
+
current.repoCardMessageId = undefined;
|
|
1691
|
+
const session = sessionStore.createSession(current.chatId, current.scope === 'chat' ? oldSession.rootMessageId : rootId, displayName, current.chatType, current.scope);
|
|
1692
|
+
current.session = session;
|
|
1693
|
+
current.lastUserPrompt = undefined;
|
|
1694
|
+
current.lastCliInput = undefined;
|
|
1695
|
+
current.workingDir = selectedPath;
|
|
1696
|
+
session.workingDir = selectedPath;
|
|
1697
|
+
session.larkAppId = current.larkAppId;
|
|
1698
|
+
session.chatDisplayName = oldSession.chatDisplayName;
|
|
1699
|
+
session.ownerOpenId = oldSession.ownerOpenId;
|
|
1700
|
+
session.creatorOpenId = oldSession.creatorOpenId;
|
|
1701
|
+
session.lastCallerOpenId = oldSession.lastCallerOpenId;
|
|
1702
|
+
sessionStore.updateSession(session);
|
|
1703
|
+
current.hasHistory = false;
|
|
1704
|
+
activeSessions.set(key, current);
|
|
1705
|
+
forkWorker(current, '', false);
|
|
1706
|
+
// Brand-new CLI in a brand-new session record: it has never
|
|
1707
|
+
// seen the botmux opening context either, so the next real
|
|
1708
|
+
// business message is its new-topic first turn (same invariant
|
|
1709
|
+
// as the pending path).
|
|
1710
|
+
markInitialUserTurnPending(current);
|
|
1711
|
+
return { ok: true, current, closedCard, cardToWithdraw };
|
|
1712
|
+
});
|
|
1713
|
+
});
|
|
1714
|
+
if (!switched.ok) {
|
|
1715
|
+
if (switched.error === 'dispatch_pending') {
|
|
1716
|
+
await sessionReply(rootId, '当前 Codex App 仍有未结算消息,暂不能切换仓库;请等待本轮完成或关闭会话。');
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
logger.warn(`[${logTag}] Repo switch aborted because the session was replaced`);
|
|
1720
|
+
}
|
|
1603
1721
|
return false;
|
|
1604
1722
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
// repo switches cannot turn a chat session into a legacy scope-less
|
|
1609
|
-
// record that the CLI later mistakes for a thread.
|
|
1610
|
-
const session = sessionStore.createSession(ds.chatId, ds.scope === 'chat' ? oldSession.rootMessageId : rootId, displayName, ds.chatType, ds.scope);
|
|
1611
|
-
ds.session = session;
|
|
1612
|
-
ds.lastUserPrompt = undefined;
|
|
1613
|
-
ds.lastCliInput = undefined;
|
|
1614
|
-
ds.workingDir = selectedPath;
|
|
1615
|
-
ds.session.workingDir = selectedPath;
|
|
1616
|
-
ds.session.larkAppId = ds.larkAppId;
|
|
1617
|
-
ds.session.chatDisplayName = oldSession.chatDisplayName;
|
|
1618
|
-
ds.session.ownerOpenId = oldSession.ownerOpenId;
|
|
1619
|
-
ds.session.creatorOpenId = oldSession.creatorOpenId;
|
|
1620
|
-
ds.session.lastCallerOpenId = oldSession.lastCallerOpenId;
|
|
1621
|
-
sessionStore.updateSession(ds.session);
|
|
1622
|
-
ds.hasHistory = false;
|
|
1623
|
-
forkWorker(ds, '', false);
|
|
1624
|
-
// Brand-new CLI in a brand-new session record: it has never seen the
|
|
1625
|
-
// botmux opening context either, so the next real business message
|
|
1626
|
-
// is its new-topic first turn (same invariant as the pending path).
|
|
1627
|
-
markInitialUserTurnPending(ds);
|
|
1628
|
-
try {
|
|
1629
|
-
await sessionReply(rootId, t('cmd.repo.switched_to', { name: displayName }, loc));
|
|
1630
|
-
}
|
|
1631
|
-
catch (e) {
|
|
1632
|
-
logger.warn(`[${logTag}] Confirm reply after mid-session repo switch failed: ${e instanceof Error ? e.message : e}`);
|
|
1633
|
-
}
|
|
1634
|
-
if (claimedCard) {
|
|
1723
|
+
await deliverEphemeralOrReply(switched.current, message.senderId, switched.closedCard, 'interactive', () => sessionReply(rootId, switched.closedCard, 'interactive'));
|
|
1724
|
+
await sessionReply(rootId, t('cmd.repo.switched_to', { name: displayName }, loc));
|
|
1725
|
+
if (switched.cardToWithdraw) {
|
|
1635
1726
|
try {
|
|
1636
|
-
await deleteMessage(
|
|
1727
|
+
await deleteMessage(switched.current.larkAppId, switched.cardToWithdraw);
|
|
1637
1728
|
}
|
|
1638
1729
|
catch { /* best-effort */ }
|
|
1639
1730
|
}
|
|
1640
1731
|
}
|
|
1732
|
+
if (ds.repoCardMessageId) {
|
|
1733
|
+
deleteMessage(ds.larkAppId, ds.repoCardMessageId);
|
|
1734
|
+
ds.repoCardMessageId = undefined;
|
|
1735
|
+
}
|
|
1641
1736
|
logger.info(`[${logTag}] Repo selected via ${how}: ${selectedPath}`);
|
|
1642
1737
|
return true;
|
|
1643
1738
|
};
|
|
@@ -3776,6 +3871,21 @@ async function blockTakeoverWhilePendingRepo(ds, sessionReply) {
|
|
|
3776
3871
|
logger.info(`[${tag(ds)}] Takeover refused: session still on pendingRepo gate — posted close-session card`);
|
|
3777
3872
|
return true;
|
|
3778
3873
|
}
|
|
3874
|
+
/**
|
|
3875
|
+
* A live Riff worker cannot be replaced through the generic adopt/import
|
|
3876
|
+
* refork path: that path sends a request-less close and then kills the local
|
|
3877
|
+
* worker, while Riff requires its remote task to finish the explicit
|
|
3878
|
+
* prepare/commit close protocol first. Refuse before target validation or any
|
|
3879
|
+
* persisted ownership mutation so the original lineage stays recoverable.
|
|
3880
|
+
*/
|
|
3881
|
+
async function blockRiffTakeover(ds, sessionReply) {
|
|
3882
|
+
if (!isRiffBackendSession(ds))
|
|
3883
|
+
return false;
|
|
3884
|
+
const loc = localeForBot(ds.larkAppId);
|
|
3885
|
+
await sessionReply(sessionAnchorId(ds), t('cmd.takeover.riff_unsupported', undefined, loc));
|
|
3886
|
+
logger.warn(`[${tag(ds)}] Takeover refused: Riff session requires explicit close before replacement`);
|
|
3887
|
+
return true;
|
|
3888
|
+
}
|
|
3779
3889
|
export async function startCodexAppThreadSession(thread, ds, deps, larkAppId) {
|
|
3780
3890
|
const sessionReply = (rid, content, msgType) => deps.sessionReply(rid, content, msgType, larkAppId);
|
|
3781
3891
|
const loc = localeForBot(ds.larkAppId ?? larkAppId);
|
|
@@ -3784,22 +3894,43 @@ export async function startCodexAppThreadSession(thread, ds, deps, larkAppId) {
|
|
|
3784
3894
|
await sessionReply(sessionAnchorId(ds), t('cmd.session.transfer_in_progress', undefined, loc));
|
|
3785
3895
|
return;
|
|
3786
3896
|
}
|
|
3897
|
+
if (await blockRiffTakeover(ds, sessionReply))
|
|
3898
|
+
return;
|
|
3787
3899
|
if (await blockTakeoverWhilePendingRepo(ds, sessionReply))
|
|
3788
3900
|
return;
|
|
3789
|
-
|
|
3790
|
-
ds.
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3901
|
+
const targetSessionId = ds.session.sessionId;
|
|
3902
|
+
const switched = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
3903
|
+
const current = [...deps.activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId
|
|
3904
|
+
&& candidate.session.status === 'active');
|
|
3905
|
+
if (!current || current !== ds)
|
|
3906
|
+
return { status: 'gone' };
|
|
3907
|
+
if (hasProtectedSessionMutationOwnership(current)) {
|
|
3908
|
+
return { status: 'pending', anchor: sessionAnchorId(current) };
|
|
3909
|
+
}
|
|
3910
|
+
current.adoptedFrom = undefined;
|
|
3911
|
+
current.workingDir = thread.cwd;
|
|
3912
|
+
current.hasHistory = true;
|
|
3913
|
+
current.currentTurnTitle = undefined;
|
|
3914
|
+
current.lastScreenContent = undefined;
|
|
3915
|
+
current.lastScreenStatus = undefined;
|
|
3916
|
+
current.session.workingDir = thread.cwd;
|
|
3917
|
+
current.session.title = `Codex App: ${title}`;
|
|
3918
|
+
current.session.cliId = 'codex-app';
|
|
3919
|
+
current.session.cliSessionId = thread.threadId;
|
|
3920
|
+
current.session.adoptedFrom = undefined;
|
|
3921
|
+
sessionStore.updateSession(current.session);
|
|
3922
|
+
forkWorker(current, '', true);
|
|
3923
|
+
return { status: 'switched', anchor: sessionAnchorId(current) };
|
|
3924
|
+
});
|
|
3925
|
+
if (switched.status === 'gone') {
|
|
3926
|
+
await sessionReply(sessionAnchorId(ds), t('cmd.no_active_session', undefined, loc));
|
|
3927
|
+
return;
|
|
3928
|
+
}
|
|
3929
|
+
if (switched.status === 'pending') {
|
|
3930
|
+
await sessionReply(switched.anchor, '当前 Codex App 仍有未结算消息,不能切换原生 thread;请等待本轮完成或先关闭会话。');
|
|
3931
|
+
return;
|
|
3932
|
+
}
|
|
3933
|
+
await sessionReply(switched.anchor, t('cmd.codex_app_adopt.success', { title }, loc));
|
|
3803
3934
|
}
|
|
3804
3935
|
export async function startAdoptSession(target, ds, deps, larkAppId) {
|
|
3805
3936
|
const sessionReply = (rid, content, msgType) => deps.sessionReply(rid, content, msgType, larkAppId);
|
|
@@ -3808,6 +3939,8 @@ export async function startAdoptSession(target, ds, deps, larkAppId) {
|
|
|
3808
3939
|
await sessionReply(sessionAnchorId(ds), t('cmd.session.transfer_in_progress', undefined, loc));
|
|
3809
3940
|
return;
|
|
3810
3941
|
}
|
|
3942
|
+
if (await blockRiffTakeover(ds, sessionReply))
|
|
3943
|
+
return;
|
|
3811
3944
|
const zellij = isZellijTarget(target);
|
|
3812
3945
|
if (!zellij && target.source === 'herdr' && target.herdrSessionName && target.herdrAgentName) {
|
|
3813
3946
|
const occupied = [...deps.activeSessions.values()].some(active => {
|
|
@@ -3852,29 +3985,48 @@ export async function startAdoptSession(target, ds, deps, larkAppId) {
|
|
|
3852
3985
|
}
|
|
3853
3986
|
const project = target.cwd.split('/').pop() || target.cwd;
|
|
3854
3987
|
const pane = zellij ? `${target.zellijSession}/${target.zellijPaneId}` : adoptTargetLabel(target);
|
|
3855
|
-
|
|
3856
|
-
ds.
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3988
|
+
const targetSessionId = ds.session.sessionId;
|
|
3989
|
+
const adopted = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
3990
|
+
const current = [...deps.activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId
|
|
3991
|
+
&& candidate.session.status === 'active');
|
|
3992
|
+
if (!current || current !== ds)
|
|
3993
|
+
return { status: 'gone' };
|
|
3994
|
+
if (hasProtectedSessionMutationOwnership(current)) {
|
|
3995
|
+
return { status: 'pending', anchor: sessionAnchorId(current) };
|
|
3996
|
+
}
|
|
3997
|
+
current.workingDir = target.cwd;
|
|
3998
|
+
current.session.workingDir = target.cwd;
|
|
3999
|
+
current.session.title = `Adopt: ${project}`;
|
|
4000
|
+
current.adoptedFrom = {
|
|
4001
|
+
source: zellij ? 'zellij' : target.source,
|
|
4002
|
+
tmuxTarget: zellij ? undefined : target.tmuxTarget,
|
|
4003
|
+
zellijSession: zellij ? target.zellijSession : undefined,
|
|
4004
|
+
zellijPaneId: zellij ? target.zellijPaneId : undefined,
|
|
4005
|
+
herdrSessionName: zellij ? undefined : target.herdrSessionName,
|
|
4006
|
+
herdrTarget: zellij ? undefined : target.herdrTarget,
|
|
4007
|
+
herdrPaneId: zellij ? undefined : target.herdrPaneId,
|
|
4008
|
+
herdrAgentName: zellij ? undefined : target.herdrAgentName,
|
|
4009
|
+
herdrTerminalId: zellij ? undefined : target.herdrTerminalId,
|
|
4010
|
+
originalCliPid: target.cliPid,
|
|
4011
|
+
sessionId: target.sessionId,
|
|
4012
|
+
cliId: target.cliId,
|
|
4013
|
+
cwd: target.cwd,
|
|
4014
|
+
paneCols: target.paneCols,
|
|
4015
|
+
paneRows: target.paneRows,
|
|
4016
|
+
};
|
|
4017
|
+
current.session.adoptedFrom = { ...current.adoptedFrom };
|
|
4018
|
+
sessionStore.updateSession(current.session);
|
|
4019
|
+
forkAdoptWorker(current);
|
|
4020
|
+
return { status: 'adopted', anchor: sessionAnchorId(current) };
|
|
4021
|
+
});
|
|
4022
|
+
if (adopted.status === 'gone') {
|
|
4023
|
+
await sessionReply(sessionAnchorId(ds), t('cmd.no_active_session', undefined, loc));
|
|
4024
|
+
return;
|
|
4025
|
+
}
|
|
4026
|
+
if (adopted.status === 'pending') {
|
|
4027
|
+
await sessionReply(adopted.anchor, '当前 Codex App 仍有未结算消息,不能切换到外部会话;请等待本轮完成或先关闭会话。');
|
|
4028
|
+
return;
|
|
4029
|
+
}
|
|
3878
4030
|
const cliName = sessionCliDisplayName(ds);
|
|
3879
4031
|
await sessionReply(sessionAnchorId(ds), t('cmd.adopt.success', { cliName, project, pane }, loc));
|
|
3880
4032
|
}
|
|
@@ -3931,18 +4083,38 @@ export async function startResumeImportSession(target, ds, deps, larkAppId) {
|
|
|
3931
4083
|
await sessionReply(sessionAnchorId(ds), t('cmd.session.transfer_in_progress', undefined, loc));
|
|
3932
4084
|
return;
|
|
3933
4085
|
}
|
|
4086
|
+
if (await blockRiffTakeover(ds, sessionReply))
|
|
4087
|
+
return;
|
|
3934
4088
|
if (await blockTakeoverWhilePendingRepo(ds, sessionReply))
|
|
3935
4089
|
return;
|
|
3936
|
-
|
|
3937
|
-
ds.
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
4090
|
+
const targetSessionId = ds.session.sessionId;
|
|
4091
|
+
const resumed = await withBotTurnMutation(ds.larkAppId, async () => {
|
|
4092
|
+
const current = [...deps.activeSessions.values()].find(candidate => candidate.session.sessionId === targetSessionId
|
|
4093
|
+
&& candidate.session.status === 'active');
|
|
4094
|
+
if (!current || current !== ds)
|
|
4095
|
+
return { status: 'gone' };
|
|
4096
|
+
if (hasProtectedSessionMutationOwnership(current)) {
|
|
4097
|
+
return { status: 'pending', anchor: sessionAnchorId(current) };
|
|
4098
|
+
}
|
|
4099
|
+
current.workingDir = target.cwd;
|
|
4100
|
+
current.session.workingDir = target.cwd;
|
|
4101
|
+
current.session.cliSessionId = target.cliSessionId;
|
|
4102
|
+
current.session.title = target.title || `Import: ${project}`;
|
|
4103
|
+
// Resume sandbox decision is left to forkWorker (resume=true → not
|
|
4104
|
+
// sandboxed, matching restore semantics). Mark history so this is a resume.
|
|
4105
|
+
current.hasHistory = true;
|
|
4106
|
+
sessionStore.updateSession(current.session);
|
|
4107
|
+
forkWorker(current, '', true);
|
|
4108
|
+
return { status: 'resumed', anchor: sessionAnchorId(current) };
|
|
4109
|
+
});
|
|
4110
|
+
if (resumed.status === 'gone') {
|
|
4111
|
+
await sessionReply(sessionAnchorId(ds), t('cmd.no_active_session', undefined, loc));
|
|
4112
|
+
return;
|
|
4113
|
+
}
|
|
4114
|
+
if (resumed.status === 'pending') {
|
|
4115
|
+
await sessionReply(resumed.anchor, '当前 Codex App 仍有未结算消息,不能导入外部会话;请等待本轮完成或先关闭会话。');
|
|
4116
|
+
return;
|
|
4117
|
+
}
|
|
3946
4118
|
const cliName = sessionCliDisplayName(ds);
|
|
3947
4119
|
await sessionReply(sessionAnchorId(ds), t('cmd.adopt.resume_success', { cliName, project, title: target.title || target.cliSessionId.slice(0, 8) }, loc));
|
|
3948
4120
|
}
|