@xopcai/xopc 0.0.82 → 0.0.84
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 +3 -1
- package/README.zh-CN.md +3 -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-tR-nNP04.js +222 -0
- package/dist/gateway/static/root/assets/{apps-page-pJ27dsqn.js → apps-page-BDw6SP-d.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DEFd-jj1.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-D1KYmOmi.js → channels-status-swr-DI5FHdGe.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-Y2wfSJVI.js → cron-api-BSqY8LwW.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-B97KU_RG.js → cron-page-D7lVDjcR.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-CboA_Css.js → dist-CqNMNhJM.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DN_zNmpo.js → extension-debug-page-gf2L0kY_.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BUXtOzv5.js → extension-page-CQo2Xsmg.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-C2dX4KCW.js → extension-settings-page-CZf0WoZg.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-DTtlp-l8.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-DvfiRVrc.js → heartbeat-config-api-B0drdQEJ.js} +1 -1
- package/dist/gateway/static/root/assets/{index-DQuaMye9.js → index-0Gt3TG4j.js} +94 -85
- package/dist/gateway/static/root/assets/index-BuFldCsB.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-BQuBpHcc.js → logs-page-DMuORLfC.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-_UO8g6NN.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-2Yu-FASs.js → settings-form-section-DkmHkknc.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-Cz8FoW_A.js +3 -0
- package/dist/gateway/static/root/assets/skills-page-HrUOxF7H.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-BFwcR6pL.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-JF8-aqc5.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/command-catalog.js +110 -8
- package/dist/src/cli/command-catalog.js.map +1 -1
- package/dist/src/cli/command-loaders.js +2 -0
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +9 -1
- package/dist/src/cli/command-manifest.js.map +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/config.js +70 -19
- package/dist/src/cli/commands/config.js.map +1 -1
- package/dist/src/cli/commands/cron-cli.d.ts +2 -0
- package/dist/src/cli/commands/cron-cli.js +15 -0
- package/dist/src/cli/commands/cron-cli.js.map +1 -0
- package/dist/src/cli/commands/cron.d.ts +4 -1
- package/dist/src/cli/commands/cron.js +76 -41
- package/dist/src/cli/commands/cron.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +2 -2
- package/dist/src/cli/commands/doctor/checks/config-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/gateway-health.js +2 -2
- package/dist/src/cli/commands/doctor/checks/gateway-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/gateway-service.js +2 -2
- package/dist/src/cli/commands/doctor/checks/gateway-service.js.map +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 +2 -2
- package/dist/src/cli/commands/doctor/checks/state-integrity.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +4 -4
- package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +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/index.d.ts +1 -1
- package/dist/src/cli/commands/gateway/index.js +2 -2
- 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.d.ts +4 -0
- package/dist/src/cli/commands/gateway/service.js +18 -3
- 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/subcommands.js +1 -4
- package/dist/src/cli/commands/gateway/subcommands.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 +31 -4
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/models.d.ts +4 -1
- package/dist/src/cli/commands/models.js +87 -75
- 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 +11 -64
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/profile.d.ts +3 -5
- package/dist/src/cli/commands/profile.js +31 -31
- package/dist/src/cli/commands/profile.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/setup.js +6 -1
- package/dist/src/cli/commands/setup.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 +16 -9
- 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 +1 -1
- 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 +122 -904
- 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/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
|
@@ -46,15 +46,12 @@ var CommandHandler = class {
|
|
|
46
46
|
this.config = config;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
49
|
+
* Build the unified command context shared by all execute paths.
|
|
50
|
+
* When `recorder` is set, every reply text is also captured (for SSE / CLI aggregation).
|
|
50
51
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
command: commandName,
|
|
55
|
-
sessionKey: context.sessionKey
|
|
56
|
-
}, "Executing command via new system");
|
|
57
|
-
const cmdCtx = createCommandContext({
|
|
52
|
+
buildCommandContext(context, recorder) {
|
|
53
|
+
const skipBusOutbound = shouldSkipBusOutboundForChannel(context.channel);
|
|
54
|
+
return createCommandContext({
|
|
58
55
|
sessionKey: context.sessionKey,
|
|
59
56
|
source: context.channel,
|
|
60
57
|
channelId: context.channel,
|
|
@@ -67,7 +64,8 @@ var CommandHandler = class {
|
|
|
67
64
|
sessionConfigStore: this.sessionConfigStore,
|
|
68
65
|
applySessionThinkingLevel: this.applySessionThinkingLevel,
|
|
69
66
|
replyHandler: async (text, _options) => {
|
|
70
|
-
|
|
67
|
+
recorder?.(text);
|
|
68
|
+
if (skipBusOutbound) return;
|
|
71
69
|
await this.bus.publishOutbound({
|
|
72
70
|
channel: context.channel,
|
|
73
71
|
chat_id: context.chatId,
|
|
@@ -76,7 +74,7 @@ var CommandHandler = class {
|
|
|
76
74
|
});
|
|
77
75
|
},
|
|
78
76
|
typingHandler: async (typing) => {
|
|
79
|
-
if (
|
|
77
|
+
if (skipBusOutbound) return;
|
|
80
78
|
await this.bus.publishOutbound({
|
|
81
79
|
channel: context.channel,
|
|
82
80
|
chat_id: context.chatId,
|
|
@@ -131,6 +129,17 @@ var CommandHandler = class {
|
|
|
131
129
|
inboundMetadata: context.inboundMetadata
|
|
132
130
|
})
|
|
133
131
|
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Execute a command using the unified command system
|
|
135
|
+
*/
|
|
136
|
+
async executeCommand(commandName, args, context) {
|
|
137
|
+
if (!commandRegistry.has(commandName)) return false;
|
|
138
|
+
log.info({
|
|
139
|
+
command: commandName,
|
|
140
|
+
sessionKey: context.sessionKey
|
|
141
|
+
}, "Executing command via new system");
|
|
142
|
+
const cmdCtx = this.buildCommandContext(context);
|
|
134
143
|
const result = await commandRegistry.execute(commandName, cmdCtx, args);
|
|
135
144
|
if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) await this.bus.publishOutbound({
|
|
136
145
|
channel: context.channel,
|
|
@@ -153,92 +162,8 @@ var CommandHandler = class {
|
|
|
153
162
|
command: commandName,
|
|
154
163
|
sessionKey: context.sessionKey
|
|
155
164
|
}, "Executing command (aggregate reply)");
|
|
156
|
-
const { aggregatedText } = await this.runRegistryExecuteWithCapture(args, commandName, context);
|
|
157
|
-
return {
|
|
158
|
-
handled: true,
|
|
159
|
-
aggregatedText
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
async runRegistryExecuteWithCapture(args, commandName, context) {
|
|
163
165
|
const segments = [];
|
|
164
|
-
const wrapped =
|
|
165
|
-
sessionKey: context.sessionKey,
|
|
166
|
-
source: context.channel,
|
|
167
|
-
channelId: context.channel,
|
|
168
|
-
chatId: context.chatId,
|
|
169
|
-
senderId: context.senderId,
|
|
170
|
-
isGroup: context.isGroup,
|
|
171
|
-
config: this.config,
|
|
172
|
-
bus: this.bus,
|
|
173
|
-
sessionStore: this.sessionStore,
|
|
174
|
-
sessionConfigStore: this.sessionConfigStore,
|
|
175
|
-
applySessionThinkingLevel: this.applySessionThinkingLevel,
|
|
176
|
-
replyHandler: async (text, _options) => {
|
|
177
|
-
segments.push(text);
|
|
178
|
-
if (shouldSkipBusOutboundForChannel(context.channel)) return;
|
|
179
|
-
await this.bus.publishOutbound({
|
|
180
|
-
channel: context.channel,
|
|
181
|
-
chat_id: context.chatId,
|
|
182
|
-
content: text,
|
|
183
|
-
type: "message"
|
|
184
|
-
});
|
|
185
|
-
},
|
|
186
|
-
typingHandler: async (typing) => {
|
|
187
|
-
if (shouldSkipBusOutboundForChannel(context.channel)) return;
|
|
188
|
-
await this.bus.publishOutbound({
|
|
189
|
-
channel: context.channel,
|
|
190
|
-
chat_id: context.chatId,
|
|
191
|
-
type: typing ? "typing_on" : "typing_off"
|
|
192
|
-
});
|
|
193
|
-
},
|
|
194
|
-
supportedFeatures: ["markdown", "typing"],
|
|
195
|
-
getCurrentModel: this.getCurrentModel,
|
|
196
|
-
switchModel: async (modelId) => {
|
|
197
|
-
return this.switchModelForSession(context.sessionKey, modelId);
|
|
198
|
-
},
|
|
199
|
-
listModels: async () => {
|
|
200
|
-
const providers = getAllProviders();
|
|
201
|
-
const models = [];
|
|
202
|
-
for (const providerId of providers) if (isProviderConfiguredSync(providerId)) {
|
|
203
|
-
const providerModels = getModelsByProvider(providerId);
|
|
204
|
-
for (const m of providerModels) models.push({
|
|
205
|
-
id: `${m.provider}/${m.id}`,
|
|
206
|
-
name: m.name || m.id,
|
|
207
|
-
provider: getProviderDisplayName(providerId)
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return models;
|
|
211
|
-
},
|
|
212
|
-
getUsage: async () => {
|
|
213
|
-
const messages = await this.sessionStore.load(context.sessionKey);
|
|
214
|
-
let promptTokens = 0;
|
|
215
|
-
let completionTokens = 0;
|
|
216
|
-
for (const msg of messages) if ("usage" in msg && msg.usage) {
|
|
217
|
-
const usage = msg.usage;
|
|
218
|
-
promptTokens += usage.input || 0;
|
|
219
|
-
completionTokens += usage.output || 0;
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
promptTokens,
|
|
223
|
-
completionTokens,
|
|
224
|
-
totalTokens: promptTokens + completionTokens,
|
|
225
|
-
messageCount: messages.length
|
|
226
|
-
};
|
|
227
|
-
},
|
|
228
|
-
invalidateAgentSession: this.invalidateAgentSession,
|
|
229
|
-
abortCurrentTurn: this.abortSessionTurn ? async () => {
|
|
230
|
-
await this.abortSessionTurn(context.sessionKey);
|
|
231
|
-
} : void 0,
|
|
232
|
-
compactSession: this.compactSession,
|
|
233
|
-
btwQuery: this.btwQuery,
|
|
234
|
-
getSessionContextReport: this.getSessionContextReport,
|
|
235
|
-
persistentGoalApis: this.getPersistentGoalApisForCommand({
|
|
236
|
-
sessionKey: context.sessionKey,
|
|
237
|
-
channel: context.channel,
|
|
238
|
-
chatId: context.chatId,
|
|
239
|
-
inboundMetadata: context.inboundMetadata
|
|
240
|
-
})
|
|
241
|
-
});
|
|
166
|
+
const wrapped = this.buildCommandContext(context, (text) => segments.push(text));
|
|
242
167
|
const result = await commandRegistry.execute(commandName, wrapped, args);
|
|
243
168
|
if (result.content) {
|
|
244
169
|
segments.push(result.content);
|
|
@@ -249,7 +174,10 @@ var CommandHandler = class {
|
|
|
249
174
|
type: "message"
|
|
250
175
|
});
|
|
251
176
|
}
|
|
252
|
-
return {
|
|
177
|
+
return {
|
|
178
|
+
handled: true,
|
|
179
|
+
aggregatedText: segments.filter((s) => s && s.trim()).join("\n\n")
|
|
180
|
+
};
|
|
253
181
|
}
|
|
254
182
|
};
|
|
255
183
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.js","names":[],"sources":["../../../../src/agent/messaging/command-handler.ts"],"sourcesContent":["/**\n * Command Handler - Parses and executes commands\n *\n * Handles command execution using the unified command system.\n */\n\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { isProviderConfiguredSync } from '../../providers/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { CompactionResult } from '../memory/compaction.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { commandRegistry, createCommandContext } from '../../chat-commands/index.js';\nimport { getAllProviders, getModelsByProvider, getProviderDisplayName } from '../../providers/index.js';\nimport type { PersistentGoalApis } from '../goals/persistent-goal-apis.js';\n\nconst log = createLogger('CommandHandler');\n\n/** Gateway console direct stream uses SSE tokens; there is no ChannelPlugin outbound for `webchat`. */\nfunction shouldSkipBusOutboundForChannel(channel: string): boolean {\n return channel === 'webchat';\n}\n\nexport interface CommandContext {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId: string;\n isGroup: boolean;\n /** From inbound message metadata (thread/account, etc.) for `/goal` continuation routing. */\n inboundMetadata?: Record<string, unknown>;\n}\n\nexport interface CommandHandlerConfig {\n config: Config;\n bus: MessageBus;\n sessionStore: SessionStore;\n sessionConfigStore?: SessionConfigStore;\n /** After /think persists, sync pi-agent */\n applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n getCurrentModel: () => string;\n switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n /** Drop in-memory agent after session file is cleared (e.g. /new) */\n invalidateAgentSession?: (sessionKey: string) => void;\n /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */\n abortSessionTurn?: (sessionKey: string) => Promise<void>;\n\n compactSession?: (\n sessionKey: string,\n options?: { instructions?: string; force?: boolean },\n ) => Promise<CompactionResult>;\n\n btwQuery?: (sessionKey: string, question: string) => Promise<{ text: string; error?: string }>;\n\n getSessionContextReport?: (\n sessionKey: string,\n mode: 'list' | 'detail' | 'json',\n ) => Promise<string>;\n\n getPersistentGoalApisForCommand: (routing: {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundMetadata?: Record<string, unknown>;\n }) => PersistentGoalApis;\n}\n\nexport class CommandHandler {\n private config: Config;\n private bus: MessageBus;\n private sessionStore: SessionStore;\n private sessionConfigStore?: SessionConfigStore;\n private applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n private getCurrentModel: () => string;\n private switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n private invalidateAgentSession?: (sessionKey: string) => void;\n private abortSessionTurn?: (sessionKey: string) => Promise<void>;\n private compactSession?: CommandHandlerConfig['compactSession'];\n private btwQuery?: CommandHandlerConfig['btwQuery'];\n private getSessionContextReport?: CommandHandlerConfig['getSessionContextReport'];\n private getPersistentGoalApisForCommand: CommandHandlerConfig['getPersistentGoalApisForCommand'];\n\n constructor(handlerConfig: CommandHandlerConfig) {\n this.config = handlerConfig.config;\n this.bus = handlerConfig.bus;\n this.sessionStore = handlerConfig.sessionStore;\n this.sessionConfigStore = handlerConfig.sessionConfigStore;\n this.applySessionThinkingLevel = handlerConfig.applySessionThinkingLevel;\n this.getCurrentModel = handlerConfig.getCurrentModel;\n this.switchModelForSession = handlerConfig.switchModelForSession;\n this.invalidateAgentSession = handlerConfig.invalidateAgentSession;\n this.abortSessionTurn = handlerConfig.abortSessionTurn;\n this.compactSession = handlerConfig.compactSession;\n this.btwQuery = handlerConfig.btwQuery;\n this.getSessionContextReport = handlerConfig.getSessionContextReport;\n this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;\n }\n\n /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */\n updateAgentConfig(config: Config): void {\n this.config = config;\n }\n\n /**\n * Execute a command using the unified command system\n */\n async executeCommand(\n commandName: string,\n args: string,\n context: CommandContext\n ): Promise<boolean> {\n // Check if command exists\n if (!commandRegistry.has(commandName)) {\n return false;\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command via new system');\n\n // Create command context\n const cmdCtx = createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n if (shouldSkipBusOutboundForChannel(context.channel)) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (shouldSkipBusOutboundForChannel(context.channel)) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as any;\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n });\n\n const result = await commandRegistry.execute(commandName, cmdCtx, args);\n\n if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n\n return true;\n }\n\n /**\n * Run command and return all user-visible text (ctx.reply + result.content) for SSE/CLI.\n * Same bus side effects as {@link executeCommand}.\n */\n async executeCommandAndAggregateReply(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<{ handled: boolean; aggregatedText: string }> {\n if (!commandRegistry.has(commandName)) {\n return { handled: false, aggregatedText: '' };\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command (aggregate reply)');\n\n const { aggregatedText } = await this.runRegistryExecuteWithCapture(args, commandName, context);\n\n return { handled: true, aggregatedText };\n }\n\n private async runRegistryExecuteWithCapture(\n args: string,\n commandName: string,\n context: CommandContext,\n ): Promise<{ aggregatedText: string }> {\n const segments: string[] = [];\n\n const wrapped = createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n segments.push(text);\n if (shouldSkipBusOutboundForChannel(context.channel)) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (shouldSkipBusOutboundForChannel(context.channel)) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as { input?: number; output?: number };\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n });\n\n const result = await commandRegistry.execute(commandName, wrapped, args);\n\n if (result.content) {\n segments.push(result.content);\n if (!shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n }\n\n const aggregatedText = segments.filter((s) => s && s.trim()).join('\\n\\n');\n return { aggregatedText };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"command-handler.js","names":[],"sources":["../../../../src/agent/messaging/command-handler.ts"],"sourcesContent":["/**\n * Command Handler - Parses and executes commands\n *\n * Handles command execution using the unified command system.\n */\n\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { isProviderConfiguredSync } from '../../providers/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { CompactionResult } from '../memory/compaction.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n commandRegistry,\n createCommandContext,\n type CommandContext as UnifiedCommandContext,\n} from '../../chat-commands/index.js';\nimport { getAllProviders, getModelsByProvider, getProviderDisplayName } from '../../providers/index.js';\nimport type { PersistentGoalApis } from '../goals/persistent-goal-apis.js';\n\nconst log = createLogger('CommandHandler');\n\n/** Gateway console direct stream uses SSE tokens; there is no ChannelPlugin outbound for `webchat`. */\nfunction shouldSkipBusOutboundForChannel(channel: string): boolean {\n return channel === 'webchat';\n}\n\nexport interface CommandContext {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId: string;\n isGroup: boolean;\n /** From inbound message metadata (thread/account, etc.) for `/goal` continuation routing. */\n inboundMetadata?: Record<string, unknown>;\n}\n\nexport interface CommandHandlerConfig {\n config: Config;\n bus: MessageBus;\n sessionStore: SessionStore;\n sessionConfigStore?: SessionConfigStore;\n /** After /think persists, sync pi-agent */\n applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n getCurrentModel: () => string;\n switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n /** Drop in-memory agent after session file is cleared (e.g. /new) */\n invalidateAgentSession?: (sessionKey: string) => void;\n /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */\n abortSessionTurn?: (sessionKey: string) => Promise<void>;\n\n compactSession?: (\n sessionKey: string,\n options?: { instructions?: string; force?: boolean },\n ) => Promise<CompactionResult>;\n\n btwQuery?: (sessionKey: string, question: string) => Promise<{ text: string; error?: string }>;\n\n getSessionContextReport?: (\n sessionKey: string,\n mode: 'list' | 'detail' | 'json',\n ) => Promise<string>;\n\n getPersistentGoalApisForCommand: (routing: {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundMetadata?: Record<string, unknown>;\n }) => PersistentGoalApis;\n}\n\nexport class CommandHandler {\n private config: Config;\n private bus: MessageBus;\n private sessionStore: SessionStore;\n private sessionConfigStore?: SessionConfigStore;\n private applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n private getCurrentModel: () => string;\n private switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n private invalidateAgentSession?: (sessionKey: string) => void;\n private abortSessionTurn?: (sessionKey: string) => Promise<void>;\n private compactSession?: CommandHandlerConfig['compactSession'];\n private btwQuery?: CommandHandlerConfig['btwQuery'];\n private getSessionContextReport?: CommandHandlerConfig['getSessionContextReport'];\n private getPersistentGoalApisForCommand: CommandHandlerConfig['getPersistentGoalApisForCommand'];\n\n constructor(handlerConfig: CommandHandlerConfig) {\n this.config = handlerConfig.config;\n this.bus = handlerConfig.bus;\n this.sessionStore = handlerConfig.sessionStore;\n this.sessionConfigStore = handlerConfig.sessionConfigStore;\n this.applySessionThinkingLevel = handlerConfig.applySessionThinkingLevel;\n this.getCurrentModel = handlerConfig.getCurrentModel;\n this.switchModelForSession = handlerConfig.switchModelForSession;\n this.invalidateAgentSession = handlerConfig.invalidateAgentSession;\n this.abortSessionTurn = handlerConfig.abortSessionTurn;\n this.compactSession = handlerConfig.compactSession;\n this.btwQuery = handlerConfig.btwQuery;\n this.getSessionContextReport = handlerConfig.getSessionContextReport;\n this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;\n }\n\n /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */\n updateAgentConfig(config: Config): void {\n this.config = config;\n }\n\n /**\n * Build the unified command context shared by all execute paths.\n * When `recorder` is set, every reply text is also captured (for SSE / CLI aggregation).\n */\n private buildCommandContext(\n context: CommandContext,\n recorder?: (text: string) => void,\n ): UnifiedCommandContext {\n const skipBusOutbound = shouldSkipBusOutboundForChannel(context.channel);\n\n return createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n recorder?.(text);\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as { input?: number; output?: number };\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n });\n }\n\n /**\n * Execute a command using the unified command system\n */\n async executeCommand(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<boolean> {\n if (!commandRegistry.has(commandName)) {\n return false;\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command via new system');\n\n const cmdCtx = this.buildCommandContext(context);\n const result = await commandRegistry.execute(commandName, cmdCtx, args);\n\n if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n\n return true;\n }\n\n /**\n * Run command and return all user-visible text (ctx.reply + result.content) for SSE/CLI.\n * Same bus side effects as {@link executeCommand}.\n */\n async executeCommandAndAggregateReply(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<{ handled: boolean; aggregatedText: string }> {\n if (!commandRegistry.has(commandName)) {\n return { handled: false, aggregatedText: '' };\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command (aggregate reply)');\n\n const segments: string[] = [];\n const wrapped = this.buildCommandContext(context, (text) => segments.push(text));\n const result = await commandRegistry.execute(commandName, wrapped, args);\n\n if (result.content) {\n segments.push(result.content);\n if (!shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n }\n\n const aggregatedText = segments.filter((s) => s && s.trim()).join('\\n\\n');\n return { handled: true, aggregatedText };\n }\n}\n"],"mappings":"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"}
|
|
@@ -4,3 +4,4 @@
|
|
|
4
4
|
export { MessageRouter, type MessageRoutingResult } from './message-router.js';
|
|
5
5
|
export { CommandHandler, type CommandContext, type CommandHandlerConfig } from './command-handler.js';
|
|
6
6
|
export { StreamManager, type StreamHandle } from './stream-manager.js';
|
|
7
|
+
export { OutboundCoordinator, type OutboundCoordinatorConfig, type SessionTurnCompletePayload, } from './outbound-coordinator.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MessageRouter } from "./message-router.js";
|
|
2
2
|
import { CommandHandler } from "./command-handler.js";
|
|
3
3
|
import { StreamManager } from "./stream-manager.js";
|
|
4
|
-
|
|
4
|
+
import { OutboundCoordinator } from "./outbound-coordinator.js";
|
|
5
|
+
export { CommandHandler, MessageRouter, OutboundCoordinator, StreamManager };
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles message classification, session key resolution, and routing logic.
|
|
5
5
|
*/
|
|
6
6
|
import type { InboundMessage } from '../../infra/bus/index.js';
|
|
7
|
-
import type { AgentContext } from '../service.js';
|
|
7
|
+
import type { AgentContext } from '../service.types.js';
|
|
8
8
|
export interface MessageRoutingResult {
|
|
9
9
|
context: AgentContext;
|
|
10
10
|
isCommand: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-router.js","names":[],"sources":["../../../../src/agent/messaging/message-router.ts"],"sourcesContent":["/**\n * Message Router - Routes inbound messages to appropriate handlers\n *\n * Handles message classification, session key resolution, and routing logic.\n */\n\nimport type { InboundMessage } from '../../infra/bus/index.js';\nimport { parseSlashCommand } from '../../chat-commands/command-parse.js';\nimport type { AgentContext } from '../service.js';\n\nexport interface MessageRoutingResult {\n context: AgentContext;\n isCommand: boolean;\n command?: string;\n commandArgs?: string;\n}\n\nexport class MessageRouter {\n /**\n * Route an inbound message and determine handling strategy\n */\n async routeMessage(msg: InboundMessage): Promise<MessageRoutingResult> {\n const sessionKey = this.resolveSessionKey(msg);\n\n const context: AgentContext = {\n channel: msg.channel,\n chatId: msg.chat_id,\n sessionKey,\n senderId: (msg.metadata?.senderId as string) || msg.sender_id,\n isGroup: (msg.metadata?.isGroup as boolean) || false,\n };\n\n const commandInfo = parseSlashCommand(msg.content);\n\n return {\n context,\n isCommand: commandInfo !== null,\n command: commandInfo?.command,\n commandArgs: commandInfo?.args,\n };\n }\n\n /**\n * Resolve session key from message metadata or derive from channel/chat_id\n */\n private resolveSessionKey(msg: InboundMessage): string {\n // Use sessionKey from metadata if available (for channels with custom session key format like Telegram)\n if (msg.metadata?.sessionKey) {\n return msg.metadata.sessionKey as string;\n }\n\n // For system messages, parse origin channel from chat_id\n if (msg.channel === 'system') {\n if (msg.chat_id.includes(':')) {\n const [ch, ...rest] = msg.chat_id.split(':');\n return `${ch}:${rest.join(':')}`;\n }\n }\n\n // Default: combine channel and chat_id\n return `${msg.channel}:${msg.chat_id}`;\n }\n}\n"],"mappings":";;AAiBA,IAAa,gBAAb,MAA2B;;;;CAIzB,MAAM,aAAa,KAAoD;EACrE,MAAM,aAAa,KAAK,kBAAkB,IAAI;EAE9C,MAAM,UAAwB;GAC5B,SAAS,IAAI;GACb,QAAQ,IAAI;GACZ;GACA,UAAW,IAAI,UAAU,YAAuB,IAAI;GACpD,SAAU,IAAI,UAAU,WAAuB;GAChD;EAED,MAAM,cAAc,kBAAkB,IAAI,QAAQ;AAElD,SAAO;GACL;GACA,WAAW,gBAAgB;GAC3B,SAAS,aAAa;GACtB,aAAa,aAAa;GAC3B;;;;;CAMH,kBAA0B,KAA6B;AAErD,MAAI,IAAI,UAAU,WAChB,QAAO,IAAI,SAAS;AAItB,MAAI,IAAI,YAAY;OACd,IAAI,QAAQ,SAAS,IAAI,EAAE;IAC7B,MAAM,CAAC,IAAI,GAAG,QAAQ,IAAI,QAAQ,MAAM,IAAI;AAC5C,WAAO,GAAG,GAAG,GAAG,KAAK,KAAK,IAAI;;;AAKlC,SAAO,GAAG,IAAI,QAAQ,GAAG,IAAI"}
|
|
1
|
+
{"version":3,"file":"message-router.js","names":[],"sources":["../../../../src/agent/messaging/message-router.ts"],"sourcesContent":["/**\n * Message Router - Routes inbound messages to appropriate handlers\n *\n * Handles message classification, session key resolution, and routing logic.\n */\n\nimport type { InboundMessage } from '../../infra/bus/index.js';\nimport { parseSlashCommand } from '../../chat-commands/command-parse.js';\nimport type { AgentContext } from '../service.types.js';\n\nexport interface MessageRoutingResult {\n context: AgentContext;\n isCommand: boolean;\n command?: string;\n commandArgs?: string;\n}\n\nexport class MessageRouter {\n /**\n * Route an inbound message and determine handling strategy\n */\n async routeMessage(msg: InboundMessage): Promise<MessageRoutingResult> {\n const sessionKey = this.resolveSessionKey(msg);\n\n const context: AgentContext = {\n channel: msg.channel,\n chatId: msg.chat_id,\n sessionKey,\n senderId: (msg.metadata?.senderId as string) || msg.sender_id,\n isGroup: (msg.metadata?.isGroup as boolean) || false,\n };\n\n const commandInfo = parseSlashCommand(msg.content);\n\n return {\n context,\n isCommand: commandInfo !== null,\n command: commandInfo?.command,\n commandArgs: commandInfo?.args,\n };\n }\n\n /**\n * Resolve session key from message metadata or derive from channel/chat_id\n */\n private resolveSessionKey(msg: InboundMessage): string {\n // Use sessionKey from metadata if available (for channels with custom session key format like Telegram)\n if (msg.metadata?.sessionKey) {\n return msg.metadata.sessionKey as string;\n }\n\n // For system messages, parse origin channel from chat_id\n if (msg.channel === 'system') {\n if (msg.chat_id.includes(':')) {\n const [ch, ...rest] = msg.chat_id.split(':');\n return `${ch}:${rest.join(':')}`;\n }\n }\n\n // Default: combine channel and chat_id\n return `${msg.channel}:${msg.chat_id}`;\n }\n}\n"],"mappings":";;AAiBA,IAAa,gBAAb,MAA2B;;;;CAIzB,MAAM,aAAa,KAAoD;EACrE,MAAM,aAAa,KAAK,kBAAkB,IAAI;EAE9C,MAAM,UAAwB;GAC5B,SAAS,IAAI;GACb,QAAQ,IAAI;GACZ;GACA,UAAW,IAAI,UAAU,YAAuB,IAAI;GACpD,SAAU,IAAI,UAAU,WAAuB;GAChD;EAED,MAAM,cAAc,kBAAkB,IAAI,QAAQ;AAElD,SAAO;GACL;GACA,WAAW,gBAAgB;GAC3B,SAAS,aAAa;GACtB,aAAa,aAAa;GAC3B;;;;;CAMH,kBAA0B,KAA6B;AAErD,MAAI,IAAI,UAAU,WAChB,QAAO,IAAI,SAAS;AAItB,MAAI,IAAI,YAAY;OACd,IAAI,QAAQ,SAAS,IAAI,EAAE;IAC7B,MAAM,CAAC,IAAI,GAAG,QAAQ,IAAI,QAAQ,MAAM,IAAI;AAC5C,WAAO,GAAG,GAAG,GAAG,KAAK,KAAK,IAAI;;;AAKlC,SAAO,GAAG,IAAI,QAAQ,GAAG,IAAI"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OutboundCoordinator — owns the post-turn outbound pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Concentrates the responsibilities that used to be scattered across
|
|
5
|
+
* `AgentService`:
|
|
6
|
+
* - typing-on / typing-off lifecycle for channels that surface "is typing…"
|
|
7
|
+
* - final assistant response delivery (silence guard + hook + bus publish)
|
|
8
|
+
* - cross-cutting `webchat_turn_complete` hook + `/goal` post-turn
|
|
9
|
+
* - thin pass-through for extension `message_sending` / `message_sent` hooks
|
|
10
|
+
*
|
|
11
|
+
* The class is intentionally framework-agnostic: it pulls everything it needs
|
|
12
|
+
* via the constructor config (no direct AgentService reference), so it is
|
|
13
|
+
* unit-testable and lets the parent `AgentService` shrink to a coordinator.
|
|
14
|
+
*/
|
|
15
|
+
import type { MessageBus, InboundMessage } from '../../infra/bus/index.js';
|
|
16
|
+
import type { Config } from '../../config/schema.js';
|
|
17
|
+
import type { HookHandler } from '../lifecycle/hook-handler.js';
|
|
18
|
+
import type { SessionContext } from '../session/index.js';
|
|
19
|
+
import { type TypingController } from '../lifecycle/typing.js';
|
|
20
|
+
import type { StreamManager } from './stream-manager.js';
|
|
21
|
+
export interface OutboundCoordinatorConfig {
|
|
22
|
+
bus: MessageBus;
|
|
23
|
+
hookHandler: HookHandler;
|
|
24
|
+
streamManager: StreamManager;
|
|
25
|
+
/** Reads the effective config snapshot (honours runtime overrides). */
|
|
26
|
+
getConfig: () => Config | undefined;
|
|
27
|
+
/** Resolves the last visible assistant text for a session (in-memory + agent fallback). */
|
|
28
|
+
getLastAssistantPlainText: (sessionKey: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Run the `/goal` post-turn verdict for a completed user turn. Owned by
|
|
31
|
+
* `PersistentGoalService`; OutboundCoordinator only forwards.
|
|
32
|
+
*/
|
|
33
|
+
runPersistentGoalPostTurn: (payload: SessionTurnCompletePayload) => Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface SessionTurnCompletePayload {
|
|
36
|
+
sessionKey: string;
|
|
37
|
+
channel: string;
|
|
38
|
+
chatId: string;
|
|
39
|
+
inboundUserText: string;
|
|
40
|
+
assistantPlainText: string;
|
|
41
|
+
aborted: boolean;
|
|
42
|
+
streamError?: string;
|
|
43
|
+
skipPersistentGoalPostTurn?: boolean;
|
|
44
|
+
outboundMetadata?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
export declare class OutboundCoordinator {
|
|
47
|
+
private readonly bus;
|
|
48
|
+
private readonly hookHandler;
|
|
49
|
+
private readonly streamManager;
|
|
50
|
+
private readonly getConfig;
|
|
51
|
+
private readonly getLastAssistantPlainText;
|
|
52
|
+
private readonly runPersistentGoalPostTurn;
|
|
53
|
+
constructor(config: OutboundCoordinatorConfig);
|
|
54
|
+
/**
|
|
55
|
+
* Build the typing indicator controller for an inbound message. Returns
|
|
56
|
+
* `null` for the CLI channel (no typing UI). Caller is responsible for
|
|
57
|
+
* `start()` and `stop()` (`stop()` should run AFTER the final outbound so
|
|
58
|
+
* Telegram/Weixin see `typing_off` only once the message is delivered).
|
|
59
|
+
*/
|
|
60
|
+
createTypingControllerForInbound(msg: InboundMessage): TypingController | null;
|
|
61
|
+
/**
|
|
62
|
+
* Publish the assistant's visible text as the final bus message. Honours the
|
|
63
|
+
* stream-manager "channel already streamed the final text" hint, the heartbeat
|
|
64
|
+
* silence guard, and the extension `message_sending` hook.
|
|
65
|
+
*/
|
|
66
|
+
sendFinalResponse(msg: InboundMessage, sessionContext: SessionContext): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Post-turn hook + `/goal` checklist evaluation. Wired into both the bus-driven
|
|
69
|
+
* inbound finally block and the webchat direct-stream finally. The goal verdict
|
|
70
|
+
* itself lives in `PersistentGoalService`; we just trigger the extension hook
|
|
71
|
+
* here and delegate the `/goal` work.
|
|
72
|
+
*/
|
|
73
|
+
emitSessionTurnComplete(payload: SessionTurnCompletePayload): Promise<void>;
|
|
74
|
+
/** Extension hook pass-through (Gateway ChannelManager). */
|
|
75
|
+
invokeOutboundMessageSending(to: string, content: string, channel: string): Promise<{
|
|
76
|
+
send: boolean;
|
|
77
|
+
content?: string;
|
|
78
|
+
reason?: string;
|
|
79
|
+
}>;
|
|
80
|
+
/** Extension hook pass-through (Gateway ChannelManager). */
|
|
81
|
+
invokeOutboundMessageSent(to: string, content: string, success: boolean, error: string | undefined, channel: string): Promise<void>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createLogger } from "../../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { createTypingController } from "../lifecycle/typing.js";
|
|
4
|
+
import { shouldSilence } from "../../heartbeat/tokens.js";
|
|
5
|
+
//#region src/agent/messaging/outbound-coordinator.ts
|
|
6
|
+
init_logger();
|
|
7
|
+
const log = createLogger("OutboundCoordinator");
|
|
8
|
+
var OutboundCoordinator = class {
|
|
9
|
+
bus;
|
|
10
|
+
hookHandler;
|
|
11
|
+
streamManager;
|
|
12
|
+
getConfig;
|
|
13
|
+
getLastAssistantPlainText;
|
|
14
|
+
runPersistentGoalPostTurn;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.bus = config.bus;
|
|
17
|
+
this.hookHandler = config.hookHandler;
|
|
18
|
+
this.streamManager = config.streamManager;
|
|
19
|
+
this.getConfig = config.getConfig;
|
|
20
|
+
this.getLastAssistantPlainText = config.getLastAssistantPlainText;
|
|
21
|
+
this.runPersistentGoalPostTurn = config.runPersistentGoalPostTurn;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build the typing indicator controller for an inbound message. Returns
|
|
25
|
+
* `null` for the CLI channel (no typing UI). Caller is responsible for
|
|
26
|
+
* `start()` and `stop()` (`stop()` should run AFTER the final outbound so
|
|
27
|
+
* Telegram/Weixin see `typing_off` only once the message is delivered).
|
|
28
|
+
*/
|
|
29
|
+
createTypingControllerForInbound(msg) {
|
|
30
|
+
if (msg.channel === "cli") return null;
|
|
31
|
+
const meta = msg.metadata;
|
|
32
|
+
return createTypingController({
|
|
33
|
+
intervalSeconds: 5,
|
|
34
|
+
onStart: async () => {
|
|
35
|
+
await this.bus.publishOutbound({
|
|
36
|
+
channel: msg.channel,
|
|
37
|
+
chat_id: msg.chat_id,
|
|
38
|
+
content: "",
|
|
39
|
+
type: "typing_on",
|
|
40
|
+
metadata: {
|
|
41
|
+
accountId: meta?.accountId,
|
|
42
|
+
threadId: meta?.threadId,
|
|
43
|
+
sessionWebhook: meta?.sessionWebhook,
|
|
44
|
+
conversationId: meta?.conversationId
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
onStop: async () => {
|
|
49
|
+
await this.bus.publishOutbound({
|
|
50
|
+
channel: msg.channel,
|
|
51
|
+
chat_id: msg.chat_id,
|
|
52
|
+
content: "",
|
|
53
|
+
type: "typing_off",
|
|
54
|
+
metadata: {
|
|
55
|
+
accountId: meta?.accountId,
|
|
56
|
+
threadId: meta?.threadId,
|
|
57
|
+
sessionWebhook: meta?.sessionWebhook,
|
|
58
|
+
conversationId: meta?.conversationId
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Publish the assistant's visible text as the final bus message. Honours the
|
|
66
|
+
* stream-manager "channel already streamed the final text" hint, the heartbeat
|
|
67
|
+
* silence guard, and the extension `message_sending` hook.
|
|
68
|
+
*/
|
|
69
|
+
async sendFinalResponse(msg, sessionContext) {
|
|
70
|
+
if (this.streamManager.consumeSkipFinalOutbound()) return;
|
|
71
|
+
const finalContent = this.getLastAssistantPlainText(sessionContext.sessionKey);
|
|
72
|
+
if (!finalContent?.trim()) return;
|
|
73
|
+
if (shouldSilence(finalContent, this.getConfig()?.gateway?.heartbeat?.ackMaxChars ?? 300) || finalContent.trim() === "NO_REPLY") {
|
|
74
|
+
log.debug({ sessionKey: sessionContext.sessionKey }, "Silent reply — skipping outbound");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const hookResult = await this.hookHandler.runMessageSending(sessionContext.chatId, finalContent, sessionContext.channel);
|
|
78
|
+
if (!hookResult.send) return;
|
|
79
|
+
await this.bus.publishOutbound({
|
|
80
|
+
channel: sessionContext.channel,
|
|
81
|
+
chat_id: sessionContext.chatId,
|
|
82
|
+
content: hookResult.content || finalContent,
|
|
83
|
+
type: "message",
|
|
84
|
+
metadata: {
|
|
85
|
+
accountId: msg.metadata?.accountId,
|
|
86
|
+
threadId: msg.metadata?.threadId,
|
|
87
|
+
transcribedVoice: sessionContext.metadata?.transcribedVoice,
|
|
88
|
+
sessionWebhook: msg.metadata?.sessionWebhook,
|
|
89
|
+
conversationId: msg.metadata?.conversationId
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Post-turn hook + `/goal` checklist evaluation. Wired into both the bus-driven
|
|
95
|
+
* inbound finally block and the webchat direct-stream finally. The goal verdict
|
|
96
|
+
* itself lives in `PersistentGoalService`; we just trigger the extension hook
|
|
97
|
+
* here and delegate the `/goal` work.
|
|
98
|
+
*/
|
|
99
|
+
async emitSessionTurnComplete(payload) {
|
|
100
|
+
await this.hookHandler.triggerWithSessionKey(payload.sessionKey, "webchat_turn_complete", {
|
|
101
|
+
sessionKey: payload.sessionKey,
|
|
102
|
+
channel: payload.channel,
|
|
103
|
+
chatId: payload.chatId,
|
|
104
|
+
inboundUserText: payload.inboundUserText,
|
|
105
|
+
assistantPlainText: payload.assistantPlainText,
|
|
106
|
+
aborted: payload.aborted,
|
|
107
|
+
...payload.streamError !== void 0 ? { streamError: payload.streamError } : {}
|
|
108
|
+
});
|
|
109
|
+
await this.runPersistentGoalPostTurn(payload);
|
|
110
|
+
}
|
|
111
|
+
/** Extension hook pass-through (Gateway ChannelManager). */
|
|
112
|
+
invokeOutboundMessageSending(to, content, channel) {
|
|
113
|
+
return this.hookHandler.runMessageSending(to, content, channel);
|
|
114
|
+
}
|
|
115
|
+
/** Extension hook pass-through (Gateway ChannelManager). */
|
|
116
|
+
invokeOutboundMessageSent(to, content, success, error, channel) {
|
|
117
|
+
return this.hookHandler.runMessageSent(to, content, success, error, channel);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
//#endregion
|
|
121
|
+
export { OutboundCoordinator };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=outbound-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-coordinator.js","names":[],"sources":["../../../../src/agent/messaging/outbound-coordinator.ts"],"sourcesContent":["/**\n * OutboundCoordinator — owns the post-turn outbound pipeline.\n *\n * Concentrates the responsibilities that used to be scattered across\n * `AgentService`:\n * - typing-on / typing-off lifecycle for channels that surface \"is typing…\"\n * - final assistant response delivery (silence guard + hook + bus publish)\n * - cross-cutting `webchat_turn_complete` hook + `/goal` post-turn\n * - thin pass-through for extension `message_sending` / `message_sent` hooks\n *\n * The class is intentionally framework-agnostic: it pulls everything it needs\n * via the constructor config (no direct AgentService reference), so it is\n * unit-testable and lets the parent `AgentService` shrink to a coordinator.\n */\n\nimport type { MessageBus, InboundMessage } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport type { HookHandler } from '../lifecycle/hook-handler.js';\nimport type { SessionContext } from '../session/index.js';\nimport { createTypingController, type TypingController } from '../lifecycle/typing.js';\nimport { DEFAULT_ACK_MAX_CHARS, NO_REPLY, shouldSilence } from '../../heartbeat/tokens.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { StreamManager } from './stream-manager.js';\n\nconst log = createLogger('OutboundCoordinator');\n\nexport interface OutboundCoordinatorConfig {\n bus: MessageBus;\n hookHandler: HookHandler;\n streamManager: StreamManager;\n /** Reads the effective config snapshot (honours runtime overrides). */\n getConfig: () => Config | undefined;\n /** Resolves the last visible assistant text for a session (in-memory + agent fallback). */\n getLastAssistantPlainText: (sessionKey: string) => string;\n /**\n * Run the `/goal` post-turn verdict for a completed user turn. Owned by\n * `PersistentGoalService`; OutboundCoordinator only forwards.\n */\n runPersistentGoalPostTurn: (payload: SessionTurnCompletePayload) => Promise<void>;\n}\n\nexport interface SessionTurnCompletePayload {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundUserText: string;\n assistantPlainText: string;\n aborted: boolean;\n streamError?: string;\n skipPersistentGoalPostTurn?: boolean;\n outboundMetadata?: Record<string, unknown>;\n}\n\nexport class OutboundCoordinator {\n private readonly bus: MessageBus;\n private readonly hookHandler: HookHandler;\n private readonly streamManager: StreamManager;\n private readonly getConfig: () => Config | undefined;\n private readonly getLastAssistantPlainText: (sessionKey: string) => string;\n private readonly runPersistentGoalPostTurn: OutboundCoordinatorConfig['runPersistentGoalPostTurn'];\n\n constructor(config: OutboundCoordinatorConfig) {\n this.bus = config.bus;\n this.hookHandler = config.hookHandler;\n this.streamManager = config.streamManager;\n this.getConfig = config.getConfig;\n this.getLastAssistantPlainText = config.getLastAssistantPlainText;\n this.runPersistentGoalPostTurn = config.runPersistentGoalPostTurn;\n }\n\n /**\n * Build the typing indicator controller for an inbound message. Returns\n * `null` for the CLI channel (no typing UI). Caller is responsible for\n * `start()` and `stop()` (`stop()` should run AFTER the final outbound so\n * Telegram/Weixin see `typing_off` only once the message is delivered).\n */\n createTypingControllerForInbound(msg: InboundMessage): TypingController | null {\n if (msg.channel === 'cli') {\n return null;\n }\n const meta = msg.metadata as Record<string, unknown> | undefined;\n return createTypingController({\n intervalSeconds: 5,\n onStart: async () => {\n await this.bus.publishOutbound({\n channel: msg.channel,\n chat_id: msg.chat_id,\n content: '',\n type: 'typing_on',\n metadata: {\n accountId: meta?.accountId,\n threadId: meta?.threadId,\n sessionWebhook: meta?.sessionWebhook,\n conversationId: meta?.conversationId,\n },\n });\n },\n onStop: async () => {\n await this.bus.publishOutbound({\n channel: msg.channel,\n chat_id: msg.chat_id,\n content: '',\n type: 'typing_off',\n metadata: {\n accountId: meta?.accountId,\n threadId: meta?.threadId,\n sessionWebhook: meta?.sessionWebhook,\n conversationId: meta?.conversationId,\n },\n });\n },\n });\n }\n\n /**\n * Publish the assistant's visible text as the final bus message. Honours the\n * stream-manager \"channel already streamed the final text\" hint, the heartbeat\n * silence guard, and the extension `message_sending` hook.\n */\n async sendFinalResponse(msg: InboundMessage, sessionContext: SessionContext): Promise<void> {\n if (this.streamManager.consumeSkipFinalOutbound()) {\n return;\n }\n\n const finalContent = this.getLastAssistantPlainText(sessionContext.sessionKey);\n if (!finalContent?.trim()) {\n return;\n }\n\n const ackMax = this.getConfig()?.gateway?.heartbeat?.ackMaxChars ?? DEFAULT_ACK_MAX_CHARS;\n if (shouldSilence(finalContent, ackMax) || finalContent.trim() === NO_REPLY) {\n log.debug({ sessionKey: sessionContext.sessionKey }, 'Silent reply — skipping outbound');\n return;\n }\n\n const hookResult = await this.hookHandler.runMessageSending(\n sessionContext.chatId,\n finalContent,\n sessionContext.channel,\n );\n if (!hookResult.send) {\n return;\n }\n\n await this.bus.publishOutbound({\n channel: sessionContext.channel,\n chat_id: sessionContext.chatId,\n content: hookResult.content || finalContent,\n type: 'message',\n metadata: {\n accountId: msg.metadata?.accountId,\n threadId: msg.metadata?.threadId,\n transcribedVoice: sessionContext.metadata?.transcribedVoice,\n sessionWebhook: msg.metadata?.sessionWebhook,\n conversationId: msg.metadata?.conversationId,\n },\n });\n }\n\n /**\n * Post-turn hook + `/goal` checklist evaluation. Wired into both the bus-driven\n * inbound finally block and the webchat direct-stream finally. The goal verdict\n * itself lives in `PersistentGoalService`; we just trigger the extension hook\n * here and delegate the `/goal` work.\n */\n async emitSessionTurnComplete(payload: SessionTurnCompletePayload): Promise<void> {\n await this.hookHandler.triggerWithSessionKey(payload.sessionKey, 'webchat_turn_complete', {\n sessionKey: payload.sessionKey,\n channel: payload.channel,\n chatId: payload.chatId,\n inboundUserText: payload.inboundUserText,\n assistantPlainText: payload.assistantPlainText,\n aborted: payload.aborted,\n ...(payload.streamError !== undefined ? { streamError: payload.streamError } : {}),\n });\n\n await this.runPersistentGoalPostTurn(payload);\n }\n\n /** Extension hook pass-through (Gateway ChannelManager). */\n invokeOutboundMessageSending(\n to: string,\n content: string,\n channel: string,\n ): Promise<{ send: boolean; content?: string; reason?: string }> {\n return this.hookHandler.runMessageSending(to, content, channel);\n }\n\n /** Extension hook pass-through (Gateway ChannelManager). */\n invokeOutboundMessageSent(\n to: string,\n content: string,\n success: boolean,\n error: string | undefined,\n channel: string,\n ): Promise<void> {\n return this.hookHandler.runMessageSent(to, content, success, error, channel);\n }\n}\n"],"mappings":";;;;;aAqBqD;AAGrD,MAAM,MAAM,aAAa,sBAAsB;AA6B/C,IAAa,sBAAb,MAAiC;CAC/B;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,QAAmC;AAC7C,OAAK,MAAM,OAAO;AAClB,OAAK,cAAc,OAAO;AAC1B,OAAK,gBAAgB,OAAO;AAC5B,OAAK,YAAY,OAAO;AACxB,OAAK,4BAA4B,OAAO;AACxC,OAAK,4BAA4B,OAAO;;;;;;;;CAS1C,iCAAiC,KAA8C;AAC7E,MAAI,IAAI,YAAY,MAClB,QAAO;EAET,MAAM,OAAO,IAAI;AACjB,SAAO,uBAAuB;GAC5B,iBAAiB;GACjB,SAAS,YAAY;AACnB,UAAM,KAAK,IAAI,gBAAgB;KAC7B,SAAS,IAAI;KACb,SAAS,IAAI;KACb,SAAS;KACT,MAAM;KACN,UAAU;MACR,WAAW,MAAM;MACjB,UAAU,MAAM;MAChB,gBAAgB,MAAM;MACtB,gBAAgB,MAAM;MACvB;KACF,CAAC;;GAEJ,QAAQ,YAAY;AAClB,UAAM,KAAK,IAAI,gBAAgB;KAC7B,SAAS,IAAI;KACb,SAAS,IAAI;KACb,SAAS;KACT,MAAM;KACN,UAAU;MACR,WAAW,MAAM;MACjB,UAAU,MAAM;MAChB,gBAAgB,MAAM;MACtB,gBAAgB,MAAM;MACvB;KACF,CAAC;;GAEL,CAAC;;;;;;;CAQJ,MAAM,kBAAkB,KAAqB,gBAA+C;AAC1F,MAAI,KAAK,cAAc,0BAA0B,CAC/C;EAGF,MAAM,eAAe,KAAK,0BAA0B,eAAe,WAAW;AAC9E,MAAI,CAAC,cAAc,MAAM,CACvB;AAIF,MAAI,cAAc,cADH,KAAK,WAAW,EAAE,SAAS,WAAW,eAAA,IACd,IAAI,aAAa,MAAM,KAAA,YAAe;AAC3E,OAAI,MAAM,EAAE,YAAY,eAAe,YAAY,EAAE,mCAAmC;AACxF;;EAGF,MAAM,aAAa,MAAM,KAAK,YAAY,kBACxC,eAAe,QACf,cACA,eAAe,QAChB;AACD,MAAI,CAAC,WAAW,KACd;AAGF,QAAM,KAAK,IAAI,gBAAgB;GAC7B,SAAS,eAAe;GACxB,SAAS,eAAe;GACxB,SAAS,WAAW,WAAW;GAC/B,MAAM;GACN,UAAU;IACR,WAAW,IAAI,UAAU;IACzB,UAAU,IAAI,UAAU;IACxB,kBAAkB,eAAe,UAAU;IAC3C,gBAAgB,IAAI,UAAU;IAC9B,gBAAgB,IAAI,UAAU;IAC/B;GACF,CAAC;;;;;;;;CASJ,MAAM,wBAAwB,SAAoD;AAChF,QAAM,KAAK,YAAY,sBAAsB,QAAQ,YAAY,yBAAyB;GACxF,YAAY,QAAQ;GACpB,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,iBAAiB,QAAQ;GACzB,oBAAoB,QAAQ;GAC5B,SAAS,QAAQ;GACjB,GAAI,QAAQ,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,aAAa,GAAG,EAAE;GAClF,CAAC;AAEF,QAAM,KAAK,0BAA0B,QAAQ;;;CAI/C,6BACE,IACA,SACA,SAC+D;AAC/D,SAAO,KAAK,YAAY,kBAAkB,IAAI,SAAS,QAAQ;;;CAIjE,0BACE,IACA,SACA,SACA,OACA,SACe;AACf,SAAO,KAAK,YAAY,eAAe,IAAI,SAAS,SAAS,OAAO,QAAQ"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
4
4
|
import { getAllModels, getDefaultModelSync, init_providers, resolveModel } from "../../providers/index.js";
|
|
5
5
|
import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
|
|
6
6
|
import { isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure } from "../orchestration/llm-turn-retry.js";
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent Event Handler
|
|
2
|
+
* Agent Event Handler — coordinates listeners on pi-agent events.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Previously a single god-handler with ten manager fields and one `switch`. Now a
|
|
5
|
+
* thin façade around {@link SessionEventBus}: each concern (progress, lifecycle
|
|
6
|
+
* hooks, tool-chain recording, error tracking, self-verify, etc.) registers its
|
|
7
|
+
* own listener at construction time, and external code can add new listeners via
|
|
8
|
+
* {@link AgentEventHandler.registerListener} without modifying this file (OCP).
|
|
9
|
+
*
|
|
10
|
+
* Ordering note: a few listeners are order-sensitive (notably the
|
|
11
|
+
* `tool_execution_end` chain — `SystemReminder` mutates `event.result` in place
|
|
12
|
+
* and downstream listeners read the mutated value). The `installX` calls below
|
|
13
|
+
* preserve the exact order from the previous implementation.
|
|
6
14
|
*/
|
|
7
15
|
import type { AgentEvent } from '@earendil-works/pi-agent-core';
|
|
8
16
|
import type { SessionContext } from '../session/session-context.js';
|
|
@@ -15,7 +23,18 @@ import type { SelfVerifyMiddleware } from '../middleware/index.js';
|
|
|
15
23
|
import type { SystemReminder } from '../prompt/system-reminder.js';
|
|
16
24
|
import type { ToolUsageAnalyzer } from '../tools/usage-analyzer.js';
|
|
17
25
|
import type { ErrorPatternMatcher } from '../tools/error-pattern-matcher.js';
|
|
18
|
-
|
|
26
|
+
export type SessionEventListener = (event: AgentEvent, context: SessionContext) => void;
|
|
27
|
+
export type SessionEventTypeFilter = AgentEvent['type'] | 'all';
|
|
28
|
+
/**
|
|
29
|
+
* Typed pub/sub for agent events. Listeners run in registration order; the bus
|
|
30
|
+
* itself is synchronous — listeners that need async work must dispatch their own
|
|
31
|
+
* promises (typically by awaiting and logging on error, like the lifecycle hooks).
|
|
32
|
+
*/
|
|
33
|
+
export declare class SessionEventBus {
|
|
34
|
+
private readonly listeners;
|
|
35
|
+
on(type: SessionEventTypeFilter, listener: SessionEventListener): () => void;
|
|
36
|
+
dispatch(event: AgentEvent, context: SessionContext | null): void;
|
|
37
|
+
}
|
|
19
38
|
export interface AgentEventHandlerConfig {
|
|
20
39
|
progressManager: ProgressFeedbackManager;
|
|
21
40
|
errorTracker: ToolErrorTracker;
|
|
@@ -26,39 +45,23 @@ export interface AgentEventHandlerConfig {
|
|
|
26
45
|
systemReminder: SystemReminder;
|
|
27
46
|
toolUsageAnalyzer: ToolUsageAnalyzer;
|
|
28
47
|
errorPatternMatcher: ErrorPatternMatcher;
|
|
29
|
-
modelManager: ModelManager;
|
|
30
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Thin façade over {@link SessionEventBus} that pre-registers all built-in
|
|
51
|
+
* listeners in their required order. `handle(event, ctx)` is the entry point
|
|
52
|
+
* used by `AgentService.handleSessionEvent`; extensions can hook in via
|
|
53
|
+
* {@link registerListener} without touching this class.
|
|
54
|
+
*/
|
|
31
55
|
export declare class AgentEventHandler {
|
|
32
|
-
private
|
|
33
|
-
private errorTracker;
|
|
34
|
-
private requestLimiter;
|
|
35
|
-
private lifecycleManager;
|
|
36
|
-
private toolChainTracker;
|
|
37
|
-
private selfVerifyMiddleware;
|
|
38
|
-
private systemReminder;
|
|
39
|
-
private toolUsageAnalyzer;
|
|
40
|
-
private errorPatternMatcher;
|
|
41
|
-
private modelManager;
|
|
42
|
-
private taskStartTime;
|
|
56
|
+
private readonly bus;
|
|
43
57
|
constructor(config: AgentEventHandlerConfig);
|
|
44
|
-
/**
|
|
45
|
-
* Handle an agent event
|
|
46
|
-
*/
|
|
58
|
+
/** Dispatch a pi-agent event to all registered listeners. */
|
|
47
59
|
handle(event: AgentEvent, context: SessionContext | null): void;
|
|
48
|
-
private handleAgentStart;
|
|
49
|
-
private handleTurnStart;
|
|
50
|
-
private handleMessageStart;
|
|
51
|
-
private handleMessageEnd;
|
|
52
|
-
private handleToolExecutionStart;
|
|
53
|
-
private handleToolExecutionUpdate;
|
|
54
|
-
private handleToolExecutionEnd;
|
|
55
|
-
private handleTurnEnd;
|
|
56
|
-
private handleAgentEnd;
|
|
57
|
-
private trackFileEdit;
|
|
58
|
-
private recordToolResult;
|
|
59
|
-
private extractError;
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
61
|
+
* Register an additional listener (e.g. from an extension). Returns an
|
|
62
|
+
* unsubscribe function. Listeners run after the built-ins in registration
|
|
63
|
+
* order; if you need to run before a built-in, you must create your own
|
|
64
|
+
* {@link SessionEventBus} instance.
|
|
62
65
|
*/
|
|
63
|
-
|
|
66
|
+
registerListener(type: SessionEventTypeFilter, listener: SessionEventListener): () => void;
|
|
64
67
|
}
|