@xopcai/xopc 0.0.102 → 0.0.104
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 +8 -5
- package/README.zh-CN.md +8 -5
- package/dist/_virtual/_rolldown/runtime.js +2 -3
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.d.ts +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.js +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
- package/dist/extensions/feishu/src/adapters/gateway-setup.d.ts +2 -0
- package/dist/extensions/feishu/src/adapters/gateway-setup.js +225 -0
- package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -0
- package/dist/extensions/feishu/src/index.d.ts +8 -1
- package/dist/extensions/feishu/src/index.js +14 -1
- package/dist/extensions/feishu/src/index.js.map +1 -0
- package/dist/extensions/feishu/src/outbound/outbound-adapter.js +1 -1
- package/dist/extensions/feishu/src/plugin.d.ts +2 -1
- package/dist/extensions/feishu/src/plugin.js +2 -0
- package/dist/extensions/feishu/src/plugin.js.map +1 -1
- package/dist/extensions/feishu/src/streaming/streaming-adapter.js +1 -1
- package/dist/extensions/feishu/src/transport/webhook/monitor.js +2 -2
- package/dist/extensions/feishu/src/transport/webhook/monitor.js.map +1 -1
- package/dist/extensions/feishu/xopc.extension.json +66 -1
- package/dist/extensions/telegram/src/adapters/gateway-setup.d.ts +2 -0
- package/dist/extensions/telegram/src/adapters/gateway-setup.js +146 -0
- package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -0
- package/dist/extensions/telegram/src/adapters/security-adapter.js +1 -1
- package/dist/extensions/telegram/src/command-handler.js +1 -2
- package/dist/extensions/telegram/src/command-handler.js.map +1 -1
- package/dist/extensions/telegram/src/config-schema.js +2 -2
- package/dist/extensions/telegram/src/config-schema.js.map +1 -1
- package/dist/extensions/telegram/src/doctor.d.ts +1 -0
- package/dist/extensions/telegram/src/doctor.js +68 -0
- package/dist/extensions/telegram/src/doctor.js.map +1 -1
- package/dist/extensions/telegram/src/index.d.ts +8 -1
- package/dist/extensions/telegram/src/index.js +15 -2
- package/dist/extensions/telegram/src/index.js.map +1 -0
- package/dist/extensions/telegram/src/plugin.d.ts +13 -5
- package/dist/extensions/telegram/src/plugin.js +32 -12
- package/dist/extensions/telegram/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/proxy-fetch.js +22 -5
- package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -1
- package/dist/extensions/telegram/src/send-options.js +8 -5
- package/dist/extensions/telegram/src/send-options.js.map +1 -1
- package/dist/extensions/telegram/xopc.extension.json +412 -5
- package/dist/extensions/weixin/src/adapters/onboard-cli.js +2 -2
- package/dist/extensions/weixin/src/adapters/onboard-cli.js.map +1 -1
- package/dist/extensions/weixin/src/api/api.js +1 -1
- package/dist/extensions/weixin/src/index.d.ts +8 -0
- package/dist/extensions/weixin/src/index.js +12 -1
- package/dist/extensions/weixin/src/index.js.map +1 -0
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.d.ts +2 -1
- package/dist/extensions/weixin/src/plugin.js +77 -2
- package/dist/extensions/weixin/src/plugin.js.map +1 -1
- package/dist/extensions/weixin/xopc.extension.json +52 -0
- package/dist/gateway/static/root/assets/agents-CvsBrBfi.js +396 -0
- package/dist/gateway/static/root/assets/{apps-page-Uv4kOmDE.js → apps-page-L-IwQTe0.js} +1 -1
- package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-D95KuPeP.js +1 -0
- package/dist/gateway/static/root/assets/cron-page-CfkWXDAI.js +1 -0
- package/dist/gateway/static/root/assets/{dist-DH4IuRV0.js → dist-C6vclgEL.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BNkhvRQW.js → extension-debug-page-D4JYAbsX.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CcIGQah2.js → extension-page-_T62gi6e.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-CkJbjyM-.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-drJUxxKP.js → fetch-B5aiIguv.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-startup-retry-DqmLXhs6.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-config-api-HwJV1K_Y.js +1 -0
- package/dist/gateway/static/root/assets/index-BPYKW7FB.css +1 -0
- package/dist/gateway/static/root/assets/index-DvTb6wNR.js +4845 -0
- package/dist/gateway/static/root/assets/{logs-page-CiG0m81R.js → logs-page-DsjtTjBy.js} +2 -2
- package/dist/gateway/static/root/assets/{note-detail-page-DG3DVFTf.js → note-detail-page-B2V7RhgD.js} +43 -43
- package/dist/gateway/static/root/assets/{note-time-DjlllCF3.js → note-time-BG8GCTr4.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-xrcVBQ6Z.js +1 -0
- package/dist/gateway/static/root/assets/schema-form-S-QUvhul.js +1 -0
- package/dist/gateway/static/root/assets/sessions-page-CrQer6Au.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-DujQl9c7.js +2 -0
- package/dist/gateway/static/root/assets/{settings-form-section-C3_sEFfD.js → settings-form-section-r1V7dRV6.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-C9nrONQ2.js +3 -0
- package/dist/gateway/static/root/assets/share-preview-page-DOFy0FNt.js +2 -0
- package/dist/gateway/static/root/assets/skills-page-DmTsrs_a.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-B6KXPHgK.js → theme-store-Bo3j5Ovv.js} +1 -1
- package/dist/gateway/static/root/assets/url-WgQIjFZu.js +3 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-AjmUAlEQ.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-page.utils-g57BRfEd.js → workflow-page.utils-DLEJ92gK.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-BnjjKrM1.js +27 -0
- package/dist/gateway/static/root/index.html +6 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +18 -6
- package/dist/src/agent/agent-manager.js +60 -35
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/builtin-agent-ids.d.ts +2 -0
- package/dist/src/agent/builtin-agent-ids.js +17 -0
- package/dist/src/agent/builtin-agent-ids.js.map +1 -0
- package/dist/src/agent/child-agent-factory.d.ts +4 -0
- package/dist/src/agent/child-agent-factory.js +28 -8
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/context/workspace-seed.js +1 -1
- package/dist/src/agent/context/workspace-templates/AGENTS.md +23 -184
- package/dist/src/agent/embedded/run-turn.js +8 -2
- package/dist/src/agent/embedded/run-turn.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
- package/dist/src/agent/embedded/subscribe-session.js +33 -51
- package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
- package/dist/src/agent/embedded/types.d.ts +36 -35
- package/dist/src/agent/fallback/candidates.js +1 -1
- package/dist/src/agent/fallback/candidates.js.map +1 -1
- package/dist/src/agent/inbound/attachment-pipeline.js +2 -2
- package/dist/src/agent/inbound/attachment-pipeline.js.map +1 -1
- package/dist/src/agent/inbound/inbound-loop.js +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +24 -5
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/models/manager.d.ts +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/models/manager.js.map +1 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +1 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +1 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +1 -1
- package/dist/src/agent/prompt/sections/tooling.js +4 -0
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
- package/dist/src/agent/service/process-direct-streaming.js +35 -18
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service-inbound-utils.d.ts +0 -1
- package/dist/src/agent/service-inbound-utils.js +1 -17
- package/dist/src/agent/service-inbound-utils.js.map +1 -1
- package/dist/src/agent/service.d.ts +4 -4
- package/dist/src/agent/service.js +27 -15
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-config-service.d.ts +1 -0
- package/dist/src/agent/session/session-config-service.js +9 -1
- package/dist/src/agent/session/session-config-service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.d.ts +2 -1
- package/dist/src/agent/session/session-inspector.js +4 -0
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/skills/config.js +1 -3
- package/dist/src/agent/skills/config.js.map +1 -1
- package/dist/src/agent/skills/format-skills-prompt.d.ts +1 -0
- package/dist/src/agent/skills/format-skills-prompt.js +3 -2
- package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/index.js +20 -5
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/installer.js +14 -27
- package/dist/src/agent/skills/installer.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -1
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +18 -4
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +11 -2
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -2
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.d.ts +4 -1
- package/dist/src/agent/skills/skill-manager.js +3 -3
- package/dist/src/agent/skills/skill-manager.js.map +1 -1
- package/dist/src/agent/skills/skill-view-path.d.ts +1 -17
- package/dist/src/agent/skills/skill-view-path.js +3 -66
- package/dist/src/agent/skills/skill-view-path.js.map +1 -1
- package/dist/src/agent/skills/test-framework.js +2 -3
- package/dist/src/agent/skills/test-framework.js.map +1 -1
- package/dist/src/agent/streaming/reasoning-visibility-sse.js +1 -0
- package/dist/src/agent/streaming/reasoning-visibility-sse.js.map +1 -1
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -0
- package/{skills/browser/SKILL.md → dist/src/agent/tool-manuals/browser.js} +51 -54
- package/dist/src/agent/tool-manuals/browser.js.map +1 -0
- package/dist/src/agent/tool-manuals/index.d.ts +10 -0
- package/dist/src/agent/tool-manuals/index.js +28 -0
- package/dist/src/agent/tool-manuals/index.js.map +1 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.js +7 -5
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +5 -4
- package/dist/src/agent/tools/send-media.js +1 -2
- package/dist/src/agent/tools/send-media.js.map +1 -1
- package/dist/src/agent/tools/session-search-tool.js +1 -1
- package/dist/src/agent/tools/shell.js +1 -1
- package/dist/src/agent/tools/skills-tools.js +37 -8
- package/dist/src/agent/tools/skills-tools.js.map +1 -1
- package/dist/src/agent/tools/tool-manual-tool.d.ts +6 -0
- package/dist/src/agent/tools/tool-manual-tool.js +34 -0
- package/dist/src/agent/tools/tool-manual-tool.js.map +1 -0
- package/dist/src/agent/tools/web-extract.js +2 -2
- package/dist/src/agent/tools/web.js +1 -1
- package/dist/src/agent/workflow/catalog.d.ts +7 -2
- package/dist/src/agent/workflow/catalog.js +66 -25
- package/dist/src/agent/workflow/catalog.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.d.ts +3 -0
- package/dist/src/agent/workflow/subagent-runner.js +50 -4
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +10 -0
- package/dist/src/auth/credentials.d.ts +7 -0
- package/dist/src/auth/credentials.js +45 -7
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/auth/index.d.ts +1 -1
- package/dist/src/auth/index.js.map +1 -1
- package/dist/src/auth/oauth/github-copilot.d.ts +1 -1
- package/dist/src/auth/oauth/google-antigravity.d.ts +1 -3
- package/dist/src/auth/oauth/google-antigravity.js +1 -1
- package/dist/src/auth/oauth/google-gemini-cli.d.ts +1 -3
- package/dist/src/auth/oauth/google-gemini-cli.js +1 -1
- package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-antigravity.js +3 -5
- package/dist/src/auth/oauth/google-oauth/google-antigravity.js.map +1 -0
- package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-gemini-cli.js +4 -5
- package/dist/src/auth/oauth/google-oauth/google-gemini-cli.js.map +1 -0
- package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/oauth-page.js +12 -4
- package/dist/src/auth/oauth/google-oauth/oauth-page.js.map +1 -0
- package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/pkce.d.ts +1 -1
- package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/pkce.js +2 -2
- package/dist/src/auth/oauth/google-oauth/pkce.js.map +1 -0
- package/dist/src/auth/oauth/index.js +2 -2
- package/dist/src/auth/oauth/kimi-coding.d.ts +1 -1
- package/dist/src/auth/oauth/kimi-coding.js +1 -1
- package/dist/src/auth/oauth/kimi-coding.js.map +1 -1
- package/dist/src/auth/oauth/minimax-cn.js +1 -1
- package/dist/src/auth/oauth/minimax-cn.js.map +1 -1
- package/dist/src/auth/oauth/minimax.js +1 -1
- package/dist/src/auth/oauth/minimax.js.map +1 -1
- package/dist/src/auth/oauth/openai-codex.d.ts +7 -2
- package/dist/src/auth/oauth/openai-codex.js +318 -1
- package/dist/src/auth/oauth/openai-codex.js.map +1 -0
- package/dist/src/auth/profiles/store.js +3 -2
- package/dist/src/auth/profiles/store.js.map +1 -1
- package/dist/src/browser/actions/extension-registry-bridge.js +1 -1
- package/dist/src/browser/actions/registry.js +2 -2
- package/dist/src/browser/cdp-local-launcher.js +1 -1
- package/dist/src/browser/index.js +3 -3
- package/dist/src/browser/providers/browser-ext-install.js +1 -1
- package/dist/src/browser/providers/cloakbrowser.js +1 -1
- package/dist/src/channels/attachments/attachment-classifiers.d.ts +1 -0
- package/dist/src/channels/attachments/attachment-classifiers.js +13 -2
- package/dist/src/channels/attachments/attachment-classifiers.js.map +1 -1
- package/dist/src/channels/catalog/channel-catalog-service.d.ts +11 -0
- package/dist/src/channels/catalog/channel-catalog-service.js +168 -0
- package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -0
- package/dist/src/channels/catalog/channel-catalog-types.d.ts +22 -0
- package/dist/src/channels/catalog/channel-catalog-types.js +1 -0
- package/dist/src/channels/dock.d.ts +0 -7
- package/dist/src/channels/dock.js +1 -21
- package/dist/src/channels/index.d.ts +1 -3
- package/dist/src/channels/index.js +1 -5
- package/dist/src/channels/lifecycle-supervisor.d.ts +1 -0
- package/dist/src/channels/lifecycle-supervisor.js +11 -0
- package/dist/src/channels/lifecycle-supervisor.js.map +1 -1
- package/dist/src/channels/manager.d.ts +1 -0
- package/dist/src/channels/manager.js +3 -0
- package/dist/src/channels/manager.js.map +1 -1
- package/dist/src/channels/pairing/pairing-channel.d.ts +2 -3
- package/dist/src/channels/pairing/pairing-messages.js +1 -1
- package/dist/src/channels/pairing/pairing-messages.js.map +1 -1
- package/dist/src/channels/pairing/pairing-service.d.ts +1 -1
- package/dist/src/channels/pairing/pairing-service.js +8 -27
- package/dist/src/channels/pairing/pairing-service.js.map +1 -1
- package/dist/src/channels/plugin-types.d.ts +3 -1
- package/dist/src/channels/plugins/types.adapters.d.ts +55 -2
- package/dist/src/channels/telegram/index.js +1 -1
- package/dist/src/chat-commands/builtins/config.js +4 -4
- package/dist/src/chat-commands/builtins/config.js.map +1 -1
- package/dist/src/chat-commands/builtins/model.js +2 -2
- package/dist/src/chat-commands/builtins/model.js.map +1 -1
- package/dist/src/chat-commands/config-paths.js +1 -1
- package/dist/src/chat-commands/config-paths.js.map +1 -1
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/cli/bin.js +1 -1
- package/dist/src/cli/command-manifest.js +2 -2
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/agents.js +2 -4
- package/dist/src/cli/commands/agents.js.map +1 -1
- package/dist/src/cli/commands/auth.js +40 -52
- package/dist/src/cli/commands/auth.js.map +1 -1
- package/dist/src/cli/commands/browser-cli-helpers.js +1 -1
- package/dist/src/cli/commands/channels.d.ts +1 -5
- package/dist/src/cli/commands/channels.js +115 -281
- package/dist/src/cli/commands/channels.js.map +1 -1
- package/dist/src/cli/commands/config.js +2 -2
- package/dist/src/cli/commands/config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js +16 -69
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +6 -4
- package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-plugins.js +2 -2
- package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +13 -9
- package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -1
- package/dist/src/cli/commands/extension-dev.js.map +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +2 -1
- package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
- package/dist/src/cli/commands/extension-pack.js +2 -1
- package/dist/src/cli/commands/extension-pack.js.map +1 -1
- package/dist/src/cli/commands/models.js +192 -54
- package/dist/src/cli/commands/models.js.map +1 -1
- package/dist/src/cli/commands/onboard/channels/index.js +1 -1
- package/dist/src/cli/commands/onboard/channels/index.js.map +1 -1
- package/dist/src/cli/commands/onboard/channels/registry.d.ts +2 -1
- package/dist/src/cli/commands/onboard/channels/registry.js +32 -8
- package/dist/src/cli/commands/onboard/channels/registry.js.map +1 -1
- package/dist/src/cli/commands/onboard/model.d.ts +1 -4
- package/dist/src/cli/commands/onboard/model.js +257 -184
- package/dist/src/cli/commands/onboard/model.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +4 -6
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/setup-shared/runner.d.ts +1 -1
- package/dist/src/cli/commands/setup-shared/runner.js.map +1 -1
- package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
- package/dist/src/cli/commands/setup-shared/types.js.map +1 -1
- package/dist/src/cli/commands/tui.js +13 -5
- package/dist/src/cli/commands/tui.js.map +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/cli/utils/oauth-login.d.ts +17 -0
- package/dist/src/cli/utils/oauth-login.js +93 -0
- package/dist/src/cli/utils/oauth-login.js.map +1 -0
- package/dist/src/cli/utils/oauth-providers.js +2 -2
- package/dist/src/commands/agents.config.d.ts +3 -3
- package/dist/src/commands/agents.config.js +7 -7
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-profile.d.ts +1 -1
- package/dist/src/config/agent-profile.js +6 -2
- package/dist/src/config/agent-profile.js.map +1 -1
- package/dist/src/config/agent-typed-models.d.ts +2 -2
- package/dist/src/config/agent-typed-models.js +13 -2
- package/dist/src/config/agent-typed-models.js.map +1 -1
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/integration.d.ts +1 -1
- package/dist/src/config/loader.d.ts +0 -1
- package/dist/src/config/loader.js +4 -9
- package/dist/src/config/loader.js.map +1 -1
- package/dist/src/config/models-json.d.ts +6 -6
- package/dist/src/config/rules.js +2 -12
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/config/schema.d.ts +74 -47
- package/dist/src/config/schema.js +28 -66
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/validate-channel-configs.d.ts +0 -3
- package/dist/src/config/validate-channel-configs.js +29 -10
- package/dist/src/config/validate-channel-configs.js.map +1 -1
- package/dist/src/cron/executor.js +1 -4
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/extensions/activation-context.js +3 -1
- package/dist/src/extensions/activation-context.js.map +1 -1
- package/dist/src/extensions/activation-planner.js +12 -0
- package/dist/src/extensions/activation-planner.js.map +1 -1
- package/dist/src/extensions/api.d.ts +5 -1
- package/dist/src/extensions/api.js +12 -0
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/discover-extensions.js +17 -13
- package/dist/src/extensions/discover-extensions.js.map +1 -1
- package/dist/src/extensions/extension-metadata-snapshot.js +11 -5
- package/dist/src/extensions/extension-metadata-snapshot.js.map +1 -1
- package/dist/src/extensions/index.js +12 -4
- package/dist/src/extensions/index.js.map +1 -0
- package/dist/src/extensions/loader.d.ts +5 -1
- package/dist/src/extensions/loader.js +12 -11
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/manifest-registry.js +98 -93
- package/dist/src/extensions/manifest-registry.js.map +1 -1
- package/dist/src/extensions/normalize-manifest.js +91 -15
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/extensions/sdk/testing.js +4 -0
- package/dist/src/extensions/sdk/testing.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +32 -1
- package/dist/src/extensions/types/manifest.d.ts +60 -0
- package/dist/src/extensions/types/tui.d.ts +414 -5
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +16 -0
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/agent-run-relay.d.ts +2 -3
- package/dist/src/gateway/agent-run-relay.js +10 -3
- package/dist/src/gateway/agent-run-relay.js.map +1 -1
- package/dist/src/gateway/agents-admin.d.ts +32 -19
- package/dist/src/gateway/agents-admin.js +113 -93
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/chat-stream/mapper.d.ts +34 -0
- package/dist/src/gateway/chat-stream/mapper.js +244 -0
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -0
- package/dist/src/gateway/chat-stream/protocol.d.ts +100 -0
- package/dist/src/gateway/chat-stream/protocol.js +1 -0
- package/dist/src/gateway/hono/lib/agent-model.d.ts +4 -4
- package/dist/src/gateway/hono/lib/agent-model.js +13 -11
- package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +19 -7
- package/dist/src/gateway/hono/lib/config-payload.js +16 -15
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/oauth-async.js +2 -2
- package/dist/src/gateway/hono/oauth.js +2 -2
- package/dist/src/gateway/hono/routes/agents.js +83 -48
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/channels.js +134 -214
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +10 -4
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.js +26 -13
- package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +1 -11
- package/dist/src/gateway/hono/routes/config-patch/channels.js +18 -165
- package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +5 -2
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +13 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +25 -5
- package/dist/src/gateway/hono/routes/models.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +2 -4
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +179 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/tui.d.ts +3 -0
- package/dist/src/gateway/hono/routes/tui.js +16 -0
- package/dist/src/gateway/hono/routes/tui.js.map +1 -0
- package/dist/src/gateway/hono/routes/workflows.js +25 -1
- package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +5 -7
- package/dist/src/gateway/hono/sse.js +21 -38
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/protocol.js.map +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +2 -4
- package/dist/src/gateway/service/agent-runner.js +1 -1
- package/dist/src/gateway/service/agent-runner.js.map +1 -1
- package/dist/src/gateway/service/marketplace-service.d.ts +4 -3
- package/dist/src/gateway/service/marketplace-service.js +7 -4
- package/dist/src/gateway/service/marketplace-service.js.map +1 -1
- package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -6
- package/dist/src/gateway/service/run-gateway-agent.js +63 -36
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +19 -0
- package/dist/src/gateway/service/sessions-api.js +12 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +6 -0
- package/dist/src/gateway/service.js +73 -57
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/media/store.js +3 -0
- package/dist/src/media/store.js.map +1 -1
- package/dist/src/notes/service.js +1 -1
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/project-trust/trust-store.d.ts +30 -0
- package/dist/src/project-trust/trust-store.js +194 -0
- package/dist/src/project-trust/trust-store.js.map +1 -0
- package/dist/src/providers/index.d.ts +4 -4
- package/dist/src/providers/index.js +41 -22
- package/dist/src/providers/index.js.map +1 -1
- package/dist/src/providers/presentation.d.ts +34 -0
- package/dist/src/providers/presentation.js +162 -0
- package/dist/src/providers/presentation.js.map +1 -0
- package/dist/src/routing/resolve-route.d.ts +0 -3
- package/dist/src/routing/resolve-route.js.map +1 -1
- package/dist/src/routing/resolve-tui-session-key.d.ts +2 -0
- package/dist/src/routing/resolve-tui-session-key.js +8 -3
- package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
- package/dist/src/session/client-history.d.ts +32 -0
- package/dist/src/session/client-history.js +232 -1
- package/dist/src/session/client-history.js.map +1 -1
- package/dist/src/session/manager.d.ts +37 -4
- package/dist/src/session/manager.js +39 -15
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/session-context-for-llm.d.ts +93 -1
- package/dist/src/session/session-context-for-llm.js +105 -2
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/session/store.d.ts +37 -0
- package/dist/src/session/store.js +127 -2
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/stored-rows-to-file-entries.js +37 -1
- package/dist/src/session/stored-rows-to-file-entries.js.map +1 -1
- package/dist/src/session/types.d.ts +14 -1
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/share/share-thumbnail.js +1 -1
- package/dist/src/storage/sqlite/migrations/004_add_session_type_metadata.sql +15 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/row-mappers.d.ts +14 -1
- package/dist/src/storage/sqlite/row-mappers.js +14 -1
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/session-metadata.js +1 -0
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
- package/dist/src/storage/sqlite/session-repository.js +52 -25
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +53 -4
- package/dist/src/tui/backends/embedded-backend.js +227 -39
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +59 -3
- package/dist/src/tui/backends/gateway-sse-backend.js +416 -26
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/chat-history.d.ts +5 -1
- package/dist/src/tui/chat-history.js +78 -8
- package/dist/src/tui/chat-history.js.map +1 -1
- package/dist/src/tui/clipboard-text.d.ts +5 -0
- package/dist/src/tui/clipboard-text.js +46 -0
- package/dist/src/tui/clipboard-text.js.map +1 -0
- package/dist/src/tui/components/assistant-message.d.ts +19 -3
- package/dist/src/tui/components/assistant-message.js +115 -9
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/components/bash-execution.d.ts +3 -2
- package/dist/src/tui/components/bash-execution.js +31 -3
- package/dist/src/tui/components/bash-execution.js.map +1 -1
- package/dist/src/tui/components/bash-summary.d.ts +23 -0
- package/dist/src/tui/components/bash-summary.js +87 -0
- package/dist/src/tui/components/bash-summary.js.map +1 -0
- package/dist/src/tui/components/branch-message-summary.d.ts +17 -0
- package/dist/src/tui/components/branch-message-summary.js +43 -0
- package/dist/src/tui/components/branch-message-summary.js.map +1 -0
- package/dist/src/tui/components/branch-summary.d.ts +13 -0
- package/dist/src/tui/components/branch-summary.js +51 -0
- package/dist/src/tui/components/branch-summary.js.map +1 -0
- package/dist/src/tui/components/chat-log.d.ts +46 -6
- package/dist/src/tui/components/chat-log.js +183 -21
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/components/compaction-summary.d.ts +13 -0
- package/dist/src/tui/components/compaction-summary.js +46 -0
- package/dist/src/tui/components/compaction-summary.js.map +1 -0
- package/dist/src/tui/components/custom-editor.d.ts +1 -0
- package/dist/src/tui/components/custom-editor.js +2 -0
- package/dist/src/tui/components/custom-editor.js.map +1 -1
- package/dist/src/tui/components/custom-message.d.ts +23 -0
- package/dist/src/tui/components/custom-message.js +65 -0
- package/dist/src/tui/components/custom-message.js.map +1 -0
- package/dist/src/tui/components/extension-dialog.d.ts +42 -0
- package/dist/src/tui/components/extension-dialog.js +127 -0
- package/dist/src/tui/components/extension-dialog.js.map +1 -0
- package/dist/src/tui/components/scoped-models-selector.d.ts +7 -2
- package/dist/src/tui/components/scoped-models-selector.js +89 -16
- package/dist/src/tui/components/scoped-models-selector.js.map +1 -1
- package/dist/src/tui/components/searchable-select-list.d.ts +30 -3
- package/dist/src/tui/components/searchable-select-list.js +82 -10
- package/dist/src/tui/components/searchable-select-list.js.map +1 -1
- package/dist/src/tui/components/session-selector.d.ts +18 -4
- package/dist/src/tui/components/session-selector.js +207 -40
- package/dist/src/tui/components/session-selector.js.map +1 -1
- package/dist/src/tui/components/settings-selector.d.ts +6 -2
- package/dist/src/tui/components/settings-selector.js +126 -7
- package/dist/src/tui/components/settings-selector.js.map +1 -1
- package/dist/src/tui/components/thinking-selector.d.ts +12 -0
- package/dist/src/tui/components/thinking-selector.js +48 -0
- package/dist/src/tui/components/thinking-selector.js.map +1 -0
- package/dist/src/tui/components/tool-execution.d.ts +57 -3
- package/dist/src/tui/components/tool-execution.js +378 -28
- package/dist/src/tui/components/tool-execution.js.map +1 -1
- package/dist/src/tui/components/tui-bottom-bar.d.ts +9 -1
- package/dist/src/tui/components/tui-bottom-bar.js +56 -11
- package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
- package/dist/src/tui/components/tui-header.d.ts +9 -2
- package/dist/src/tui/components/tui-header.js +25 -5
- package/dist/src/tui/components/tui-header.js.map +1 -1
- package/dist/src/tui/components/user-message.d.ts +4 -2
- package/dist/src/tui/components/user-message.js +42 -9
- package/dist/src/tui/components/user-message.js.map +1 -1
- package/dist/src/tui/components/visual-truncate.d.ts +11 -0
- package/dist/src/tui/components/visual-truncate.js +27 -0
- package/dist/src/tui/components/visual-truncate.js.map +1 -0
- package/dist/src/tui/extension-host/autocomplete.d.ts +43 -0
- package/dist/src/tui/extension-host/autocomplete.js +116 -0
- package/dist/src/tui/extension-host/autocomplete.js.map +1 -0
- package/dist/src/tui/extension-host/host.d.ts +31 -1
- package/dist/src/tui/extension-host/host.js +123 -6
- package/dist/src/tui/extension-host/host.js.map +1 -1
- package/dist/src/tui/extension-host/load-extensions.d.ts +6 -1
- package/dist/src/tui/extension-host/load-extensions.js +4 -3
- package/dist/src/tui/extension-host/load-extensions.js.map +1 -1
- package/dist/src/tui/extension-host/runtime-context.d.ts +21 -0
- package/dist/src/tui/extension-host/runtime-context.js +152 -0
- package/dist/src/tui/extension-host/runtime-context.js.map +1 -0
- package/dist/src/tui/extension-host/runtime.d.ts +52 -4
- package/dist/src/tui/extension-host/runtime.js +547 -85
- package/dist/src/tui/extension-host/runtime.js.map +1 -1
- package/dist/src/tui/extension-host/surface.d.ts +20 -0
- package/dist/src/tui/extension-host/surface.js +30 -6
- package/dist/src/tui/extension-host/surface.js.map +1 -1
- package/dist/src/tui/extension-host/tool-renderers.d.ts +6 -3
- package/dist/src/tui/extension-host/tool-renderers.js +43 -5
- package/dist/src/tui/extension-host/tool-renderers.js.map +1 -1
- package/dist/src/tui/format-tui-hotkeys.d.ts +12 -2
- package/dist/src/tui/format-tui-hotkeys.js +22 -5
- package/dist/src/tui/format-tui-hotkeys.js.map +1 -1
- package/dist/src/tui/tui-agent-events.d.ts +8 -6
- package/dist/src/tui/tui-agent-events.js +200 -59
- package/dist/src/tui/tui-agent-events.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +169 -3
- package/dist/src/tui/tui-command-formatters.d.ts +76 -0
- package/dist/src/tui/tui-command-formatters.js +594 -0
- package/dist/src/tui/tui-command-formatters.js.map +1 -0
- package/dist/src/tui/tui-commands.d.ts +57 -7
- package/dist/src/tui/tui-commands.js +639 -43
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-context-usage.d.ts +1 -1
- package/dist/src/tui/tui-context-usage.js +9 -1
- package/dist/src/tui/tui-context-usage.js.map +1 -1
- package/dist/src/tui/tui-extension-user-message.d.ts +8 -0
- package/dist/src/tui/tui-extension-user-message.js +32 -0
- package/dist/src/tui/tui-extension-user-message.js.map +1 -0
- package/dist/src/tui/tui-follow-up-queue.d.ts +9 -0
- package/dist/src/tui/tui-follow-up-queue.js +18 -0
- package/dist/src/tui/tui-follow-up-queue.js.map +1 -0
- package/dist/src/tui/tui-local-shell.d.ts +11 -1
- package/dist/src/tui/tui-local-shell.js +50 -8
- package/dist/src/tui/tui-local-shell.js.map +1 -1
- package/dist/src/tui/tui-model-picker.d.ts +26 -0
- package/dist/src/tui/tui-model-picker.js +152 -0
- package/dist/src/tui/tui-model-picker.js.map +1 -0
- package/dist/src/tui/tui-oauth-login.d.ts +16 -0
- package/dist/src/tui/tui-oauth-login.js +189 -0
- package/dist/src/tui/tui-oauth-login.js.map +1 -0
- package/dist/src/tui/tui-overlays.d.ts +3 -3
- package/dist/src/tui/tui-overlays.js +6 -7
- package/dist/src/tui/tui-overlays.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.d.ts +27 -32
- package/dist/src/tui/tui-picker-overlay.js +340 -30
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/tui/tui-picker-services.d.ts +41 -0
- package/dist/src/tui/tui-picker-services.js +1 -0
- package/dist/src/tui/tui-run-state.d.ts +11 -0
- package/dist/src/tui/tui-run-state.js +114 -0
- package/dist/src/tui/tui-run-state.js.map +1 -0
- package/dist/src/tui/tui-runtime-hints.d.ts +4 -0
- package/dist/src/tui/tui-runtime-hints.js +18 -0
- package/dist/src/tui/tui-runtime-hints.js.map +1 -0
- package/dist/src/tui/tui-scoped-models.d.ts +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-scoped-models.js.map +1 -1
- package/dist/src/tui/tui-session-actions.d.ts +5 -3
- package/dist/src/tui/tui-session-actions.js +21 -9
- package/dist/src/tui/tui-session-actions.js.map +1 -1
- package/dist/src/tui/tui-session-format.d.ts +4 -1
- package/dist/src/tui/tui-session-format.js +17 -3
- package/dist/src/tui/tui-session-format.js.map +1 -1
- package/dist/src/tui/tui-session-snapshot.d.ts +82 -0
- package/dist/src/tui/tui-session-snapshot.js +184 -0
- package/dist/src/tui/tui-session-snapshot.js.map +1 -0
- package/dist/src/tui/tui-session-stats.d.ts +3 -0
- package/dist/src/tui/tui-session-stats.js +59 -0
- package/dist/src/tui/tui-session-stats.js.map +1 -0
- package/dist/src/tui/tui-settings.d.ts +21 -0
- package/dist/src/tui/tui-settings.js +28 -1
- package/dist/src/tui/tui-settings.js.map +1 -1
- package/dist/src/tui/tui-skills-autocomplete.js +1 -1
- package/dist/src/tui/tui-skills-autocomplete.js.map +1 -1
- package/dist/src/tui/tui-startup-resources.d.ts +3 -0
- package/dist/src/tui/tui-startup-resources.js +39 -0
- package/dist/src/tui/tui-startup-resources.js.map +1 -0
- package/dist/src/tui/tui-startup-text.d.ts +10 -0
- package/dist/src/tui/tui-startup-text.js +58 -0
- package/dist/src/tui/tui-startup-text.js.map +1 -0
- package/dist/src/tui/tui-stdio-filter.d.ts +1 -0
- package/dist/src/tui/tui-stdio-filter.js +11 -7
- package/dist/src/tui/tui-stdio-filter.js.map +1 -1
- package/dist/src/tui/tui-submit.d.ts +2 -0
- package/dist/src/tui/tui-submit.js +2 -1
- package/dist/src/tui/tui-submit.js.map +1 -1
- package/dist/src/tui/tui-tool-diff.js +61 -7
- package/dist/src/tui/tui-tool-diff.js.map +1 -1
- package/dist/src/tui/tui-tool-result.d.ts +17 -0
- package/dist/src/tui/tui-tool-result.js +74 -0
- package/dist/src/tui/tui-tool-result.js.map +1 -0
- package/dist/src/tui/tui-transcript-tree-picker.d.ts +57 -0
- package/dist/src/tui/tui-transcript-tree-picker.js +604 -0
- package/dist/src/tui/tui-transcript-tree-picker.js.map +1 -0
- package/dist/src/tui/tui-transcript-tree.d.ts +7 -0
- package/dist/src/tui/tui-transcript-tree.js +316 -0
- package/dist/src/tui/tui-transcript-tree.js.map +1 -0
- package/dist/src/tui/tui-types.d.ts +25 -34
- package/dist/src/tui/tui-types.js +12 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +1288 -112
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/tui/xopc-tui-keybindings.d.ts +127 -2
- package/dist/src/tui/xopc-tui-keybindings.js +127 -2
- package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
- package/dist/src/workflows/domain/definition-utils.d.ts +2 -1
- package/dist/src/workflows/domain/definition-utils.js +18 -8
- package/dist/src/workflows/domain/definition-utils.js.map +1 -1
- package/dist/src/workflows/domain/definition.d.ts +25 -0
- package/dist/src/workflows/domain/event.d.ts +1 -0
- package/dist/src/workflows/domain/result.d.ts +15 -0
- package/dist/src/workflows/domain/run.d.ts +2 -0
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/engine/projector.js +4 -0
- package/dist/src/workflows/engine/projector.js.map +1 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +37 -1
- package/dist/src/workflows/engine/workflow-engine.js +75 -11
- package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
- package/dist/src/workflows/index.d.ts +1 -0
- package/dist/src/workflows/index.js +4 -1
- package/dist/src/workflows/registry/catalog-workflow-definition-registry.d.ts +9 -0
- package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +40 -0
- package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -0
- package/dist/src/workflows/registry/index.d.ts +2 -0
- package/dist/src/workflows/registry/index.js +2 -0
- package/dist/src/workflows/registry/workflow-definition-registry.d.ts +15 -0
- package/dist/src/workflows/registry/workflow-definition-registry.js +1 -0
- package/dist/src/workflows/runtime/index.d.ts +2 -0
- package/dist/src/workflows/runtime/index.js +2 -1
- package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +5 -0
- package/dist/src/workflows/runtime/script-workflow-runtime.js +15 -0
- package/dist/src/workflows/runtime/script-workflow-runtime.js.map +1 -0
- package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +16 -0
- package/dist/src/workflows/runtime/workflow-runtime-port.js +1 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js +3 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
- package/dist/src/workflows/service/workflow-run-service.js +10 -15
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +21 -15
- package/skills/creative/frontend-design/SKILL.md +1 -1
- package/skills/creative/theme-factory/SKILL.md +1 -1
- package/skills/documents/xlsx/SKILL.md +1 -1
- package/skills/engineering/diagnose/SKILL.md +2 -2
- package/skills/engineering/tdd/SKILL.md +1 -1
- package/skills/tools/github/SKILL.md +6 -1
- package/skills/tools/webapp-testing/SKILL.md +4 -1
- package/dist/extensions/telegram/src/adapters/config-surface.d.ts +0 -2
- package/dist/extensions/telegram/src/adapters/config-surface.js +0 -26
- package/dist/extensions/telegram/src/adapters/config-surface.js.map +0 -1
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +0 -158
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +0 -1
- package/dist/gateway/static/root/assets/agents-DQ0mQxIA.js +0 -222
- package/dist/gateway/static/root/assets/channels-settings-BEtP53V6.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CxTtS1hI.js +0 -8
- package/dist/gateway/static/root/assets/cron-api-CznlPIZT.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-Dx6dE3eD.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-DuDCSb3J.js +0 -1
- package/dist/gateway/static/root/assets/field-primitives-BUwUiDf5.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-BjFW1cl-.js +0 -1
- package/dist/gateway/static/root/assets/index-DKgHC1Ta.js +0 -4840
- package/dist/gateway/static/root/assets/index-DjNDHzwG.css +0 -1
- package/dist/gateway/static/root/assets/notes-page-D40ZpS0Y.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BvtdbmW8.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BQamRjkV.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-D972_jaS.js +0 -3
- package/dist/gateway/static/root/assets/share-preview-page-CKCTMo0_.js +0 -2
- package/dist/gateway/static/root/assets/skills-page-QwFCB4yV.js +0 -2
- package/dist/gateway/static/root/assets/url-q28QhI7l.js +0 -3
- package/dist/gateway/static/root/assets/utils-DCm11_KW.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CywiB7Dw.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-Be7l_SWw.js +0 -27
- package/dist/src/agent/embedded/map-stream-events.d.ts +0 -9
- package/dist/src/agent/embedded/map-stream-events.js +0 -63
- package/dist/src/agent/embedded/map-stream-events.js.map +0 -1
- package/dist/src/auth/oauth/vendor-pi-google/google-antigravity.js.map +0 -1
- package/dist/src/auth/oauth/vendor-pi-google/google-gemini-cli.js.map +0 -1
- package/dist/src/auth/oauth/vendor-pi-google/oauth-page.js.map +0 -1
- package/dist/src/auth/oauth/vendor-pi-google/pkce.js.map +0 -1
- package/dist/src/channels/dock.js.map +0 -1
- package/dist/src/channels/plugins/bundled.d.ts +0 -11
- package/dist/src/channels/plugins/bundled.js +0 -10
- package/dist/src/channels/plugins/bundled.js.map +0 -1
- package/dist/src/channels/registry.d.ts +0 -25
- package/dist/src/channels/registry.js +0 -82
- package/dist/src/channels/registry.js.map +0 -1
- package/dist/src/config/localized-text.d.ts +0 -6
- package/dist/src/config/localized-text.js +0 -42
- package/dist/src/config/localized-text.js.map +0 -1
- package/dist/src/generated/bundled-channel-plugins.d.ts +0 -10
- package/dist/src/generated/bundled-channel-plugins.js +0 -16
- package/dist/src/generated/bundled-channel-plugins.js.map +0 -1
- package/dist/src/tui/stream-assembler.d.ts +0 -22
- package/dist/src/tui/stream-assembler.js +0 -63
- package/dist/src/tui/stream-assembler.js.map +0 -1
- package/skills/browser/SKILL-zh.md +0 -188
- package/skills/business/company-values/SKILL-zh.md +0 -80
- package/skills/business/company-values/SKILL.md +0 -80
- package/skills/business/find-community/SKILL-zh.md +0 -50
- package/skills/business/find-community/SKILL.md +0 -50
- package/skills/business/first-customers/SKILL-zh.md +0 -76
- package/skills/business/first-customers/SKILL.md +0 -76
- package/skills/business/grow-sustainably/SKILL-zh.md +0 -92
- package/skills/business/grow-sustainably/SKILL.md +0 -92
- package/skills/business/marketing-plan/SKILL-zh.md +0 -100
- package/skills/business/marketing-plan/SKILL.md +0 -100
- package/skills/business/minimalist-review/SKILL-zh.md +0 -82
- package/skills/business/minimalist-review/SKILL.md +0 -82
- package/skills/business/mvp/SKILL-zh.md +0 -81
- package/skills/business/mvp/SKILL.md +0 -81
- package/skills/business/pricing/SKILL-zh.md +0 -64
- package/skills/business/pricing/SKILL.md +0 -64
- package/skills/business/processize/SKILL-zh.md +0 -91
- package/skills/business/processize/SKILL.md +0 -91
- package/skills/business/validate-idea/SKILL-zh.md +0 -68
- package/skills/business/validate-idea/SKILL.md +0 -68
- package/skills/creative/algorithmic-art/LICENSE.txt +0 -202
- package/skills/creative/algorithmic-art/SKILL-zh.md +0 -405
- package/skills/creative/algorithmic-art/SKILL.md +0 -405
- package/skills/creative/algorithmic-art/templates/generator_template.js +0 -223
- package/skills/creative/algorithmic-art/templates/viewer.html +0 -599
- package/skills/creative/frontend-design/SKILL-zh.md +0 -42
- package/skills/creative/theme-factory/SKILL-zh.md +0 -59
- package/skills/creative/web-artifacts-builder/LICENSE.txt +0 -202
- package/skills/creative/web-artifacts-builder/SKILL-zh.md +0 -74
- package/skills/creative/web-artifacts-builder/SKILL.md +0 -74
- package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
- package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +0 -322
- package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/documents/doc-coauthoring/SKILL-zh.md +0 -375
- package/skills/documents/doc-coauthoring/SKILL.md +0 -375
- package/skills/documents/docx/LICENSE.txt +0 -30
- package/skills/documents/docx/SKILL-zh.md +0 -590
- package/skills/documents/docx/SKILL.md +0 -590
- package/skills/documents/docx/scripts/__init__.py +0 -1
- package/skills/documents/docx/scripts/accept_changes.py +0 -135
- package/skills/documents/docx/scripts/comment.py +0 -318
- package/skills/documents/docx/scripts/office/helpers/__init__.py +0 -0
- package/skills/documents/docx/scripts/office/helpers/merge_runs.py +0 -199
- package/skills/documents/docx/scripts/office/helpers/simplify_redlines.py +0 -197
- package/skills/documents/docx/scripts/office/pack.py +0 -159
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/documents/docx/scripts/office/schemas/mce/mc.xsd +0 -75
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/documents/docx/scripts/office/soffice.py +0 -183
- package/skills/documents/docx/scripts/office/unpack.py +0 -132
- package/skills/documents/docx/scripts/office/validate.py +0 -111
- package/skills/documents/docx/scripts/office/validators/__init__.py +0 -15
- package/skills/documents/docx/scripts/office/validators/base.py +0 -847
- package/skills/documents/docx/scripts/office/validators/docx.py +0 -446
- package/skills/documents/docx/scripts/office/validators/pptx.py +0 -275
- package/skills/documents/docx/scripts/office/validators/redlining.py +0 -247
- package/skills/documents/docx/scripts/templates/comments.xml +0 -3
- package/skills/documents/docx/scripts/templates/commentsExtended.xml +0 -3
- package/skills/documents/docx/scripts/templates/commentsExtensible.xml +0 -3
- package/skills/documents/docx/scripts/templates/commentsIds.xml +0 -3
- package/skills/documents/docx/scripts/templates/people.xml +0 -3
- package/skills/documents/pdf/LICENSE.txt +0 -30
- package/skills/documents/pdf/SKILL-zh.md +0 -314
- package/skills/documents/pdf/SKILL.md +0 -314
- package/skills/documents/pdf/forms.md +0 -294
- package/skills/documents/pdf/reference.md +0 -612
- package/skills/documents/pdf/scripts/check_bounding_boxes.py +0 -65
- package/skills/documents/pdf/scripts/check_fillable_fields.py +0 -11
- package/skills/documents/pdf/scripts/convert_pdf_to_images.py +0 -33
- package/skills/documents/pdf/scripts/create_validation_image.py +0 -37
- package/skills/documents/pdf/scripts/extract_form_field_info.py +0 -122
- package/skills/documents/pdf/scripts/extract_form_structure.py +0 -115
- package/skills/documents/pdf/scripts/fill_fillable_fields.py +0 -98
- package/skills/documents/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
- package/skills/documents/pptx/LICENSE.txt +0 -30
- package/skills/documents/pptx/SKILL-zh.md +0 -232
- package/skills/documents/pptx/SKILL.md +0 -232
- package/skills/documents/pptx/editing.md +0 -205
- package/skills/documents/pptx/pptxgenjs.md +0 -420
- package/skills/documents/pptx/scripts/__init__.py +0 -0
- package/skills/documents/pptx/scripts/add_slide.py +0 -195
- package/skills/documents/pptx/scripts/clean.py +0 -286
- package/skills/documents/pptx/scripts/office/helpers/__init__.py +0 -0
- package/skills/documents/pptx/scripts/office/helpers/merge_runs.py +0 -199
- package/skills/documents/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
- package/skills/documents/pptx/scripts/office/pack.py +0 -159
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/documents/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/documents/pptx/scripts/office/soffice.py +0 -183
- package/skills/documents/pptx/scripts/office/unpack.py +0 -132
- package/skills/documents/pptx/scripts/office/validate.py +0 -111
- package/skills/documents/pptx/scripts/office/validators/__init__.py +0 -15
- package/skills/documents/pptx/scripts/office/validators/base.py +0 -847
- package/skills/documents/pptx/scripts/office/validators/docx.py +0 -446
- package/skills/documents/pptx/scripts/office/validators/pptx.py +0 -275
- package/skills/documents/pptx/scripts/office/validators/redlining.py +0 -247
- package/skills/documents/pptx/scripts/thumbnail.py +0 -289
- package/skills/documents/xlsx/SKILL-zh.md +0 -292
- package/skills/engineering/diagnose/SKILL-zh.md +0 -117
- package/skills/engineering/grill-with-docs/ADR-FORMAT.md +0 -47
- package/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +0 -77
- package/skills/engineering/grill-with-docs/SKILL-zh.md +0 -88
- package/skills/engineering/grill-with-docs/SKILL.md +0 -88
- package/skills/engineering/improve-codebase-architecture/DEEPENING.md +0 -37
- package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
- package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +0 -53
- package/skills/engineering/improve-codebase-architecture/SKILL-zh.md +0 -71
- package/skills/engineering/improve-codebase-architecture/SKILL.md +0 -71
- package/skills/engineering/tdd/SKILL-zh.md +0 -109
- package/skills/engineering/to-issues/SKILL-zh.md +0 -81
- package/skills/engineering/to-issues/SKILL.md +0 -81
- package/skills/engineering/to-prd/SKILL-zh.md +0 -76
- package/skills/engineering/to-prd/SKILL.md +0 -74
- package/skills/engineering/zoom-out/SKILL-zh.md +0 -7
- package/skills/engineering/zoom-out/SKILL.md +0 -7
- package/skills/tools/find-skills/SKILL-zh.md +0 -440
- package/skills/tools/github/SKILL-zh.md +0 -48
- package/skills/tools/internal-comms/LICENSE.txt +0 -202
- package/skills/tools/internal-comms/SKILL-zh.md +0 -32
- package/skills/tools/internal-comms/SKILL.md +0 -32
- package/skills/tools/internal-comms/examples/3p-updates.md +0 -47
- package/skills/tools/internal-comms/examples/company-newsletter.md +0 -65
- package/skills/tools/internal-comms/examples/faq-answers.md +0 -30
- package/skills/tools/internal-comms/examples/general-comms.md +0 -16
- package/skills/tools/skill-creator/LICENSE.txt +0 -202
- package/skills/tools/skill-creator/SKILL-zh.md +0 -483
- package/skills/tools/skill-creator/SKILL.md +0 -485
- package/skills/tools/skill-creator/agents/analyzer.md +0 -274
- package/skills/tools/skill-creator/agents/comparator.md +0 -202
- package/skills/tools/skill-creator/agents/grader.md +0 -223
- package/skills/tools/skill-creator/assets/eval_review.html +0 -146
- package/skills/tools/skill-creator/eval-viewer/generate_review.py +0 -471
- package/skills/tools/skill-creator/eval-viewer/viewer.html +0 -1325
- package/skills/tools/skill-creator/references/schemas.md +0 -430
- package/skills/tools/skill-creator/scripts/__init__.py +0 -0
- package/skills/tools/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/skills/tools/skill-creator/scripts/generate_report.py +0 -326
- package/skills/tools/skill-creator/scripts/improve_description.py +0 -247
- package/skills/tools/skill-creator/scripts/package_skill.py +0 -136
- package/skills/tools/skill-creator/scripts/quick_validate.py +0 -103
- package/skills/tools/skill-creator/scripts/run_eval.py +0 -310
- package/skills/tools/skill-creator/scripts/run_loop.py +0 -328
- package/skills/tools/skill-creator/scripts/utils.py +0 -47
- package/skills/tools/summarize/SKILL-zh.md +0 -47
- package/skills/tools/weather/SKILL-zh.md +0 -46
- package/skills/tools/weather/SKILL.md +0 -46
- package/skills/tools/webapp-testing/SKILL-zh.md +0 -96
- /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-antigravity.d.ts +0 -0
- /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-gemini-cli.d.ts +0 -0
- /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/oauth-page.d.ts +0 -0
|
@@ -27,13 +27,11 @@ function maxBase64CharsForBinary(maxBinaryBytes) {
|
|
|
27
27
|
* Accept: text/event-stream → SSE stream
|
|
28
28
|
* Accept: application/json → wait for full response, return JSON
|
|
29
29
|
*
|
|
30
|
-
* SSE events:
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* event: error — { content }
|
|
36
|
-
* event: result — { ok, payload: { status, summary } }
|
|
30
|
+
* SSE events follow XOPC Chat Stream Protocol v1:
|
|
31
|
+
* run_start, user_message, user_transcript, assistant_message_start,
|
|
32
|
+
* assistant_delta, thinking_delta, thinking_end, tool_start, tool_update,
|
|
33
|
+
* tool_end, assistant_message_end, compaction, tts_audio, clarify_request,
|
|
34
|
+
* run_end, error.
|
|
37
35
|
*/
|
|
38
36
|
function createAgentSSEHandler(config) {
|
|
39
37
|
const { service } = config;
|
|
@@ -100,7 +98,7 @@ function createAgentSSEHandler(config) {
|
|
|
100
98
|
break;
|
|
101
99
|
}
|
|
102
100
|
const chunk = value;
|
|
103
|
-
if (chunk.type === "
|
|
101
|
+
if (chunk.type === "assistant_delta" && typeof chunk.payload?.delta === "string") tokens.push(chunk.payload.delta);
|
|
104
102
|
}
|
|
105
103
|
return c.json({
|
|
106
104
|
ok: true,
|
|
@@ -144,20 +142,10 @@ function createAgentSSEHandler(config) {
|
|
|
144
142
|
try {
|
|
145
143
|
while (true) {
|
|
146
144
|
const { done, value } = await generator.next();
|
|
147
|
-
if (done)
|
|
148
|
-
await stream.writeSSE({
|
|
149
|
-
id: String(++eventId),
|
|
150
|
-
event: "result",
|
|
151
|
-
data: JSON.stringify({
|
|
152
|
-
ok: true,
|
|
153
|
-
payload: value
|
|
154
|
-
})
|
|
155
|
-
});
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
145
|
+
if (done) break;
|
|
158
146
|
const chunk = value;
|
|
159
147
|
await stream.writeSSE({
|
|
160
|
-
id: String(++eventId),
|
|
148
|
+
id: typeof chunk.seq === "number" ? String(chunk.seq) : String(++eventId),
|
|
161
149
|
event: chunk.type || "message",
|
|
162
150
|
data: stringifySSEData(chunk)
|
|
163
151
|
});
|
|
@@ -167,9 +155,12 @@ function createAgentSSEHandler(config) {
|
|
|
167
155
|
await stream.writeSSE({
|
|
168
156
|
id: String(++eventId),
|
|
169
157
|
event: "error",
|
|
170
|
-
data:
|
|
171
|
-
|
|
172
|
-
|
|
158
|
+
data: stringifySSEData({
|
|
159
|
+
type: "error",
|
|
160
|
+
runId: "unknown",
|
|
161
|
+
sessionKey: chatId,
|
|
162
|
+
timestamp: Date.now(),
|
|
163
|
+
payload: {
|
|
173
164
|
code: "INTERNAL_ERROR",
|
|
174
165
|
message: error instanceof Error ? error.message : "Unknown error"
|
|
175
166
|
}
|
|
@@ -220,21 +211,10 @@ function createAgentResumeHandler(config) {
|
|
|
220
211
|
let eventId = 0;
|
|
221
212
|
try {
|
|
222
213
|
for await (const event of service.runRelay.subscribe(runId)) await stream.writeSSE({
|
|
223
|
-
id: String(++eventId),
|
|
214
|
+
id: typeof event.seq === "number" ? String(event.seq) : String(++eventId),
|
|
224
215
|
event: event.type || "message",
|
|
225
216
|
data: stringifySSEData(event)
|
|
226
217
|
});
|
|
227
|
-
await stream.writeSSE({
|
|
228
|
-
id: String(++eventId),
|
|
229
|
-
event: "result",
|
|
230
|
-
data: JSON.stringify({
|
|
231
|
-
ok: true,
|
|
232
|
-
payload: {
|
|
233
|
-
status: "ok",
|
|
234
|
-
summary: "Resumed run completed"
|
|
235
|
-
}
|
|
236
|
-
})
|
|
237
|
-
});
|
|
238
218
|
} catch (error) {
|
|
239
219
|
log.error({
|
|
240
220
|
err: error,
|
|
@@ -243,9 +223,12 @@ function createAgentResumeHandler(config) {
|
|
|
243
223
|
await stream.writeSSE({
|
|
244
224
|
id: String(++eventId),
|
|
245
225
|
event: "error",
|
|
246
|
-
data:
|
|
247
|
-
|
|
248
|
-
|
|
226
|
+
data: stringifySSEData({
|
|
227
|
+
type: "error",
|
|
228
|
+
runId,
|
|
229
|
+
sessionKey: typeof resumeChatId === "string" ? resumeChatId : "",
|
|
230
|
+
timestamp: Date.now(),
|
|
231
|
+
payload: {
|
|
249
232
|
code: "INTERNAL_ERROR",
|
|
250
233
|
message: error instanceof Error ? error.message : "Unknown error"
|
|
251
234
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","names":[],"sources":["../../../../src/gateway/hono/sse.ts"],"sourcesContent":["import { streamSSE } from 'hono/streaming';\nimport type { Context } from 'hono';\nimport type { GatewayService } from '../service.js';\nimport { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from '../chat-limits.js';\nimport { createLogger, updateAsyncLogContext } from '../../utils/logger.js';\nimport { stringifySSEData } from './sse-json.js';\nimport { resolveWebchatSessionKey } from '../resolve-webchat-session-key.js';\n\nconst log = createLogger('Gateway:SSE');\n\n// Active SSE connections tracking for connection limiting\nconst activeConnections = new Map<string, AbortController>();\n\nexport interface SSEHandlerConfig {\n service: GatewayService;\n maxSseConnections?: number;\n}\n\n// Type validation for agent request body\ninterface AgentRequestBody {\n message: string;\n channel?: string;\n chatId?: string;\n /** Alias for `chatId` (gateway console + extension clients). */\n sessionKey?: string;\n /** Epoch ms when the client started this send (abort cutoff / stale POST drop). */\n clientCreatedAtMs?: number;\n /** When true and `channel` is `webchat`, start a new peer id (new session). */\n newSession?: boolean;\n thinking?: string;\n attachments?: Array<{\n type: string;\n mimeType?: string;\n data?: string;\n name?: string;\n size?: number;\n }>;\n}\n\nfunction isValidAgentRequest(body: unknown): body is AgentRequestBody {\n if (!body || typeof body !== 'object') return false;\n const b = body as Record<string, unknown>;\n // Allow empty message if attachments are provided\n const hasMessage = typeof b.message === 'string';\n const hasAttachments = Array.isArray(b.attachments) && b.attachments.length > 0;\n return hasMessage || hasAttachments;\n}\n\n/** Max base64 character length that can decode to `MAX_WEBCHAT_ATTACHMENT_FILE_BYTES`. */\nfunction maxBase64CharsForBinary(maxBinaryBytes: number): number {\n return 4 * Math.ceil(maxBinaryBytes / 3);\n}\n\n/**\n * POST /api/agent — Send a message to the agent, stream response via SSE.\n *\n * Request body: { message, channel?, chatId?, attachments? }\n * Accept: text/event-stream → SSE stream\n * Accept: application/json → wait for full response, return JSON\n *\n * SSE events:\n * event: status — { status, runId }\n * event: user_message — { timestamp, content?, attachments? } (user turn accepted, before agent tokens)\n * event: user_transcript — { text, attachments? } (voice STT complete, before agent tokens)\n * event: token — { content }\n * event: error — { content }\n * event: result — { ok, payload: { status, summary } }\n */\nexport function createAgentSSEHandler(config: SSEHandlerConfig) {\n const { service } = config;\n\n return async (c: Context) => {\n const body = await c.req.json().catch(() => null);\n\n // Input validation\n if (!isValidAgentRequest(body)) {\n return c.json({\n ok: false,\n error: { code: 'BAD_REQUEST', message: 'Missing required field: message or attachments' }\n }, 400);\n }\n\n const { message, channel = 'webchat', attachments, thinking } = body;\n const clientCreatedAtMs =\n typeof body.clientCreatedAtMs === 'number' && Number.isFinite(body.clientCreatedAtMs)\n ? body.clientCreatedAtMs\n : undefined;\n const newSession = Boolean(body.newSession);\n const cfg = service.currentConfig;\n const resolved = resolveWebchatSessionKey({\n cfg,\n sessionKey: typeof body.sessionKey === 'string' ? body.sessionKey : undefined,\n chatId: typeof body.chatId === 'string' ? body.chatId : undefined,\n newSession,\n });\n if (resolved.ok === false) {\n return c.json({\n ok: false,\n error: { code: 'BAD_REQUEST', message: resolved.error },\n }, 400);\n }\n const chatId = resolved.sessionKey;\n\n updateAsyncLogContext({ sessionId: String(chatId) });\n\n if (Array.isArray(attachments)) {\n const maxDataChars = maxBase64CharsForBinary(MAX_WEBCHAT_ATTACHMENT_FILE_BYTES);\n for (const a of attachments) {\n if (!a || typeof a !== 'object') continue;\n const data = (a as { data?: unknown }).data;\n if (typeof data === 'string' && data.length > maxDataChars) {\n return c.json(\n {\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: `Attachment exceeds maximum size (${MAX_WEBCHAT_ATTACHMENT_FILE_BYTES} bytes)`,\n },\n },\n 400,\n );\n }\n }\n }\n\n const accept = c.req.header('Accept') || '';\n const wantSSE = accept.includes('text/event-stream');\n\n const clientAbort = new AbortController();\n const raw = c.req.raw;\n // Keep webchat runs alive across transient disconnects (page refresh / tab route switch)\n // so the client can reattach via /api/agent/resume using runId from `status`.\n // Explicit cancellation still goes through /api/agent/abort.\n if (channel !== 'webchat') {\n if (raw.signal.aborted) {\n clientAbort.abort();\n } else {\n raw.signal.addEventListener('abort', () => clientAbort.abort(), { once: true });\n }\n }\n\n // --- Non-streaming fallback: collect everything, return JSON ---\n if (!wantSSE) {\n const jsonSessionKey = channel === 'webchat' ? chatId : undefined;\n\n const generator = service.runAgent(message, channel, chatId, attachments, thinking, {\n signal: clientAbort.signal,\n ...(clientCreatedAtMs !== undefined ? { clientCreatedAtMs } : {}),\n });\n try {\n let finalResult: { status: string; summary: string } | undefined;\n const tokens: string[] = [];\n\n while (true) {\n const { done, value } = await generator.next();\n if (done) {\n finalResult = value as { status: string; summary: string };\n break;\n }\n const chunk = value as { type: string; content?: string; status?: string; runId?: string };\n if (chunk.type === 'token' && chunk.content) {\n tokens.push(chunk.content);\n }\n }\n\n return c.json({\n ok: true,\n payload: {\n ...finalResult,\n content: tokens.join(''),\n ...(jsonSessionKey !== undefined\n ? { sessionKey: jsonSessionKey, key: jsonSessionKey }\n : {}),\n },\n });\n } catch (error) {\n const em = error instanceof Error ? error.message : String(error);\n log.error(\n { err: error, errorMessage: em, phase: 'gateway.agent_run', sessionKey: jsonSessionKey, channel },\n `Agent run failed (JSON mode): ${em}`,\n );\n return c.json({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' },\n }, 500);\n }\n }\n\n // --- SSE streaming ---\n c.header('X-Accel-Buffering', 'no');\n return streamSSE(c, async (stream) => {\n if (channel !== 'webchat') {\n stream.onAbort(() => {\n clientAbort.abort();\n });\n }\n\n const generator = service.runAgent(message, channel, chatId, attachments, thinking, {\n signal: clientAbort.signal,\n ...(clientCreatedAtMs !== undefined ? { clientCreatedAtMs } : {}),\n });\n\n let eventId = 0;\n\n try {\n while (true) {\n const { done, value } = await generator.next();\n\n if (done) {\n // Final result\n await stream.writeSSE({\n id: String(++eventId),\n event: 'result',\n data: JSON.stringify({ ok: true, payload: value }),\n });\n break;\n }\n\n const chunk = value as { type: string; content?: string; status?: string; runId?: string };\n\n // Intermediate events: status / token / error\n await stream.writeSSE({\n id: String(++eventId),\n event: chunk.type || 'message',\n data: stringifySSEData(chunk),\n });\n }\n } catch (error) {\n log.error({ err: error }, 'Agent run failed (SSE mode)');\n await stream.writeSSE({\n id: String(++eventId),\n event: 'error',\n data: JSON.stringify({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' },\n }),\n });\n }\n });\n };\n}\n\n/**\n * POST /api/agent/resume — Re-attach to an in-progress agent run via SSE.\n *\n * Request body: { runId, chatId }\n * The relay replays all buffered events from the beginning and then live-tails\n * until the run completes.\n *\n * SSE events are identical to those from POST /api/agent.\n */\nexport function createAgentResumeHandler(config: SSEHandlerConfig) {\n const { service } = config;\n\n return async (c: Context) => {\n const body = await c.req.json().catch(() => null);\n if (!body || typeof body !== 'object') {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Invalid JSON body' } }, 400);\n }\n\n const { runId, chatId: resumeChatId } = body as { runId?: string; chatId?: string };\n if (typeof resumeChatId === 'string' && resumeChatId.trim()) {\n updateAsyncLogContext({ sessionId: resumeChatId.trim() });\n }\n if (!runId || typeof runId !== 'string') {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Missing required field: runId' } }, 400);\n }\n\n if (!service.runRelay.hasRun(runId)) {\n return c.json({ ok: false, error: { code: 'NOT_FOUND', message: 'Run not found or already expired' } }, 404);\n }\n\n c.header('X-Accel-Buffering', 'no');\n return streamSSE(c, async (stream) => {\n let eventId = 0;\n try {\n for await (const event of service.runRelay.subscribe(runId)) {\n await stream.writeSSE({\n id: String(++eventId),\n event: event.type || 'message',\n data: stringifySSEData(event),\n });\n }\n // Run completed — send a final result event\n await stream.writeSSE({\n id: String(++eventId),\n event: 'result',\n data: JSON.stringify({ ok: true, payload: { status: 'ok', summary: 'Resumed run completed' } }),\n });\n } catch (error) {\n log.error({ err: error, runId }, 'Resume stream failed');\n await stream.writeSSE({\n id: String(++eventId),\n event: 'error',\n data: JSON.stringify({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' },\n }),\n });\n }\n });\n };\n}\n\n/**\n * POST /api/send — Send a message through a channel (non-streaming).\n */\nexport function createSendHandler(config: SSEHandlerConfig) {\n const { service } = config;\n\n return async (c: Context) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel as string;\n const chatId = body.chatId as string;\n const content = body.content as string;\n\n if (!channel || !chatId || !content) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing required fields: channel, chatId, content' } },\n 400,\n );\n }\n\n updateAsyncLogContext({ sessionId: String(chatId) });\n\n try {\n const result = await service.sendMessage(channel, chatId, content);\n return c.json({ ok: true, payload: result });\n } catch (error) {\n log.error({ err: error }, 'Send failed');\n return c.json(\n { ok: false, error: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' } },\n 500,\n );\n }\n };\n}\n\n/**\n * GET /api/events — Server-pushed event stream (SSE).\n *\n * The client opens this long-lived connection to receive:\n * - channel status changes\n * - config reload notifications\n * - cron execution results\n * - any other server-initiated events\n *\n * Supports Last-Event-ID for reconnection.\n * Enforces maximum connection limit to prevent DoS.\n */\nexport function createEventsSSEHandler(config: SSEHandlerConfig) {\n const { service } = config;\n const maxConnections = config.maxSseConnections ?? 100;\n\n return async (c: Context) => {\n // Check maximum connections limit\n if (activeConnections.size >= maxConnections) {\n log.warn({ current: activeConnections.size, max: maxConnections }, 'SSE connection limit reached');\n return c.json({\n ok: false,\n error: { code: 'TOO_MANY_CONNECTIONS', message: 'Maximum SSE connections exceeded' }\n }, 503);\n }\n\n const lastEventId = c.req.header('Last-Event-ID') || undefined;\n const sessionId = c.req.header('X-Session-Id')\n || c.req.query('sessionId')\n || crypto.randomUUID();\n\n updateAsyncLogContext({ sessionId: String(sessionId) });\n\n const abortController = new AbortController();\n activeConnections.set(sessionId, abortController);\n\n return streamSSE(c, async (stream) => {\n let aborted = false;\n\n // Send a hello event so the client knows the stream is established\n await stream.writeSSE({\n id: '0',\n event: 'connected',\n data: JSON.stringify({ sessionId }),\n });\n\n // Subscribe to service events\n const cleanup = service.subscribe(sessionId, async (event) => {\n if (aborted) return;\n try {\n await stream.writeSSE({\n id: event.id,\n event: event.type,\n data: JSON.stringify(event.payload),\n });\n } catch {\n // Stream closed, will be cleaned up by onAbort\n }\n });\n\n // Replay missed events on reconnect\n if (lastEventId) {\n const missed = service.getEventsSince(sessionId, lastEventId);\n for (const event of missed) {\n await stream.writeSSE({\n id: event.id,\n event: event.type,\n data: JSON.stringify(event.payload),\n });\n }\n }\n\n // Keep alive with periodic comments (every 30s)\n const keepAlive = setInterval(async () => {\n if (aborted) { clearInterval(keepAlive); return; }\n try {\n await stream.writeSSE({ event: 'ping', data: '' });\n } catch {\n clearInterval(keepAlive);\n }\n }, 30_000);\n\n // Block until aborted — streamSSE closes when the callback returns\n await new Promise<void>((resolve) => {\n stream.onAbort(() => {\n aborted = true;\n clearInterval(keepAlive);\n cleanup();\n activeConnections.delete(sessionId);\n log.debug({ sessionId }, 'Event stream disconnected');\n resolve();\n });\n });\n });\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sse.js","names":[],"sources":["../../../../src/gateway/hono/sse.ts"],"sourcesContent":["import { streamSSE } from 'hono/streaming';\nimport type { Context } from 'hono';\nimport type { GatewayService } from '../service.js';\nimport { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from '../chat-limits.js';\nimport { createLogger, updateAsyncLogContext } from '../../utils/logger.js';\nimport { stringifySSEData } from './sse-json.js';\nimport { resolveWebchatSessionKey } from '../resolve-webchat-session-key.js';\n\nconst log = createLogger('Gateway:SSE');\n\n// Active SSE connections tracking for connection limiting\nconst activeConnections = new Map<string, AbortController>();\n\nexport interface SSEHandlerConfig {\n service: GatewayService;\n maxSseConnections?: number;\n}\n\n// Type validation for agent request body\ninterface AgentRequestBody {\n message: string;\n channel?: string;\n chatId?: string;\n /** Alias for `chatId` (gateway console + extension clients). */\n sessionKey?: string;\n /** Epoch ms when the client started this send (abort cutoff / stale POST drop). */\n clientCreatedAtMs?: number;\n /** When true and `channel` is `webchat`, start a new peer id (new session). */\n newSession?: boolean;\n thinking?: string;\n attachments?: Array<{\n type: string;\n mimeType?: string;\n data?: string;\n name?: string;\n size?: number;\n }>;\n}\n\nfunction isValidAgentRequest(body: unknown): body is AgentRequestBody {\n if (!body || typeof body !== 'object') return false;\n const b = body as Record<string, unknown>;\n // Allow empty message if attachments are provided\n const hasMessage = typeof b.message === 'string';\n const hasAttachments = Array.isArray(b.attachments) && b.attachments.length > 0;\n return hasMessage || hasAttachments;\n}\n\n/** Max base64 character length that can decode to `MAX_WEBCHAT_ATTACHMENT_FILE_BYTES`. */\nfunction maxBase64CharsForBinary(maxBinaryBytes: number): number {\n return 4 * Math.ceil(maxBinaryBytes / 3);\n}\n\n/**\n * POST /api/agent — Send a message to the agent, stream response via SSE.\n *\n * Request body: { message, channel?, chatId?, attachments? }\n * Accept: text/event-stream → SSE stream\n * Accept: application/json → wait for full response, return JSON\n *\n * SSE events follow XOPC Chat Stream Protocol v1:\n * run_start, user_message, user_transcript, assistant_message_start,\n * assistant_delta, thinking_delta, thinking_end, tool_start, tool_update,\n * tool_end, assistant_message_end, compaction, tts_audio, clarify_request,\n * run_end, error.\n */\nexport function createAgentSSEHandler(config: SSEHandlerConfig) {\n const { service } = config;\n\n return async (c: Context) => {\n const body = await c.req.json().catch(() => null);\n\n // Input validation\n if (!isValidAgentRequest(body)) {\n return c.json({\n ok: false,\n error: { code: 'BAD_REQUEST', message: 'Missing required field: message or attachments' }\n }, 400);\n }\n\n const { message, channel = 'webchat', attachments, thinking } = body;\n const clientCreatedAtMs =\n typeof body.clientCreatedAtMs === 'number' && Number.isFinite(body.clientCreatedAtMs)\n ? body.clientCreatedAtMs\n : undefined;\n const newSession = Boolean(body.newSession);\n const cfg = service.currentConfig;\n const resolved = resolveWebchatSessionKey({\n cfg,\n sessionKey: typeof body.sessionKey === 'string' ? body.sessionKey : undefined,\n chatId: typeof body.chatId === 'string' ? body.chatId : undefined,\n newSession,\n });\n if (resolved.ok === false) {\n return c.json({\n ok: false,\n error: { code: 'BAD_REQUEST', message: resolved.error },\n }, 400);\n }\n const chatId = resolved.sessionKey;\n\n updateAsyncLogContext({ sessionId: String(chatId) });\n\n if (Array.isArray(attachments)) {\n const maxDataChars = maxBase64CharsForBinary(MAX_WEBCHAT_ATTACHMENT_FILE_BYTES);\n for (const a of attachments) {\n if (!a || typeof a !== 'object') continue;\n const data = (a as { data?: unknown }).data;\n if (typeof data === 'string' && data.length > maxDataChars) {\n return c.json(\n {\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: `Attachment exceeds maximum size (${MAX_WEBCHAT_ATTACHMENT_FILE_BYTES} bytes)`,\n },\n },\n 400,\n );\n }\n }\n }\n\n const accept = c.req.header('Accept') || '';\n const wantSSE = accept.includes('text/event-stream');\n\n const clientAbort = new AbortController();\n const raw = c.req.raw;\n // Keep webchat runs alive across transient disconnects (page refresh / tab route switch)\n // so the client can reattach via /api/agent/resume using runId from `run_start`.\n // Explicit cancellation still goes through /api/agent/abort.\n if (channel !== 'webchat') {\n if (raw.signal.aborted) {\n clientAbort.abort();\n } else {\n raw.signal.addEventListener('abort', () => clientAbort.abort(), { once: true });\n }\n }\n\n // --- Non-streaming fallback: collect everything, return JSON ---\n if (!wantSSE) {\n const jsonSessionKey = channel === 'webchat' ? chatId : undefined;\n\n const generator = service.runAgent(message, channel, chatId, attachments, thinking, {\n signal: clientAbort.signal,\n ...(clientCreatedAtMs !== undefined ? { clientCreatedAtMs } : {}),\n });\n try {\n let finalResult: { status: string; summary: string } | undefined;\n const tokens: string[] = [];\n\n while (true) {\n const { done, value } = await generator.next();\n if (done) {\n finalResult = value as { status: string; summary: string };\n break;\n }\n const chunk = value as { type: string; payload?: { delta?: unknown } };\n if (chunk.type === 'assistant_delta' && typeof chunk.payload?.delta === 'string') {\n tokens.push(chunk.payload.delta);\n }\n }\n\n return c.json({\n ok: true,\n payload: {\n ...finalResult,\n content: tokens.join(''),\n ...(jsonSessionKey !== undefined\n ? { sessionKey: jsonSessionKey, key: jsonSessionKey }\n : {}),\n },\n });\n } catch (error) {\n const em = error instanceof Error ? error.message : String(error);\n log.error(\n { err: error, errorMessage: em, phase: 'gateway.agent_run', sessionKey: jsonSessionKey, channel },\n `Agent run failed (JSON mode): ${em}`,\n );\n return c.json({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' },\n }, 500);\n }\n }\n\n // --- SSE streaming ---\n c.header('X-Accel-Buffering', 'no');\n return streamSSE(c, async (stream) => {\n if (channel !== 'webchat') {\n stream.onAbort(() => {\n clientAbort.abort();\n });\n }\n\n const generator = service.runAgent(message, channel, chatId, attachments, thinking, {\n signal: clientAbort.signal,\n ...(clientCreatedAtMs !== undefined ? { clientCreatedAtMs } : {}),\n });\n\n let eventId = 0;\n\n try {\n while (true) {\n const { done, value } = await generator.next();\n\n if (done) break;\n\n const chunk = value as { type: string; seq?: unknown };\n await stream.writeSSE({\n id: typeof chunk.seq === 'number' ? String(chunk.seq) : String(++eventId),\n event: chunk.type || 'message',\n data: stringifySSEData(chunk),\n });\n }\n } catch (error) {\n log.error({ err: error }, 'Agent run failed (SSE mode)');\n await stream.writeSSE({\n id: String(++eventId),\n event: 'error',\n data: stringifySSEData({\n type: 'error',\n runId: 'unknown',\n sessionKey: chatId,\n timestamp: Date.now(),\n payload: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' },\n }),\n });\n }\n });\n };\n}\n\n/**\n * POST /api/agent/resume — Re-attach to an in-progress agent run via SSE.\n *\n * Request body: { runId, chatId }\n * The relay replays all buffered events from the beginning and then live-tails\n * until the run completes.\n *\n * SSE events are identical to those from POST /api/agent.\n */\nexport function createAgentResumeHandler(config: SSEHandlerConfig) {\n const { service } = config;\n\n return async (c: Context) => {\n const body = await c.req.json().catch(() => null);\n if (!body || typeof body !== 'object') {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Invalid JSON body' } }, 400);\n }\n\n const { runId, chatId: resumeChatId } = body as { runId?: string; chatId?: string };\n if (typeof resumeChatId === 'string' && resumeChatId.trim()) {\n updateAsyncLogContext({ sessionId: resumeChatId.trim() });\n }\n if (!runId || typeof runId !== 'string') {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Missing required field: runId' } }, 400);\n }\n\n if (!service.runRelay.hasRun(runId)) {\n return c.json({ ok: false, error: { code: 'NOT_FOUND', message: 'Run not found or already expired' } }, 404);\n }\n\n c.header('X-Accel-Buffering', 'no');\n return streamSSE(c, async (stream) => {\n let eventId = 0;\n try {\n for await (const event of service.runRelay.subscribe(runId)) {\n await stream.writeSSE({\n id: typeof event.seq === 'number' ? String(event.seq) : String(++eventId),\n event: event.type || 'message',\n data: stringifySSEData(event),\n });\n }\n } catch (error) {\n log.error({ err: error, runId }, 'Resume stream failed');\n await stream.writeSSE({\n id: String(++eventId),\n event: 'error',\n data: stringifySSEData({\n type: 'error',\n runId,\n sessionKey: typeof resumeChatId === 'string' ? resumeChatId : '',\n timestamp: Date.now(),\n payload: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' },\n }),\n });\n }\n });\n };\n}\n\n/**\n * POST /api/send — Send a message through a channel (non-streaming).\n */\nexport function createSendHandler(config: SSEHandlerConfig) {\n const { service } = config;\n\n return async (c: Context) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel as string;\n const chatId = body.chatId as string;\n const content = body.content as string;\n\n if (!channel || !chatId || !content) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing required fields: channel, chatId, content' } },\n 400,\n );\n }\n\n updateAsyncLogContext({ sessionId: String(chatId) });\n\n try {\n const result = await service.sendMessage(channel, chatId, content);\n return c.json({ ok: true, payload: result });\n } catch (error) {\n log.error({ err: error }, 'Send failed');\n return c.json(\n { ok: false, error: { code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' } },\n 500,\n );\n }\n };\n}\n\n/**\n * GET /api/events — Server-pushed event stream (SSE).\n *\n * The client opens this long-lived connection to receive:\n * - channel status changes\n * - config reload notifications\n * - cron execution results\n * - any other server-initiated events\n *\n * Supports Last-Event-ID for reconnection.\n * Enforces maximum connection limit to prevent DoS.\n */\nexport function createEventsSSEHandler(config: SSEHandlerConfig) {\n const { service } = config;\n const maxConnections = config.maxSseConnections ?? 100;\n\n return async (c: Context) => {\n // Check maximum connections limit\n if (activeConnections.size >= maxConnections) {\n log.warn({ current: activeConnections.size, max: maxConnections }, 'SSE connection limit reached');\n return c.json({\n ok: false,\n error: { code: 'TOO_MANY_CONNECTIONS', message: 'Maximum SSE connections exceeded' }\n }, 503);\n }\n\n const lastEventId = c.req.header('Last-Event-ID') || undefined;\n const sessionId = c.req.header('X-Session-Id')\n || c.req.query('sessionId')\n || crypto.randomUUID();\n\n updateAsyncLogContext({ sessionId: String(sessionId) });\n\n const abortController = new AbortController();\n activeConnections.set(sessionId, abortController);\n\n return streamSSE(c, async (stream) => {\n let aborted = false;\n\n // Send a hello event so the client knows the stream is established\n await stream.writeSSE({\n id: '0',\n event: 'connected',\n data: JSON.stringify({ sessionId }),\n });\n\n // Subscribe to service events\n const cleanup = service.subscribe(sessionId, async (event) => {\n if (aborted) return;\n try {\n await stream.writeSSE({\n id: event.id,\n event: event.type,\n data: JSON.stringify(event.payload),\n });\n } catch {\n // Stream closed, will be cleaned up by onAbort\n }\n });\n\n // Replay missed events on reconnect\n if (lastEventId) {\n const missed = service.getEventsSince(sessionId, lastEventId);\n for (const event of missed) {\n await stream.writeSSE({\n id: event.id,\n event: event.type,\n data: JSON.stringify(event.payload),\n });\n }\n }\n\n // Keep alive with periodic comments (every 30s)\n const keepAlive = setInterval(async () => {\n if (aborted) { clearInterval(keepAlive); return; }\n try {\n await stream.writeSSE({ event: 'ping', data: '' });\n } catch {\n clearInterval(keepAlive);\n }\n }, 30_000);\n\n // Block until aborted — streamSSE closes when the callback returns\n await new Promise<void>((resolve) => {\n stream.onAbort(() => {\n aborted = true;\n clearInterval(keepAlive);\n cleanup();\n activeConnections.delete(sessionId);\n log.debug({ sessionId }, 'Event stream disconnected');\n resolve();\n });\n });\n });\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","names":[],"sources":["../../../src/gateway/protocol.ts"],"sourcesContent":["/**\n * Gateway protocol types — Streamable HTTP / SSE transport.\n *\n * All client → server communication uses standard HTTP (POST/GET/PATCH/DELETE).\n * Server → client streaming uses SSE (text/event-stream).\n */\n\n// ---------- HTTP response envelope ----------\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n payload?: T;\n error?: ApiError;\n}\n\nexport interface ApiError {\n code: string;\n message: string;\n}\n\n// ---------- SSE event shape ----------\n\nexport interface SSEEvent {\n id: string;\n event: string; // e.g. \"
|
|
1
|
+
{"version":3,"file":"protocol.js","names":[],"sources":["../../../src/gateway/protocol.ts"],"sourcesContent":["/**\n * Gateway protocol types — Streamable HTTP / SSE transport.\n *\n * All client → server communication uses standard HTTP (POST/GET/PATCH/DELETE).\n * Server → client streaming uses SSE (text/event-stream).\n */\n\n// ---------- HTTP response envelope ----------\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n payload?: T;\n error?: ApiError;\n}\n\nexport interface ApiError {\n code: string;\n message: string;\n}\n\n// ---------- SSE event shape ----------\n\nexport interface SSEEvent {\n id: string;\n event: string; // e.g. \"run_start\", \"assistant_delta\", \"tool_end\", \"config.reload\"\n data: unknown;\n}\n\n// ---------- Gateway config ----------\n\nexport interface GatewayConfig {\n host: string;\n port: number;\n token?: string;\n verbose?: boolean;\n}\n\n// ---------- Helpers ----------\n\nexport function apiOk<T>(payload: T): ApiResponse<T> {\n return { ok: true, payload };\n}\n\nexport function apiError(code: string, message: string): ApiResponse<never> {\n return { ok: false, error: { code, message } };\n}\n"],"mappings":";AAuCA,SAAgB,MAAS,SAA4B;AACnD,QAAO;EAAE,IAAI;EAAM;EAAS;;AAG9B,SAAgB,SAAS,MAAc,SAAqC;AAC1E,QAAO;EAAE,IAAI;EAAO,OAAO;GAAE;GAAM;GAAS;EAAE"}
|
|
@@ -64,14 +64,12 @@ export declare class GatewayAgentRunner {
|
|
|
64
64
|
clientCreatedAtMs?: number;
|
|
65
65
|
}): AsyncGenerator<{
|
|
66
66
|
type: string;
|
|
67
|
-
|
|
68
|
-
status?: string;
|
|
69
|
-
runId?: string;
|
|
67
|
+
[key: string]: unknown;
|
|
70
68
|
}, {
|
|
71
69
|
status: string;
|
|
72
70
|
summary: string;
|
|
73
71
|
}, unknown>;
|
|
74
|
-
/** Abort an in-flight webchat agent run (matches `runId` from SSE `
|
|
72
|
+
/** Abort an in-flight webchat agent run (matches `runId` from SSE `run_start`). */
|
|
75
73
|
abortAgentRun(runId: string): boolean;
|
|
76
74
|
/**
|
|
77
75
|
* Queue steering text for an active webchat run (`Agent.steer` /
|
|
@@ -53,7 +53,7 @@ var GatewayAgentRunner = class {
|
|
|
53
53
|
}
|
|
54
54
|
return step.value;
|
|
55
55
|
}
|
|
56
|
-
/** Abort an in-flight webchat agent run (matches `runId` from SSE `
|
|
56
|
+
/** Abort an in-flight webchat agent run (matches `runId` from SSE `run_start`). */
|
|
57
57
|
abortAgentRun(runId) {
|
|
58
58
|
this.clarifyBridge.cancelForRun(runId);
|
|
59
59
|
const keysToMark = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-runner.js","names":[],"sources":["../../../../src/gateway/service/agent-runner.ts"],"sourcesContent":["/**\n * GatewayAgentRunner — webchat agent invocation and the surrounding control\n * surface (abort, steer, clarify-bridge plumbing, scheduled continuations).\n *\n * Was 200 lines of `GatewayService` covering seven concerns that all hung off\n * the same handful of fields (`activeWebchatRunBySession`, `runAbortControllers`,\n * `clarifyBridge`, `runRelay`):\n *\n * - `runAgent(message, channel, chatId, ...)` — wraps {@link runGatewayAgent}\n * - `abortAgentRun(runId)` — POST /api/agent/abort + cleanup\n * - `steerWebchatAgent(chatId, message)` — Agent.steer queue at tool boundary\n * - `submitClarifyResponse(requestId, answer)` — UI answers a `clarify` call\n * - `enqueueWebchatPersistentGoalKickoff(sessionKey, goalText)` — initial\n * `/goal` kickoff posts the goal text as the next user turn\n * - `drainScheduledWebchatContinuation(sk, msg)` — background continuation\n * (extension scheduler + persistent-goal flow)\n * - `clarifyForSession({ sessionKey, request })` — clarify-bridge dispatch\n * used by `gatewayClarify.requestClarification` in AgentService\n *\n * Owns the two state maps (`activeWebchatRunBySession`, `runAbortControllers`)\n * directly so peer coordinators (sessions-api, marketplace, config) cannot\n * accidentally mutate them.\n */\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { AgentService } from '../../agent/service.js';\nimport type { ChannelManager } from '../../channels/manager.js';\nimport type { SessionIndex } from '../../session/index.js';\nimport { AgentRunRelay, type RelayEvent } from '../agent-run-relay.js';\nimport { ClarifyBridge, type ClarifyBridgeRequest } from '../clarify-bridge.js';\nimport { buildSessionKey, parseSessionKey } from '../../routing/session-key.js';\nimport { getDefaultAgentId } from '../../routing/resolve-route.js';\nimport { runGatewayAgent } from './run-gateway-agent.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('Gateway:AgentRunner');\n\nexport interface GatewayAgentRunnerOptions {\n bus: MessageBus;\n sessionIndex: SessionIndex;\n /** Resolved lazily — the runner is constructed before AgentService exists. */\n getAgentService: () => AgentService;\n getChannelManager: () => ChannelManager;\n getConfig: () => Config;\n /** SSE emit (re-used so `runAgent` events broadcast to subscribers). */\n emit: (type: string, payload: unknown) => void;\n}\n\nexport class GatewayAgentRunner {\n private readonly opts: GatewayAgentRunnerOptions;\n readonly runRelay = new AgentRunRelay();\n /** Per-run abort for webchat (POST /api/agent/abort or client disconnect). */\n private readonly runAbortControllers = new Map<string, AbortController>();\n private readonly clarifyBridge = new ClarifyBridge();\n /** Maps webchat session key → active `runId` for `clarify` tool routing. */\n private readonly activeWebchatRunBySession = new Map<string, string>();\n\n constructor(opts: GatewayAgentRunnerOptions) {\n this.opts = opts;\n }\n\n // ── Read-only accessors (so peers don't get a Map ref) ────────────────\n\n /** True when a webchat agent run is currently in-flight for `sessionKey`. */\n hasActiveRun(sessionKey: string): boolean {\n return this.activeWebchatRunBySession.has(sessionKey);\n }\n\n getActiveRunId(sessionKey: string): string | undefined {\n return this.activeWebchatRunBySession.get(sessionKey);\n }\n\n getClarifyBridge(): ClarifyBridge {\n return this.clarifyBridge;\n }\n\n /** Called from `GatewayService.stop()` so the bridge gets cleaned up. */\n disposeClarifyBridge(): void {\n this.clarifyBridge.dispose();\n }\n\n // ── runAgent (webchat HTTP POST) ──────────────────────────────────────\n\n async *runAgent(\n message: string,\n channel: string,\n chatId: string,\n attachments?: Array<{\n type: string;\n mimeType?: string;\n data?: string;\n name?: string;\n size?: number;\n }>,\n thinking?: string,\n runOptions?: { signal?: AbortSignal; clientCreatedAtMs?: number },\n ): AsyncGenerator<\n { type: string; content?: string; status?: string; runId?: string },\n { status: string; summary: string },\n unknown\n > {\n const iter = runGatewayAgent(\n {\n config: this.opts.getConfig(),\n agentService: this.opts.getAgentService(),\n bus: this.opts.bus,\n runRelay: this.runRelay,\n runAbortControllers: this.runAbortControllers,\n activeWebchatRunBySession: this.activeWebchatRunBySession,\n sessionIndex: this.opts.sessionIndex,\n emit: this.opts.emit,\n },\n message,\n channel,\n chatId,\n attachments,\n thinking,\n runOptions,\n );\n\n let step = await iter.next();\n while (!step.done) {\n yield step.value as { type: string; content?: string; status?: string; runId?: string };\n step = await iter.next();\n }\n return step.value;\n }\n\n /** Abort an in-flight webchat agent run (matches `runId` from SSE `status`). */\n abortAgentRun(runId: string): boolean {\n this.clarifyBridge.cancelForRun(runId);\n const keysToMark: string[] = [];\n for (const [sk, id] of this.activeWebchatRunBySession) {\n if (id === runId) {\n keysToMark.push(sk);\n }\n }\n for (const sk of keysToMark) {\n this.activeWebchatRunBySession.delete(sk);\n }\n const relaySk = this.runRelay.getSessionKey(runId);\n if (relaySk && !keysToMark.includes(relaySk)) {\n keysToMark.push(relaySk);\n }\n const c = this.runAbortControllers.get(runId);\n if (!c) {\n return false;\n }\n const cutoffTs = Date.now();\n for (const sk of keysToMark) {\n void this.opts.sessionIndex\n .updateSessionMetadata(sk, { abortCutoffTimestamp: cutoffTs })\n .catch(() => {});\n void this.opts.sessionIndex\n .appendTranscriptContextEntry(sk, {\n text: 'Webchat agent run aborted',\n data: { runId, abortCutoffTimestamp: cutoffTs },\n })\n .catch(() => {});\n }\n c.abort();\n for (const sk of keysToMark) {\n void import('../../agent/embedded/runs.js').then(({ abortEmbeddedRun }) =>\n abortEmbeddedRun(sk),\n );\n }\n return true;\n }\n\n /**\n * Queue steering text for an active webchat run (`Agent.steer` /\n * tool-boundary injection). `chatId` is the same as `POST /api/agent` body\n * (`sessionKey` or legacy peer id).\n */\n async steerWebchatAgent(\n chatId: string,\n message: string,\n ): Promise<\n { ok: true } | { ok: false; code: 'BAD_REQUEST' | 'NO_ACTIVE_RUN' | 'STEER_FAILED' }\n > {\n const trimmed = message.trim();\n if (!trimmed) {\n return { ok: false, code: 'BAD_REQUEST' };\n }\n const cfg = this.opts.getConfig();\n const parsedKey = parseSessionKey(chatId);\n const sessionKey = parsedKey\n ? chatId\n : buildSessionKey({\n agentId: getDefaultAgentId(cfg),\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n if (!this.activeWebchatRunBySession.has(sessionKey)) {\n return { ok: false, code: 'NO_ACTIVE_RUN' };\n }\n const steered = await this.opts\n .getAgentService()\n .turnDispatcher.steerWebchatSession(sessionKey, trimmed);\n if (!steered) {\n return { ok: false, code: 'STEER_FAILED' };\n }\n return { ok: true };\n }\n\n /** Deliver a user's answer to a pending `clarify` tool call. */\n submitClarifyResponse(requestId: string, answer: string): boolean {\n return this.clarifyBridge.handleResponse(requestId, answer);\n }\n\n /** Hermes-style: after HTTP sets a goal, enqueue the goal text as the next user turn. */\n enqueueWebchatPersistentGoalKickoff(sessionKey: string, goalText: string): void {\n queueMicrotask(() => {\n void this.drainScheduledWebchatContinuation(sessionKey, goalText);\n });\n }\n\n /** Background drain for extension-initiated webchat turns (`scheduleWebchatContinuation`). */\n async drainScheduledWebchatContinuation(sessionKey: string, message: string): Promise<void> {\n try {\n const gen = this.runAgent(message, 'webchat', sessionKey, undefined, undefined, {\n clientCreatedAtMs: Date.now(),\n });\n for await (const _ of gen) {\n // Relay + `agent.stream` broadcast; UI attaches via pending runId + resume.\n }\n } catch (err) {\n log.warn({ err, sessionKey }, 'Scheduled webchat continuation failed');\n }\n }\n\n // ── Clarify dispatch (called from AgentService.gatewayClarify) ────────\n\n /**\n * Resolve clarify-bridge config for `sessionKey`: who delivers the question\n * (webchat SSE, Telegram message, or both), then start the bridge request.\n * Rejects when neither path is available (e.g. CLI without webchat or TG).\n *\n * `publishSseFor(runId)` is the bridge into AgentService's\n * `turnDispatcher.enqueueWebchatSseEvent`. We take it as a callback so the\n * runner does not import AgentService statically.\n */\n requestClarification(opts: {\n sessionKey: string;\n request: ClarifyBridgeRequest;\n publishSseFor: (runId: string) => (e: RelayEvent) => void;\n }): Promise<string> {\n const { sessionKey, request, publishSseFor } = opts;\n const runId = this.activeWebchatRunBySession.get(sessionKey);\n const publishSse = runId ? publishSseFor(runId) : undefined;\n const parsed = parseSessionKey(sessionKey);\n const deliver =\n parsed?.source === 'telegram'\n ? async (ctx: {\n sessionKey: string;\n requestId: string;\n request: ClarifyBridgeRequest;\n }) => {\n await this.deliverTelegramClarify(ctx);\n }\n : undefined;\n if (!runId && !deliver) {\n return Promise.reject(\n new Error('Clarify is not available for this session (use webchat, Telegram, or CLI)'),\n );\n }\n return this.clarifyBridge.startRequest({\n sessionKey,\n runId,\n relay: this.runRelay,\n publishSse,\n request,\n deliver,\n });\n }\n\n private async deliverTelegramClarify(ctx: {\n sessionKey: string;\n requestId: string;\n request: ClarifyBridgeRequest;\n }): Promise<void> {\n const parsed = parseSessionKey(ctx.sessionKey);\n if (!parsed || parsed.source !== 'telegram') {\n return;\n }\n\n let body = ctx.request.question;\n if (ctx.request.default) {\n body += `\\n\\nDefault if unsure: ${ctx.request.default}`;\n }\n\n const choices = ctx.request.choices;\n const buttonRows =\n choices && choices.length >= 2\n ? choices.map((c, i) => [\n {\n text: c.length > 64 ? `${c.slice(0, 61)}…` : c,\n callback_data: `clarify:${ctx.requestId}:${i}`,\n },\n ])\n : undefined;\n\n if (!buttonRows) {\n body += '\\n\\nReply with your answer in this chat.';\n }\n\n await this.opts.getChannelManager().send({\n channel: 'telegram',\n chat_id: parsed.peerId,\n content: body,\n metadata: {\n accountId: parsed.accountId,\n ...(parsed.threadId ? { threadId: parsed.threadId } : {}),\n },\n buttons: buttonRows,\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent-runner.js","names":[],"sources":["../../../../src/gateway/service/agent-runner.ts"],"sourcesContent":["/**\n * GatewayAgentRunner — webchat agent invocation and the surrounding control\n * surface (abort, steer, clarify-bridge plumbing, scheduled continuations).\n *\n * Was 200 lines of `GatewayService` covering seven concerns that all hung off\n * the same handful of fields (`activeWebchatRunBySession`, `runAbortControllers`,\n * `clarifyBridge`, `runRelay`):\n *\n * - `runAgent(message, channel, chatId, ...)` — wraps {@link runGatewayAgent}\n * - `abortAgentRun(runId)` — POST /api/agent/abort + cleanup\n * - `steerWebchatAgent(chatId, message)` — Agent.steer queue at tool boundary\n * - `submitClarifyResponse(requestId, answer)` — UI answers a `clarify` call\n * - `enqueueWebchatPersistentGoalKickoff(sessionKey, goalText)` — initial\n * `/goal` kickoff posts the goal text as the next user turn\n * - `drainScheduledWebchatContinuation(sk, msg)` — background continuation\n * (extension scheduler + persistent-goal flow)\n * - `clarifyForSession({ sessionKey, request })` — clarify-bridge dispatch\n * used by `gatewayClarify.requestClarification` in AgentService\n *\n * Owns the two state maps (`activeWebchatRunBySession`, `runAbortControllers`)\n * directly so peer coordinators (sessions-api, marketplace, config) cannot\n * accidentally mutate them.\n */\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { AgentService } from '../../agent/service.js';\nimport type { ChannelManager } from '../../channels/manager.js';\nimport type { SessionIndex } from '../../session/index.js';\nimport { AgentRunRelay, type RelayEvent } from '../agent-run-relay.js';\nimport { ClarifyBridge, type ClarifyBridgeRequest } from '../clarify-bridge.js';\nimport { buildSessionKey, parseSessionKey } from '../../routing/session-key.js';\nimport { getDefaultAgentId } from '../../routing/resolve-route.js';\nimport { runGatewayAgent } from './run-gateway-agent.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('Gateway:AgentRunner');\n\nexport interface GatewayAgentRunnerOptions {\n bus: MessageBus;\n sessionIndex: SessionIndex;\n /** Resolved lazily — the runner is constructed before AgentService exists. */\n getAgentService: () => AgentService;\n getChannelManager: () => ChannelManager;\n getConfig: () => Config;\n /** SSE emit (re-used so `runAgent` events broadcast to subscribers). */\n emit: (type: string, payload: unknown) => void;\n}\n\nexport class GatewayAgentRunner {\n private readonly opts: GatewayAgentRunnerOptions;\n readonly runRelay = new AgentRunRelay();\n /** Per-run abort for webchat (POST /api/agent/abort or client disconnect). */\n private readonly runAbortControllers = new Map<string, AbortController>();\n private readonly clarifyBridge = new ClarifyBridge();\n /** Maps webchat session key → active `runId` for `clarify` tool routing. */\n private readonly activeWebchatRunBySession = new Map<string, string>();\n\n constructor(opts: GatewayAgentRunnerOptions) {\n this.opts = opts;\n }\n\n // ── Read-only accessors (so peers don't get a Map ref) ────────────────\n\n /** True when a webchat agent run is currently in-flight for `sessionKey`. */\n hasActiveRun(sessionKey: string): boolean {\n return this.activeWebchatRunBySession.has(sessionKey);\n }\n\n getActiveRunId(sessionKey: string): string | undefined {\n return this.activeWebchatRunBySession.get(sessionKey);\n }\n\n getClarifyBridge(): ClarifyBridge {\n return this.clarifyBridge;\n }\n\n /** Called from `GatewayService.stop()` so the bridge gets cleaned up. */\n disposeClarifyBridge(): void {\n this.clarifyBridge.dispose();\n }\n\n // ── runAgent (webchat HTTP POST) ──────────────────────────────────────\n\n async *runAgent(\n message: string,\n channel: string,\n chatId: string,\n attachments?: Array<{\n type: string;\n mimeType?: string;\n data?: string;\n name?: string;\n size?: number;\n }>,\n thinking?: string,\n runOptions?: { signal?: AbortSignal; clientCreatedAtMs?: number },\n ): AsyncGenerator<\n { type: string; [key: string]: unknown },\n { status: string; summary: string },\n unknown\n > {\n const iter = runGatewayAgent(\n {\n config: this.opts.getConfig(),\n agentService: this.opts.getAgentService(),\n bus: this.opts.bus,\n runRelay: this.runRelay,\n runAbortControllers: this.runAbortControllers,\n activeWebchatRunBySession: this.activeWebchatRunBySession,\n sessionIndex: this.opts.sessionIndex,\n emit: this.opts.emit,\n },\n message,\n channel,\n chatId,\n attachments,\n thinking,\n runOptions,\n );\n\n let step = await iter.next();\n while (!step.done) {\n yield step.value as unknown as { type: string; [key: string]: unknown };\n step = await iter.next();\n }\n return step.value;\n }\n\n /** Abort an in-flight webchat agent run (matches `runId` from SSE `run_start`). */\n abortAgentRun(runId: string): boolean {\n this.clarifyBridge.cancelForRun(runId);\n const keysToMark: string[] = [];\n for (const [sk, id] of this.activeWebchatRunBySession) {\n if (id === runId) {\n keysToMark.push(sk);\n }\n }\n for (const sk of keysToMark) {\n this.activeWebchatRunBySession.delete(sk);\n }\n const relaySk = this.runRelay.getSessionKey(runId);\n if (relaySk && !keysToMark.includes(relaySk)) {\n keysToMark.push(relaySk);\n }\n const c = this.runAbortControllers.get(runId);\n if (!c) {\n return false;\n }\n const cutoffTs = Date.now();\n for (const sk of keysToMark) {\n void this.opts.sessionIndex\n .updateSessionMetadata(sk, { abortCutoffTimestamp: cutoffTs })\n .catch(() => {});\n void this.opts.sessionIndex\n .appendTranscriptContextEntry(sk, {\n text: 'Webchat agent run aborted',\n data: { runId, abortCutoffTimestamp: cutoffTs },\n })\n .catch(() => {});\n }\n c.abort();\n for (const sk of keysToMark) {\n void import('../../agent/embedded/runs.js').then(({ abortEmbeddedRun }) =>\n abortEmbeddedRun(sk),\n );\n }\n return true;\n }\n\n /**\n * Queue steering text for an active webchat run (`Agent.steer` /\n * tool-boundary injection). `chatId` is the same as `POST /api/agent` body\n * (`sessionKey` or legacy peer id).\n */\n async steerWebchatAgent(\n chatId: string,\n message: string,\n ): Promise<\n { ok: true } | { ok: false; code: 'BAD_REQUEST' | 'NO_ACTIVE_RUN' | 'STEER_FAILED' }\n > {\n const trimmed = message.trim();\n if (!trimmed) {\n return { ok: false, code: 'BAD_REQUEST' };\n }\n const cfg = this.opts.getConfig();\n const parsedKey = parseSessionKey(chatId);\n const sessionKey = parsedKey\n ? chatId\n : buildSessionKey({\n agentId: getDefaultAgentId(cfg),\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n if (!this.activeWebchatRunBySession.has(sessionKey)) {\n return { ok: false, code: 'NO_ACTIVE_RUN' };\n }\n const steered = await this.opts\n .getAgentService()\n .turnDispatcher.steerWebchatSession(sessionKey, trimmed);\n if (!steered) {\n return { ok: false, code: 'STEER_FAILED' };\n }\n return { ok: true };\n }\n\n /** Deliver a user's answer to a pending `clarify` tool call. */\n submitClarifyResponse(requestId: string, answer: string): boolean {\n return this.clarifyBridge.handleResponse(requestId, answer);\n }\n\n /** Hermes-style: after HTTP sets a goal, enqueue the goal text as the next user turn. */\n enqueueWebchatPersistentGoalKickoff(sessionKey: string, goalText: string): void {\n queueMicrotask(() => {\n void this.drainScheduledWebchatContinuation(sessionKey, goalText);\n });\n }\n\n /** Background drain for extension-initiated webchat turns (`scheduleWebchatContinuation`). */\n async drainScheduledWebchatContinuation(sessionKey: string, message: string): Promise<void> {\n try {\n const gen = this.runAgent(message, 'webchat', sessionKey, undefined, undefined, {\n clientCreatedAtMs: Date.now(),\n });\n for await (const _ of gen) {\n // Relay + `agent.stream` broadcast; UI attaches via pending runId + resume.\n }\n } catch (err) {\n log.warn({ err, sessionKey }, 'Scheduled webchat continuation failed');\n }\n }\n\n // ── Clarify dispatch (called from AgentService.gatewayClarify) ────────\n\n /**\n * Resolve clarify-bridge config for `sessionKey`: who delivers the question\n * (webchat SSE, Telegram message, or both), then start the bridge request.\n * Rejects when neither path is available (e.g. CLI without webchat or TG).\n *\n * `publishSseFor(runId)` is the bridge into AgentService's\n * `turnDispatcher.enqueueWebchatSseEvent`. We take it as a callback so the\n * runner does not import AgentService statically.\n */\n requestClarification(opts: {\n sessionKey: string;\n request: ClarifyBridgeRequest;\n publishSseFor: (runId: string) => (e: RelayEvent) => void;\n }): Promise<string> {\n const { sessionKey, request, publishSseFor } = opts;\n const runId = this.activeWebchatRunBySession.get(sessionKey);\n const publishSse = runId ? publishSseFor(runId) : undefined;\n const parsed = parseSessionKey(sessionKey);\n const deliver =\n parsed?.source === 'telegram'\n ? async (ctx: {\n sessionKey: string;\n requestId: string;\n request: ClarifyBridgeRequest;\n }) => {\n await this.deliverTelegramClarify(ctx);\n }\n : undefined;\n if (!runId && !deliver) {\n return Promise.reject(\n new Error('Clarify is not available for this session (use webchat, Telegram, or CLI)'),\n );\n }\n return this.clarifyBridge.startRequest({\n sessionKey,\n runId,\n relay: this.runRelay,\n publishSse,\n request,\n deliver,\n });\n }\n\n private async deliverTelegramClarify(ctx: {\n sessionKey: string;\n requestId: string;\n request: ClarifyBridgeRequest;\n }): Promise<void> {\n const parsed = parseSessionKey(ctx.sessionKey);\n if (!parsed || parsed.source !== 'telegram') {\n return;\n }\n\n let body = ctx.request.question;\n if (ctx.request.default) {\n body += `\\n\\nDefault if unsure: ${ctx.request.default}`;\n }\n\n const choices = ctx.request.choices;\n const buttonRows =\n choices && choices.length >= 2\n ? choices.map((c, i) => [\n {\n text: c.length > 64 ? `${c.slice(0, 61)}…` : c,\n callback_data: `clarify:${ctx.requestId}:${i}`,\n },\n ])\n : undefined;\n\n if (!buttonRows) {\n body += '\\n\\nReply with your answer in this chat.';\n }\n\n await this.opts.getChannelManager().send({\n channel: 'telegram',\n chat_id: parsed.peerId,\n content: body,\n metadata: {\n accountId: parsed.accountId,\n ...(parsed.threadId ? { threadId: parsed.threadId } : {}),\n },\n buttons: buttonRows,\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import type { Config } from '../../config/schema.js';
|
|
|
2
2
|
import type { AgentService } from '../../agent/service.js';
|
|
3
3
|
import type { ChannelManager } from '../../channels/manager.js';
|
|
4
4
|
import type { ExtensionLoader } from '../../extensions/loader.js';
|
|
5
|
-
import type { SkillCatalogEntry } from '../../agent/agent-manager.js';
|
|
5
|
+
import type { AgentSkillAvailabilityPayload, SkillCatalogEntry } from '../../agent/agent-manager.js';
|
|
6
6
|
import type { ManagedSkillListItem } from '../../agent/skills/managed-store.js';
|
|
7
7
|
import type { SkillMarkdownPreviewPayload } from '../../agent/skills/types.js';
|
|
8
8
|
import type { MarketplaceCategoryOption, SkillsStoreListParams, UnifiedMarketplaceListResponse, UnifiedMarketplacePackageDetail } from '../../agent/skills/skills-marketplace.js';
|
|
@@ -21,11 +21,12 @@ export interface GatewayMarketplaceServiceOptions {
|
|
|
21
21
|
export declare class GatewayMarketplaceService {
|
|
22
22
|
private readonly opts;
|
|
23
23
|
constructor(opts: GatewayMarketplaceServiceOptions);
|
|
24
|
-
getSkillsApi(
|
|
24
|
+
getSkillsApi(): {
|
|
25
25
|
catalog: SkillCatalogEntry[];
|
|
26
26
|
managed: ManagedSkillListItem[];
|
|
27
27
|
};
|
|
28
|
-
|
|
28
|
+
getAgentSkillsApi(agentId: string): AgentSkillAvailabilityPayload;
|
|
29
|
+
getSkillMarkdownSource(skillName: string): SkillMarkdownPreviewPayload | null;
|
|
29
30
|
deleteSkill(skillId: string): void;
|
|
30
31
|
installSkillZip(buffer: Buffer, opts: {
|
|
31
32
|
skillId?: string;
|
|
@@ -39,14 +39,17 @@ var GatewayMarketplaceService = class {
|
|
|
39
39
|
constructor(opts) {
|
|
40
40
|
this.opts = opts;
|
|
41
41
|
}
|
|
42
|
-
getSkillsApi(
|
|
42
|
+
getSkillsApi() {
|
|
43
43
|
return {
|
|
44
|
-
catalog: this.opts.getAgentService().getSkillCatalog(
|
|
44
|
+
catalog: this.opts.getAgentService().getSkillCatalog(),
|
|
45
45
|
managed: listManagedSkillDirs()
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
return this.opts.getAgentService().
|
|
48
|
+
getAgentSkillsApi(agentId) {
|
|
49
|
+
return this.opts.getAgentService().getAgentSkillAvailability(agentId);
|
|
50
|
+
}
|
|
51
|
+
getSkillMarkdownSource(skillName) {
|
|
52
|
+
return this.opts.getAgentService().getSkillMarkdownSource(skillName);
|
|
50
53
|
}
|
|
51
54
|
deleteSkill(skillId) {
|
|
52
55
|
removeSkillsLockEntry(skillId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-service.js","names":[],"sources":["../../../../src/gateway/service/marketplace-service.ts"],"sourcesContent":["/**\n * GatewayMarketplaceService — install / browse / remove for the two marketplaces\n * the gateway exposes:\n *\n * • **Skills** (`~/.xopc/skills/managed/<id>`) — zip-bundled markdown skills\n * pulled from a provider catalog (`agent/skills/skills-marketplace.ts`).\n * • **Extensions** (`~/.xopc/extensions/<id>`) — full extension packages from\n * the xopc-store.\n *\n * Owns the install/uninstall composite operations:\n * - download zip → unpack → upsert lockfile → refresh loader → emit reload\n * - rm dir → remove from `extensions.enabled` → refresh loader → emit reload\n *\n * Local-only skill management (install-from-zip, delete, enable/disable, list)\n * lives here too so callers (commands-skills routes) depend on a single narrow\n * service instead of the full `GatewayService`.\n */\nimport { existsSync, mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport type { AgentService } from '../../agent/service.js';\nimport type { ChannelManager } from '../../channels/manager.js';\nimport type { ExtensionLoader } from '../../extensions/loader.js';\nimport type { SkillCatalogEntry } from '../../agent/agent-manager.js';\nimport type {\n ManagedSkillListItem,\n} from '../../agent/skills/managed-store.js';\nimport type { SkillMarkdownPreviewPayload } from '../../agent/skills/types.js';\nimport type {\n MarketplaceCategoryOption,\n SkillsStoreListParams,\n UnifiedMarketplaceListResponse,\n UnifiedMarketplacePackageDetail,\n} from '../../agent/skills/skills-marketplace.js';\nimport type { MarketplacePackageDetail } from '../../agent/skills/marketplace/adapters/store/store-api-client.js';\nimport {\n deleteManagedSkill as deleteManagedSkillDir,\n installSkillFromZip,\n listManagedSkillDirs,\n} from '../../agent/skills/managed-store.js';\nimport {\n downloadFromMarketplace,\n getMarketplacePackageDetail,\n getMarketplaceProviderDisplayName,\n listMarketplaceCategories,\n listMarketplacePackages,\n listRegisteredProviders,\n resolveSkillsMarketplaceProvider,\n} from '../../agent/skills/skills-marketplace.js';\nimport {\n downloadExtensionStoreZipBuffer,\n fetchMarketplacePackageDetail,\n resolveExtensionZipDownloadUrl,\n resolveExtensionsStoreBaseUrl,\n} from '../../agent/skills/marketplace/adapters/store/store-api-client.js';\nimport { installExtensionFromStoreZip, peekExtensionIdFromStoreZip } from '../../extensions/install.js';\nimport { createSkillConfigManager } from '../../agent/skills/config.js';\nimport { removeSkillsLockEntry } from '../../agent/skills/hub-lock.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport { resolveExtensionsDir, resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('Gateway:Marketplace');\n\nexport interface GatewayMarketplaceServiceOptions {\n getConfig: () => Config;\n getAgentService: () => AgentService;\n getExtensionLoader: () => ExtensionLoader | null;\n getChannelManager: () => ChannelManager;\n saveConfig: (config: Config) => Promise<{ saved: boolean; error?: string }>;\n emit: (type: string, payload: unknown) => void;\n}\n\nexport class GatewayMarketplaceService {\n private readonly opts: GatewayMarketplaceServiceOptions;\n\n constructor(opts: GatewayMarketplaceServiceOptions) {\n this.opts = opts;\n }\n\n // ── Local skills (managed dir) ────────────────────────────────────────\n\n getSkillsApi(lang?: string): {\n catalog: SkillCatalogEntry[];\n managed: ManagedSkillListItem[];\n } {\n return {\n catalog: this.opts.getAgentService().getSkillCatalog(lang),\n managed: listManagedSkillDirs(),\n };\n }\n\n getSkillMarkdownSource(skillName: string, lang?: string): SkillMarkdownPreviewPayload | null {\n return this.opts.getAgentService().getSkillMarkdownSource(skillName, lang);\n }\n\n deleteSkill(skillId: string): void {\n removeSkillsLockEntry(skillId);\n deleteManagedSkillDir(skillId);\n this.opts.getAgentService().refreshSkillsAfterDiskChange();\n }\n\n installSkillZip(\n buffer: Buffer,\n opts: { skillId?: string; overwrite?: boolean },\n ): { skillId: string; path: string } {\n const result = installSkillFromZip(buffer, opts);\n removeSkillsLockEntry(result.skillId);\n this.opts.getAgentService().refreshSkillsAfterDiskChange();\n return result;\n }\n\n reloadSkills(): void {\n this.opts.getAgentService().refreshSkillsAfterDiskChange();\n }\n\n patchSkillEnabled(skillName: string, enabled: boolean): void {\n createSkillConfigManager(resolveStateDir()).setSkillEnabled(skillName, enabled);\n this.opts.getAgentService().refreshSkillsAfterSkillConfigChange();\n }\n\n // ── Skills marketplace catalog ────────────────────────────────────────\n\n async fetchSkillsCatalog(\n params: SkillsStoreListParams,\n provider?: string,\n ): Promise<UnifiedMarketplaceListResponse> {\n return listMarketplacePackages(this.opts.getConfig(), params, provider);\n }\n\n async fetchSkillsCategories(\n provider?: string,\n ): Promise<{ items: MarketplaceCategoryOption[] }> {\n return listMarketplaceCategories(this.opts.getConfig(), provider);\n }\n\n async fetchSkillsPackageDetail(\n packageName: string,\n provider?: string,\n ): Promise<UnifiedMarketplacePackageDetail> {\n return getMarketplacePackageDetail(this.opts.getConfig(), packageName, provider);\n }\n\n async installSkill(opts: {\n name: string;\n version?: string;\n overwrite?: boolean;\n provider?: string;\n }): Promise<{ skillId: string; path: string }> {\n const { buffer, skillId } = await downloadFromMarketplace(\n this.opts.getConfig(),\n opts.name,\n opts.version,\n opts.provider,\n );\n return this.installSkillZip(buffer, { skillId, overwrite: opts.overwrite ?? false });\n }\n\n getSkillsProvider(): { provider: string; displayName: string } {\n const provider = resolveSkillsMarketplaceProvider(this.opts.getConfig());\n return {\n provider,\n displayName: getMarketplaceProviderDisplayName(provider),\n };\n }\n\n /** All registered marketplace providers (built-in + extension-contributed). */\n getSkillsProviders(): Array<{ id: string; displayName: string }> {\n return listRegisteredProviders();\n }\n\n // ── Extension marketplace ─────────────────────────────────────────────\n\n /** xopc-store extension package preview (type must be `extension`). */\n async fetchExtensionPackageDetail(packageName: string): Promise<MarketplacePackageDetail> {\n const base = resolveExtensionsStoreBaseUrl(this.opts.getConfig());\n const detail = await fetchMarketplacePackageDetail(base, packageName.trim());\n if (detail.type !== 'extension') {\n throw new Error(\n `Package \"${packageName}\" is not an extension (store type: ${detail.type}).`,\n );\n }\n return detail;\n }\n\n /**\n * Install an extension from xopc-store into `~/.xopc/extensions`, append id\n * to `extensions.enabled`, refresh the loader, and emit `config.reload`.\n * Returns `requiresGatewayRestart=true` when a new channel plugin would have\n * to wire into the running gateway (channel registration cannot hot-patch).\n */\n async installExtension(opts: {\n name: string;\n version?: string;\n overwrite?: boolean;\n }): Promise<{ extensionId: string; version: string; requiresGatewayRestart: boolean }> {\n const packageName = opts.name.trim();\n if (!packageName) {\n throw new Error('Package name is required');\n }\n const cfg = this.opts.getConfig();\n const storeBase = resolveExtensionsStoreBaseUrl(cfg);\n const targetDir = resolveExtensionsDir();\n mkdirSync(targetDir, { recursive: true });\n\n const { downloadUrl, version } = await resolveExtensionZipDownloadUrl(\n storeBase,\n packageName,\n opts.version,\n );\n const buf = await downloadExtensionStoreZipBuffer(storeBase, downloadUrl);\n\n if (opts.overwrite) {\n const peekId = peekExtensionIdFromStoreZip(buf);\n if (peekId && existsSync(join(targetDir, peekId))) {\n rmSync(join(targetDir, peekId), { recursive: true, force: true });\n }\n }\n\n const result = await installExtensionFromStoreZip(buf, targetDir);\n if (!result.ok || !result.extensionId) {\n throw new Error(result.error ?? 'Extension install failed');\n }\n\n const lock = getExtensionLockfileManager();\n await lock.upsert(result.extensionId, {\n name: result.extensionId,\n version,\n resolved: packageName,\n source: 'store',\n });\n\n const nextConfig = this.mergeExtensionEnabledIntoConfig(cfg, result.extensionId);\n const saved = await this.opts.saveConfig(nextConfig);\n if (!saved.saved) {\n throw new Error(saved.error ?? 'Failed to save config after extension install');\n }\n\n const channelIdsBefore = new Set(this.opts.getChannelManager().getAllPlugins().map((p) => p.id));\n let requiresGatewayRestart = false;\n const loader = this.opts.getExtensionLoader();\n try {\n if (loader) {\n loader.invalidateManifestCache();\n await loader.loadByActivationPlan();\n const reg = loader.getRegistry();\n for (const p of reg.channelPlugins) {\n if (!channelIdsBefore.has(p.id)) {\n requiresGatewayRestart = true;\n break;\n }\n }\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Extension loader refresh after marketplace install failed: ${em}`);\n requiresGatewayRestart = true;\n }\n\n this.opts.emit('config.reload', { section: 'extensions', source: 'marketplace-install' });\n return { extensionId: result.extensionId, version, requiresGatewayRestart };\n }\n\n /** Remove a user-installed extension (global or per-agent dir) from disk and config. */\n async uninstallExtension(extensionId: string): Promise<{ requiresGatewayRestart: boolean }> {\n const id = extensionId.trim();\n if (!id) {\n throw new Error('extensionId is required');\n }\n const loader = this.opts.getExtensionLoader();\n if (!loader) {\n throw new Error('Extensions unavailable');\n }\n const discovered = loader.discoverExtensions();\n const ext = discovered.find((e) => e.id === id);\n if (!ext) {\n throw new Error(`Extension not found: ${id}`);\n }\n if (ext.source === 'bundled') {\n throw new Error('Built-in extensions cannot be uninstalled from the marketplace UI');\n }\n if (existsSync(ext.path)) {\n rmSync(ext.path, { recursive: true, force: true });\n }\n await getExtensionLockfileManager().remove(id);\n\n const nextConfig = this.mergeExtensionRemovedFromEnabledConfig(this.opts.getConfig(), id);\n const saved = await this.opts.saveConfig(nextConfig);\n if (!saved.saved) {\n throw new Error(saved.error ?? 'Failed to save config after extension uninstall');\n }\n try {\n loader.invalidateManifestCache();\n await loader.loadByActivationPlan();\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Extension loader refresh after uninstall failed: ${em}`);\n }\n this.opts.emit('config.reload', { section: 'extensions', source: 'marketplace-uninstall' });\n return { requiresGatewayRestart: true };\n }\n\n // ── Internals ─────────────────────────────────────────────────────────\n\n private mergeExtensionEnabledIntoConfig(currentConfig: Config, extensionId: string): Config {\n const id = extensionId.trim();\n const prevExt = currentConfig.extensions;\n const baseExt =\n prevExt && typeof prevExt === 'object' && !Array.isArray(prevExt)\n ? { ...(prevExt as Record<string, unknown>) }\n : {};\n const enabledRaw = baseExt.enabled;\n const enabled = Array.isArray(enabledRaw)\n ? [...enabledRaw.filter((x): x is string => typeof x === 'string')]\n : [];\n if (!enabled.includes(id)) enabled.push(id);\n\n const disabledRaw = baseExt.disabled;\n const nextExt: Record<string, unknown> = { ...baseExt, enabled };\n if (Array.isArray(disabledRaw)) {\n const next = disabledRaw.filter((x): x is string => typeof x === 'string' && x !== id);\n if (next.length > 0) nextExt.disabled = next;\n else delete nextExt.disabled;\n }\n\n return {\n ...currentConfig,\n extensions: nextExt,\n } as Config;\n }\n\n private mergeExtensionRemovedFromEnabledConfig(currentConfig: Config, extensionId: string): Config {\n const id = extensionId.trim();\n const prevExt = currentConfig.extensions;\n const baseExt =\n prevExt && typeof prevExt === 'object' && !Array.isArray(prevExt)\n ? { ...(prevExt as Record<string, unknown>) }\n : {};\n const enabledRaw = baseExt.enabled;\n const enabled = Array.isArray(enabledRaw)\n ? enabledRaw.filter((x): x is string => typeof x === 'string' && x !== id)\n : [];\n return {\n ...currentConfig,\n extensions: { ...baseExt, enabled },\n } as Config;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"marketplace-service.js","names":[],"sources":["../../../../src/gateway/service/marketplace-service.ts"],"sourcesContent":["/**\n * GatewayMarketplaceService — install / browse / remove for the two marketplaces\n * the gateway exposes:\n *\n * • **Skills** (`~/.xopc/skills/managed/<id>`) — zip-bundled markdown skills\n * pulled from a provider catalog (`agent/skills/skills-marketplace.ts`).\n * • **Extensions** (`~/.xopc/extensions/<id>`) — full extension packages from\n * the xopc-store.\n *\n * Owns the install/uninstall composite operations:\n * - download zip → unpack → upsert lockfile → refresh loader → emit reload\n * - rm dir → remove from `extensions.enabled` → refresh loader → emit reload\n *\n * Local-only skill management (install-from-zip, delete, enable/disable, list)\n * lives here too so callers (commands-skills routes) depend on a single narrow\n * service instead of the full `GatewayService`.\n */\nimport { existsSync, mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport type { AgentService } from '../../agent/service.js';\nimport type { ChannelManager } from '../../channels/manager.js';\nimport type { ExtensionLoader } from '../../extensions/loader.js';\nimport type { AgentSkillAvailabilityPayload, SkillCatalogEntry } from '../../agent/agent-manager.js';\nimport type {\n ManagedSkillListItem,\n} from '../../agent/skills/managed-store.js';\nimport type { SkillMarkdownPreviewPayload } from '../../agent/skills/types.js';\nimport type {\n MarketplaceCategoryOption,\n SkillsStoreListParams,\n UnifiedMarketplaceListResponse,\n UnifiedMarketplacePackageDetail,\n} from '../../agent/skills/skills-marketplace.js';\nimport type { MarketplacePackageDetail } from '../../agent/skills/marketplace/adapters/store/store-api-client.js';\nimport {\n deleteManagedSkill as deleteManagedSkillDir,\n installSkillFromZip,\n listManagedSkillDirs,\n} from '../../agent/skills/managed-store.js';\nimport {\n downloadFromMarketplace,\n getMarketplacePackageDetail,\n getMarketplaceProviderDisplayName,\n listMarketplaceCategories,\n listMarketplacePackages,\n listRegisteredProviders,\n resolveSkillsMarketplaceProvider,\n} from '../../agent/skills/skills-marketplace.js';\nimport {\n downloadExtensionStoreZipBuffer,\n fetchMarketplacePackageDetail,\n resolveExtensionZipDownloadUrl,\n resolveExtensionsStoreBaseUrl,\n} from '../../agent/skills/marketplace/adapters/store/store-api-client.js';\nimport { installExtensionFromStoreZip, peekExtensionIdFromStoreZip } from '../../extensions/install.js';\nimport { createSkillConfigManager } from '../../agent/skills/config.js';\nimport { removeSkillsLockEntry } from '../../agent/skills/hub-lock.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport { resolveExtensionsDir, resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('Gateway:Marketplace');\n\nexport interface GatewayMarketplaceServiceOptions {\n getConfig: () => Config;\n getAgentService: () => AgentService;\n getExtensionLoader: () => ExtensionLoader | null;\n getChannelManager: () => ChannelManager;\n saveConfig: (config: Config) => Promise<{ saved: boolean; error?: string }>;\n emit: (type: string, payload: unknown) => void;\n}\n\nexport class GatewayMarketplaceService {\n private readonly opts: GatewayMarketplaceServiceOptions;\n\n constructor(opts: GatewayMarketplaceServiceOptions) {\n this.opts = opts;\n }\n\n // ── Local skills (managed dir) ────────────────────────────────────────\n\n getSkillsApi(): {\n catalog: SkillCatalogEntry[];\n managed: ManagedSkillListItem[];\n } {\n return {\n catalog: this.opts.getAgentService().getSkillCatalog(),\n managed: listManagedSkillDirs(),\n };\n }\n\n getAgentSkillsApi(agentId: string): AgentSkillAvailabilityPayload {\n return this.opts.getAgentService().getAgentSkillAvailability(agentId);\n }\n\n getSkillMarkdownSource(skillName: string): SkillMarkdownPreviewPayload | null {\n return this.opts.getAgentService().getSkillMarkdownSource(skillName);\n }\n\n deleteSkill(skillId: string): void {\n removeSkillsLockEntry(skillId);\n deleteManagedSkillDir(skillId);\n this.opts.getAgentService().refreshSkillsAfterDiskChange();\n }\n\n installSkillZip(\n buffer: Buffer,\n opts: { skillId?: string; overwrite?: boolean },\n ): { skillId: string; path: string } {\n const result = installSkillFromZip(buffer, opts);\n removeSkillsLockEntry(result.skillId);\n this.opts.getAgentService().refreshSkillsAfterDiskChange();\n return result;\n }\n\n reloadSkills(): void {\n this.opts.getAgentService().refreshSkillsAfterDiskChange();\n }\n\n patchSkillEnabled(skillName: string, enabled: boolean): void {\n createSkillConfigManager(resolveStateDir()).setSkillEnabled(skillName, enabled);\n this.opts.getAgentService().refreshSkillsAfterSkillConfigChange();\n }\n\n // ── Skills marketplace catalog ────────────────────────────────────────\n\n async fetchSkillsCatalog(\n params: SkillsStoreListParams,\n provider?: string,\n ): Promise<UnifiedMarketplaceListResponse> {\n return listMarketplacePackages(this.opts.getConfig(), params, provider);\n }\n\n async fetchSkillsCategories(\n provider?: string,\n ): Promise<{ items: MarketplaceCategoryOption[] }> {\n return listMarketplaceCategories(this.opts.getConfig(), provider);\n }\n\n async fetchSkillsPackageDetail(\n packageName: string,\n provider?: string,\n ): Promise<UnifiedMarketplacePackageDetail> {\n return getMarketplacePackageDetail(this.opts.getConfig(), packageName, provider);\n }\n\n async installSkill(opts: {\n name: string;\n version?: string;\n overwrite?: boolean;\n provider?: string;\n }): Promise<{ skillId: string; path: string }> {\n const { buffer, skillId } = await downloadFromMarketplace(\n this.opts.getConfig(),\n opts.name,\n opts.version,\n opts.provider,\n );\n return this.installSkillZip(buffer, { skillId, overwrite: opts.overwrite ?? false });\n }\n\n getSkillsProvider(): { provider: string; displayName: string } {\n const provider = resolveSkillsMarketplaceProvider(this.opts.getConfig());\n return {\n provider,\n displayName: getMarketplaceProviderDisplayName(provider),\n };\n }\n\n /** All registered marketplace providers (built-in + extension-contributed). */\n getSkillsProviders(): Array<{ id: string; displayName: string }> {\n return listRegisteredProviders();\n }\n\n // ── Extension marketplace ─────────────────────────────────────────────\n\n /** xopc-store extension package preview (type must be `extension`). */\n async fetchExtensionPackageDetail(packageName: string): Promise<MarketplacePackageDetail> {\n const base = resolveExtensionsStoreBaseUrl(this.opts.getConfig());\n const detail = await fetchMarketplacePackageDetail(base, packageName.trim());\n if (detail.type !== 'extension') {\n throw new Error(\n `Package \"${packageName}\" is not an extension (store type: ${detail.type}).`,\n );\n }\n return detail;\n }\n\n /**\n * Install an extension from xopc-store into `~/.xopc/extensions`, append id\n * to `extensions.enabled`, refresh the loader, and emit `config.reload`.\n * Returns `requiresGatewayRestart=true` when a new channel plugin would have\n * to wire into the running gateway (channel registration cannot hot-patch).\n */\n async installExtension(opts: {\n name: string;\n version?: string;\n overwrite?: boolean;\n }): Promise<{ extensionId: string; version: string; requiresGatewayRestart: boolean }> {\n const packageName = opts.name.trim();\n if (!packageName) {\n throw new Error('Package name is required');\n }\n const cfg = this.opts.getConfig();\n const storeBase = resolveExtensionsStoreBaseUrl(cfg);\n const targetDir = resolveExtensionsDir();\n mkdirSync(targetDir, { recursive: true });\n\n const { downloadUrl, version } = await resolveExtensionZipDownloadUrl(\n storeBase,\n packageName,\n opts.version,\n );\n const buf = await downloadExtensionStoreZipBuffer(storeBase, downloadUrl);\n\n if (opts.overwrite) {\n const peekId = peekExtensionIdFromStoreZip(buf);\n if (peekId && existsSync(join(targetDir, peekId))) {\n rmSync(join(targetDir, peekId), { recursive: true, force: true });\n }\n }\n\n const result = await installExtensionFromStoreZip(buf, targetDir);\n if (!result.ok || !result.extensionId) {\n throw new Error(result.error ?? 'Extension install failed');\n }\n\n const lock = getExtensionLockfileManager();\n await lock.upsert(result.extensionId, {\n name: result.extensionId,\n version,\n resolved: packageName,\n source: 'store',\n });\n\n const nextConfig = this.mergeExtensionEnabledIntoConfig(cfg, result.extensionId);\n const saved = await this.opts.saveConfig(nextConfig);\n if (!saved.saved) {\n throw new Error(saved.error ?? 'Failed to save config after extension install');\n }\n\n const channelIdsBefore = new Set(this.opts.getChannelManager().getAllPlugins().map((p) => p.id));\n let requiresGatewayRestart = false;\n const loader = this.opts.getExtensionLoader();\n try {\n if (loader) {\n loader.invalidateManifestCache();\n await loader.loadByActivationPlan();\n const reg = loader.getRegistry();\n for (const p of reg.channelPlugins) {\n if (!channelIdsBefore.has(p.id)) {\n requiresGatewayRestart = true;\n break;\n }\n }\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Extension loader refresh after marketplace install failed: ${em}`);\n requiresGatewayRestart = true;\n }\n\n this.opts.emit('config.reload', { section: 'extensions', source: 'marketplace-install' });\n return { extensionId: result.extensionId, version, requiresGatewayRestart };\n }\n\n /** Remove a user-installed extension (global or per-agent dir) from disk and config. */\n async uninstallExtension(extensionId: string): Promise<{ requiresGatewayRestart: boolean }> {\n const id = extensionId.trim();\n if (!id) {\n throw new Error('extensionId is required');\n }\n const loader = this.opts.getExtensionLoader();\n if (!loader) {\n throw new Error('Extensions unavailable');\n }\n const discovered = loader.discoverExtensions();\n const ext = discovered.find((e) => e.id === id);\n if (!ext) {\n throw new Error(`Extension not found: ${id}`);\n }\n if (ext.source === 'bundled') {\n throw new Error('Built-in extensions cannot be uninstalled from the marketplace UI');\n }\n if (existsSync(ext.path)) {\n rmSync(ext.path, { recursive: true, force: true });\n }\n await getExtensionLockfileManager().remove(id);\n\n const nextConfig = this.mergeExtensionRemovedFromEnabledConfig(this.opts.getConfig(), id);\n const saved = await this.opts.saveConfig(nextConfig);\n if (!saved.saved) {\n throw new Error(saved.error ?? 'Failed to save config after extension uninstall');\n }\n try {\n loader.invalidateManifestCache();\n await loader.loadByActivationPlan();\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Extension loader refresh after uninstall failed: ${em}`);\n }\n this.opts.emit('config.reload', { section: 'extensions', source: 'marketplace-uninstall' });\n return { requiresGatewayRestart: true };\n }\n\n // ── Internals ─────────────────────────────────────────────────────────\n\n private mergeExtensionEnabledIntoConfig(currentConfig: Config, extensionId: string): Config {\n const id = extensionId.trim();\n const prevExt = currentConfig.extensions;\n const baseExt =\n prevExt && typeof prevExt === 'object' && !Array.isArray(prevExt)\n ? { ...(prevExt as Record<string, unknown>) }\n : {};\n const enabledRaw = baseExt.enabled;\n const enabled = Array.isArray(enabledRaw)\n ? [...enabledRaw.filter((x): x is string => typeof x === 'string')]\n : [];\n if (!enabled.includes(id)) enabled.push(id);\n\n const disabledRaw = baseExt.disabled;\n const nextExt: Record<string, unknown> = { ...baseExt, enabled };\n if (Array.isArray(disabledRaw)) {\n const next = disabledRaw.filter((x): x is string => typeof x === 'string' && x !== id);\n if (next.length > 0) nextExt.disabled = next;\n else delete nextExt.disabled;\n }\n\n return {\n ...currentConfig,\n extensions: nextExt,\n } as Config;\n }\n\n private mergeExtensionRemovedFromEnabledConfig(currentConfig: Config, extensionId: string): Config {\n const id = extensionId.trim();\n const prevExt = currentConfig.extensions;\n const baseExt =\n prevExt && typeof prevExt === 'object' && !Array.isArray(prevExt)\n ? { ...(prevExt as Record<string, unknown>) }\n : {};\n const enabledRaw = baseExt.enabled;\n const enabled = Array.isArray(enabledRaw)\n ? enabledRaw.filter((x): x is string => typeof x === 'string' && x !== id)\n : [];\n return {\n ...currentConfig,\n extensions: { ...baseExt, enabled },\n } as Config;\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,13 +2,9 @@ import type { AgentService } from '../../agent/service.js';
|
|
|
2
2
|
import type { Config } from '../../config/schema.js';
|
|
3
3
|
import type { MessageBus } from '../../infra/bus/index.js';
|
|
4
4
|
import type { SessionIndex } from '../../session/index.js';
|
|
5
|
+
import type { ChatStreamEvent } from '../chat-stream/protocol.js';
|
|
5
6
|
import type { AgentRunRelay } from '../agent-run-relay.js';
|
|
6
|
-
export type RunGatewayAgentYield =
|
|
7
|
-
type: string;
|
|
8
|
-
content?: string;
|
|
9
|
-
status?: string;
|
|
10
|
-
runId?: string;
|
|
11
|
-
};
|
|
7
|
+
export type RunGatewayAgentYield = ChatStreamEvent;
|
|
12
8
|
export type RunGatewayAgentDeps = {
|
|
13
9
|
config: Config;
|
|
14
10
|
agentService: AgentService;
|
|
@@ -6,6 +6,7 @@ import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
|
|
|
6
6
|
import { shouldSkipWebchatInboundByAbortCutoff } from "../../session/abort-cutoff.js";
|
|
7
7
|
import "../chat-limits.js";
|
|
8
8
|
import { resolveWebchatSessionKey } from "../resolve-webchat-session-key.js";
|
|
9
|
+
import { ChatStreamMapper } from "../chat-stream/mapper.js";
|
|
9
10
|
import crypto from "crypto";
|
|
10
11
|
//#region src/gateway/service/run-gateway-agent.ts
|
|
11
12
|
init_logger();
|
|
@@ -38,16 +39,28 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
38
39
|
runRelay.ensureRun(runId, webchatSessionKey);
|
|
39
40
|
runAbortControllers.set(runId, new AbortController());
|
|
40
41
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
const streamSessionKey = webchatSessionKey ?? chatId;
|
|
43
|
+
const mapper = new ChatStreamMapper({
|
|
44
|
+
runId,
|
|
45
|
+
sessionKey: streamSessionKey,
|
|
46
|
+
channel
|
|
47
|
+
});
|
|
48
|
+
const publishStreamEvent = (event) => channel === "webchat" ? runRelay.publish(runId, event) ?? event : event;
|
|
49
|
+
const emitAndYield = function* (events) {
|
|
50
|
+
for (const event of events) {
|
|
51
|
+
const relayedEvent = publishStreamEvent(event);
|
|
52
|
+
if (channel === "webchat") emit("agent.stream", {
|
|
53
|
+
sessionKey: streamSessionKey,
|
|
54
|
+
event: relayedEvent
|
|
55
|
+
});
|
|
56
|
+
yield relayedEvent;
|
|
57
|
+
}
|
|
45
58
|
};
|
|
46
|
-
|
|
47
|
-
yield statusEvent;
|
|
59
|
+
yield* emitAndYield(mapper.start());
|
|
48
60
|
try {
|
|
49
61
|
if (channel === "webchat" && webchatSessionKey) {
|
|
50
62
|
if (webchatStaleSkip) {
|
|
63
|
+
yield* emitAndYield(mapper.end("cancelled", "Stale inbound after abort (clientCreatedAtMs before cutoff)"));
|
|
51
64
|
runRelay.complete(runId);
|
|
52
65
|
runAbortControllers.delete(runId);
|
|
53
66
|
return {
|
|
@@ -67,19 +80,14 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
67
80
|
activeWebchatRunBySession.set(sessionKey, runId);
|
|
68
81
|
let streamError;
|
|
69
82
|
try {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
83
|
+
const eventStream = agentService.turnDispatcher.processDirectStreaming(stampedMessage, sessionKey, prepared, thinking, {
|
|
84
|
+
signal: mergedSignal,
|
|
85
|
+
runId
|
|
73
86
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
sessionKey,
|
|
79
|
-
event
|
|
80
|
-
});
|
|
81
|
-
yield event;
|
|
82
|
-
}
|
|
87
|
+
for await (const event of eventStream) yield* emitAndYield(mapper.map(event));
|
|
88
|
+
const endStatus = mergedSignal.aborted ? "cancelled" : "success";
|
|
89
|
+
const endSummary = mergedSignal.aborted ? "Interrupted" : "Message processed successfully";
|
|
90
|
+
yield* emitAndYield(mapper.end(endStatus, endSummary));
|
|
83
91
|
runRelay.complete(runId);
|
|
84
92
|
try {
|
|
85
93
|
const metaAfter = await sessionIndex.getSessionMetadata(sessionKey);
|
|
@@ -103,17 +111,10 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
103
111
|
channel: "webchat"
|
|
104
112
|
}, `Agent processing failed: ${em}`);
|
|
105
113
|
streamError = em;
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
runRelay.publish(runId, errorEvent);
|
|
111
|
-
emit("agent.stream", {
|
|
112
|
-
sessionKey,
|
|
113
|
-
event: errorEvent
|
|
114
|
-
});
|
|
114
|
+
const errorContent = formatAgentRunErrorForClient(streamError);
|
|
115
|
+
yield* emitAndYield(mapper.error(errorContent));
|
|
116
|
+
yield* emitAndYield(mapper.end("error", streamError));
|
|
115
117
|
runRelay.complete(runId);
|
|
116
|
-
yield errorEvent;
|
|
117
118
|
return {
|
|
118
119
|
status: "error",
|
|
119
120
|
summary: streamError
|
|
@@ -152,15 +153,41 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
152
153
|
content: message,
|
|
153
154
|
...correlationMeta ? { metadata: correlationMeta } : {}
|
|
154
155
|
});
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
const messageId = `msg_${runId.replace(/[^a-zA-Z0-9_-]/g, "_")}_1`;
|
|
157
|
+
yield* emitAndYield([{
|
|
158
|
+
type: "assistant_message_start",
|
|
159
|
+
runId,
|
|
160
|
+
sessionKey: streamSessionKey,
|
|
161
|
+
timestamp: Date.now(),
|
|
162
|
+
payload: { messageId }
|
|
163
|
+
}, {
|
|
164
|
+
type: "assistant_delta",
|
|
165
|
+
runId,
|
|
166
|
+
sessionKey: streamSessionKey,
|
|
167
|
+
timestamp: Date.now(),
|
|
168
|
+
payload: {
|
|
169
|
+
messageId,
|
|
170
|
+
delta: "Processing...\n"
|
|
171
|
+
}
|
|
172
|
+
}]);
|
|
159
173
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
160
|
-
yield {
|
|
161
|
-
type: "
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
yield* emitAndYield([{
|
|
175
|
+
type: "assistant_delta",
|
|
176
|
+
runId,
|
|
177
|
+
sessionKey: streamSessionKey,
|
|
178
|
+
timestamp: Date.now(),
|
|
179
|
+
payload: {
|
|
180
|
+
messageId,
|
|
181
|
+
delta: "Done\n"
|
|
182
|
+
}
|
|
183
|
+
}, {
|
|
184
|
+
type: "assistant_message_end",
|
|
185
|
+
runId,
|
|
186
|
+
sessionKey: streamSessionKey,
|
|
187
|
+
timestamp: Date.now(),
|
|
188
|
+
payload: { messageId }
|
|
189
|
+
}]);
|
|
190
|
+
yield* emitAndYield(mapper.end("success", "Message processed"));
|
|
164
191
|
return {
|
|
165
192
|
status: "ok",
|
|
166
193
|
summary: "Message processed"
|