@xopcai/xopc 0.0.82 → 0.0.83
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +2 -3
- package/dist/extensions/feishu/src/outbound/media-load.js.map +1 -1
- package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
- package/dist/extensions/telegram/src/config-schema.d.ts +6 -6
- package/dist/extensions/telegram/src/plugin.d.ts +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +3 -3
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/gateway/static/root/assets/agents-CrpYTHJS.js +222 -0
- package/dist/gateway/static/root/assets/{apps-page-pJ27dsqn.js → apps-page-1mcKh5Rh.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-zd6QNKPx.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-D1KYmOmi.js → channels-status-swr-uRAuhiUo.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-Y2wfSJVI.js → cron-api-O2Q_ruV6.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-B97KU_RG.js → cron-page-By09AQD-.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-CboA_Css.js → dist-BpQxde0t.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DN_zNmpo.js → extension-debug-page-CY27wj_p.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BUXtOzv5.js → extension-page-C-Ed5ZmP.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-C2dX4KCW.js → extension-settings-page-raLux7E7.js} +1 -1
- package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +3 -0
- package/dist/gateway/static/root/assets/{field-primitives-B9rOLqdm.js → field-primitives-fa_hiQcX.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-DvfiRVrc.js → heartbeat-config-api-BVl5VHvL.js} +1 -1
- package/dist/gateway/static/root/assets/index-BuFldCsB.css +1 -0
- package/dist/gateway/static/root/assets/{index-DQuaMye9.js → index-Y-iqo-gL.js} +94 -85
- package/dist/gateway/static/root/assets/{logs-page-BQuBpHcc.js → logs-page-BdH2n7ZW.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-Vpchzdp-.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-2Yu-FASs.js → settings-form-section-Kk1yAGBl.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-KBm0u6Dz.js +3 -0
- package/dist/gateway/static/root/assets/skills-page-BjeXXaOn.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-DnwYutiX.js → theme-store-D01dJt95.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-D2Gn2qod.js → utils-DpTxN4AF.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CwO8Cf01.js +1 -0
- package/dist/gateway/static/root/index.html +4 -4
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +50 -0
- package/dist/src/agent/agent-instance-gateway.js +1 -0
- package/dist/src/agent/agent-manager.d.ts +20 -14
- package/dist/src/agent/agent-manager.js +74 -186
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/background-review/coordinator.d.ts +61 -0
- package/dist/src/agent/background-review/coordinator.js +120 -0
- package/dist/src/agent/background-review/coordinator.js.map +1 -0
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +14 -0
- package/dist/src/agent/child-agent-factory.js +2 -8
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/context/workspace-seed.js +3 -3
- package/dist/src/agent/embedded/index.d.ts +1 -2
- package/dist/src/agent/embedded/index.js +2 -3
- package/dist/src/agent/embedded/run-for-session.d.ts +2 -2
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/agent/embedded/runs.d.ts +32 -0
- package/dist/src/agent/embedded/runs.js +79 -19
- package/dist/src/agent/embedded/runs.js.map +1 -1
- package/dist/src/agent/embedded/session-manager-cache.d.ts +14 -0
- package/dist/src/agent/embedded/session-manager-cache.js +32 -11
- package/dist/src/agent/embedded/session-manager-cache.js.map +1 -1
- package/dist/src/agent/embedded/session-runner.d.ts +37 -7
- package/dist/src/agent/embedded/session-runner.js +184 -153
- package/dist/src/agent/embedded/session-runner.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.d.ts +57 -9
- package/dist/src/agent/embedded/session-tool-result-guard.js +159 -67
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/persistent-goal-service.d.ts +84 -0
- package/dist/src/agent/goals/persistent-goal-service.js +139 -0
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -0
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/goals/state.d.ts +1 -1
- package/dist/src/agent/goals/state.js.map +1 -1
- package/dist/src/agent/image/load-image-media.js +1 -1
- package/dist/src/agent/inbound/inbound-loop.d.ts +77 -0
- package/dist/src/agent/inbound/inbound-loop.js +226 -0
- package/dist/src/agent/inbound/inbound-loop.js.map +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +80 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +138 -0
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -0
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +2 -2
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -1
- package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
- package/dist/src/agent/lifecycle/manager.d.ts +1 -1
- package/dist/src/agent/lifecycle/manager.js.map +1 -1
- package/dist/src/agent/lifecycle/types.d.ts +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.d.ts +12 -2
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js.map +1 -1
- package/dist/src/agent/memory/index.js +3 -3
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/memory/prefetch-coordinator.d.ts +37 -0
- package/dist/src/agent/memory/prefetch-coordinator.js +45 -0
- package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -0
- package/dist/src/agent/messaging/command-handler.d.ts +5 -1
- package/dist/src/agent/messaging/command-handler.js +24 -96
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/messaging/index.d.ts +1 -0
- package/dist/src/agent/messaging/index.js +2 -1
- package/dist/src/agent/messaging/message-router.d.ts +1 -1
- package/dist/src/agent/messaging/message-router.js.map +1 -1
- package/dist/src/agent/messaging/outbound-coordinator.d.ts +82 -0
- package/dist/src/agent/messaging/outbound-coordinator.js +123 -0
- package/dist/src/agent/messaging/outbound-coordinator.js.map +1 -0
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/orchestration/agent-event-handler.d.ts +36 -33
- package/dist/src/agent/orchestration/agent-event-handler.js +212 -174
- package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.d.ts +4 -4
- package/dist/src/agent/orchestration/agent-orchestrator.js +4 -8
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/orchestration/index.d.ts +1 -1
- package/dist/src/agent/orchestration/index.js +2 -2
- package/dist/src/agent/prompt/service-prompt-builder.js +4 -4
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +1 -1
- package/dist/src/agent/service/async-queue.d.ts +20 -0
- package/dist/src/agent/service/async-queue.js +53 -0
- package/dist/src/agent/service/async-queue.js.map +1 -0
- package/dist/src/agent/service/build-direct-message-content.d.ts +2 -2
- package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +70 -0
- package/dist/src/agent/service/direct-turn-helpers.js +90 -0
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -0
- package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -3
- package/dist/src/agent/service/process-direct-one-shot.js +17 -34
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
- package/dist/src/agent/service/process-direct-streaming.js +122 -168
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service/webchat-tts.d.ts +2 -2
- package/dist/src/agent/service/webchat-tts.js +1 -1
- package/dist/src/agent/service/webchat-tts.js.map +1 -1
- package/dist/src/agent/service.d.ts +62 -167
- package/dist/src/agent/service.js +177 -786
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/index.d.ts +4 -0
- package/dist/src/agent/session/index.js +5 -1
- package/dist/src/agent/session/session-config-service.d.ts +68 -0
- package/dist/src/agent/session/session-config-service.js +172 -0
- package/dist/src/agent/session/session-config-service.js.map +1 -0
- package/dist/src/agent/session/session-context.d.ts +27 -19
- package/dist/src/agent/session/session-context.js +39 -24
- package/dist/src/agent/session/session-context.js.map +1 -1
- package/dist/src/agent/session/session-hydrator.d.ts +42 -0
- package/dist/src/agent/session/session-hydrator.js +66 -0
- package/dist/src/agent/session/session-hydrator.js.map +1 -0
- package/dist/src/agent/session/session-inspector.d.ts +80 -0
- package/dist/src/agent/session/session-inspector.js +119 -0
- package/dist/src/agent/session/session-inspector.js.map +1 -0
- package/dist/src/agent/session/session-state-bag.d.ts +83 -0
- package/dist/src/agent/session/session-state-bag.js +192 -0
- package/dist/src/agent/session/session-state-bag.js.map +1 -0
- package/dist/src/agent/skills/config.js +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +2 -2
- package/dist/src/agent/skills/index.d.ts +0 -2
- package/dist/src/agent/skills/index.js +3 -5
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -6
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +35 -7
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +2 -2
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +7 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +37 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/delegate-tool.d.ts +7 -0
- package/dist/src/agent/tools/delegate-tool.js +2 -1
- package/dist/src/agent/tools/delegate-tool.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/executor.d.ts +34 -15
- package/dist/src/agent/tools/executor.js +44 -79
- package/dist/src/agent/tools/executor.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +6 -0
- package/dist/src/agent/tools/factory.js +63 -4
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/skills-tools.js +1 -1
- package/dist/src/agent/tools/tts-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/agent/workspace-runtime/registry.d.ts +48 -0
- package/dist/src/agent/workspace-runtime/registry.js +59 -0
- package/dist/src/agent/workspace-runtime/registry.js.map +1 -0
- package/dist/src/auth/credentials.js +3 -3
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +4 -3
- package/dist/src/browser/cdp-local-launcher.js.map +1 -1
- package/dist/src/browser/index.d.ts +1 -0
- package/dist/src/browser/index.js +2 -1
- package/dist/src/browser/manager.js +3 -2
- package/dist/src/browser/manager.js.map +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/browser-use.js +2 -1
- package/dist/src/browser/providers/browser-use.js.map +1 -1
- package/dist/src/browser/providers/browserbase.js +2 -1
- package/dist/src/browser/providers/browserbase.js.map +1 -1
- package/dist/src/browser/providers/cloakbrowser.js +7 -6
- package/dist/src/browser/providers/cloakbrowser.js.map +1 -1
- package/dist/src/browser/providers/playwright-doctor.d.ts +2 -0
- package/dist/src/browser/providers/playwright-doctor.js +7 -3
- package/dist/src/browser/providers/playwright-doctor.js.map +1 -1
- package/dist/src/browser/readiness.d.ts +33 -0
- package/dist/src/browser/readiness.js +138 -0
- package/dist/src/browser/readiness.js.map +1 -0
- package/dist/src/browser/stealth.js +2 -2
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/channel-domain.d.ts +1 -1
- package/dist/src/channels/config-helpers.d.ts +1 -1
- package/dist/src/channels/config-helpers.js.map +1 -1
- package/dist/src/channels/heartbeat-scheduler.d.ts +40 -0
- package/dist/src/channels/heartbeat-scheduler.js +94 -0
- package/dist/src/channels/heartbeat-scheduler.js.map +1 -0
- package/dist/src/channels/lifecycle-supervisor.d.ts +81 -0
- package/dist/src/channels/lifecycle-supervisor.js +263 -0
- package/dist/src/channels/lifecycle-supervisor.js.map +1 -0
- package/dist/src/channels/manager.d.ts +34 -68
- package/dist/src/channels/manager.js +107 -477
- package/dist/src/channels/manager.js.map +1 -1
- package/dist/src/channels/outbound/deliver.d.ts +1 -1
- package/dist/src/channels/outbound/deliver.js.map +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/outbound-sender.d.ts +51 -0
- package/dist/src/channels/outbound-sender.js +125 -0
- package/dist/src/channels/outbound-sender.js.map +1 -0
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-service.d.ts +3 -10
- package/dist/src/channels/pairing/pairing-service.js.map +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/channels/pairing/pairing-types.d.ts +15 -0
- package/dist/src/channels/pairing/pairing-types.js +1 -0
- package/dist/src/channels/plugin-registry.d.ts +22 -0
- package/dist/src/channels/plugin-registry.js +44 -0
- package/dist/src/channels/plugin-registry.js.map +1 -0
- package/dist/src/channels/plugin-types.d.ts +1 -1
- package/dist/src/channels/plugins/types.adapters.d.ts +2 -2
- package/dist/src/channels/security-helpers.d.ts +1 -1
- package/dist/src/channels/security-helpers.js.map +1 -1
- package/dist/src/channels/setup-wizard.d.ts +1 -1
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/commands/agent/stream-renderer.js +1 -1
- package/dist/src/cli/commands/agent/stream-renderer.js.map +1 -1
- package/dist/src/cli/commands/agent.js +4 -4
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/browser-cli-helpers.js +2 -1
- package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -2
- package/dist/src/cli/commands/extension-dev.js.map +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/call.js +1 -1
- package/dist/src/cli/commands/gateway/call.js.map +1 -1
- package/dist/src/cli/commands/gateway/health.js +1 -1
- package/dist/src/cli/commands/gateway/health.js.map +1 -1
- package/dist/src/cli/commands/gateway/lifecycle-core.d.ts +31 -12
- package/dist/src/cli/commands/gateway/lifecycle-core.js +167 -116
- package/dist/src/cli/commands/gateway/lifecycle-core.js.map +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.d.ts +11 -0
- package/dist/src/cli/commands/gateway/lifecycle.js +102 -0
- package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -0
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/gateway/logs.js.map +1 -1
- package/dist/src/cli/commands/gateway/probe.js +1 -1
- package/dist/src/cli/commands/gateway/probe.js.map +1 -1
- package/dist/src/cli/commands/gateway/restart-health.d.ts +12 -0
- package/dist/src/cli/commands/gateway/restart-health.js +45 -1
- package/dist/src/cli/commands/gateway/restart-health.js.map +1 -1
- package/dist/src/cli/commands/gateway/restart.js +3 -3
- package/dist/src/cli/commands/gateway/restart.js.map +1 -1
- package/dist/src/cli/commands/gateway/run-foreground.d.ts +0 -1
- package/dist/src/cli/commands/gateway/run-foreground.js +0 -35
- package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
- package/dist/src/cli/commands/gateway/service.js +1 -1
- package/dist/src/cli/commands/gateway/service.js.map +1 -1
- package/dist/src/cli/commands/gateway/shared.d.ts +3 -0
- package/dist/src/cli/commands/gateway/shared.js +54 -0
- package/dist/src/cli/commands/gateway/shared.js.map +1 -0
- package/dist/src/cli/commands/gateway/status.js +1 -1
- package/dist/src/cli/commands/gateway/status.js.map +1 -1
- package/dist/src/cli/commands/gateway/stop.js +2 -2
- package/dist/src/cli/commands/gateway/stop.js.map +1 -1
- package/dist/src/cli/commands/gateway/token.js +1 -1
- package/dist/src/cli/commands/gateway/token.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +5 -5
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/image.js +2 -2
- package/dist/src/cli/commands/image.js.map +1 -1
- package/dist/src/cli/commands/init.js +4 -4
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/models.js.map +1 -1
- package/dist/src/cli/commands/onboard/gateway.d.ts +0 -8
- package/dist/src/cli/commands/onboard/gateway.js +48 -49
- package/dist/src/cli/commands/onboard/gateway.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +9 -64
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/session/utils.js +1 -1
- package/dist/src/cli/commands/session/utils.js.map +1 -1
- package/dist/src/cli/commands/skills.js +1 -1
- package/dist/src/cli/commands/tailscale.js +1 -1
- package/dist/src/cli/commands/tailscale.js.map +1 -1
- package/dist/src/cli/context.d.ts +20 -0
- package/dist/src/cli/context.js +23 -0
- package/dist/src/cli/context.js.map +1 -0
- package/dist/src/cli/extension-cli-register.js +3 -3
- package/dist/src/cli/gateway-run-argv.js +1 -4
- package/dist/src/cli/gateway-run-argv.js.map +1 -1
- package/dist/src/cli/gateway-run-fast-path.js +1 -1
- package/dist/src/cli/gateway-run-fast-path.js.map +1 -1
- package/dist/src/cli/index.d.ts +1 -7
- package/dist/src/cli/index.js +4 -6
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/config/commands.flags.d.ts +3 -0
- package/dist/src/config/commands.flags.js +11 -0
- package/dist/src/config/commands.flags.js.map +1 -0
- package/dist/src/config/index.d.ts +1 -0
- package/dist/src/config/index.js +6 -5
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/schema.d.ts +11 -4
- package/dist/src/config/schema.js +13 -12
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/workspace-path-helpers.d.ts +15 -0
- package/dist/src/config/workspace-path-helpers.js +14 -0
- package/dist/src/config/workspace-path-helpers.js.map +1 -0
- package/dist/src/cron/executor.js +4 -4
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/daemon/index.d.ts +0 -1
- package/dist/src/daemon/index.js +1 -2
- package/dist/src/daemon/install-plan.js +3 -2
- package/dist/src/daemon/install-plan.js.map +1 -1
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/daemon/types.d.ts +0 -6
- package/dist/src/extensions/api.d.ts +1 -1
- package/dist/src/extensions/api.js +2 -2
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/extension-registry-impl.d.ts +51 -0
- package/dist/src/extensions/extension-registry-impl.js +117 -0
- package/dist/src/extensions/extension-registry-impl.js.map +1 -0
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/index.js +3 -2
- package/dist/src/extensions/loader.d.ts +3 -43
- package/dist/src/extensions/loader.js +3 -110
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/extensions/sdk/index.js +2 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/events.d.ts +7 -1
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/heartbeat/service.js +2 -2
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/app.js +5 -53
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +1 -1
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/middleware/auth.d.ts +5 -14
- package/dist/src/gateway/hono/middleware/auth.js +89 -126
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- package/dist/src/gateway/hono/middleware/logger.js +1 -1
- package/dist/src/gateway/hono/middleware/logger.js.map +1 -1
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +14 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +62 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js.map +1 -0
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +4 -4
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
- package/dist/src/gateway/hono/routes/browser.d.ts +20 -0
- package/dist/src/gateway/hono/routes/browser.js +626 -0
- package/dist/src/gateway/hono/routes/browser.js.map +1 -0
- package/dist/src/gateway/hono/routes/commands-skills.js +13 -13
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.d.ts +18 -0
- package/dist/src/gateway/hono/routes/config-patch/agents.js +418 -0
- package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +12 -0
- package/dist/src/gateway/hono/routes/config-patch/channels.js +186 -0
- package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +18 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +264 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/index.d.ts +9 -0
- package/dist/src/gateway/hono/routes/config-patch/index.js +6 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +23 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.js +139 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/result.d.ts +18 -0
- package/dist/src/gateway/hono/routes/config-patch/result.js +13 -0
- package/dist/src/gateway/hono/routes/config-patch/result.js.map +1 -0
- package/dist/src/gateway/hono/routes/config.js +20 -1764
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +2 -3
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -5
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +1 -2
- package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +32 -32
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +4 -4
- package/dist/src/gateway/hono/routes/shares.js.map +1 -1
- package/dist/src/gateway/hono/routes/tunnel.js +1 -1
- package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +6 -7
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/index.d.ts +1 -1
- package/dist/src/gateway/index.js +4 -2
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/rate-limit/auth-policy.d.ts +34 -0
- package/dist/src/gateway/rate-limit/auth-policy.js +49 -0
- package/dist/src/gateway/rate-limit/auth-policy.js.map +1 -0
- package/dist/src/gateway/rate-limit/buckets.d.ts +63 -0
- package/dist/src/gateway/rate-limit/buckets.js +143 -0
- package/dist/src/gateway/rate-limit/buckets.js.map +1 -0
- package/dist/src/gateway/rate-limit/env-flags.d.ts +13 -0
- package/dist/src/gateway/rate-limit/env-flags.js +16 -0
- package/dist/src/gateway/rate-limit/env-flags.js.map +1 -0
- package/dist/src/gateway/rate-limit/index.d.ts +3 -0
- package/dist/src/gateway/rate-limit/index.js +4 -0
- package/dist/src/gateway/run-loop.d.ts +1 -1
- package/dist/src/gateway/run-loop.js +24 -4
- package/dist/src/gateway/run-loop.js.map +1 -1
- package/dist/src/gateway/runtime-config.js +2 -1
- package/dist/src/gateway/runtime-config.js.map +1 -1
- package/dist/src/gateway/security/audit.js +2 -1
- package/dist/src/gateway/security/audit.js.map +1 -1
- package/dist/src/gateway/security/index.d.ts +0 -1
- package/dist/src/gateway/security/index.js +1 -2
- package/dist/src/gateway/security/loopback.d.ts +13 -0
- package/dist/src/gateway/security/loopback.js +45 -0
- package/dist/src/gateway/security/loopback.js.map +1 -0
- package/dist/src/gateway/service/agent-runner.d.ts +108 -0
- package/dist/src/gateway/service/agent-runner.js +184 -0
- package/dist/src/gateway/service/agent-runner.js.map +1 -0
- package/dist/src/gateway/service/config-coordinator.d.ts +119 -0
- package/dist/src/gateway/service/config-coordinator.js +351 -0
- package/dist/src/gateway/service/config-coordinator.js.map +1 -0
- package/dist/src/gateway/service/marketplace-service.d.ts +85 -0
- package/dist/src/gateway/service/marketplace-service.js +239 -0
- package/dist/src/gateway/service/marketplace-service.js.map +1 -0
- package/dist/src/gateway/service/run-gateway-agent.js +5 -5
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +125 -0
- package/dist/src/gateway/service/sessions-api.js +135 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -0
- package/dist/src/gateway/service.d.ts +30 -360
- package/dist/src/gateway/service.js +121 -903
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -2
- package/dist/src/gateway/workspace-heartbeat-path.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/gateway-process-argv.d.ts +4 -0
- package/dist/src/infra/gateway-process-argv.js +26 -0
- package/dist/src/infra/gateway-process-argv.js.map +1 -0
- package/dist/src/infra/gateway-processes.d.ts +5 -0
- package/dist/src/infra/gateway-processes.js +65 -0
- package/dist/src/infra/gateway-processes.js.map +1 -0
- package/dist/src/infra/rate-limit/failure-limiter.d.ts +50 -0
- package/dist/src/infra/rate-limit/failure-limiter.js +100 -0
- package/dist/src/infra/rate-limit/failure-limiter.js.map +1 -0
- package/dist/src/infra/rate-limit/index.d.ts +5 -0
- package/dist/src/infra/rate-limit/index.js +3 -0
- package/dist/src/infra/rate-limit/keyed-store.d.ts +34 -0
- package/dist/src/infra/rate-limit/keyed-store.js +44 -0
- package/dist/src/infra/rate-limit/keyed-store.js.map +1 -0
- package/dist/src/infra/rate-limit/rate-limiter.d.ts +39 -0
- package/dist/src/infra/rate-limit/rate-limiter.js +65 -0
- package/dist/src/infra/rate-limit/rate-limiter.js.map +1 -0
- package/dist/src/infra/restart.d.ts +21 -0
- package/dist/src/infra/restart.js +122 -0
- package/dist/src/infra/restart.js.map +1 -0
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-lock.js +3 -3
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +2 -2
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/mcp/channel-bridge.d.ts +0 -6
- package/dist/src/mcp/channel-bridge.js +1 -5
- package/dist/src/mcp/channel-bridge.js.map +1 -1
- package/dist/src/media-shared/http/ssrf-guard.js +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.js +2 -2
- package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
- package/dist/src/session/parity/sessions-json-file-read.d.ts +2 -1
- package/dist/src/session/parity/sessions-json-file-read.js.map +1 -1
- package/dist/src/session/parity/sessions-json-file.js +1 -1
- package/dist/src/session/parity/transcript-file-lock.js +2 -2
- package/dist/src/session/parity/transcript-paths.js +1 -1
- package/dist/src/session/search-index-cache.js +1 -1
- package/dist/src/session/search-index.js +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +5 -5
- package/dist/src/share/share-rate-limit.d.ts +10 -2
- package/dist/src/share/share-rate-limit.js +33 -42
- package/dist/src/share/share-rate-limit.js.map +1 -1
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/tui/backends/embedded-backend.js +16 -12
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/clipboard-image.js +2 -2
- package/dist/src/tui/extension-host/load-extensions.js +1 -1
- package/dist/src/tui/format-tui-hotkeys.js +1 -1
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +1 -1
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui-skills-autocomplete.js +1 -1
- package/dist/src/tui/tui.js +1 -2
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/tui/xopc-tui-keybindings.d.ts +0 -1
- package/dist/src/tui/xopc-tui-keybindings.js +1 -2
- package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
- package/dist/src/tunnel/frpc-binary.js +2 -2
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/pairing-rate-limit.d.ts +10 -2
- package/dist/src/tunnel/pairing-rate-limit.js +19 -15
- package/dist/src/tunnel/pairing-rate-limit.js.map +1 -1
- package/dist/src/tunnel/tunnel-rate-limit.d.ts +6 -3
- package/dist/src/tunnel/tunnel-rate-limit.js +11 -22
- package/dist/src/tunnel/tunnel-rate-limit.js.map +1 -1
- package/dist/src/tunnel/tunnel-state.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/utils/logger/stats.d.ts +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/factory.js +1 -1
- package/dist/src/voice/tts/index.js +2 -2
- package/dist/src/voice/tts/merge-config.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +1 -1
- package/dist/src/voice/tts/service.js +1 -1
- package/dist/src/voice/tts/service.js.map +1 -1
- package/dist/src/voice/tts/speak-core.js +1 -1
- package/package.json +10 -5
- package/dist/gateway/static/root/assets/agents-Cqh1ts38.js +0 -222
- package/dist/gateway/static/root/assets/channels-settings-wTiWStg9.js +0 -1
- package/dist/gateway/static/root/assets/fetch-BAAh_kXG.js +0 -3
- package/dist/gateway/static/root/assets/index-C8yHX-AA.css +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BeiFm0Ms.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-RPAz_Wg_.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-Wu4aNWDx.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-BxIGhhEL.js +0 -1
- package/dist/src/agent/embedded/session-raw-append-message.d.ts +0 -11
- package/dist/src/agent/embedded/session-raw-append-message.js +0 -15
- package/dist/src/agent/embedded/session-raw-append-message.js.map +0 -1
- package/dist/src/agent/embedded/session-tool-result-guard-wrapper.d.ts +0 -15
- package/dist/src/agent/embedded/session-tool-result-guard-wrapper.js +0 -24
- package/dist/src/agent/embedded/session-tool-result-guard-wrapper.js.map +0 -1
- package/dist/src/agent/embedded/session-tool-result-state.d.ts +0 -17
- package/dist/src/agent/embedded/session-tool-result-state.js +0 -26
- package/dist/src/agent/embedded/session-tool-result-state.js.map +0 -1
- package/dist/src/daemon/launchd-restart-handoff.d.ts +0 -25
- package/dist/src/daemon/launchd-restart-handoff.js +0 -132
- package/dist/src/daemon/launchd-restart-handoff.js.map +0 -1
- package/dist/src/gateway/auth-rate-limit.d.ts +0 -71
- package/dist/src/gateway/auth-rate-limit.js +0 -192
- package/dist/src/gateway/auth-rate-limit.js.map +0 -1
- package/dist/src/gateway/restart-handler.d.ts +0 -14
- package/dist/src/gateway/restart-handler.js +0 -64
- package/dist/src/gateway/restart-handler.js.map +0 -1
- package/dist/src/gateway/security/flood-guard.d.ts +0 -28
- package/dist/src/gateway/security/flood-guard.js +0 -42
- package/dist/src/gateway/security/flood-guard.js.map +0 -1
- package/dist/src/infra/rate-limit.d.ts +0 -38
- package/dist/src/infra/rate-limit.js +0 -60
- package/dist/src/infra/rate-limit.js.map +0 -1
- package/dist/src/infra/restart-intent.d.ts +0 -13
- package/dist/src/infra/restart-intent.js +0 -40
- package/dist/src/infra/restart-intent.js.map +0 -1
- package/dist/src/infra/restart-sentinel.d.ts +0 -23
- package/dist/src/infra/restart-sentinel.js +0 -75
- package/dist/src/infra/restart-sentinel.js.map +0 -1
- package/skills/creative/canvas-design/LICENSE.txt +0 -202
- package/skills/creative/canvas-design/SKILL-zh.md +0 -130
- package/skills/creative/canvas-design/SKILL.md +0 -130
- package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
- package/skills/creative/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
//#region src/channels/heartbeat-scheduler.ts
|
|
4
|
+
init_logger();
|
|
5
|
+
const log = createLogger("ChannelHeartbeatScheduler");
|
|
6
|
+
/** Minimum gap between successive soft-restart attempts for the same channel. */
|
|
7
|
+
const HEARTBEAT_RESTART_THROTTLE_MS = 6e4;
|
|
8
|
+
var ChannelHeartbeatScheduler = class {
|
|
9
|
+
opts;
|
|
10
|
+
/** Key shape: `${pluginId}:${accountId}`. */
|
|
11
|
+
timers = /* @__PURE__ */ new Map();
|
|
12
|
+
lastRestartAt = /* @__PURE__ */ new Map();
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
this.opts = opts;
|
|
15
|
+
}
|
|
16
|
+
/** Register heartbeat checks for every account exposed by the plugin. */
|
|
17
|
+
schedule(plugin) {
|
|
18
|
+
const hb = plugin.heartbeat;
|
|
19
|
+
if (!hb) return;
|
|
20
|
+
this.clear(plugin.id);
|
|
21
|
+
let accountIds;
|
|
22
|
+
try {
|
|
23
|
+
accountIds = plugin.config.listAccountIds(this.opts.getConfig());
|
|
24
|
+
} catch (err) {
|
|
25
|
+
log.warn({
|
|
26
|
+
channel: plugin.id,
|
|
27
|
+
err
|
|
28
|
+
}, "Heartbeat: failed to list accounts");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const accountId of accountIds) {
|
|
32
|
+
const key = `${plugin.id}:${accountId}`;
|
|
33
|
+
const timer = setInterval(() => void this.runProbe(plugin, accountId), hb.intervalMs);
|
|
34
|
+
this.timers.set(key, timer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Drop every probe scheduled for `pluginId` (called on stop / soft-restart). */
|
|
38
|
+
clear(pluginId) {
|
|
39
|
+
const prefix = `${pluginId}:`;
|
|
40
|
+
for (const key of [...this.timers.keys()]) {
|
|
41
|
+
if (!key.startsWith(prefix)) continue;
|
|
42
|
+
clearInterval(this.timers.get(key));
|
|
43
|
+
this.timers.delete(key);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Test helper / process shutdown. */
|
|
47
|
+
clearAll() {
|
|
48
|
+
for (const timer of this.timers.values()) clearInterval(timer);
|
|
49
|
+
this.timers.clear();
|
|
50
|
+
this.lastRestartAt.clear();
|
|
51
|
+
}
|
|
52
|
+
async runProbe(plugin, accountId) {
|
|
53
|
+
const hb = plugin.heartbeat;
|
|
54
|
+
if (!hb) return;
|
|
55
|
+
const cfg = this.opts.getConfig();
|
|
56
|
+
try {
|
|
57
|
+
const r = await hb.check({
|
|
58
|
+
cfg,
|
|
59
|
+
accountId
|
|
60
|
+
});
|
|
61
|
+
this.opts.healthMonitor.set(plugin.id, accountId, {
|
|
62
|
+
healthy: r.healthy,
|
|
63
|
+
lastCheckAt: Date.now(),
|
|
64
|
+
detail: typeof r.details === "string" ? r.details : r.details != null ? JSON.stringify(r.details) : void 0
|
|
65
|
+
});
|
|
66
|
+
if (!r.healthy) {
|
|
67
|
+
log.warn({
|
|
68
|
+
channel: plugin.id,
|
|
69
|
+
accountId,
|
|
70
|
+
detail: r.details
|
|
71
|
+
}, "Channel heartbeat unhealthy");
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
if (now - (this.lastRestartAt.get(plugin.id) ?? 0) < HEARTBEAT_RESTART_THROTTLE_MS) return;
|
|
74
|
+
this.lastRestartAt.set(plugin.id, now);
|
|
75
|
+
this.opts.requestSoftRestart(plugin.id);
|
|
76
|
+
}
|
|
77
|
+
} catch (err) {
|
|
78
|
+
this.opts.healthMonitor.set(plugin.id, accountId, {
|
|
79
|
+
healthy: false,
|
|
80
|
+
lastCheckAt: Date.now(),
|
|
81
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
82
|
+
});
|
|
83
|
+
log.error({
|
|
84
|
+
channel: plugin.id,
|
|
85
|
+
accountId,
|
|
86
|
+
err
|
|
87
|
+
}, "Channel heartbeat check failed");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
//#endregion
|
|
92
|
+
export { ChannelHeartbeatScheduler };
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=heartbeat-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat-scheduler.js","names":[],"sources":["../../../src/channels/heartbeat-scheduler.ts"],"sourcesContent":["/**\n * ChannelHeartbeatScheduler — runs per-account heartbeat probes for plugins\n * that expose a `heartbeat.check(...)` hook, records the result in the shared\n * {@link ChannelHealthMonitor}, and asks the lifecycle supervisor for a soft\n * restart when a check fails (rate-limited to once per minute per channel).\n *\n * Previously this lived as `_scheduleHeartbeat` + `_clearHeartbeatTimers` +\n * `_softRestartChannel` + two private Maps on `ChannelManager`. Extracting it\n * makes the heartbeat policy testable in isolation and lets the lifecycle\n * supervisor focus on plugin start/stop without worrying about timer wiring.\n */\n\nimport type { Config } from '../config/schema.js';\n\nimport type { ChannelPlugin } from './plugin-types.js';\nimport type { ChannelHealthMonitor } from './health-monitor.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst log = createLogger('ChannelHeartbeatScheduler');\n\n/** Minimum gap between successive soft-restart attempts for the same channel. */\nconst HEARTBEAT_RESTART_THROTTLE_MS = 60_000;\n\nexport interface ChannelHeartbeatSchedulerOptions {\n /** Effective config snapshot (per-account listing comes from `plugin.config.listAccountIds(cfg)`). */\n getConfig: () => Config;\n /** Shared health monitor that channel APIs surface to the UI. */\n healthMonitor: ChannelHealthMonitor;\n /**\n * Triggered when a check fails AND we are past the restart-throttle window.\n * The supervisor performs `stop()` + `startPlugin()`; the scheduler does not\n * touch plugin lifecycle directly.\n */\n requestSoftRestart: (channelId: string) => void;\n}\n\nexport class ChannelHeartbeatScheduler {\n private readonly opts: ChannelHeartbeatSchedulerOptions;\n /** Key shape: `${pluginId}:${accountId}`. */\n private readonly timers = new Map<string, ReturnType<typeof setInterval>>();\n private readonly lastRestartAt = new Map<string, number>();\n\n constructor(opts: ChannelHeartbeatSchedulerOptions) {\n this.opts = opts;\n }\n\n /** Register heartbeat checks for every account exposed by the plugin. */\n schedule(plugin: ChannelPlugin): void {\n const hb = plugin.heartbeat;\n if (!hb) return;\n\n this.clear(plugin.id);\n\n let accountIds: string[];\n try {\n accountIds = plugin.config.listAccountIds(this.opts.getConfig());\n } catch (err) {\n log.warn({ channel: plugin.id, err }, 'Heartbeat: failed to list accounts');\n return;\n }\n\n for (const accountId of accountIds) {\n const key = `${plugin.id}:${accountId}`;\n const timer = setInterval(\n () => void this.runProbe(plugin, accountId),\n hb.intervalMs,\n );\n this.timers.set(key, timer);\n }\n }\n\n /** Drop every probe scheduled for `pluginId` (called on stop / soft-restart). */\n clear(pluginId: string): void {\n const prefix = `${pluginId}:`;\n for (const key of [...this.timers.keys()]) {\n if (!key.startsWith(prefix)) continue;\n clearInterval(this.timers.get(key)!);\n this.timers.delete(key);\n }\n }\n\n /** Test helper / process shutdown. */\n clearAll(): void {\n for (const timer of this.timers.values()) {\n clearInterval(timer);\n }\n this.timers.clear();\n this.lastRestartAt.clear();\n }\n\n private async runProbe(plugin: ChannelPlugin, accountId: string): Promise<void> {\n const hb = plugin.heartbeat;\n if (!hb) return;\n const cfg = this.opts.getConfig();\n try {\n const r = await hb.check({ cfg, accountId });\n this.opts.healthMonitor.set(plugin.id, accountId, {\n healthy: r.healthy,\n lastCheckAt: Date.now(),\n detail:\n typeof r.details === 'string'\n ? r.details\n : r.details != null\n ? JSON.stringify(r.details)\n : undefined,\n });\n if (!r.healthy) {\n log.warn(\n { channel: plugin.id, accountId, detail: r.details },\n 'Channel heartbeat unhealthy',\n );\n const now = Date.now();\n const last = this.lastRestartAt.get(plugin.id) ?? 0;\n if (now - last < HEARTBEAT_RESTART_THROTTLE_MS) {\n return;\n }\n this.lastRestartAt.set(plugin.id, now);\n this.opts.requestSoftRestart(plugin.id);\n }\n } catch (err) {\n this.opts.healthMonitor.set(plugin.id, accountId, {\n healthy: false,\n lastCheckAt: Date.now(),\n detail: err instanceof Error ? err.message : String(err),\n });\n log.error({ channel: plugin.id, accountId, err }, 'Channel heartbeat check failed');\n }\n }\n}\n"],"mappings":";;;aAgBkD;AAElD,MAAM,MAAM,aAAa,4BAA4B;;AAGrD,MAAM,gCAAgC;AAetC,IAAa,4BAAb,MAAuC;CACrC;;CAEA,yBAA0B,IAAI,KAA6C;CAC3E,gCAAiC,IAAI,KAAqB;CAE1D,YAAY,MAAwC;AAClD,OAAK,OAAO;;;CAId,SAAS,QAA6B;EACpC,MAAM,KAAK,OAAO;AAClB,MAAI,CAAC,GAAI;AAET,OAAK,MAAM,OAAO,GAAG;EAErB,IAAI;AACJ,MAAI;AACF,gBAAa,OAAO,OAAO,eAAe,KAAK,KAAK,WAAW,CAAC;WACzD,KAAK;AACZ,OAAI,KAAK;IAAE,SAAS,OAAO;IAAI;IAAK,EAAE,qCAAqC;AAC3E;;AAGF,OAAK,MAAM,aAAa,YAAY;GAClC,MAAM,MAAM,GAAG,OAAO,GAAG,GAAG;GAC5B,MAAM,QAAQ,kBACN,KAAK,KAAK,SAAS,QAAQ,UAAU,EAC3C,GAAG,WACJ;AACD,QAAK,OAAO,IAAI,KAAK,MAAM;;;;CAK/B,MAAM,UAAwB;EAC5B,MAAM,SAAS,GAAG,SAAS;AAC3B,OAAK,MAAM,OAAO,CAAC,GAAG,KAAK,OAAO,MAAM,CAAC,EAAE;AACzC,OAAI,CAAC,IAAI,WAAW,OAAO,CAAE;AAC7B,iBAAc,KAAK,OAAO,IAAI,IAAI,CAAE;AACpC,QAAK,OAAO,OAAO,IAAI;;;;CAK3B,WAAiB;AACf,OAAK,MAAM,SAAS,KAAK,OAAO,QAAQ,CACtC,eAAc,MAAM;AAEtB,OAAK,OAAO,OAAO;AACnB,OAAK,cAAc,OAAO;;CAG5B,MAAc,SAAS,QAAuB,WAAkC;EAC9E,MAAM,KAAK,OAAO;AAClB,MAAI,CAAC,GAAI;EACT,MAAM,MAAM,KAAK,KAAK,WAAW;AACjC,MAAI;GACF,MAAM,IAAI,MAAM,GAAG,MAAM;IAAE;IAAK;IAAW,CAAC;AAC5C,QAAK,KAAK,cAAc,IAAI,OAAO,IAAI,WAAW;IAChD,SAAS,EAAE;IACX,aAAa,KAAK,KAAK;IACvB,QACE,OAAO,EAAE,YAAY,WACjB,EAAE,UACF,EAAE,WAAW,OACX,KAAK,UAAU,EAAE,QAAQ,GACzB,KAAA;IACT,CAAC;AACF,OAAI,CAAC,EAAE,SAAS;AACd,QAAI,KACF;KAAE,SAAS,OAAO;KAAI;KAAW,QAAQ,EAAE;KAAS,EACpD,8BACD;IACD,MAAM,MAAM,KAAK,KAAK;AAEtB,QAAI,OADS,KAAK,cAAc,IAAI,OAAO,GAAG,IAAI,KACjC,8BACf;AAEF,SAAK,cAAc,IAAI,OAAO,IAAI,IAAI;AACtC,SAAK,KAAK,mBAAmB,OAAO,GAAG;;WAElC,KAAK;AACZ,QAAK,KAAK,cAAc,IAAI,OAAO,IAAI,WAAW;IAChD,SAAS;IACT,aAAa,KAAK,KAAK;IACvB,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACzD,CAAC;AACF,OAAI,MAAM;IAAE,SAAS,OAAO;IAAI;IAAW;IAAK,EAAE,iCAAiC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChannelLifecycleSupervisor — owns the start/stop/restart state machine for
|
|
3
|
+
* every channel plugin.
|
|
4
|
+
*
|
|
5
|
+
* Concerns:
|
|
6
|
+
* - `initialize()` — call each plugin's `init(...)` once and remember success
|
|
7
|
+
* - Two-phase `start()` + `startDeferredConnects()` for channels whose
|
|
8
|
+
* `meta.deferConnectUntilAfterListen` is true (HTTP listener has to be up
|
|
9
|
+
* before they dial out)
|
|
10
|
+
* - Per-channel manual stop / start (UI-driven; suppresses auto-restart)
|
|
11
|
+
* - Exponential restart backoff via {@link CHANNEL_RESTART_POLICY}
|
|
12
|
+
* - Soft restart (called from heartbeat) — stop + startPlugin, manual-stop guarded
|
|
13
|
+
*
|
|
14
|
+
* Heartbeat probes themselves live in {@link ChannelHeartbeatScheduler}; this
|
|
15
|
+
* supervisor schedules them via `onPluginStarted` / `onPluginStopped` callbacks
|
|
16
|
+
* passed in by the caller.
|
|
17
|
+
*
|
|
18
|
+
* Extracted from `ChannelManager` so the manager can be a thin composition root.
|
|
19
|
+
*/
|
|
20
|
+
import type { Config } from '../config/schema.js';
|
|
21
|
+
import type { MessageBus } from '../infra/bus/index.js';
|
|
22
|
+
import type { ChannelPlugin, ChannelPluginSessionModelHooks } from './plugin-types.js';
|
|
23
|
+
import type { ChannelPluginRegistry } from './plugin-registry.js';
|
|
24
|
+
export interface ChannelLifecycleSupervisorOptions {
|
|
25
|
+
bus: MessageBus;
|
|
26
|
+
registry: ChannelPluginRegistry;
|
|
27
|
+
/** Effective config snapshot (per-channel `channels.<id>.*`). */
|
|
28
|
+
getConfig: () => Config;
|
|
29
|
+
/** Hooks for sub-classes / external observers: heartbeat scheduling, etc. */
|
|
30
|
+
onPluginStarted?: (plugin: ChannelPlugin) => void;
|
|
31
|
+
onPluginStopped?: (pluginId: string) => void;
|
|
32
|
+
/** Optional session-model hooks forwarded into `plugin.init()`. */
|
|
33
|
+
getSessionModelHooks?: () => ChannelPluginSessionModelHooks | undefined;
|
|
34
|
+
}
|
|
35
|
+
export declare class ChannelLifecycleSupervisor {
|
|
36
|
+
private readonly opts;
|
|
37
|
+
/** Plugin ids whose `init()` completed (used by start/stop loops). */
|
|
38
|
+
private readonly initializedPluginIds;
|
|
39
|
+
private readonly restartAttempts;
|
|
40
|
+
/** When set, failed-start auto-restart is suppressed for that channel id. */
|
|
41
|
+
private readonly manuallyStopped;
|
|
42
|
+
/** Plugins that skipped `start()` until `startDeferredConnects()`. */
|
|
43
|
+
private readonly deferredConnectPending;
|
|
44
|
+
private initialized;
|
|
45
|
+
private running;
|
|
46
|
+
constructor(opts: ChannelLifecycleSupervisorOptions);
|
|
47
|
+
isInitialized(pluginId: string): boolean;
|
|
48
|
+
snapshot(): {
|
|
49
|
+
initialized: boolean;
|
|
50
|
+
running: boolean;
|
|
51
|
+
initializedPluginIds: string[];
|
|
52
|
+
manuallyStopped: string[];
|
|
53
|
+
restartAttempts: Record<string, number>;
|
|
54
|
+
};
|
|
55
|
+
/** Channel ids that would run and declare `meta.deferConnectUntilAfterListen` (for logging / metrics). */
|
|
56
|
+
listDeferConnectChannelIds(cfg: Config): string[];
|
|
57
|
+
initialize(): Promise<void>;
|
|
58
|
+
/** Phase 1: start every enabled channel except those in `deferConnectPluginIds`. */
|
|
59
|
+
start(options?: {
|
|
60
|
+
deferConnectPluginIds?: ReadonlySet<string>;
|
|
61
|
+
}): Promise<void>;
|
|
62
|
+
/** Phase 2: `start()` for channels deferred at Phase 1. No-op if none pending. */
|
|
63
|
+
startDeferredConnects(): Promise<void>;
|
|
64
|
+
stop(): Promise<void>;
|
|
65
|
+
/** Stop one channel and suppress automatic restart until `startChannel` is called. */
|
|
66
|
+
stopChannel(channelId: string): Promise<void>;
|
|
67
|
+
/** Clear manual-stop and start one channel (requires prior `initialize()`). */
|
|
68
|
+
startChannel(channelId: string): Promise<void>;
|
|
69
|
+
/** Called by heartbeat: stop + start without clearing manualStop. No-op if user stopped it. */
|
|
70
|
+
softRestart(channelId: string): Promise<void>;
|
|
71
|
+
/** Forward a config snapshot to every initialised plugin's `onConfigUpdated` hook. */
|
|
72
|
+
forwardConfigUpdate(cfg: Config): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Builtin channels require `channels.<id>.enabled`. Extension-managed channels
|
|
75
|
+
* run unless explicitly disabled.
|
|
76
|
+
*/
|
|
77
|
+
private shouldRunChannelPlugin;
|
|
78
|
+
private initializePlugin;
|
|
79
|
+
private startPlugin;
|
|
80
|
+
private stopPlugin;
|
|
81
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { CHANNEL_RESTART_POLICY, computeBackoff } from "./restart-policy.js";
|
|
4
|
+
//#region src/channels/lifecycle-supervisor.ts
|
|
5
|
+
init_logger();
|
|
6
|
+
const log = createLogger("ChannelLifecycleSupervisor");
|
|
7
|
+
function asChannelConfig(raw) {
|
|
8
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) return raw;
|
|
9
|
+
}
|
|
10
|
+
var ChannelLifecycleSupervisor = class {
|
|
11
|
+
opts;
|
|
12
|
+
/** Plugin ids whose `init()` completed (used by start/stop loops). */
|
|
13
|
+
initializedPluginIds = /* @__PURE__ */ new Set();
|
|
14
|
+
restartAttempts = /* @__PURE__ */ new Map();
|
|
15
|
+
/** When set, failed-start auto-restart is suppressed for that channel id. */
|
|
16
|
+
manuallyStopped = /* @__PURE__ */ new Set();
|
|
17
|
+
/** Plugins that skipped `start()` until `startDeferredConnects()`. */
|
|
18
|
+
deferredConnectPending = /* @__PURE__ */ new Set();
|
|
19
|
+
initialized = false;
|
|
20
|
+
running = false;
|
|
21
|
+
constructor(opts) {
|
|
22
|
+
this.opts = opts;
|
|
23
|
+
}
|
|
24
|
+
isInitialized(pluginId) {
|
|
25
|
+
return this.initializedPluginIds.has(pluginId);
|
|
26
|
+
}
|
|
27
|
+
snapshot() {
|
|
28
|
+
return {
|
|
29
|
+
initialized: this.initialized,
|
|
30
|
+
running: this.running,
|
|
31
|
+
initializedPluginIds: [...this.initializedPluginIds],
|
|
32
|
+
manuallyStopped: [...this.manuallyStopped],
|
|
33
|
+
restartAttempts: Object.fromEntries(this.restartAttempts)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Channel ids that would run and declare `meta.deferConnectUntilAfterListen` (for logging / metrics). */
|
|
37
|
+
listDeferConnectChannelIds(cfg) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const [id, plugin] of this.opts.registry.entries()) {
|
|
40
|
+
const channelConfig = asChannelConfig(cfg.channels?.[id]);
|
|
41
|
+
if (!this.shouldRunChannelPlugin(plugin, channelConfig)) continue;
|
|
42
|
+
if (plugin.meta.deferConnectUntilAfterListen === true) out.push(id);
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
async initialize() {
|
|
47
|
+
if (this.initialized) {
|
|
48
|
+
log.warn({ pluginCount: this.opts.registry.ids().length }, "initialize() called again; channels already initialized — skipping");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const cfg = this.opts.getConfig();
|
|
52
|
+
const initPromises = [];
|
|
53
|
+
for (const [id, plugin] of this.opts.registry.entries()) {
|
|
54
|
+
const channelConfig = asChannelConfig(cfg.channels?.[id]);
|
|
55
|
+
initPromises.push(this.initializePlugin(plugin, channelConfig ?? {}));
|
|
56
|
+
}
|
|
57
|
+
await Promise.allSettled(initPromises);
|
|
58
|
+
this.initialized = true;
|
|
59
|
+
log.info("All channel plugins initialized");
|
|
60
|
+
}
|
|
61
|
+
/** Phase 1: start every enabled channel except those in `deferConnectPluginIds`. */
|
|
62
|
+
async start(options) {
|
|
63
|
+
if (!this.initialized) throw new Error("Channels not initialized");
|
|
64
|
+
if (this.running) {
|
|
65
|
+
log.warn({ pluginCount: this.opts.registry.ids().length }, "start() called while channels already running — skipping");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const deferIds = options?.deferConnectPluginIds ?? /* @__PURE__ */ new Set();
|
|
69
|
+
this.deferredConnectPending.clear();
|
|
70
|
+
const cfg = this.opts.getConfig();
|
|
71
|
+
const startPromises = [];
|
|
72
|
+
for (const [id, plugin] of this.opts.registry.entries()) {
|
|
73
|
+
const channelConfig = asChannelConfig(cfg.channels?.[id]);
|
|
74
|
+
if (!this.shouldRunChannelPlugin(plugin, channelConfig)) continue;
|
|
75
|
+
if (deferIds.has(id)) {
|
|
76
|
+
this.deferredConnectPending.add(id);
|
|
77
|
+
log.info({ channel: id }, "Channel connect deferred until HTTP listen");
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
startPromises.push(this.startPlugin(plugin, {}).catch((err) => {
|
|
81
|
+
log.error({
|
|
82
|
+
channel: id,
|
|
83
|
+
err
|
|
84
|
+
}, "Failed to start channel plugin");
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
await Promise.allSettled(startPromises);
|
|
88
|
+
this.running = true;
|
|
89
|
+
log.info({ deferred: [...this.deferredConnectPending] }, this.deferredConnectPending.size > 0 ? "Channel plugins started (deferred connects pending)" : "All channel plugins started");
|
|
90
|
+
}
|
|
91
|
+
/** Phase 2: `start()` for channels deferred at Phase 1. No-op if none pending. */
|
|
92
|
+
async startDeferredConnects() {
|
|
93
|
+
if (this.deferredConnectPending.size === 0) return;
|
|
94
|
+
if (!this.running) {
|
|
95
|
+
log.warn("startDeferredConnects called before channel phase-1 start; skipping");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const ids = [...this.deferredConnectPending];
|
|
99
|
+
this.deferredConnectPending.clear();
|
|
100
|
+
const cfg = this.opts.getConfig();
|
|
101
|
+
const startPromises = [];
|
|
102
|
+
for (const id of ids) {
|
|
103
|
+
const plugin = this.opts.registry.get(id);
|
|
104
|
+
if (!plugin) continue;
|
|
105
|
+
const channelConfig = asChannelConfig(cfg.channels?.[id]);
|
|
106
|
+
if (!this.shouldRunChannelPlugin(plugin, channelConfig)) continue;
|
|
107
|
+
startPromises.push(this.startPlugin(plugin, {}).catch((err) => {
|
|
108
|
+
log.error({
|
|
109
|
+
channel: id,
|
|
110
|
+
err
|
|
111
|
+
}, "Failed to start deferred channel plugin");
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
await Promise.allSettled(startPromises);
|
|
115
|
+
log.info({ channels: ids }, "Deferred channel connects completed");
|
|
116
|
+
}
|
|
117
|
+
async stop() {
|
|
118
|
+
if (!this.running) return;
|
|
119
|
+
this.deferredConnectPending.clear();
|
|
120
|
+
const stopPromises = [];
|
|
121
|
+
for (const id of this.initializedPluginIds) {
|
|
122
|
+
const plugin = this.opts.registry.get(id);
|
|
123
|
+
if (!plugin) continue;
|
|
124
|
+
stopPromises.push(this.stopPlugin(plugin).catch((err) => {
|
|
125
|
+
log.error({
|
|
126
|
+
channel: id,
|
|
127
|
+
err
|
|
128
|
+
}, "Failed to stop channel plugin");
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
await Promise.allSettled(stopPromises);
|
|
132
|
+
this.running = false;
|
|
133
|
+
log.info("All channel plugins stopped");
|
|
134
|
+
}
|
|
135
|
+
/** Stop one channel and suppress automatic restart until `startChannel` is called. */
|
|
136
|
+
async stopChannel(channelId) {
|
|
137
|
+
this.manuallyStopped.add(channelId);
|
|
138
|
+
const plugin = this.opts.registry.get(channelId);
|
|
139
|
+
if (!plugin || !this.initializedPluginIds.has(channelId)) return;
|
|
140
|
+
await this.stopPlugin(plugin).catch((err) => {
|
|
141
|
+
log.error({
|
|
142
|
+
channel: channelId,
|
|
143
|
+
err
|
|
144
|
+
}, "Failed to stop channel plugin");
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/** Clear manual-stop and start one channel (requires prior `initialize()`). */
|
|
148
|
+
async startChannel(channelId) {
|
|
149
|
+
this.manuallyStopped.delete(channelId);
|
|
150
|
+
const plugin = this.opts.registry.get(channelId);
|
|
151
|
+
if (!plugin) {
|
|
152
|
+
log.warn({ channel: channelId }, "Unknown channel");
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!this.initialized) {
|
|
156
|
+
log.warn({ channel: channelId }, "Channels not initialized");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const channelConfig = asChannelConfig(this.opts.getConfig().channels?.[channelId]);
|
|
160
|
+
if (!this.shouldRunChannelPlugin(plugin, channelConfig)) {
|
|
161
|
+
log.debug({ channel: channelId }, "Channel disabled in config, skipping start");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (!this.initializedPluginIds.has(channelId)) {
|
|
165
|
+
log.warn({ channel: channelId }, "Channel was never initialized; call initialize() first");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
await this.startPlugin(plugin, {});
|
|
169
|
+
}
|
|
170
|
+
/** Called by heartbeat: stop + start without clearing manualStop. No-op if user stopped it. */
|
|
171
|
+
async softRestart(channelId) {
|
|
172
|
+
if (this.manuallyStopped.has(channelId)) return;
|
|
173
|
+
const plugin = this.opts.registry.get(channelId);
|
|
174
|
+
if (!plugin || !this.initializedPluginIds.has(channelId)) return;
|
|
175
|
+
try {
|
|
176
|
+
await this.stopPlugin(plugin);
|
|
177
|
+
await this.startPlugin(plugin, {});
|
|
178
|
+
} catch (err) {
|
|
179
|
+
log.error({
|
|
180
|
+
channel: channelId,
|
|
181
|
+
err
|
|
182
|
+
}, "Channel soft restart after heartbeat failed");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/** Forward a config snapshot to every initialised plugin's `onConfigUpdated` hook. */
|
|
186
|
+
async forwardConfigUpdate(cfg) {
|
|
187
|
+
for (const id of this.initializedPluginIds) {
|
|
188
|
+
const plugin = this.opts.registry.get(id);
|
|
189
|
+
if (plugin?.onConfigUpdated) await Promise.resolve(plugin.onConfigUpdated(cfg));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Builtin channels require `channels.<id>.enabled`. Extension-managed channels
|
|
194
|
+
* run unless explicitly disabled.
|
|
195
|
+
*/
|
|
196
|
+
shouldRunChannelPlugin(plugin, channelConfig) {
|
|
197
|
+
if (plugin.extensionManagedConfig) return channelConfig?.enabled !== false;
|
|
198
|
+
return !!channelConfig?.enabled;
|
|
199
|
+
}
|
|
200
|
+
async initializePlugin(plugin, channelConfig) {
|
|
201
|
+
try {
|
|
202
|
+
const options = {
|
|
203
|
+
bus: this.opts.bus,
|
|
204
|
+
config: this.opts.getConfig(),
|
|
205
|
+
channelConfig,
|
|
206
|
+
sessionModel: this.opts.getSessionModelHooks?.()
|
|
207
|
+
};
|
|
208
|
+
await plugin.init(options);
|
|
209
|
+
this.initializedPluginIds.add(plugin.id);
|
|
210
|
+
log.debug({ channel: plugin.id }, "Channel plugin initialized");
|
|
211
|
+
} catch (err) {
|
|
212
|
+
log.error({
|
|
213
|
+
channel: plugin.id,
|
|
214
|
+
err
|
|
215
|
+
}, "Failed to initialize channel plugin");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async startPlugin(plugin, opts) {
|
|
219
|
+
const options = {};
|
|
220
|
+
try {
|
|
221
|
+
await plugin.start(options);
|
|
222
|
+
if (!opts.preserveRestartAttempts) this.restartAttempts.delete(plugin.id);
|
|
223
|
+
this.opts.onPluginStarted?.(plugin);
|
|
224
|
+
log.debug({ channel: plugin.id }, "Channel plugin started");
|
|
225
|
+
} catch (err) {
|
|
226
|
+
const attempt = (this.restartAttempts.get(plugin.id) ?? 0) + 1;
|
|
227
|
+
this.restartAttempts.set(plugin.id, attempt);
|
|
228
|
+
if (attempt <= CHANNEL_RESTART_POLICY.maxAttempts) {
|
|
229
|
+
const delayMs = computeBackoff(CHANNEL_RESTART_POLICY, attempt);
|
|
230
|
+
log.warn({
|
|
231
|
+
channel: plugin.id,
|
|
232
|
+
attempt,
|
|
233
|
+
delayMs,
|
|
234
|
+
err
|
|
235
|
+
}, "Channel failed to start, scheduling restart");
|
|
236
|
+
setTimeout(() => {
|
|
237
|
+
if (this.manuallyStopped.has(plugin.id)) {
|
|
238
|
+
log.debug({ channel: plugin.id }, "Skipping scheduled restart (manual stop)");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
this.startPlugin(plugin, { preserveRestartAttempts: true }).catch((e) => {
|
|
242
|
+
log.error({
|
|
243
|
+
channel: plugin.id,
|
|
244
|
+
err: e
|
|
245
|
+
}, "Channel restart attempt failed");
|
|
246
|
+
});
|
|
247
|
+
}, delayMs);
|
|
248
|
+
} else log.error({
|
|
249
|
+
channel: plugin.id,
|
|
250
|
+
err
|
|
251
|
+
}, "Channel exceeded max restart attempts");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async stopPlugin(plugin) {
|
|
255
|
+
this.opts.onPluginStopped?.(plugin.id);
|
|
256
|
+
await plugin.stop();
|
|
257
|
+
log.info({ channel: plugin.id }, "Channel plugin stopped");
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
//#endregion
|
|
261
|
+
export { ChannelLifecycleSupervisor };
|
|
262
|
+
|
|
263
|
+
//# sourceMappingURL=lifecycle-supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-supervisor.js","names":[],"sources":["../../../src/channels/lifecycle-supervisor.ts"],"sourcesContent":["/**\n * ChannelLifecycleSupervisor — owns the start/stop/restart state machine for\n * every channel plugin.\n *\n * Concerns:\n * - `initialize()` — call each plugin's `init(...)` once and remember success\n * - Two-phase `start()` + `startDeferredConnects()` for channels whose\n * `meta.deferConnectUntilAfterListen` is true (HTTP listener has to be up\n * before they dial out)\n * - Per-channel manual stop / start (UI-driven; suppresses auto-restart)\n * - Exponential restart backoff via {@link CHANNEL_RESTART_POLICY}\n * - Soft restart (called from heartbeat) — stop + startPlugin, manual-stop guarded\n *\n * Heartbeat probes themselves live in {@link ChannelHeartbeatScheduler}; this\n * supervisor schedules them via `onPluginStarted` / `onPluginStopped` callbacks\n * passed in by the caller.\n *\n * Extracted from `ChannelManager` so the manager can be a thin composition root.\n */\n\nimport type { Config } from '../config/schema.js';\nimport type { MessageBus } from '../infra/bus/index.js';\n\nimport type {\n ChannelPlugin,\n ChannelPluginInitOptions,\n ChannelPluginSessionModelHooks,\n ChannelPluginStartOptions,\n} from './plugin-types.js';\nimport type { ChannelPluginRegistry } from './plugin-registry.js';\nimport { CHANNEL_RESTART_POLICY, computeBackoff } from './restart-policy.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst log = createLogger('ChannelLifecycleSupervisor');\n\nfunction asChannelConfig(raw: unknown): Record<string, unknown> | undefined {\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as Record<string, unknown>;\n }\n return undefined;\n}\n\nexport interface ChannelLifecycleSupervisorOptions {\n bus: MessageBus;\n registry: ChannelPluginRegistry;\n /** Effective config snapshot (per-channel `channels.<id>.*`). */\n getConfig: () => Config;\n /** Hooks for sub-classes / external observers: heartbeat scheduling, etc. */\n onPluginStarted?: (plugin: ChannelPlugin) => void;\n onPluginStopped?: (pluginId: string) => void;\n /** Optional session-model hooks forwarded into `plugin.init()`. */\n getSessionModelHooks?: () => ChannelPluginSessionModelHooks | undefined;\n}\n\nexport class ChannelLifecycleSupervisor {\n private readonly opts: ChannelLifecycleSupervisorOptions;\n /** Plugin ids whose `init()` completed (used by start/stop loops). */\n private readonly initializedPluginIds = new Set<string>();\n private readonly restartAttempts = new Map<string, number>();\n /** When set, failed-start auto-restart is suppressed for that channel id. */\n private readonly manuallyStopped = new Set<string>();\n /** Plugins that skipped `start()` until `startDeferredConnects()`. */\n private readonly deferredConnectPending = new Set<string>();\n private initialized = false;\n private running = false;\n\n constructor(opts: ChannelLifecycleSupervisorOptions) {\n this.opts = opts;\n }\n\n isInitialized(pluginId: string): boolean {\n return this.initializedPluginIds.has(pluginId);\n }\n\n snapshot(): {\n initialized: boolean;\n running: boolean;\n initializedPluginIds: string[];\n manuallyStopped: string[];\n restartAttempts: Record<string, number>;\n } {\n return {\n initialized: this.initialized,\n running: this.running,\n initializedPluginIds: [...this.initializedPluginIds],\n manuallyStopped: [...this.manuallyStopped],\n restartAttempts: Object.fromEntries(this.restartAttempts),\n };\n }\n\n /** Channel ids that would run and declare `meta.deferConnectUntilAfterListen` (for logging / metrics). */\n listDeferConnectChannelIds(cfg: Config): string[] {\n const out: string[] = [];\n for (const [id, plugin] of this.opts.registry.entries()) {\n const channelConfig = asChannelConfig(cfg.channels?.[id]);\n if (!this.shouldRunChannelPlugin(plugin, channelConfig)) continue;\n if (plugin.meta.deferConnectUntilAfterListen === true) {\n out.push(id);\n }\n }\n return out;\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n log.warn(\n { pluginCount: this.opts.registry.ids().length },\n 'initialize() called again; channels already initialized — skipping',\n );\n return;\n }\n\n const cfg = this.opts.getConfig();\n const initPromises: Promise<void>[] = [];\n\n for (const [id, plugin] of this.opts.registry.entries()) {\n const channelConfig = asChannelConfig(cfg.channels?.[id]);\n // Always init so `onConfigUpdated` runs on hot reload (e.g. Weixin turned off after QR-login\n // started monitors while the plugin was previously skipped here and had no bus/`initialized` id).\n initPromises.push(this.initializePlugin(plugin, channelConfig ?? {}));\n }\n\n await Promise.allSettled(initPromises);\n this.initialized = true;\n log.info('All channel plugins initialized');\n }\n\n /** Phase 1: start every enabled channel except those in `deferConnectPluginIds`. */\n async start(options?: { deferConnectPluginIds?: ReadonlySet<string> }): Promise<void> {\n if (!this.initialized) {\n throw new Error('Channels not initialized');\n }\n if (this.running) {\n log.warn(\n { pluginCount: this.opts.registry.ids().length },\n 'start() called while channels already running — skipping',\n );\n return;\n }\n\n const deferIds = options?.deferConnectPluginIds ?? new Set<string>();\n this.deferredConnectPending.clear();\n\n const cfg = this.opts.getConfig();\n const startPromises: Promise<void>[] = [];\n\n for (const [id, plugin] of this.opts.registry.entries()) {\n const channelConfig = asChannelConfig(cfg.channels?.[id]);\n if (!this.shouldRunChannelPlugin(plugin, channelConfig)) continue;\n\n if (deferIds.has(id)) {\n this.deferredConnectPending.add(id);\n log.info({ channel: id }, 'Channel connect deferred until HTTP listen');\n continue;\n }\n\n startPromises.push(\n this.startPlugin(plugin, {}).catch((err) => {\n log.error({ channel: id, err }, 'Failed to start channel plugin');\n }),\n );\n }\n\n await Promise.allSettled(startPromises);\n this.running = true;\n log.info(\n { deferred: [...this.deferredConnectPending] },\n this.deferredConnectPending.size > 0\n ? 'Channel plugins started (deferred connects pending)'\n : 'All channel plugins started',\n );\n }\n\n /** Phase 2: `start()` for channels deferred at Phase 1. No-op if none pending. */\n async startDeferredConnects(): Promise<void> {\n if (this.deferredConnectPending.size === 0) return;\n if (!this.running) {\n log.warn('startDeferredConnects called before channel phase-1 start; skipping');\n return;\n }\n const ids = [...this.deferredConnectPending];\n this.deferredConnectPending.clear();\n const cfg = this.opts.getConfig();\n const startPromises: Promise<void>[] = [];\n for (const id of ids) {\n const plugin = this.opts.registry.get(id);\n if (!plugin) continue;\n const channelConfig = asChannelConfig(cfg.channels?.[id]);\n if (!this.shouldRunChannelPlugin(plugin, channelConfig)) continue;\n startPromises.push(\n this.startPlugin(plugin, {}).catch((err) => {\n log.error({ channel: id, err }, 'Failed to start deferred channel plugin');\n }),\n );\n }\n await Promise.allSettled(startPromises);\n log.info({ channels: ids }, 'Deferred channel connects completed');\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n this.deferredConnectPending.clear();\n\n const stopPromises: Promise<void>[] = [];\n for (const id of this.initializedPluginIds) {\n const plugin = this.opts.registry.get(id);\n if (!plugin) continue;\n stopPromises.push(\n this.stopPlugin(plugin).catch((err) => {\n log.error({ channel: id, err }, 'Failed to stop channel plugin');\n }),\n );\n }\n\n await Promise.allSettled(stopPromises);\n this.running = false;\n log.info('All channel plugins stopped');\n }\n\n /** Stop one channel and suppress automatic restart until `startChannel` is called. */\n async stopChannel(channelId: string): Promise<void> {\n this.manuallyStopped.add(channelId);\n const plugin = this.opts.registry.get(channelId);\n if (!plugin || !this.initializedPluginIds.has(channelId)) {\n return;\n }\n await this.stopPlugin(plugin).catch((err) => {\n log.error({ channel: channelId, err }, 'Failed to stop channel plugin');\n });\n }\n\n /** Clear manual-stop and start one channel (requires prior `initialize()`). */\n async startChannel(channelId: string): Promise<void> {\n this.manuallyStopped.delete(channelId);\n const plugin = this.opts.registry.get(channelId);\n if (!plugin) {\n log.warn({ channel: channelId }, 'Unknown channel');\n return;\n }\n if (!this.initialized) {\n log.warn({ channel: channelId }, 'Channels not initialized');\n return;\n }\n const cfg = this.opts.getConfig();\n const channelConfig = asChannelConfig(cfg.channels?.[channelId]);\n if (!this.shouldRunChannelPlugin(plugin, channelConfig)) {\n log.debug({ channel: channelId }, 'Channel disabled in config, skipping start');\n return;\n }\n if (!this.initializedPluginIds.has(channelId)) {\n log.warn({ channel: channelId }, 'Channel was never initialized; call initialize() first');\n return;\n }\n await this.startPlugin(plugin, {});\n }\n\n /** Called by heartbeat: stop + start without clearing manualStop. No-op if user stopped it. */\n async softRestart(channelId: string): Promise<void> {\n if (this.manuallyStopped.has(channelId)) return;\n const plugin = this.opts.registry.get(channelId);\n if (!plugin || !this.initializedPluginIds.has(channelId)) return;\n try {\n await this.stopPlugin(plugin);\n await this.startPlugin(plugin, {});\n } catch (err) {\n log.error({ channel: channelId, err }, 'Channel soft restart after heartbeat failed');\n }\n }\n\n /** Forward a config snapshot to every initialised plugin's `onConfigUpdated` hook. */\n async forwardConfigUpdate(cfg: Config): Promise<void> {\n for (const id of this.initializedPluginIds) {\n const plugin = this.opts.registry.get(id);\n if (plugin?.onConfigUpdated) {\n await Promise.resolve(plugin.onConfigUpdated(cfg));\n }\n }\n }\n\n // ── Internals ───────────────────────────────────────────────────────────\n\n /**\n * Builtin channels require `channels.<id>.enabled`. Extension-managed channels\n * run unless explicitly disabled.\n */\n private shouldRunChannelPlugin(\n plugin: ChannelPlugin,\n channelConfig: Record<string, unknown> | undefined,\n ): boolean {\n if (plugin.extensionManagedConfig) {\n return channelConfig?.enabled !== false;\n }\n return !!channelConfig?.enabled;\n }\n\n private async initializePlugin(\n plugin: ChannelPlugin,\n channelConfig: Record<string, unknown>,\n ): Promise<void> {\n try {\n const options: ChannelPluginInitOptions = {\n bus: this.opts.bus,\n config: this.opts.getConfig(),\n channelConfig,\n sessionModel: this.opts.getSessionModelHooks?.(),\n };\n await plugin.init(options);\n this.initializedPluginIds.add(plugin.id);\n log.debug({ channel: plugin.id }, 'Channel plugin initialized');\n } catch (err) {\n log.error({ channel: plugin.id, err }, 'Failed to initialize channel plugin');\n }\n }\n\n private async startPlugin(\n plugin: ChannelPlugin,\n opts: { preserveRestartAttempts?: boolean },\n ): Promise<void> {\n const options: ChannelPluginStartOptions = {};\n try {\n await plugin.start(options);\n if (!opts.preserveRestartAttempts) {\n this.restartAttempts.delete(plugin.id);\n }\n this.opts.onPluginStarted?.(plugin);\n log.debug({ channel: plugin.id }, 'Channel plugin started');\n } catch (err) {\n const attempt = (this.restartAttempts.get(plugin.id) ?? 0) + 1;\n this.restartAttempts.set(plugin.id, attempt);\n if (attempt <= CHANNEL_RESTART_POLICY.maxAttempts) {\n const delayMs = computeBackoff(CHANNEL_RESTART_POLICY, attempt);\n log.warn(\n { channel: plugin.id, attempt, delayMs, err },\n 'Channel failed to start, scheduling restart',\n );\n setTimeout(() => {\n if (this.manuallyStopped.has(plugin.id)) {\n log.debug({ channel: plugin.id }, 'Skipping scheduled restart (manual stop)');\n return;\n }\n void this.startPlugin(plugin, { preserveRestartAttempts: true }).catch((e) => {\n log.error({ channel: plugin.id, err: e }, 'Channel restart attempt failed');\n });\n }, delayMs);\n } else {\n log.error({ channel: plugin.id, err }, 'Channel exceeded max restart attempts');\n }\n }\n }\n\n private async stopPlugin(plugin: ChannelPlugin): Promise<void> {\n this.opts.onPluginStopped?.(plugin.id);\n await plugin.stop();\n log.info({ channel: plugin.id }, 'Channel plugin stopped');\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,100 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Channel Manager
|
|
2
|
+
* Channel Manager — thin composition root for the channel subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Wires together the four coordinators that own what used to be the eight
|
|
5
|
+
* concerns of this 707-line class:
|
|
6
|
+
*
|
|
7
|
+
* - {@link ChannelPluginRegistry} — plugins Map, register/get
|
|
8
|
+
* - {@link ChannelLifecycleSupervisor} — init/start/stop/restart-backoff
|
|
9
|
+
* - {@link ChannelHeartbeatScheduler} — per-account heartbeat probes
|
|
10
|
+
* - {@link ChannelOutboundSender} — TTS rewrite + persist + delivery
|
|
11
|
+
*
|
|
12
|
+
* The public surface (`registerPlugin`, `initialize`, `start`, `send`, etc.) is
|
|
13
|
+
* preserved so callers (`GatewayService`, CLI commands, channel plugins) are
|
|
14
|
+
* unchanged.
|
|
3
15
|
*/
|
|
4
|
-
import type { Config } from '../config/
|
|
16
|
+
import type { Config } from '../config/schema.js';
|
|
5
17
|
import type { MessageBus } from '../infra/bus/index.js';
|
|
6
18
|
import type { InboundMessage, OutboundMessage } from './transport-types.js';
|
|
7
19
|
import type { ChannelPlugin, ChannelPluginSessionModelHooks, ChannelStreamHandle } from './plugin-types.js';
|
|
8
20
|
import { ChannelHealthMonitor, type ChannelHealthState } from './health-monitor.js';
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
runMessageSending: (to: string, content: string, channel: string) => Promise<{
|
|
12
|
-
send: boolean;
|
|
13
|
-
content?: string;
|
|
14
|
-
reason?: string;
|
|
15
|
-
}>;
|
|
16
|
-
runMessageSent: (to: string, content: string, success: boolean, error: string | undefined, channel: string) => Promise<void>;
|
|
17
|
-
}
|
|
21
|
+
import { type OutboundChannelHooks } from './outbound-sender.js';
|
|
22
|
+
export type { OutboundChannelHooks } from './outbound-sender.js';
|
|
18
23
|
export declare class ChannelManager {
|
|
19
|
-
private plugins;
|
|
20
|
-
/** Plugins that completed `init()` successfully (skipped channels are not listed). */
|
|
21
|
-
private initializedPluginIds;
|
|
22
|
-
private bus;
|
|
23
24
|
private config;
|
|
24
|
-
private
|
|
25
|
-
private running;
|
|
26
|
-
private restartAttempts;
|
|
27
|
-
/** When set, failed-start auto-restart is suppressed for that channel id. */
|
|
28
|
-
private manuallyStopped;
|
|
29
|
-
private heartbeatTimers;
|
|
30
|
-
private outboundHooks?;
|
|
31
|
-
private persistStore?;
|
|
32
|
-
private _lastHeartbeatRestartAt;
|
|
25
|
+
private readonly registry;
|
|
33
26
|
private readonly healthMonitor;
|
|
27
|
+
private readonly lifecycle;
|
|
28
|
+
private readonly heartbeat;
|
|
29
|
+
private readonly outbound;
|
|
34
30
|
private sessionModelHooks?;
|
|
35
|
-
/** Plugins that skipped `start()` until `startDeferredConnects()` (see `ChannelMeta.deferConnectUntilAfterListen`). */
|
|
36
|
-
private deferredConnectPending;
|
|
37
31
|
constructor(config: Config, bus: MessageBus);
|
|
38
32
|
setOutboundHooks(hooks: OutboundChannelHooks): void;
|
|
39
|
-
/** Call before `initialize()` so plugins can persist per-session model overrides
|
|
33
|
+
/** Call before `initialize()` so plugins can persist per-session model overrides. */
|
|
40
34
|
setSessionModelHooks(hooks: ChannelPluginSessionModelHooks | undefined): void;
|
|
41
35
|
enableOutboundPersistence(agentDir: string): void;
|
|
42
|
-
/**
|
|
43
|
-
* Redeliver persisted outbound items (after channels are started). Best-effort; may duplicate if prior send succeeded but ack did not.
|
|
44
|
-
*/
|
|
45
|
-
replayPendingOutboundMessages(): Promise<void>;
|
|
46
36
|
registerPlugin(plugin: ChannelPlugin): void;
|
|
47
37
|
getPlugin(id: string): ChannelPlugin | undefined;
|
|
48
|
-
/**
|
|
49
|
-
* Optional channel hook before AgentService consumes an inbound message (e.g. Feishu card actions).
|
|
50
|
-
*/
|
|
51
|
-
dispatchInboundMessageAction(msg: InboundMessage): Promise<void>;
|
|
52
38
|
getAllPlugins(): ChannelPlugin[];
|
|
39
|
+
/** Backward-compat alias for `getAllPlugins`. */
|
|
40
|
+
getAllChannels(): ChannelPlugin[];
|
|
41
|
+
/** Channel IDs whose runtime reports connected (e.g. Telegram polling active). */
|
|
42
|
+
getRunningChannels(): string[];
|
|
53
43
|
initialize(): Promise<void>;
|
|
54
|
-
/**
|
|
55
|
-
* Builtin channels require `channels.<id>.enabled`. Extension-managed channels run unless explicitly disabled.
|
|
56
|
-
*/
|
|
57
|
-
private shouldRunChannelPlugin;
|
|
58
|
-
private initializePlugin;
|
|
59
|
-
/**
|
|
60
|
-
* Channel ids that would run and declare `meta.deferConnectUntilAfterListen` (for logging / metrics).
|
|
61
|
-
*/
|
|
62
|
-
listDeferConnectChannelIds(cfg: Config): string[];
|
|
63
|
-
/**
|
|
64
|
-
* Phase 1: start every enabled channel except those in `deferConnectPluginIds` (they stay pending).
|
|
65
|
-
*/
|
|
66
44
|
start(options?: {
|
|
67
45
|
deferConnectPluginIds?: ReadonlySet<string>;
|
|
68
46
|
}): Promise<void>;
|
|
69
|
-
/** Phase 2: run `start()` for channels deferred at `start()`. No-op if none pending. */
|
|
70
47
|
startDeferredConnects(): Promise<void>;
|
|
71
|
-
private startPlugin;
|
|
72
48
|
stop(): Promise<void>;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
private _softRestartChannel;
|
|
77
|
-
private cloneOutbound;
|
|
49
|
+
stopChannel(channelId: string): Promise<void>;
|
|
50
|
+
startChannel(channelId: string): Promise<void>;
|
|
51
|
+
listDeferConnectChannelIds(cfg: Config): string[];
|
|
78
52
|
send(msg: OutboundMessage, options?: {
|
|
79
53
|
skipPersist?: boolean;
|
|
80
54
|
}): Promise<void>;
|
|
55
|
+
replayPendingOutboundMessages(): Promise<void>;
|
|
81
56
|
startStream(channel: string, chatId: string, accountId?: string, opts?: {
|
|
82
57
|
threadId?: string;
|
|
83
58
|
replyToMessageId?: string;
|
|
84
59
|
}): ChannelStreamHandle | null;
|
|
85
60
|
getChannelStatus(channel: string): Promise<Record<string, unknown>>;
|
|
61
|
+
/**
|
|
62
|
+
* Optional channel hook before `AgentService` consumes an inbound message
|
|
63
|
+
* (e.g. Feishu card-action triggers).
|
|
64
|
+
*/
|
|
65
|
+
dispatchInboundMessageAction(msg: InboundMessage): Promise<void>;
|
|
86
66
|
updateConfig(config: Config): Promise<void>;
|
|
87
67
|
/** Replace in-memory config without running plugin `onConfigUpdated` hooks. */
|
|
88
68
|
setRuntimeConfig(config: Config): void;
|
|
89
|
-
private applyTtsIfNeeded;
|
|
90
|
-
/**
|
|
91
|
-
* Stop a single channel and suppress automatic restart until `startChannel` is called.
|
|
92
|
-
*/
|
|
93
|
-
stopChannel(channelId: string): Promise<void>;
|
|
94
|
-
/**
|
|
95
|
-
* Clear manual-stop and start one channel (requires prior `initialize()`).
|
|
96
|
-
*/
|
|
97
|
-
startChannel(channelId: string): Promise<void>;
|
|
98
69
|
getRuntimeSnapshot(): {
|
|
99
70
|
initialized: boolean;
|
|
100
71
|
running: boolean;
|
|
@@ -105,10 +76,5 @@ export declare class ChannelManager {
|
|
|
105
76
|
channelHealth: Record<string, ChannelHealthState>;
|
|
106
77
|
};
|
|
107
78
|
getHealthMonitor(): ChannelHealthMonitor;
|
|
108
|
-
/**
|
|
109
|
-
* Channel IDs whose runtime reports connected (e.g. Telegram polling active).
|
|
110
|
-
*/
|
|
111
|
-
getRunningChannels(): string[];
|
|
112
|
-
getAllChannels(): ChannelPlugin[];
|
|
113
79
|
}
|
|
114
80
|
export declare function createChannelManager(config: Config, bus: MessageBus): ChannelManager;
|