@xgjktech/xg_cwork_im 1.19.43 → 1.19.45
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/README.md +492 -492
- package/dist/src/account-connection.d.ts +1 -1
- package/dist/src/account-connection.d.ts.map +1 -1
- package/dist/src/account-connection.js +136 -25
- package/dist/src/account-connection.js.map +1 -1
- package/dist/src/account-reconciler.d.ts +17 -8
- package/dist/src/account-reconciler.d.ts.map +1 -1
- package/dist/src/account-reconciler.js +31 -11
- package/dist/src/account-reconciler.js.map +1 -1
- package/dist/src/account-reconciler.test.js +19 -1
- package/dist/src/account-reconciler.test.js.map +1 -1
- package/dist/src/action-store-access.d.ts +2 -0
- package/dist/src/action-store-access.d.ts.map +1 -1
- package/dist/src/action-store-access.js +7 -0
- package/dist/src/action-store-access.js.map +1 -1
- package/dist/src/action-store-lifecycle.test.d.ts +2 -0
- package/dist/src/action-store-lifecycle.test.d.ts.map +1 -0
- package/dist/src/action-store-lifecycle.test.js +195 -0
- package/dist/src/action-store-lifecycle.test.js.map +1 -0
- package/dist/src/active-cron-context-store.d.ts +20 -0
- package/dist/src/active-cron-context-store.d.ts.map +1 -0
- package/dist/src/active-cron-context-store.js +73 -0
- package/dist/src/active-cron-context-store.js.map +1 -0
- package/dist/src/active-round-registry.d.ts +6 -0
- package/dist/src/active-round-registry.d.ts.map +1 -1
- package/dist/src/active-round-registry.js +27 -2
- package/dist/src/active-round-registry.js.map +1 -1
- package/dist/src/agent-stream-client-registry.d.ts +2 -0
- package/dist/src/agent-stream-client-registry.d.ts.map +1 -1
- package/dist/src/agent-stream-client-registry.js +6 -1
- package/dist/src/agent-stream-client-registry.js.map +1 -1
- package/dist/src/apply-sync-mapping.d.ts +1 -1
- package/dist/src/apply-sync-mapping.d.ts.map +1 -1
- package/dist/src/assistant-item-delivery.d.ts +27 -0
- package/dist/src/assistant-item-delivery.d.ts.map +1 -0
- package/dist/src/assistant-item-delivery.js +134 -0
- package/dist/src/assistant-item-delivery.js.map +1 -0
- package/dist/src/assistant-item-delivery.test.d.ts +2 -0
- package/dist/src/assistant-item-delivery.test.d.ts.map +1 -0
- package/dist/src/assistant-item-delivery.test.js +116 -0
- package/dist/src/assistant-item-delivery.test.js.map +1 -0
- package/dist/src/assistant-item-sink.d.ts +17 -0
- package/dist/src/assistant-item-sink.d.ts.map +1 -0
- package/dist/src/assistant-item-sink.js +34 -0
- package/dist/src/assistant-item-sink.js.map +1 -0
- package/dist/src/auth.d.ts +2 -0
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/auth.js +4 -0
- package/dist/src/auth.js.map +1 -1
- package/dist/src/block-streaming-config.test.js +7 -1
- package/dist/src/block-streaming-config.test.js.map +1 -1
- package/dist/src/build-project-prompt.test.js +18 -18
- package/dist/src/channel-config.d.ts +83 -17
- package/dist/src/channel-config.d.ts.map +1 -1
- package/dist/src/channel-config.js +46 -13
- package/dist/src/channel-config.js.map +1 -1
- package/dist/src/channel-config.test.js +58 -1
- package/dist/src/channel-config.test.js.map +1 -1
- package/dist/src/channel.d.ts +4 -3
- package/dist/src/channel.d.ts.map +1 -1
- package/dist/src/channel.js +127 -4
- package/dist/src/channel.js.map +1 -1
- package/dist/src/connection-workspace-event.test.d.ts +2 -0
- package/dist/src/connection-workspace-event.test.d.ts.map +1 -0
- package/dist/src/connection-workspace-event.test.js +74 -0
- package/dist/src/connection-workspace-event.test.js.map +1 -0
- package/dist/src/connection.d.ts +28 -0
- package/dist/src/connection.d.ts.map +1 -1
- package/dist/src/connection.js +155 -78
- package/dist/src/connection.js.map +1 -1
- package/dist/src/connection.test.d.ts +2 -0
- package/dist/src/connection.test.d.ts.map +1 -0
- package/dist/src/connection.test.js +110 -0
- package/dist/src/connection.test.js.map +1 -0
- package/dist/src/cron-appkey-binding-store.d.ts +29 -0
- package/dist/src/cron-appkey-binding-store.d.ts.map +1 -0
- package/dist/src/cron-appkey-binding-store.js +239 -0
- package/dist/src/cron-appkey-binding-store.js.map +1 -0
- package/dist/src/cron-appkey-binding-store.test.d.ts +2 -0
- package/dist/src/cron-appkey-binding-store.test.d.ts.map +1 -0
- package/dist/src/cron-appkey-binding-store.test.js +387 -0
- package/dist/src/cron-appkey-binding-store.test.js.map +1 -0
- package/dist/src/deliver-text.test.js +22 -22
- package/dist/src/delivery/ai-task-push.d.ts +16 -0
- package/dist/src/delivery/ai-task-push.d.ts.map +1 -0
- package/dist/src/delivery/ai-task-push.js +44 -0
- package/dist/src/delivery/ai-task-push.js.map +1 -0
- package/dist/src/delivery/ai-task-push.test.d.ts +2 -0
- package/dist/src/delivery/ai-task-push.test.d.ts.map +1 -0
- package/dist/src/delivery/ai-task-push.test.js +44 -0
- package/dist/src/delivery/ai-task-push.test.js.map +1 -0
- package/dist/src/delivery/deliver-text.test.js +22 -22
- package/dist/src/delivery/send-service.d.ts +4 -1
- package/dist/src/delivery/send-service.d.ts.map +1 -1
- package/dist/src/delivery/send-service.js +3 -5
- package/dist/src/delivery/send-service.js.map +1 -1
- package/dist/src/delivery/turn-deliver-buffer.test.js +25 -25
- package/dist/src/dispatch-mentioned-reply.d.ts +7 -2
- package/dist/src/dispatch-mentioned-reply.d.ts.map +1 -1
- package/dist/src/dispatch-mentioned-reply.js +243 -68
- package/dist/src/dispatch-mentioned-reply.js.map +1 -1
- package/dist/src/gateway-session-queue.d.ts +2 -6
- package/dist/src/gateway-session-queue.d.ts.map +1 -1
- package/dist/src/gateway-session-queue.js +78 -21
- package/dist/src/gateway-session-queue.js.map +1 -1
- package/dist/src/group-history-tool.d.ts +1 -1
- package/dist/src/group-history-tool.d.ts.map +1 -1
- package/dist/src/inbound/dispatch-mentioned-reply.d.ts.map +1 -1
- package/dist/src/inbound/dispatch-mentioned-reply.js +43 -3
- package/dist/src/inbound/dispatch-mentioned-reply.js.map +1 -1
- package/dist/src/inbound/inbound-display.d.ts.map +1 -1
- package/dist/src/inbound/inbound-display.js +2 -0
- package/dist/src/inbound/inbound-display.js.map +1 -1
- package/dist/src/inbound/inbound-display.test.js +1 -0
- package/dist/src/inbound/inbound-display.test.js.map +1 -1
- package/dist/src/inbound-display.d.ts.map +1 -1
- package/dist/src/inbound-display.js +2 -1
- package/dist/src/inbound-display.js.map +1 -1
- package/dist/src/inbound-input-media.d.ts +1 -1
- package/dist/src/inbound-input-media.d.ts.map +1 -1
- package/dist/src/inbound-media-local.d.ts +1 -1
- package/dist/src/inbound-media-local.d.ts.map +1 -1
- package/dist/src/inbound-model.d.ts +9 -0
- package/dist/src/inbound-model.d.ts.map +1 -1
- package/dist/src/inbound-model.js +26 -0
- package/dist/src/inbound-model.js.map +1 -1
- package/dist/src/inbound-model.test.js +23 -1
- package/dist/src/inbound-model.test.js.map +1 -1
- package/dist/src/inbound-terminal-state.d.ts +2 -0
- package/dist/src/inbound-terminal-state.d.ts.map +1 -1
- package/dist/src/inbound-terminal-state.js +7 -2
- package/dist/src/inbound-terminal-state.js.map +1 -1
- package/dist/src/nas-site.d.ts +16 -0
- package/dist/src/nas-site.d.ts.map +1 -0
- package/dist/src/nas-site.js +17 -0
- package/dist/src/nas-site.js.map +1 -0
- package/dist/src/nas-volumes.d.ts +12 -2
- package/dist/src/nas-volumes.d.ts.map +1 -1
- package/dist/src/nas-volumes.js +147 -37
- package/dist/src/nas-volumes.js.map +1 -1
- package/dist/src/nas-volumes.test.js +39 -7
- package/dist/src/nas-volumes.test.js.map +1 -1
- package/dist/src/per-message-model-pending.d.ts +38 -3
- package/dist/src/per-message-model-pending.d.ts.map +1 -1
- package/dist/src/per-message-model-pending.js +96 -7
- package/dist/src/per-message-model-pending.js.map +1 -1
- package/dist/src/plan/action-store-lifecycle.test.js +5 -5
- package/dist/src/plan/plan-core-db.test.js +9 -9
- package/dist/src/plan/plan-core-snapshot.test.js +9 -9
- package/dist/src/plan-core-adapter.d.ts +54 -0
- package/dist/src/plan-core-adapter.d.ts.map +1 -0
- package/dist/src/plan-core-adapter.js +104 -0
- package/dist/src/plan-core-adapter.js.map +1 -0
- package/dist/src/plan-core-adapter.test.d.ts +2 -0
- package/dist/src/plan-core-adapter.test.d.ts.map +1 -0
- package/dist/src/plan-core-adapter.test.js +183 -0
- package/dist/src/plan-core-adapter.test.js.map +1 -0
- package/dist/src/plan-core-db.d.ts +22 -0
- package/dist/src/plan-core-db.d.ts.map +1 -0
- package/dist/src/plan-core-db.js +91 -0
- package/dist/src/plan-core-db.js.map +1 -0
- package/dist/src/plan-core-db.test.d.ts +2 -0
- package/dist/src/plan-core-db.test.d.ts.map +1 -0
- package/dist/src/plan-core-db.test.js +115 -0
- package/dist/src/plan-core-db.test.js.map +1 -0
- package/dist/src/plan-core-snapshot.d.ts +23 -0
- package/dist/src/plan-core-snapshot.d.ts.map +1 -0
- package/dist/src/plan-core-snapshot.js +66 -0
- package/dist/src/plan-core-snapshot.js.map +1 -0
- package/dist/src/plan-core-snapshot.test.d.ts +2 -0
- package/dist/src/plan-core-snapshot.test.d.ts.map +1 -0
- package/dist/src/plan-core-snapshot.test.js +157 -0
- package/dist/src/plan-core-snapshot.test.js.map +1 -0
- package/dist/src/plan-event-subscription.d.ts +1 -1
- package/dist/src/plan-event-subscription.d.ts.map +1 -1
- package/dist/src/plan-stat-event.d.ts +4 -15
- package/dist/src/plan-stat-event.d.ts.map +1 -1
- package/dist/src/plan-stat-event.js +4 -37
- package/dist/src/plan-stat-event.js.map +1 -1
- package/dist/src/plan-stat-event.test.js +1 -118
- package/dist/src/plan-stat-event.test.js.map +1 -1
- package/dist/src/plan-tool-middleware.d.ts +3 -11
- package/dist/src/plan-tool-middleware.d.ts.map +1 -1
- package/dist/src/plan-tool-middleware.js +11 -60
- package/dist/src/plan-tool-middleware.js.map +1 -1
- package/dist/src/plan-tool-middleware.test.js +83 -603
- package/dist/src/plan-tool-middleware.test.js.map +1 -1
- package/dist/src/plan-ws-registry.d.ts +4 -0
- package/dist/src/plan-ws-registry.d.ts.map +1 -1
- package/dist/src/plan-ws-registry.js +12 -0
- package/dist/src/plan-ws-registry.js.map +1 -1
- package/dist/src/plan-ws-registry.test.js +19 -1
- package/dist/src/plan-ws-registry.test.js.map +1 -1
- package/dist/src/plugin/types.d.ts +5 -0
- package/dist/src/plugin/types.d.ts.map +1 -1
- package/dist/src/plugin-dispose.d.ts +22 -0
- package/dist/src/plugin-dispose.d.ts.map +1 -0
- package/dist/src/plugin-dispose.js +66 -0
- package/dist/src/plugin-dispose.js.map +1 -0
- package/dist/src/process-shared-store.d.ts +48 -0
- package/dist/src/process-shared-store.d.ts.map +1 -0
- package/dist/src/process-shared-store.js +89 -0
- package/dist/src/process-shared-store.js.map +1 -0
- package/dist/src/process-shared-store.test.d.ts +2 -0
- package/dist/src/process-shared-store.test.d.ts.map +1 -0
- package/dist/src/process-shared-store.test.js +60 -0
- package/dist/src/process-shared-store.test.js.map +1 -0
- package/dist/src/register-exec-env-hook.d.ts +44 -0
- package/dist/src/register-exec-env-hook.d.ts.map +1 -0
- package/dist/src/register-exec-env-hook.js +473 -0
- package/dist/src/register-exec-env-hook.js.map +1 -0
- package/dist/src/register-exec-env-hook.test.d.ts +2 -0
- package/dist/src/register-exec-env-hook.test.d.ts.map +1 -0
- package/dist/src/register-exec-env-hook.test.js +189 -0
- package/dist/src/register-exec-env-hook.test.js.map +1 -0
- package/dist/src/register-group-prompt-hook.d.ts +17 -0
- package/dist/src/register-group-prompt-hook.d.ts.map +1 -0
- package/dist/src/register-group-prompt-hook.js +45 -0
- package/dist/src/register-group-prompt-hook.js.map +1 -0
- package/dist/src/register-group-prompt-hook.test.d.ts +2 -0
- package/dist/src/register-group-prompt-hook.test.d.ts.map +1 -0
- package/dist/src/register-group-prompt-hook.test.js +60 -0
- package/dist/src/register-group-prompt-hook.test.js.map +1 -0
- package/dist/src/register-per-message-model-hook.d.ts +10 -2
- package/dist/src/register-per-message-model-hook.d.ts.map +1 -1
- package/dist/src/register-per-message-model-hook.js +32 -6
- package/dist/src/register-per-message-model-hook.js.map +1 -1
- package/dist/src/register-per-message-model-hook.test.d.ts +2 -0
- package/dist/src/register-per-message-model-hook.test.d.ts.map +1 -0
- package/dist/src/register-per-message-model-hook.test.js +208 -0
- package/dist/src/register-per-message-model-hook.test.js.map +1 -0
- package/dist/src/register-run-model-context-hook.d.ts +11 -0
- package/dist/src/register-run-model-context-hook.d.ts.map +1 -0
- package/dist/src/register-run-model-context-hook.js +23 -0
- package/dist/src/register-run-model-context-hook.js.map +1 -0
- package/dist/src/reply-dispatch-driver.d.ts +89 -0
- package/dist/src/reply-dispatch-driver.d.ts.map +1 -0
- package/dist/src/reply-dispatch-driver.js +294 -0
- package/dist/src/reply-dispatch-driver.js.map +1 -0
- package/dist/src/reply-dispatch-driver.test.d.ts +2 -0
- package/dist/src/reply-dispatch-driver.test.d.ts.map +1 -0
- package/dist/src/reply-dispatch-driver.test.js +363 -0
- package/dist/src/reply-dispatch-driver.test.js.map +1 -0
- package/dist/src/resolve-inbound-group-prompt.d.ts +17 -1
- package/dist/src/resolve-inbound-group-prompt.d.ts.map +1 -1
- package/dist/src/resolve-inbound-group-prompt.js +16 -2
- package/dist/src/resolve-inbound-group-prompt.js.map +1 -1
- package/dist/src/run-model-context.d.ts +45 -0
- package/dist/src/run-model-context.d.ts.map +1 -0
- package/dist/src/run-model-context.js +108 -0
- package/dist/src/run-model-context.js.map +1 -0
- package/dist/src/run-model-context.test.d.ts +2 -0
- package/dist/src/run-model-context.test.d.ts.map +1 -0
- package/dist/src/run-model-context.test.js +68 -0
- package/dist/src/run-model-context.test.js.map +1 -0
- package/dist/src/run-usage-session.d.ts +4 -1
- package/dist/src/run-usage-session.d.ts.map +1 -1
- package/dist/src/run-usage-session.js +13 -1
- package/dist/src/run-usage-session.js.map +1 -1
- package/dist/src/run-usage.d.ts +15 -0
- package/dist/src/run-usage.d.ts.map +1 -1
- package/dist/src/run-usage.js +30 -4
- package/dist/src/run-usage.js.map +1 -1
- package/dist/src/run-usage.test.js +99 -11
- package/dist/src/run-usage.test.js.map +1 -1
- package/dist/src/send-file-tool.d.ts +1 -1
- package/dist/src/send-file-tool.d.ts.map +1 -1
- package/dist/src/send-group-message-tool.d.ts +1 -1
- package/dist/src/send-group-message-tool.d.ts.map +1 -1
- package/dist/src/session/build-project-prompt.test.js +18 -18
- package/dist/src/session/session-model-fallback.d.ts.map +1 -1
- package/dist/src/session/session-model-fallback.js +6 -3
- package/dist/src/session/session-model-fallback.js.map +1 -1
- package/dist/src/session-env-store.d.ts +55 -0
- package/dist/src/session-env-store.d.ts.map +1 -0
- package/dist/src/session-env-store.js +328 -0
- package/dist/src/session-env-store.js.map +1 -0
- package/dist/src/session-env-store.test.d.ts +2 -0
- package/dist/src/session-env-store.test.d.ts.map +1 -0
- package/dist/src/session-env-store.test.js +151 -0
- package/dist/src/session-env-store.test.js.map +1 -0
- package/dist/src/session-group-prompt.d.ts +34 -0
- package/dist/src/session-group-prompt.d.ts.map +1 -0
- package/dist/src/session-group-prompt.js +101 -0
- package/dist/src/session-group-prompt.js.map +1 -0
- package/dist/src/session-group-prompt.test.d.ts +2 -0
- package/dist/src/session-group-prompt.test.d.ts.map +1 -0
- package/dist/src/session-group-prompt.test.js +72 -0
- package/dist/src/session-group-prompt.test.js.map +1 -0
- package/dist/src/session-im-context.d.ts +2 -0
- package/dist/src/session-im-context.d.ts.map +1 -1
- package/dist/src/session-im-context.js +11 -2
- package/dist/src/session-im-context.js.map +1 -1
- package/dist/src/session-model-fallback.d.ts +13 -0
- package/dist/src/session-model-fallback.d.ts.map +1 -0
- package/dist/src/session-model-fallback.js +24 -0
- package/dist/src/session-model-fallback.js.map +1 -0
- package/dist/src/subagent-monitor.d.ts +14 -1
- package/dist/src/subagent-monitor.d.ts.map +1 -1
- package/dist/src/subagent-monitor.js +164 -36
- package/dist/src/subagent-monitor.js.map +1 -1
- package/dist/src/subagent-monitor.test.js +121 -0
- package/dist/src/subagent-monitor.test.js.map +1 -1
- package/dist/src/tool-event-adapter.d.ts +31 -0
- package/dist/src/tool-event-adapter.d.ts.map +1 -0
- package/dist/src/tool-event-adapter.js +83 -0
- package/dist/src/tool-event-adapter.js.map +1 -0
- package/dist/src/tool-event-adapter.test.d.ts +2 -0
- package/dist/src/tool-event-adapter.test.d.ts.map +1 -0
- package/dist/src/tool-event-adapter.test.js +93 -0
- package/dist/src/tool-event-adapter.test.js.map +1 -0
- package/dist/src/tool-json-result.d.ts +1 -1
- package/dist/src/tool-json-result.d.ts.map +1 -1
- package/dist/src/turn/run-usage-session.d.ts +1 -1
- package/dist/src/turn/run-usage-session.d.ts.map +1 -1
- package/dist/src/turn/run-usage-session.js +7 -4
- package/dist/src/turn/run-usage-session.js.map +1 -1
- package/dist/src/turn-agent-event-subscription.d.ts +29 -0
- package/dist/src/turn-agent-event-subscription.d.ts.map +1 -0
- package/dist/src/turn-agent-event-subscription.js +289 -0
- package/dist/src/turn-agent-event-subscription.js.map +1 -0
- package/dist/src/turn-agent-event-subscription.test.d.ts +2 -0
- package/dist/src/turn-agent-event-subscription.test.d.ts.map +1 -0
- package/dist/src/turn-agent-event-subscription.test.js +165 -0
- package/dist/src/turn-agent-event-subscription.test.js.map +1 -0
- package/dist/src/turn-deliver-buffer.test.js +25 -25
- package/dist/src/turn-end-controller.d.ts +61 -0
- package/dist/src/turn-end-controller.d.ts.map +1 -0
- package/dist/src/turn-end-controller.js +239 -0
- package/dist/src/turn-end-controller.js.map +1 -0
- package/dist/src/turn-end-controller.test.d.ts +2 -0
- package/dist/src/turn-end-controller.test.d.ts.map +1 -0
- package/dist/src/turn-end-controller.test.js +97 -0
- package/dist/src/turn-end-controller.test.js.map +1 -0
- package/dist/src/types.d.ts +48 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/workspace-event-protocol.d.ts +3 -0
- package/dist/src/workspace-event-protocol.d.ts.map +1 -0
- package/dist/src/workspace-event-protocol.js +3 -0
- package/dist/src/workspace-event-protocol.js.map +1 -0
- package/dist/src/workspace-event-scheduler.d.ts +54 -0
- package/dist/src/workspace-event-scheduler.d.ts.map +1 -0
- package/dist/src/workspace-event-scheduler.js +131 -0
- package/dist/src/workspace-event-scheduler.js.map +1 -0
- package/dist/src/workspace-event-scheduler.test.d.ts +2 -0
- package/dist/src/workspace-event-scheduler.test.d.ts.map +1 -0
- package/dist/src/workspace-event-scheduler.test.js +157 -0
- package/dist/src/workspace-event-scheduler.test.js.map +1 -0
- package/dist/src/workspace-event.d.ts +28 -0
- package/dist/src/workspace-event.d.ts.map +1 -0
- package/dist/src/workspace-event.js +674 -0
- package/dist/src/workspace-event.js.map +1 -0
- package/dist/src/workspace-event.test.d.ts +2 -0
- package/dist/src/workspace-event.test.d.ts.map +1 -0
- package/dist/src/workspace-event.test.js +265 -0
- package/dist/src/workspace-event.test.js.map +1 -0
- package/dist/src/ws-inbound-schema.d.ts.map +1 -1
- package/dist/src/ws-inbound-schema.js +1 -0
- package/dist/src/ws-inbound-schema.js.map +1 -1
- package/dist/src/ws-inbound-schema.test.d.ts +2 -0
- package/dist/src/ws-inbound-schema.test.d.ts.map +1 -0
- package/dist/src/ws-inbound-schema.test.js +58 -0
- package/dist/src/ws-inbound-schema.test.js.map +1 -0
- package/openclaw.plugin.json +30 -30
- package/package.json +83 -83
- package/dist/src/modified-file-push-tracker.d.ts +0 -24
- package/dist/src/modified-file-push-tracker.d.ts.map +0 -1
- package/dist/src/modified-file-push-tracker.js +0 -125
- package/dist/src/modified-file-push-tracker.js.map +0 -1
- package/dist/src/plan/action-dispatch-event-compat.test.d.ts +0 -2
- package/dist/src/plan/action-dispatch-event-compat.test.d.ts.map +0 -1
- package/dist/src/plan/action-dispatch-event-compat.test.js +0 -81
- package/dist/src/plan/action-dispatch-event-compat.test.js.map +0 -1
- package/dist/src/plan-store-access.d.ts +0 -23
- package/dist/src/plan-store-access.d.ts.map +0 -1
- package/dist/src/plan-store-access.js +0 -96
- package/dist/src/plan-store-access.js.map +0 -1
- package/dist/src/plan-store-access.test.d.ts +0 -2
- package/dist/src/plan-store-access.test.d.ts.map +0 -1
- package/dist/src/plan-store-access.test.js +0 -207
- package/dist/src/plan-store-access.test.js.map +0 -1
- package/dist/src/progress-display.d.ts +0 -77
- package/dist/src/progress-display.d.ts.map +0 -1
- package/dist/src/progress-display.js +0 -420
- package/dist/src/progress-display.js.map +0 -1
- package/dist/src/subagent-delivery-phase.d.ts +0 -10
- package/dist/src/subagent-delivery-phase.d.ts.map +0 -1
- package/dist/src/subagent-delivery-phase.js +0 -4
- package/dist/src/subagent-delivery-phase.js.map +0 -1
- package/dist/src/subagent-delivery-phase.test.d.ts +0 -2
- package/dist/src/subagent-delivery-phase.test.d.ts.map +0 -1
- package/dist/src/subagent-delivery-phase.test.js +0 -12
- package/dist/src/subagent-delivery-phase.test.js.map +0 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 会话级「群背景」缓存(跨回合续轮补注入)。
|
|
3
|
+
*
|
|
4
|
+
* 背景:`GroupSystemPrompt` 由入站 @ 回合构建并注入(`account-connection.ts` → `inboundCtx`),
|
|
5
|
+
* 而 heartbeat / exec 完成唤醒等**自触发回合**没有入站消息,OpenClaw 不会重新注入,
|
|
6
|
+
* 导致 agent 在续轮丢失 `userInfo.background` + `agentContext`(「待办背景未带入」)。
|
|
7
|
+
*
|
|
8
|
+
* 本缓存只保存**动态段**(用户块 + 项目块,见 `resolveInboundGroupPromptParts`),
|
|
9
|
+
* 不含配置里的静态段;最新一轮动态段为空时**清空**,避免把过期背景补进续轮。
|
|
10
|
+
*
|
|
11
|
+
* 过期与容量:TTL + 条目上限双重兜底,防止无界增长;进程级共享,跨热重载存活。
|
|
12
|
+
*/
|
|
13
|
+
import { getSharedMap } from "./process-shared-store.js";
|
|
14
|
+
/** 条目上限(防御无界增长)。 */
|
|
15
|
+
const MAX_ENTRIES = 500;
|
|
16
|
+
/**
|
|
17
|
+
* 条目有效期。唤醒轮多为 **exec 完成唤醒**,后台任务时长可达小时级,故取 24h 覆盖长任务;
|
|
18
|
+
* 内存由 `MAX_ENTRIES` 兜底,TTL 只负责防陈旧(下一次被 @ 的入站轮会覆盖或清空)。
|
|
19
|
+
*/
|
|
20
|
+
const TTL_MS = 24 * 60 * 60 * 1000;
|
|
21
|
+
const bySessionKey = getSharedMap("session-group-prompt");
|
|
22
|
+
function nonEmpty(value) {
|
|
23
|
+
if (typeof value !== "string")
|
|
24
|
+
return undefined;
|
|
25
|
+
const text = value.trim();
|
|
26
|
+
return text.length > 0 ? text : undefined;
|
|
27
|
+
}
|
|
28
|
+
function pruneExpired(now) {
|
|
29
|
+
for (const [key, entry] of bySessionKey) {
|
|
30
|
+
if (now - entry.updatedAt > TTL_MS) {
|
|
31
|
+
bySessionKey.delete(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function evictOldestIfOverCapacity() {
|
|
36
|
+
if (bySessionKey.size < MAX_ENTRIES)
|
|
37
|
+
return;
|
|
38
|
+
let oldestKey;
|
|
39
|
+
let oldestAt = Number.POSITIVE_INFINITY;
|
|
40
|
+
for (const [key, entry] of bySessionKey) {
|
|
41
|
+
if (entry.updatedAt < oldestAt) {
|
|
42
|
+
oldestAt = entry.updatedAt;
|
|
43
|
+
oldestKey = key;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (oldestKey !== undefined) {
|
|
47
|
+
bySessionKey.delete(oldestKey);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 记录一次入站构建的群背景动态段。
|
|
52
|
+
*
|
|
53
|
+
* - `prompt` 非空 → 覆盖写入并刷新 `updatedAt`;
|
|
54
|
+
* - `prompt` 为空 / undefined → **删除该会话缓存**(最新一轮没有背景,续轮不得复用旧背景)。
|
|
55
|
+
*/
|
|
56
|
+
export function setSessionGroupPrompt(sessionKey, prompt) {
|
|
57
|
+
const key = nonEmpty(sessionKey);
|
|
58
|
+
if (!key)
|
|
59
|
+
return;
|
|
60
|
+
const text = nonEmpty(prompt);
|
|
61
|
+
if (!text) {
|
|
62
|
+
bySessionKey.delete(key);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
pruneExpired(now);
|
|
67
|
+
if (!bySessionKey.has(key)) {
|
|
68
|
+
evictOldestIfOverCapacity();
|
|
69
|
+
}
|
|
70
|
+
bySessionKey.set(key, { prompt: text, updatedAt: now });
|
|
71
|
+
}
|
|
72
|
+
/** 读取某会话最近一次入站构建的群背景动态段(过期返回 undefined)。 */
|
|
73
|
+
export function getSessionGroupPrompt(sessionKey) {
|
|
74
|
+
const key = nonEmpty(sessionKey);
|
|
75
|
+
if (!key)
|
|
76
|
+
return undefined;
|
|
77
|
+
const entry = bySessionKey.get(key);
|
|
78
|
+
if (!entry)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (Date.now() - entry.updatedAt > TTL_MS) {
|
|
81
|
+
bySessionKey.delete(key);
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
return entry.prompt;
|
|
85
|
+
}
|
|
86
|
+
/** 清除某会话的群背景缓存。 */
|
|
87
|
+
export function clearSessionGroupPrompt(sessionKey) {
|
|
88
|
+
const key = nonEmpty(sessionKey);
|
|
89
|
+
if (!key)
|
|
90
|
+
return;
|
|
91
|
+
bySessionKey.delete(key);
|
|
92
|
+
}
|
|
93
|
+
/** 插件卸载/重载时清空全部缓存。 */
|
|
94
|
+
export function clearAllSessionGroupPrompts() {
|
|
95
|
+
bySessionKey.clear();
|
|
96
|
+
}
|
|
97
|
+
/** 仅供测试:内部条目数。 */
|
|
98
|
+
export function __sessionGroupPromptSizeForTests() {
|
|
99
|
+
return bySessionKey.size;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=session-group-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-group-prompt.js","sourceRoot":"","sources":["../../src/session-group-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-group-prompt.test.d.ts","sourceRoot":"","sources":["../../src/session-group-prompt.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { beforeEach, describe, it } from "node:test";
|
|
3
|
+
import { __sessionGroupPromptSizeForTests, clearAllSessionGroupPrompts, clearSessionGroupPrompt, getSessionGroupPrompt, setSessionGroupPrompt, } from "./session-group-prompt.js";
|
|
4
|
+
const TTL_MS = 24 * 60 * 60 * 1000;
|
|
5
|
+
const MAX_ENTRIES = 500;
|
|
6
|
+
describe("session-group-prompt", () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
clearAllSessionGroupPrompts();
|
|
9
|
+
});
|
|
10
|
+
it("records and reads the dynamic group prompt per session", () => {
|
|
11
|
+
setSessionGroupPrompt("session-1", "## 当前用户\n\n发送者:张三");
|
|
12
|
+
assert.equal(getSessionGroupPrompt("session-1"), "## 当前用户\n\n发送者:张三");
|
|
13
|
+
});
|
|
14
|
+
it("overwrites the previous entry for the same session", () => {
|
|
15
|
+
setSessionGroupPrompt("session-1", "first");
|
|
16
|
+
setSessionGroupPrompt("session-1", "second");
|
|
17
|
+
assert.equal(getSessionGroupPrompt("session-1"), "second");
|
|
18
|
+
assert.equal(__sessionGroupPromptSizeForTests(), 1);
|
|
19
|
+
});
|
|
20
|
+
it("clears the cache when the latest turn has no dynamic prompt", () => {
|
|
21
|
+
setSessionGroupPrompt("session-1", "stale-background");
|
|
22
|
+
setSessionGroupPrompt("session-1", undefined);
|
|
23
|
+
assert.equal(getSessionGroupPrompt("session-1"), undefined);
|
|
24
|
+
assert.equal(__sessionGroupPromptSizeForTests(), 0);
|
|
25
|
+
setSessionGroupPrompt("session-1", "stale-background");
|
|
26
|
+
setSessionGroupPrompt("session-1", " ");
|
|
27
|
+
assert.equal(getSessionGroupPrompt("session-1"), undefined);
|
|
28
|
+
assert.equal(__sessionGroupPromptSizeForTests(), 0);
|
|
29
|
+
});
|
|
30
|
+
it("trims whitespace around the stored prompt", () => {
|
|
31
|
+
setSessionGroupPrompt("session-1", " bg ");
|
|
32
|
+
assert.equal(getSessionGroupPrompt("session-1"), "bg");
|
|
33
|
+
});
|
|
34
|
+
it("isolates sessions and ignores empty session keys", () => {
|
|
35
|
+
setSessionGroupPrompt("session-1", "a");
|
|
36
|
+
setSessionGroupPrompt("session-2", "b");
|
|
37
|
+
assert.equal(getSessionGroupPrompt("session-1"), "a");
|
|
38
|
+
assert.equal(getSessionGroupPrompt("session-2"), "b");
|
|
39
|
+
assert.equal(getSessionGroupPrompt("session-3"), undefined);
|
|
40
|
+
setSessionGroupPrompt("", "ignored");
|
|
41
|
+
setSessionGroupPrompt(undefined, "ignored");
|
|
42
|
+
assert.equal(__sessionGroupPromptSizeForTests(), 2);
|
|
43
|
+
});
|
|
44
|
+
it("expires entries past the TTL", (t) => {
|
|
45
|
+
t.mock.timers.enable({ apis: ["Date"], now: 1_000_000 });
|
|
46
|
+
setSessionGroupPrompt("session-1", "bg");
|
|
47
|
+
assert.equal(getSessionGroupPrompt("session-1"), "bg");
|
|
48
|
+
t.mock.timers.tick(TTL_MS);
|
|
49
|
+
assert.equal(getSessionGroupPrompt("session-1"), "bg");
|
|
50
|
+
t.mock.timers.tick(1);
|
|
51
|
+
assert.equal(getSessionGroupPrompt("session-1"), undefined);
|
|
52
|
+
assert.equal(__sessionGroupPromptSizeForTests(), 0);
|
|
53
|
+
});
|
|
54
|
+
it("evicts the oldest entry instead of growing past MAX_ENTRIES", () => {
|
|
55
|
+
for (let i = 0; i < MAX_ENTRIES; i++) {
|
|
56
|
+
setSessionGroupPrompt(`session-${i}`, `bg-${i}`);
|
|
57
|
+
}
|
|
58
|
+
assert.equal(__sessionGroupPromptSizeForTests(), MAX_ENTRIES);
|
|
59
|
+
setSessionGroupPrompt("session-new", "bg-new");
|
|
60
|
+
assert.equal(__sessionGroupPromptSizeForTests(), MAX_ENTRIES);
|
|
61
|
+
assert.equal(getSessionGroupPrompt("session-0"), undefined);
|
|
62
|
+
assert.equal(getSessionGroupPrompt("session-new"), "bg-new");
|
|
63
|
+
});
|
|
64
|
+
it("clearSessionGroupPrompt removes a single session", () => {
|
|
65
|
+
setSessionGroupPrompt("session-1", "a");
|
|
66
|
+
setSessionGroupPrompt("session-2", "b");
|
|
67
|
+
clearSessionGroupPrompt("session-1");
|
|
68
|
+
assert.equal(getSessionGroupPrompt("session-1"), undefined);
|
|
69
|
+
assert.equal(getSessionGroupPrompt("session-2"), "b");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=session-group-prompt.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-group-prompt.test.js","sourceRoot":"","sources":["../../src/session-group-prompt.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,4 +10,6 @@ export declare function getSessionImContext(sessionKey: string): {
|
|
|
10
10
|
} | undefined;
|
|
11
11
|
export declare function clearSessionImContext(sessionKey: string, expectedReplyToMsgId?: string): boolean;
|
|
12
12
|
export declare function touchSessionImContext(sessionKey: string): void;
|
|
13
|
+
/** 插件卸载/重载时清空会话 IM 上下文与全部清理定时器。 */
|
|
14
|
+
export declare function disposeSessionImContext(): void;
|
|
13
15
|
//# sourceMappingURL=session-im-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-im-context.d.ts","sourceRoot":"","sources":["../../src/session-im-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-im-context.d.ts","sourceRoot":"","sources":["../../src/session-im-context.ts"],"names":[],"mappings":"AAkCA,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9D,IAAI,CAGN;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAOxE;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,OAAO,CAQhG;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAK9D;AAED,mCAAmC;AACnC,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
import { getSharedMap } from "./process-shared-store.js";
|
|
2
|
+
const sessionCtxMap = getSharedMap("session-im-context");
|
|
3
|
+
const cleanupTimers = getSharedMap("session-im-context-timers");
|
|
3
4
|
const CLEANUP_DELAY_MS = 60 * 60 * 1000;
|
|
4
5
|
function clearCleanupTimer(sessionKey) {
|
|
5
6
|
const t = cleanupTimers.get(sessionKey);
|
|
@@ -42,4 +43,12 @@ export function touchSessionImContext(sessionKey) {
|
|
|
42
43
|
scheduleCleanup(sessionKey);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
/** 插件卸载/重载时清空会话 IM 上下文与全部清理定时器。 */
|
|
47
|
+
export function disposeSessionImContext() {
|
|
48
|
+
for (const timer of cleanupTimers.values()) {
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
}
|
|
51
|
+
cleanupTimers.clear();
|
|
52
|
+
sessionCtxMap.clear();
|
|
53
|
+
}
|
|
45
54
|
//# sourceMappingURL=session-im-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-im-context.js","sourceRoot":"","sources":["../../src/session-im-context.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"session-im-context.js","sourceRoot":"","sources":["../../src/session-im-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,MAAM,aAAa,GAAG,YAAY,CAOhC,oBAAoB,CAAC,CAAC;AAExB,MAAM,aAAa,GAAG,YAAY,CAAwC,2BAA2B,CAAC,CAAC;AAEvG,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAEvC,SAAS,iBAAiB,CAAC,UAAkB;IAC3C,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACvC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACpB,YAAY,CAAC,CAAC,CAAC,CAAA;QACf,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAClC,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,UAAkB;IACzC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAC7B,aAAa,CAAC,GAAG,CACf,UAAU,EACV,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAChC,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAClC,CAAC,EAAE,gBAAgB,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,GAA+D;IAE/D,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;IAClC,eAAe,CAAC,UAAU,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,UAAkB;IAElB,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,iBAAiB,CAAC,UAAU,CAAC,CAAA;QAC7B,eAAe,CAAC,UAAU,CAAC,CAAA;QAC3B,OAAO,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACtC,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAkB,EAAE,oBAA6B;IACrF,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IAC7C,IAAI,CAAC,OAAO,IAAI,CAAC,oBAAoB,IAAI,OAAO,CAAC,YAAY,KAAK,oBAAoB,CAAC,EAAE,CAAC;QACxF,OAAO,KAAK,CAAA;IACd,CAAC;IACD,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAC7B,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAChC,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACtD,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,iBAAiB,CAAC,UAAU,CAAC,CAAA;QAC7B,eAAe,CAAC,UAAU,CAAC,CAAA;IAC7B,CAAC;AACH,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,uBAAuB;IACrC,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,YAAY,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC;IACD,aAAa,CAAC,KAAK,EAAE,CAAA;IACrB,aAAa,CAAC,KAAK,EAAE,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读取 session store 中的自动降级上下文,供单轮模型覆盖的守卫判定使用。
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw 在自动降级时会把 `modelOverrideSource: "auto"` 与
|
|
5
|
+
* `modelOverrideFallbackOriginProvider/Model`(被跳过的原模型)写入 session entry。
|
|
6
|
+
* 入站时读取一次即可判断「用户点名的模型是否就是冷却中的降级来源」。
|
|
7
|
+
*/
|
|
8
|
+
import { type SessionModelFallbackContext } from "./per-message-model-pending.js";
|
|
9
|
+
export declare function resolveSessionModelFallbackContext(args: {
|
|
10
|
+
storePath: string;
|
|
11
|
+
sessionKey: string;
|
|
12
|
+
}): SessionModelFallbackContext;
|
|
13
|
+
//# sourceMappingURL=session-model-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-model-fallback.d.ts","sourceRoot":"","sources":["../../src/session-model-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAEH,KAAK,2BAA2B,EACnC,MAAM,gCAAgC,CAAC;AAExC,wBAAgB,kCAAkC,CAAC,IAAI,EAAE;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB,GAAG,2BAA2B,CAW9B"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读取 session store 中的自动降级上下文,供单轮模型覆盖的守卫判定使用。
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw 在自动降级时会把 `modelOverrideSource: "auto"` 与
|
|
5
|
+
* `modelOverrideFallbackOriginProvider/Model`(被跳过的原模型)写入 session entry。
|
|
6
|
+
* 入站时读取一次即可判断「用户点名的模型是否就是冷却中的降级来源」。
|
|
7
|
+
*/
|
|
8
|
+
import { loadSessionStore, resolveSessionStoreEntry, } from "openclaw/plugin-sdk/session-store-runtime";
|
|
9
|
+
import { resolveSessionFallbackContextFromEntry, } from "./per-message-model-pending.js";
|
|
10
|
+
export function resolveSessionModelFallbackContext(args) {
|
|
11
|
+
const storePath = args.storePath?.trim();
|
|
12
|
+
const sessionKey = args.sessionKey?.trim();
|
|
13
|
+
if (!storePath || !sessionKey)
|
|
14
|
+
return { sessionInAutoFallback: false };
|
|
15
|
+
try {
|
|
16
|
+
const store = loadSessionStore(storePath, { skipCache: true });
|
|
17
|
+
const { existing } = resolveSessionStoreEntry({ store, sessionKey });
|
|
18
|
+
return resolveSessionFallbackContextFromEntry(existing);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return { sessionInAutoFallback: false };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=session-model-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-model-fallback.js","sourceRoot":"","sources":["../../src/session-model-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,gBAAgB,EAChB,wBAAwB,GAC3B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACH,sCAAsC,GAEzC,MAAM,gCAAgC,CAAC;AAExC,MAAM,UAAU,kCAAkC,CAAC,IAGlD;IACG,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC;IACvE,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,QAAQ,EAAE,GAAG,wBAAwB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QACrE,OAAO,sCAAsC,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;AACL,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-plugin-common";
|
|
2
2
|
import type { ImStreamClient } from "./connection.js";
|
|
3
3
|
interface SubagentSpawnInfo {
|
|
4
4
|
childSessionKey: string;
|
|
@@ -23,10 +23,23 @@ export declare function startMonitor(params: {
|
|
|
23
23
|
spawn: SubagentSpawnInfo;
|
|
24
24
|
}): boolean;
|
|
25
25
|
export declare function hasActiveSubagents(roundKey: string, generation: number): boolean;
|
|
26
|
+
/** 子任务结束事件定位其所属轮次(供 turn-end-controller 递减活跃子任务数)。 */
|
|
27
|
+
export declare function findChildRoundIndex(childSessionKey: string): {
|
|
28
|
+
roundKey: string;
|
|
29
|
+
generation: number;
|
|
30
|
+
runId: string;
|
|
31
|
+
} | undefined;
|
|
26
32
|
export declare function deferFinished(roundKey: string, generation: number, reason: string): void;
|
|
27
33
|
export declare function prepareSubagentInterrupt(roundKey: string, generation: number, now?: number): InterruptedSubagent[];
|
|
28
34
|
export declare function markSubagentCompleted(childSessionKey: string, runId?: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* 整轮收尾时(dispatch wrapper 在 turn-end-controller 放行后)清理本轮监控。
|
|
37
|
+
* 与 removeMonitor 的 settle 路径不同:此处轮次真正结束,直接拆监控与子任务索引。
|
|
38
|
+
*/
|
|
39
|
+
export declare function finalizeRoundMonitoring(roundKey: string, generation: number): void;
|
|
29
40
|
export declare function __tickForTests(): Promise<void>;
|
|
30
41
|
export declare function __resetSubagentMonitorForTests(): void;
|
|
42
|
+
/** 插件卸载/重载时停掉 subagent-monitor 的全部轮询与状态,避免旧实例 ticker 泄漏。 */
|
|
43
|
+
export declare function disposeSubagentMonitor(): void;
|
|
31
44
|
export {};
|
|
32
45
|
//# sourceMappingURL=subagent-monitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-monitor.d.ts","sourceRoot":"","sources":["../../src/subagent-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"subagent-monitor.d.ts","sourceRoot":"","sources":["../../src/subagent-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAGnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,UAAU,iBAAiB;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AA4BD,MAAM,WAAW,mBAAmB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,GAAG,WAAW,CAAC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAkDD,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAsCzD;AA+CD,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAsCD,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,cAAc,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,iBAAiB,CAAC;CAC5B,GAAG,OAAO,CAsDV;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAOhF;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CAC/B,eAAe,EAAE,MAAM,GACxB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAErE;AAED,wBAAgB,aAAa,CACzB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACf,IAAI,CAEN;AAED,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,GAAG,SAAa,GACjB,mBAAmB,EAAE,CAoBvB;AAED,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CA+CnF;AA4BD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAIlF;AAsKD,wBAAgB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9C;AAED,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAED,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,IAAI,CAW7C"}
|
|
@@ -1,25 +1,112 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getOrCreateShared, getSharedMap } from "./process-shared-store.js";
|
|
2
|
+
import { turnOnAllChildrenDone } from "./turn-end-controller.js";
|
|
2
3
|
/** 模块实例 ID:用于确认插件是否被重复加载(若日志出现两个不同 id,则存在双实例,spawn/end 可能被不同实例处理)。 */
|
|
3
4
|
const MODULE_INSTANCE_ID = `m${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
4
|
-
console.log(`[subagent-monitor] module loaded instance=${MODULE_INSTANCE_ID}`);
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
5
|
+
console.log(`[subagent-monitor] module loaded instance=${MODULE_INSTANCE_ID} pid=${process.pid} title=${(process.title || "(none)").trim()}`);
|
|
6
|
+
// 进程级共享:跨模块重载后监控不中断——各代模块读写同一份 maps/轮询/api 候选。
|
|
7
|
+
const childToRound = getSharedMap("subagent-child-to-round");
|
|
8
|
+
const roundMonitors = getSharedMap("subagent-round-monitors");
|
|
9
|
+
const deferredFinished = getSharedMap("subagent-deferred-finished");
|
|
10
|
+
const roundAdmissionTombstones = getSharedMap("subagent-round-admission-tombstones");
|
|
9
11
|
/** 记录被 `/stop` 中断的 subagent run(按 childSessionKey 索引,存被中断 runId 与过期时间)。 */
|
|
10
|
-
const childTombstones =
|
|
12
|
+
const childTombstones = getSharedMap("subagent-child-tombstones");
|
|
11
13
|
const POLL_INTERVAL_MS = 15_000;
|
|
14
|
+
/**
|
|
15
|
+
* apiCandidates 保留上限:OpenClaw 会对同一模块反复重注册(多代 registry 并存且从不触发
|
|
16
|
+
* cleanup,见日志 `registerSeq` 递增而 `cleanup` 为 0)。每代 register 都会 push 一个新 api 进
|
|
17
|
+
* 进程级 candidates,若不停老代则数组无限增长、引用无法回收。该数组仅作为「当前 runtime 探测
|
|
18
|
+
* 不可用时的回退池」(resolveUsablePluginApi),而单进程内 register 是按时间顺序的短爆发(通常
|
|
19
|
+
* 2~4 次),功能上只需最近几代即可,故截断更早的候选。
|
|
20
|
+
*/
|
|
21
|
+
const MAX_API_CANDIDATES = 4;
|
|
12
22
|
const ROUND_TOMBSTONE_TTL_MS = 30_000;
|
|
13
23
|
const CHILD_TOMBSTONE_TTL_MS = 5 * 60_000;
|
|
14
24
|
const MAX_INCR_MSGS = 5;
|
|
15
25
|
const MSG_TRUNCATE_LEN = 40;
|
|
16
26
|
/** 单次 tick 用 openclaw `agent.wait` 对账 subagent run 状态的探测超时。 */
|
|
17
27
|
const RUN_STATUS_PROBE_TIMEOUT_MS = 1_000;
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
const m = getOrCreateShared("subagent-monitor-runtime", () => ({
|
|
29
|
+
api: null,
|
|
30
|
+
apiCandidates: [],
|
|
31
|
+
apiProbe: "unverified",
|
|
32
|
+
ticker: null,
|
|
33
|
+
}));
|
|
20
34
|
export function setPluginApi(api) {
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
const isNewCandidate = api !== m.api && !m.apiCandidates.includes(api);
|
|
36
|
+
if (isNewCandidate) {
|
|
37
|
+
m.apiCandidates.push(api);
|
|
38
|
+
if (m.apiCandidates.length > MAX_API_CANDIDATES) {
|
|
39
|
+
m.apiCandidates.splice(0, m.apiCandidates.length - MAX_API_CANDIDATES);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (m.api === null) {
|
|
43
|
+
m.api = api;
|
|
44
|
+
m.apiProbe = "unverified";
|
|
45
|
+
console.log(`[subagent-monitor] setPluginApi instance=${MODULE_INSTANCE_ID} adopt=first`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (m.apiProbe === "good") {
|
|
49
|
+
// 已有确认可用的 runtime:拒绝未验证的新 runtime 覆盖,防止无绑定 registry 劫持监控。
|
|
50
|
+
if (isNewCandidate) {
|
|
51
|
+
console.warn(`[subagent-monitor] setPluginApi instance=${MODULE_INSTANCE_ID} keep=verified ` +
|
|
52
|
+
`candidates=${m.apiCandidates.length}`);
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (m.apiProbe === "unverified") {
|
|
57
|
+
// 当前尚未探测:不切换,等首次 tick 探测出结果再决定。
|
|
58
|
+
console.log(`[subagent-monitor] setPluginApi instance=${MODULE_INSTANCE_ID} keep=unverified ` +
|
|
59
|
+
`candidates=${m.apiCandidates.length}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// 当前已确认为不可用:采纳新候选重新探测。
|
|
63
|
+
m.api = api;
|
|
64
|
+
m.apiProbe = "unverified";
|
|
65
|
+
console.log(`[subagent-monitor] setPluginApi instance=${MODULE_INSTANCE_ID} adopt=switch candidates=${m.apiCandidates.length}`);
|
|
66
|
+
}
|
|
67
|
+
function isRequestScopedSubagentError(err) {
|
|
68
|
+
return err instanceof Error && err.name === "RequestScopedSubagentRuntimeError";
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 探测某个 plugin api 的 runtime.subagent 是否可用。
|
|
72
|
+
* RequestScopedSubagentRuntimeError = 绑定不可用(无绑定 registry / 非 gateway 上下文);
|
|
73
|
+
* 其它结果(如 runId 不存在返回 error/timeout)说明绑定存在、dispatch 通了,视为可用。
|
|
74
|
+
*/
|
|
75
|
+
async function probeApiUsable(api) {
|
|
76
|
+
try {
|
|
77
|
+
await api.runtime.subagent.waitForRun({ runId: "probe", timeoutMs: 1 });
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
return !isRequestScopedSubagentError(err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 确认当前 m.api 可用;若不可用,尝试从候选里切回可用的 runtime。
|
|
86
|
+
* 返回最终使用的 m.api(所有候选都不可用时仍返回当前,由事件路径兜底)。
|
|
87
|
+
*/
|
|
88
|
+
async function resolveUsablePluginApi() {
|
|
89
|
+
if (!m.api)
|
|
90
|
+
return null;
|
|
91
|
+
if (m.apiProbe === "good")
|
|
92
|
+
return m.api;
|
|
93
|
+
if (await probeApiUsable(m.api)) {
|
|
94
|
+
m.apiProbe = "good";
|
|
95
|
+
return m.api;
|
|
96
|
+
}
|
|
97
|
+
for (const candidate of m.apiCandidates) {
|
|
98
|
+
if (candidate === m.api)
|
|
99
|
+
continue;
|
|
100
|
+
if (await probeApiUsable(candidate)) {
|
|
101
|
+
console.warn(`[subagent-monitor] m.api switch instance=${MODULE_INSTANCE_ID} ` +
|
|
102
|
+
`candidates=${m.apiCandidates.length}`);
|
|
103
|
+
m.api = candidate;
|
|
104
|
+
m.apiProbe = "good";
|
|
105
|
+
return m.api;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
m.apiProbe = "bad";
|
|
109
|
+
return m.api;
|
|
23
110
|
}
|
|
24
111
|
export function getSubagentMonitorInstanceId() {
|
|
25
112
|
return MODULE_INSTANCE_ID;
|
|
@@ -35,9 +122,9 @@ function pruneTombstones(now = Date.now()) {
|
|
|
35
122
|
}
|
|
36
123
|
}
|
|
37
124
|
function stopTickerIfIdle() {
|
|
38
|
-
if (roundMonitors.size === 0 &&
|
|
39
|
-
clearInterval(
|
|
40
|
-
|
|
125
|
+
if (roundMonitors.size === 0 && m.ticker) {
|
|
126
|
+
clearInterval(m.ticker);
|
|
127
|
+
m.ticker = null;
|
|
41
128
|
}
|
|
42
129
|
}
|
|
43
130
|
function removeMonitor(monitor, reason) {
|
|
@@ -110,6 +197,10 @@ export function hasActiveSubagents(roundKey, generation) {
|
|
|
110
197
|
monitor.generation === generation &&
|
|
111
198
|
Array.from(monitor.subagents.values()).some((record) => !record.completed));
|
|
112
199
|
}
|
|
200
|
+
/** 子任务结束事件定位其所属轮次(供 turn-end-controller 递减活跃子任务数)。 */
|
|
201
|
+
export function findChildRoundIndex(childSessionKey) {
|
|
202
|
+
return childToRound.get(childSessionKey);
|
|
203
|
+
}
|
|
113
204
|
export function deferFinished(roundKey, generation, reason) {
|
|
114
205
|
deferredFinished.set(roundKey, { reason, generation });
|
|
115
206
|
}
|
|
@@ -183,33 +274,46 @@ async function settleMonitorIfComplete(monitor) {
|
|
|
183
274
|
return;
|
|
184
275
|
if (!Array.from(monitor.subagents.values()).every((record) => record.completed))
|
|
185
276
|
return;
|
|
186
|
-
const
|
|
187
|
-
|
|
277
|
+
const signature = statSignature(monitor);
|
|
278
|
+
if (signature === monitor.lastPushedSignature)
|
|
279
|
+
return;
|
|
280
|
+
// 整轮收尾(WS FINISHED + RUN_USAGE + completeActiveRound)改由 turn-end-controller 在
|
|
281
|
+
// 主会话出现非 yield 段终态(或静默兜底)后,由 dispatch wrapper 统一执行;
|
|
282
|
+
// 这里只负责推送 SUBAGENT_STAT 快照,绝不自行 end/remove/complete ——
|
|
283
|
+
// OpenClaw 7.1+/8.x 中「所有已知子任务完成」不代表整轮结束(主会话可能 resume
|
|
284
|
+
// 继续派发新一批子任务),因此本快照允许多波次多次推送,仅对完全相同的状态去重。
|
|
188
285
|
try {
|
|
189
286
|
await sendFinalStat(monitor, monitor.streamClient);
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
groupId: monitor.groupId,
|
|
193
|
-
replyToMsgId: monitor.replyToMsgId,
|
|
194
|
-
});
|
|
287
|
+
for (const record of monitor.subagents.values()) {
|
|
288
|
+
record.sendFrom = record.messages.length;
|
|
195
289
|
}
|
|
290
|
+
monitor.lastPushedSignature = signature;
|
|
291
|
+
console.log(`[subagent-monitor] final SUBAGENT_STAT sent (settle) roundKey=${monitor.roundKey} gen=${monitor.generation} ` +
|
|
292
|
+
`subagents=${Array.from(monitor.subagents.values()).length} — waiting turn-end for FINISHED`);
|
|
196
293
|
}
|
|
197
294
|
catch (err) {
|
|
198
295
|
console.error(`[subagent-monitor] final state send failed: ${String(err)}`);
|
|
199
296
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
297
|
+
turnOnAllChildrenDone(monitor.roundKey, monitor.generation);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* 整轮收尾时(dispatch wrapper 在 turn-end-controller 放行后)清理本轮监控。
|
|
301
|
+
* 与 removeMonitor 的 settle 路径不同:此处轮次真正结束,直接拆监控与子任务索引。
|
|
302
|
+
*/
|
|
303
|
+
export function finalizeRoundMonitoring(roundKey, generation) {
|
|
304
|
+
const monitor = roundMonitors.get(roundKey);
|
|
305
|
+
if (!monitor || monitor.generation !== generation)
|
|
306
|
+
return;
|
|
307
|
+
removeMonitor(monitor, "round-finished");
|
|
204
308
|
}
|
|
205
309
|
async function readSubagentMessages(record) {
|
|
206
|
-
if (!
|
|
310
|
+
if (!m.api || record.reading)
|
|
207
311
|
return;
|
|
208
312
|
record.reading = true;
|
|
209
313
|
try {
|
|
210
314
|
let messages = [];
|
|
211
315
|
try {
|
|
212
|
-
const result = await
|
|
316
|
+
const result = await m.api.runtime.subagent.getSessionMessages({
|
|
213
317
|
sessionKey: record.childSessionKey,
|
|
214
318
|
});
|
|
215
319
|
messages = Array.isArray(result.messages) ? result.messages : [];
|
|
@@ -232,10 +336,10 @@ async function readSubagentMessages(record) {
|
|
|
232
336
|
* 探测失败(如 runId 已不存在、状态码异常)保守按「仍在运行」处理,交给事件路径兜底。
|
|
233
337
|
*/
|
|
234
338
|
async function probeRunStatus(record) {
|
|
235
|
-
if (!
|
|
339
|
+
if (!m.api)
|
|
236
340
|
return false;
|
|
237
341
|
try {
|
|
238
|
-
const result = await
|
|
342
|
+
const result = await m.api.runtime.subagent.waitForRun({
|
|
239
343
|
runId: record.runId,
|
|
240
344
|
timeoutMs: RUN_STATUS_PROBE_TIMEOUT_MS,
|
|
241
345
|
});
|
|
@@ -247,17 +351,19 @@ async function probeRunStatus(record) {
|
|
|
247
351
|
}
|
|
248
352
|
}
|
|
249
353
|
function ensureTickerRunning() {
|
|
250
|
-
if (
|
|
354
|
+
if (m.ticker)
|
|
251
355
|
return;
|
|
252
356
|
void tick();
|
|
253
|
-
|
|
254
|
-
|
|
357
|
+
m.ticker = setInterval(() => void tick(), POLL_INTERVAL_MS);
|
|
358
|
+
m.ticker.unref?.();
|
|
255
359
|
}
|
|
256
360
|
async function tick() {
|
|
257
361
|
if (roundMonitors.size === 0) {
|
|
258
362
|
stopTickerIfIdle();
|
|
259
363
|
return;
|
|
260
364
|
}
|
|
365
|
+
// 确保使用可用的 runtime:探测并必要时切回候选中的可用 api,避免坏 runtime 继续抛 RequestScoped。
|
|
366
|
+
await resolveUsablePluginApi();
|
|
261
367
|
for (const monitor of Array.from(roundMonitors.values())) {
|
|
262
368
|
try {
|
|
263
369
|
const runningRecords = Array.from(monitor.subagents.values()).filter((record) => !record.completed);
|
|
@@ -325,7 +431,22 @@ function toSubagentList(monitor, incremental) {
|
|
|
325
431
|
: record.messages,
|
|
326
432
|
}));
|
|
327
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* 客户端可见状态的稳定签名:新增子任务、状态翻转(running→completed)或消息数变化都会改变。
|
|
436
|
+
* 仅凭它做「无变化不重复推送」的去重;同一轮多波次派发不会被锁死。
|
|
437
|
+
*/
|
|
438
|
+
function statSignature(monitor) {
|
|
439
|
+
return Array.from(monitor.subagents.values())
|
|
440
|
+
.map((r) => `${r.runId}:${r.completed ? "completed" : "running"}:${r.messages.length}`)
|
|
441
|
+
.join("|");
|
|
442
|
+
}
|
|
328
443
|
function sendWsStat(monitor, client) {
|
|
444
|
+
const signature = statSignature(monitor);
|
|
445
|
+
// 有 running 子任务时保持逐 tick 推送(running/新增消息语义不变);
|
|
446
|
+
// 全部已完成且状态无变化(等 turn-end 的空窗)则去重,避免 tick 刷同一份完成快照。
|
|
447
|
+
const hasRunning = Array.from(monitor.subagents.values()).some((r) => !r.completed);
|
|
448
|
+
if (!hasRunning && signature === monitor.lastPushedSignature)
|
|
449
|
+
return;
|
|
329
450
|
const subagentList = toSubagentList(monitor, true);
|
|
330
451
|
client
|
|
331
452
|
.sendEvent({
|
|
@@ -340,6 +461,7 @@ function sendWsStat(monitor, client) {
|
|
|
340
461
|
if (record)
|
|
341
462
|
record.sendFrom += item.messages.length;
|
|
342
463
|
});
|
|
464
|
+
monitor.lastPushedSignature = signature;
|
|
343
465
|
})
|
|
344
466
|
.catch((err) => {
|
|
345
467
|
console.error(`[subagent-monitor] SUBAGENT_STAT failed: ${String(err)}`);
|
|
@@ -357,10 +479,16 @@ export function __tickForTests() {
|
|
|
357
479
|
return tick();
|
|
358
480
|
}
|
|
359
481
|
export function __resetSubagentMonitorForTests() {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
482
|
+
disposeSubagentMonitor();
|
|
483
|
+
}
|
|
484
|
+
/** 插件卸载/重载时停掉 subagent-monitor 的全部轮询与状态,避免旧实例 ticker 泄漏。 */
|
|
485
|
+
export function disposeSubagentMonitor() {
|
|
486
|
+
if (m.ticker)
|
|
487
|
+
clearInterval(m.ticker);
|
|
488
|
+
m.ticker = null;
|
|
489
|
+
m.api = null;
|
|
490
|
+
m.apiProbe = "unverified";
|
|
491
|
+
m.apiCandidates.length = 0;
|
|
364
492
|
childToRound.clear();
|
|
365
493
|
roundMonitors.clear();
|
|
366
494
|
deferredFinished.clear();
|