@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../../../extensions/feishu/src/plugin.ts"],"sourcesContent":["/**\n * Feishu/Lark channel plugin (Socket Mode first).\n *\n * This is intentionally decomposed into small modules so we can grow toward\n * openclaw `extensions/feishu` parity without turning `plugin.ts` into a monolith.\n */\n\nimport { isDeepStrictEqual } from 'node:util';\n\nimport type { Config } from '@xopcai/xopc/config/schema.js';\nimport type { MessageBus } from '@xopcai/xopc/infra/bus/index.js';\nimport type {\n ChannelCapabilities,\n ChannelDoctorAdapter,\n ChannelMessageActionAdapter,\n ChannelOutboundAdapter,\n ChannelPlugin,\n ChannelPluginDefaults,\n ChannelPluginInitOptions,\n ChannelPluginReloadMeta,\n ChannelPluginStartOptions,\n ChannelSecurityAdapter,\n ChannelSecurityContext,\n ChannelStatusAdapter,\n ChatType,\n} from '@xopcai/xopc/channels/plugin-types.js';\nimport type { ChannelCliLoginAdapter } from '@xopcai/xopc/channels/plugins/types.adapters.js';\nimport { createLogger } from '@xopcai/xopc/utils/logger.js';\nimport { evaluateAccess, resolveDmPolicy, resolveGroupPolicy } from '@xopcai/xopc/channels/security.js';\nimport { createStandardPairingAdapter } from '@xopcai/xopc/channels/pairing/pairing-store-adapter.js';\n\nimport { FeishuConfigSchema, type FeishuConfig } from './schema/config-schema.js';\nimport { listFeishuAccountIds, resolveFeishuAccount, type ResolvedFeishuAccount } from './state/accounts.js';\nimport { createFeishuSocketModeMonitor } from './transport/socket-mode/monitor.js';\nimport { createFeishuWebhookMonitor } from './transport/webhook/monitor.js';\nimport { createFeishuOutboundAdapter } from './outbound/outbound-adapter.js';\nimport { createFeishuStatusAdapter } from './status/status-adapter.js';\nimport { createFeishuDoctorAdapter } from './status/doctor.js';\nimport { feishuConfigSurface } from './ui/config-surface.js';\nimport { createFeishuStreamingAdapter } from './streaming/streaming-adapter.js';\nimport { readFrameworkAllowFromList } from './auth/pairing.js';\nimport {\n addReactionFeishu,\n editMessageFeishu,\n getMessageFeishu,\n listPinsFeishu,\n listReactionsFeishu,\n pinMessageFeishu,\n removeReactionFeishu,\n unpinMessageFeishu,\n} from './outbound/actions.js';\nimport { createFeishuDirectoryAdapter } from './directory/directory-adapter.js';\nimport { feishuWhoAmI } from './tools/tools.js';\nimport { feishuCliLoginAdapter } from './adapters/cli-login.js';\nimport { feishuOnboardAdapter } from './adapters/onboard-cli.js';\nimport { handleFeishuChannelMessageAction } from './actions/message-action-handler.js';\nimport { createFeishuInboundPipeline, type FeishuInboundWork } from './transport/reliability/inbound-pipeline.js';\nimport { getWorkflowProgressBroker } from '@xopcai/xopc/agent/workflow/index.js';\nimport { createFeishuWorkflowProgressCapability } from './workflow-progress.js';\n\nconst log = createLogger('FeishuPlugin');\n\nexport class FeishuChannelPlugin implements ChannelPlugin<ResolvedFeishuAccount> {\n readonly id = 'feishu' as const;\n\n readonly reload: ChannelPluginReloadMeta = {\n configPrefixes: ['channels.feishu'],\n };\n\n readonly meta = {\n id: 'feishu',\n label: 'Feishu',\n selectionLabel: 'Feishu/Lark (飞书)',\n docsPath: '/channels/feishu',\n blurb: 'Feishu/Lark enterprise messaging (Socket Mode).',\n order: 4,\n deferConnectUntilAfterListen: true,\n } as const;\n\n readonly capabilities: ChannelCapabilities = {\n chatTypes: ['direct', 'channel'] as ChatType[],\n reactions: true,\n threads: true,\n media: true,\n polls: false,\n nativeCommands: false,\n blockStreaming: false,\n edit: true,\n reply: true,\n } as any;\n\n readonly defaults: ChannelPluginDefaults = {\n queue: { debounceMs: 350 },\n outbound: { textChunkLimit: 4000 },\n streaming: {\n blockStreamingCoalesce: {\n minChars: 200,\n idleMs: 2500,\n },\n },\n };\n\n readonly configSchema = {\n schema: {},\n validate: (raw: unknown) => {\n const r = FeishuConfigSchema.safeParse(raw);\n return r.success ? { ok: true as const } : { ok: false as const, errors: [r.error.message] };\n },\n };\n\n readonly configSurface = feishuConfigSurface;\n\n readonly pairing = createStandardPairingAdapter('feishu');\n\n onboard = feishuOnboardAdapter;\n\n readonly cliLogin: ChannelCliLoginAdapter = feishuCliLoginAdapter;\n\n private bus!: MessageBus;\n private cfg!: Config;\n private abortControllers = new Map<string, AbortController>();\n private inboundPipeline?: ReturnType<typeof createFeishuInboundPipeline>;\n /** Unregister fn for the workflow-progress capability registered against the global broker. */\n private workflowProgressUnregister: (() => void) | null = null;\n\n config = {\n listAccountIds: (cfg: Config) => listFeishuAccountIds(cfg),\n resolveAccount: (cfg: Config, accountId?: string | null) => resolveFeishuAccount(cfg, accountId),\n isConfigured: async (account: ResolvedFeishuAccount) => account.configured,\n describeAccount: (account: ResolvedFeishuAccount) => ({\n accountId: account.accountId,\n channelId: 'feishu',\n enabled: account.enabled,\n configured: account.configured,\n status: account.configured ? undefined : 'unconfigured',\n }),\n };\n\n security: ChannelSecurityAdapter<ResolvedFeishuAccount> = {\n resolveDmPolicy: ({ account }: { account: ResolvedFeishuAccount }) =>\n resolveDmPolicy(account.dmPolicy, 'open'),\n resolveGroupPolicy: ({ account }: { account: ResolvedFeishuAccount }) =>\n resolveGroupPolicy(account.groupPolicy, 'allowlist'),\n checkAccess: (ctx: ChannelSecurityContext, account: ResolvedFeishuAccount, _cfg: Config) => {\n const isDm = !ctx.isGroup;\n const frameworkAllowFrom = readFrameworkAllowFromList(account.accountId);\n const baseAllowFrom = isDm ? account.allowFrom : account.groupAllowFrom ?? account.allowFrom;\n const allowFrom = [...(baseAllowFrom ?? []), ...frameworkAllowFrom];\n if (isDm) {\n return evaluateAccess({\n context: {\n channel: 'feishu',\n accountId: account.accountId,\n chatId: ctx.chatId,\n senderId: ctx.senderId,\n senderName: ctx.senderName,\n isGroup: false,\n isDm: true,\n },\n dmPolicy: account.dmPolicy,\n allowFrom,\n });\n }\n return evaluateAccess({\n context: {\n channel: 'feishu',\n accountId: account.accountId,\n chatId: ctx.chatId,\n senderId: ctx.senderId,\n senderName: ctx.senderName,\n isGroup: true,\n isDm: false,\n },\n groupPolicy: account.groupPolicy,\n allowFrom,\n });\n },\n };\n\n outbound: ChannelOutboundAdapter = createFeishuOutboundAdapter();\n\n streaming = createFeishuStreamingAdapter(() => this.cfg);\n\n status: ChannelStatusAdapter<ResolvedFeishuAccount> = createFeishuStatusAdapter();\n\n doctor: ChannelDoctorAdapter = createFeishuDoctorAdapter();\n\n directory = createFeishuDirectoryAdapter();\n\n actions: ChannelMessageActionAdapter = {\n handleAction: handleFeishuChannelMessageAction,\n };\n\n agentTools = [\n {\n name: 'feishu_read',\n description: 'Read a Feishu message by messageId (debug/utility).',\n execute: async (toolCtx, args) => {\n const messageId = typeof (args as any)?.messageId === 'string' ? (args as any).messageId : toolCtx.messageId;\n if (!messageId) throw new Error('feishu_read requires messageId');\n return await getMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId });\n },\n },\n {\n name: 'feishu_edit',\n description: 'Edit a Feishu message by messageId.',\n execute: async (toolCtx, args) => {\n const messageId = typeof (args as any)?.messageId === 'string' ? (args as any).messageId : toolCtx.messageId;\n const text = typeof (args as any)?.text === 'string' ? (args as any).text : '';\n if (!messageId) throw new Error('feishu_edit requires messageId');\n if (!text.trim()) throw new Error('feishu_edit requires text');\n return await editMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId, text });\n },\n },\n {\n name: 'feishu_scopes_probe',\n description: 'Probe Feishu credentials/scopes (placeholder for full docs/wiki/drive tools).',\n execute: async (toolCtx) => {\n return await feishuWhoAmI({ cfg: this.cfg, accountId: toolCtx.accountId });\n },\n },\n {\n name: 'feishu_react',\n description: 'Add/remove/list reactions for a message.',\n execute: async (toolCtx, args) => {\n const a = args as any;\n const messageId = typeof a?.messageId === 'string' ? a.messageId : toolCtx.messageId;\n if (!messageId) throw new Error('feishu_react requires messageId');\n\n const account = resolveFeishuAccount(this.cfg, toolCtx.accountId ?? 'default');\n const enabled = (account.actions as any)?.reactions !== false;\n if (!enabled) {\n throw new Error('Feishu reactions are disabled via channels.feishu.actions.reactions');\n }\n\n if (a?.list === true) {\n return await listReactionsFeishu({\n cfg: this.cfg,\n accountId: toolCtx.accountId,\n messageId,\n emojiType: typeof a?.emojiType === 'string' ? a.emojiType : undefined,\n });\n }\n\n if (a?.remove === true) {\n const reactionId = typeof a?.reactionId === 'string' ? a.reactionId : '';\n if (!reactionId) throw new Error('feishu_react remove requires reactionId');\n return await removeReactionFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId, reactionId });\n }\n\n const emojiType = typeof a?.emojiType === 'string' ? a.emojiType : '';\n if (!emojiType) throw new Error('feishu_react requires emojiType');\n return await addReactionFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId, emojiType });\n },\n },\n {\n name: 'feishu_pins',\n description: 'Pin/unpin/list pins for a chat.',\n execute: async (toolCtx, args) => {\n const a = args as any;\n const action = typeof a?.action === 'string' ? a.action : '';\n if (action === 'list') {\n const chatId = typeof a?.chatId === 'string' ? a.chatId : toolCtx.chatId;\n if (!chatId) throw new Error('feishu_pins list requires chatId');\n return await listPinsFeishu({\n cfg: this.cfg,\n accountId: toolCtx.accountId,\n chatId,\n startTime: typeof a?.startTime === 'string' ? a.startTime : undefined,\n endTime: typeof a?.endTime === 'string' ? a.endTime : undefined,\n pageSize: typeof a?.pageSize === 'number' ? a.pageSize : undefined,\n pageToken: typeof a?.pageToken === 'string' ? a.pageToken : undefined,\n });\n }\n const messageId = typeof a?.messageId === 'string' ? a.messageId : toolCtx.messageId;\n if (!messageId) throw new Error('feishu_pins requires messageId');\n if (action === 'pin') {\n return await pinMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId });\n }\n if (action === 'unpin') {\n return await unpinMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId });\n }\n throw new Error('feishu_pins requires action: pin | unpin | list');\n },\n },\n ];\n\n async init(options: ChannelPluginInitOptions): Promise<void> {\n this.bus = options.bus;\n this.cfg = options.config;\n const defaultDebounce = this.defaults.queue?.debounceMs ?? 350;\n this.inboundPipeline = createFeishuInboundPipeline({\n bus: this.bus,\n defaultDebounceMs: defaultDebounce,\n onError: (err, items) => {\n log.error({ err, count: items.length }, 'Feishu inbound pipeline flush failed');\n },\n });\n\n // Workflow progress broker capability — turns mid-run snapshots into\n // edit-in-place Feishu messages. Broker is the agent-side subscriber for\n // `tool_execution_update` on the `workflow` tool. Registration is\n // idempotent (replaces a prior cap with the same channelId).\n this.workflowProgressUnregister = getWorkflowProgressBroker().registerChannel(\n createFeishuWorkflowProgressCapability({ getConfig: () => this.cfg }),\n );\n\n log.debug('Feishu plugin initialized');\n }\n\n async start(options?: ChannelPluginStartOptions): Promise<void> {\n const section = this.cfg.channels?.feishu as FeishuConfig | undefined;\n if (!section || section.enabled !== true) {\n return;\n }\n\n const ids = options?.accountId ? [options.accountId] : listFeishuAccountIds(this.cfg);\n for (const accountId of ids) {\n const account = resolveFeishuAccount(this.cfg, accountId);\n if (!account.enabled || !account.configured) continue;\n if (this.abortControllers.has(accountId)) continue;\n\n const ac = new AbortController();\n this.abortControllers.set(accountId, ac);\n\n const defaultDebounce = this.defaults.queue?.debounceMs ?? 350;\n const enqueueInbound = (work: FeishuInboundWork) => {\n const p = this.inboundPipeline;\n if (!p) {\n return this.bus.publishInbound(work.inbound);\n }\n return p.enqueue(work);\n };\n\n const monitor = createFeishuSocketModeMonitor({\n account,\n config: this.cfg,\n enqueueInbound,\n inboundDebounceDefaultMs: defaultDebounce,\n abortSignal: ac.signal,\n security: {\n checkAccess: (ctx: ChannelSecurityContext) => this.security.checkAccess?.(ctx, account, this.cfg),\n },\n });\n\n const runner =\n account.connectionMode === 'webhook'\n ? createFeishuWebhookMonitor({\n account,\n config: this.cfg,\n enqueueInbound,\n inboundDebounceDefaultMs: defaultDebounce,\n abortSignal: ac.signal,\n security: {\n checkAccess: (ctx: ChannelSecurityContext) =>\n this.security.checkAccess?.(ctx, account, this.cfg),\n },\n })\n : monitor;\n\n void runner.run().catch((err) => {\n if ((err as { name?: string } | undefined)?.name === 'AbortError') {\n log.debug({ accountId }, 'Feishu monitor stopped');\n return;\n }\n log.error({ err, accountId }, 'Feishu monitor exited with error');\n });\n\n log.info({ accountId, mode: account.connectionMode }, 'Feishu monitor started');\n }\n }\n\n async stop(accountId?: string): Promise<void> {\n try {\n await this.inboundPipeline?.flushAll();\n } catch (err) {\n log.warn({ err }, 'Feishu inbound pipeline flushAll failed');\n }\n const ids = accountId ? [accountId] : [...this.abortControllers.keys()];\n for (const id of ids) {\n const ac = this.abortControllers.get(id);\n if (ac) {\n ac.abort();\n this.abortControllers.delete(id);\n }\n }\n // Only unregister the broker capability on a full stop. Per-account stops\n // still leave other accounts capable of delivering progress through the\n // same registered cap.\n if (!accountId) {\n this.workflowProgressUnregister?.();\n this.workflowProgressUnregister = null;\n }\n }\n\n channelIsRunning(cfg: Config): boolean {\n const ids = listFeishuAccountIds(cfg);\n return ids.some((id) => {\n const a = resolveFeishuAccount(cfg, id);\n return a.enabled !== false && a.configured && this.abortControllers.has(id);\n });\n }\n\n async onConfigUpdated(cfg: Config): Promise<void> {\n const prev = this.cfg.channels?.feishu as unknown;\n const next = cfg.channels?.feishu as { enabled?: boolean } | undefined;\n const channelOff = !next || next.enabled !== true;\n\n if (channelOff) {\n this.cfg = cfg;\n await this.stop();\n return;\n }\n\n this.cfg = cfg;\n\n if (isDeepStrictEqual(prev, next) && this.channelIsRunning(cfg)) {\n return;\n }\n\n await this.stop();\n await this.start();\n }\n}\n\nexport const feishuPlugin = new FeishuChannelPlugin();\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../../../extensions/feishu/src/plugin.ts"],"sourcesContent":["/**\n * Feishu/Lark channel plugin (Socket Mode first).\n *\n * This is intentionally decomposed into small modules so we can grow toward\n * openclaw `extensions/feishu` parity without turning `plugin.ts` into a monolith.\n */\n\nimport { isDeepStrictEqual } from 'node:util';\n\nimport type { Config } from '@xopcai/xopc/config/schema.js';\nimport type { MessageBus } from '@xopcai/xopc/infra/bus/index.js';\nimport type {\n ChannelCapabilities,\n ChannelDoctorAdapter,\n ChannelMessageActionAdapter,\n ChannelOutboundAdapter,\n ChannelPlugin,\n ChannelPluginDefaults,\n ChannelPluginInitOptions,\n ChannelPluginReloadMeta,\n ChannelPluginStartOptions,\n ChannelSecurityAdapter,\n ChannelSecurityContext,\n ChannelStatusAdapter,\n ChatType,\n} from '@xopcai/xopc/channels/plugin-types.js';\nimport type {\n ChannelCliLoginAdapter,\n ChannelRuntimeActionAdapter,\n} from '@xopcai/xopc/channels/plugins/types.adapters.js';\nimport { createLogger } from '@xopcai/xopc/utils/logger.js';\nimport { evaluateAccess, resolveDmPolicy, resolveGroupPolicy } from '@xopcai/xopc/channels/security.js';\nimport { createStandardPairingAdapter } from '@xopcai/xopc/channels/pairing/pairing-store-adapter.js';\n\nimport { FeishuConfigSchema, type FeishuConfig } from './schema/config-schema.js';\nimport { listFeishuAccountIds, resolveFeishuAccount, type ResolvedFeishuAccount } from './state/accounts.js';\nimport { createFeishuSocketModeMonitor } from './transport/socket-mode/monitor.js';\nimport { createFeishuWebhookMonitor } from './transport/webhook/monitor.js';\nimport { createFeishuOutboundAdapter } from './outbound/outbound-adapter.js';\nimport { createFeishuStatusAdapter } from './status/status-adapter.js';\nimport { createFeishuDoctorAdapter } from './status/doctor.js';\nimport { feishuConfigSurface } from './ui/config-surface.js';\nimport { createFeishuStreamingAdapter } from './streaming/streaming-adapter.js';\nimport { readFrameworkAllowFromList } from './auth/pairing.js';\nimport {\n addReactionFeishu,\n editMessageFeishu,\n getMessageFeishu,\n listPinsFeishu,\n listReactionsFeishu,\n pinMessageFeishu,\n removeReactionFeishu,\n unpinMessageFeishu,\n} from './outbound/actions.js';\nimport { createFeishuDirectoryAdapter } from './directory/directory-adapter.js';\nimport { feishuWhoAmI } from './tools/tools.js';\nimport { feishuCliLoginAdapter } from './adapters/cli-login.js';\nimport { feishuOnboardAdapter } from './adapters/onboard-cli.js';\nimport { feishuGatewaySetupActions } from './adapters/gateway-setup.js';\nimport { handleFeishuChannelMessageAction } from './actions/message-action-handler.js';\nimport { createFeishuInboundPipeline, type FeishuInboundWork } from './transport/reliability/inbound-pipeline.js';\nimport { getWorkflowProgressBroker } from '@xopcai/xopc/agent/workflow/index.js';\nimport { createFeishuWorkflowProgressCapability } from './workflow-progress.js';\n\nconst log = createLogger('FeishuPlugin');\n\nexport class FeishuChannelPlugin implements ChannelPlugin<ResolvedFeishuAccount> {\n readonly id = 'feishu' as const;\n\n readonly reload: ChannelPluginReloadMeta = {\n configPrefixes: ['channels.feishu'],\n };\n\n readonly meta = {\n id: 'feishu',\n label: 'Feishu',\n selectionLabel: 'Feishu/Lark (飞书)',\n docsPath: '/channels/feishu',\n blurb: 'Feishu/Lark enterprise messaging (Socket Mode).',\n order: 4,\n deferConnectUntilAfterListen: true,\n } as const;\n\n readonly capabilities: ChannelCapabilities = {\n chatTypes: ['direct', 'channel'] as ChatType[],\n reactions: true,\n threads: true,\n media: true,\n polls: false,\n nativeCommands: false,\n blockStreaming: false,\n edit: true,\n reply: true,\n } as any;\n\n readonly defaults: ChannelPluginDefaults = {\n queue: { debounceMs: 350 },\n outbound: { textChunkLimit: 4000 },\n streaming: {\n blockStreamingCoalesce: {\n minChars: 200,\n idleMs: 2500,\n },\n },\n };\n\n readonly configSchema = {\n schema: {},\n validate: (raw: unknown) => {\n const r = FeishuConfigSchema.safeParse(raw);\n return r.success ? { ok: true as const } : { ok: false as const, errors: [r.error.message] };\n },\n };\n\n readonly configSurface = feishuConfigSurface;\n\n readonly pairing = createStandardPairingAdapter('feishu');\n\n onboard = feishuOnboardAdapter;\n\n readonly cliLogin: ChannelCliLoginAdapter = feishuCliLoginAdapter;\n\n readonly runtimeActions: ChannelRuntimeActionAdapter = feishuGatewaySetupActions;\n\n private bus!: MessageBus;\n private cfg!: Config;\n private abortControllers = new Map<string, AbortController>();\n private inboundPipeline?: ReturnType<typeof createFeishuInboundPipeline>;\n /** Unregister fn for the workflow-progress capability registered against the global broker. */\n private workflowProgressUnregister: (() => void) | null = null;\n\n config = {\n listAccountIds: (cfg: Config) => listFeishuAccountIds(cfg),\n resolveAccount: (cfg: Config, accountId?: string | null) => resolveFeishuAccount(cfg, accountId),\n isConfigured: async (account: ResolvedFeishuAccount) => account.configured,\n describeAccount: (account: ResolvedFeishuAccount) => ({\n accountId: account.accountId,\n channelId: 'feishu',\n enabled: account.enabled,\n configured: account.configured,\n status: account.configured ? undefined : 'unconfigured',\n }),\n };\n\n security: ChannelSecurityAdapter<ResolvedFeishuAccount> = {\n resolveDmPolicy: ({ account }: { account: ResolvedFeishuAccount }) =>\n resolveDmPolicy(account.dmPolicy, 'open'),\n resolveGroupPolicy: ({ account }: { account: ResolvedFeishuAccount }) =>\n resolveGroupPolicy(account.groupPolicy, 'allowlist'),\n checkAccess: (ctx: ChannelSecurityContext, account: ResolvedFeishuAccount, _cfg: Config) => {\n const isDm = !ctx.isGroup;\n const frameworkAllowFrom = readFrameworkAllowFromList(account.accountId);\n const baseAllowFrom = isDm ? account.allowFrom : account.groupAllowFrom ?? account.allowFrom;\n const allowFrom = [...(baseAllowFrom ?? []), ...frameworkAllowFrom];\n if (isDm) {\n return evaluateAccess({\n context: {\n channel: 'feishu',\n accountId: account.accountId,\n chatId: ctx.chatId,\n senderId: ctx.senderId,\n senderName: ctx.senderName,\n isGroup: false,\n isDm: true,\n },\n dmPolicy: account.dmPolicy,\n allowFrom,\n });\n }\n return evaluateAccess({\n context: {\n channel: 'feishu',\n accountId: account.accountId,\n chatId: ctx.chatId,\n senderId: ctx.senderId,\n senderName: ctx.senderName,\n isGroup: true,\n isDm: false,\n },\n groupPolicy: account.groupPolicy,\n allowFrom,\n });\n },\n };\n\n outbound: ChannelOutboundAdapter = createFeishuOutboundAdapter();\n\n streaming = createFeishuStreamingAdapter(() => this.cfg);\n\n status: ChannelStatusAdapter<ResolvedFeishuAccount> = createFeishuStatusAdapter();\n\n doctor: ChannelDoctorAdapter = createFeishuDoctorAdapter();\n\n directory = createFeishuDirectoryAdapter();\n\n actions: ChannelMessageActionAdapter = {\n handleAction: handleFeishuChannelMessageAction,\n };\n\n agentTools = [\n {\n name: 'feishu_read',\n description: 'Read a Feishu message by messageId (debug/utility).',\n execute: async (toolCtx, args) => {\n const messageId = typeof (args as any)?.messageId === 'string' ? (args as any).messageId : toolCtx.messageId;\n if (!messageId) throw new Error('feishu_read requires messageId');\n return await getMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId });\n },\n },\n {\n name: 'feishu_edit',\n description: 'Edit a Feishu message by messageId.',\n execute: async (toolCtx, args) => {\n const messageId = typeof (args as any)?.messageId === 'string' ? (args as any).messageId : toolCtx.messageId;\n const text = typeof (args as any)?.text === 'string' ? (args as any).text : '';\n if (!messageId) throw new Error('feishu_edit requires messageId');\n if (!text.trim()) throw new Error('feishu_edit requires text');\n return await editMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId, text });\n },\n },\n {\n name: 'feishu_scopes_probe',\n description: 'Probe Feishu credentials/scopes (placeholder for full docs/wiki/drive tools).',\n execute: async (toolCtx) => {\n return await feishuWhoAmI({ cfg: this.cfg, accountId: toolCtx.accountId });\n },\n },\n {\n name: 'feishu_react',\n description: 'Add/remove/list reactions for a message.',\n execute: async (toolCtx, args) => {\n const a = args as any;\n const messageId = typeof a?.messageId === 'string' ? a.messageId : toolCtx.messageId;\n if (!messageId) throw new Error('feishu_react requires messageId');\n\n const account = resolveFeishuAccount(this.cfg, toolCtx.accountId ?? 'default');\n const enabled = (account.actions as any)?.reactions !== false;\n if (!enabled) {\n throw new Error('Feishu reactions are disabled via channels.feishu.actions.reactions');\n }\n\n if (a?.list === true) {\n return await listReactionsFeishu({\n cfg: this.cfg,\n accountId: toolCtx.accountId,\n messageId,\n emojiType: typeof a?.emojiType === 'string' ? a.emojiType : undefined,\n });\n }\n\n if (a?.remove === true) {\n const reactionId = typeof a?.reactionId === 'string' ? a.reactionId : '';\n if (!reactionId) throw new Error('feishu_react remove requires reactionId');\n return await removeReactionFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId, reactionId });\n }\n\n const emojiType = typeof a?.emojiType === 'string' ? a.emojiType : '';\n if (!emojiType) throw new Error('feishu_react requires emojiType');\n return await addReactionFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId, emojiType });\n },\n },\n {\n name: 'feishu_pins',\n description: 'Pin/unpin/list pins for a chat.',\n execute: async (toolCtx, args) => {\n const a = args as any;\n const action = typeof a?.action === 'string' ? a.action : '';\n if (action === 'list') {\n const chatId = typeof a?.chatId === 'string' ? a.chatId : toolCtx.chatId;\n if (!chatId) throw new Error('feishu_pins list requires chatId');\n return await listPinsFeishu({\n cfg: this.cfg,\n accountId: toolCtx.accountId,\n chatId,\n startTime: typeof a?.startTime === 'string' ? a.startTime : undefined,\n endTime: typeof a?.endTime === 'string' ? a.endTime : undefined,\n pageSize: typeof a?.pageSize === 'number' ? a.pageSize : undefined,\n pageToken: typeof a?.pageToken === 'string' ? a.pageToken : undefined,\n });\n }\n const messageId = typeof a?.messageId === 'string' ? a.messageId : toolCtx.messageId;\n if (!messageId) throw new Error('feishu_pins requires messageId');\n if (action === 'pin') {\n return await pinMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId });\n }\n if (action === 'unpin') {\n return await unpinMessageFeishu({ cfg: this.cfg, accountId: toolCtx.accountId, messageId });\n }\n throw new Error('feishu_pins requires action: pin | unpin | list');\n },\n },\n ];\n\n async init(options: ChannelPluginInitOptions): Promise<void> {\n this.bus = options.bus;\n this.cfg = options.config;\n const defaultDebounce = this.defaults.queue?.debounceMs ?? 350;\n this.inboundPipeline = createFeishuInboundPipeline({\n bus: this.bus,\n defaultDebounceMs: defaultDebounce,\n onError: (err, items) => {\n log.error({ err, count: items.length }, 'Feishu inbound pipeline flush failed');\n },\n });\n\n // Workflow progress broker capability — turns mid-run snapshots into\n // edit-in-place Feishu messages. Broker is the agent-side subscriber for\n // `tool_execution_update` on the `workflow` tool. Registration is\n // idempotent (replaces a prior cap with the same channelId).\n this.workflowProgressUnregister = getWorkflowProgressBroker().registerChannel(\n createFeishuWorkflowProgressCapability({ getConfig: () => this.cfg }),\n );\n\n log.debug('Feishu plugin initialized');\n }\n\n async start(options?: ChannelPluginStartOptions): Promise<void> {\n const section = this.cfg.channels?.feishu as FeishuConfig | undefined;\n if (!section || section.enabled !== true) {\n return;\n }\n\n const ids = options?.accountId ? [options.accountId] : listFeishuAccountIds(this.cfg);\n for (const accountId of ids) {\n const account = resolveFeishuAccount(this.cfg, accountId);\n if (!account.enabled || !account.configured) continue;\n if (this.abortControllers.has(accountId)) continue;\n\n const ac = new AbortController();\n this.abortControllers.set(accountId, ac);\n\n const defaultDebounce = this.defaults.queue?.debounceMs ?? 350;\n const enqueueInbound = (work: FeishuInboundWork) => {\n const p = this.inboundPipeline;\n if (!p) {\n return this.bus.publishInbound(work.inbound);\n }\n return p.enqueue(work);\n };\n\n const monitor = createFeishuSocketModeMonitor({\n account,\n config: this.cfg,\n enqueueInbound,\n inboundDebounceDefaultMs: defaultDebounce,\n abortSignal: ac.signal,\n security: {\n checkAccess: (ctx: ChannelSecurityContext) => this.security.checkAccess?.(ctx, account, this.cfg),\n },\n });\n\n const runner =\n account.connectionMode === 'webhook'\n ? createFeishuWebhookMonitor({\n account,\n config: this.cfg,\n enqueueInbound,\n inboundDebounceDefaultMs: defaultDebounce,\n abortSignal: ac.signal,\n security: {\n checkAccess: (ctx: ChannelSecurityContext) =>\n this.security.checkAccess?.(ctx, account, this.cfg),\n },\n })\n : monitor;\n\n void runner.run().catch((err) => {\n if ((err as { name?: string } | undefined)?.name === 'AbortError') {\n log.debug({ accountId }, 'Feishu monitor stopped');\n return;\n }\n log.error({ err, accountId }, 'Feishu monitor exited with error');\n });\n\n log.info({ accountId, mode: account.connectionMode }, 'Feishu monitor started');\n }\n }\n\n async stop(accountId?: string): Promise<void> {\n try {\n await this.inboundPipeline?.flushAll();\n } catch (err) {\n log.warn({ err }, 'Feishu inbound pipeline flushAll failed');\n }\n const ids = accountId ? [accountId] : [...this.abortControllers.keys()];\n for (const id of ids) {\n const ac = this.abortControllers.get(id);\n if (ac) {\n ac.abort();\n this.abortControllers.delete(id);\n }\n }\n // Only unregister the broker capability on a full stop. Per-account stops\n // still leave other accounts capable of delivering progress through the\n // same registered cap.\n if (!accountId) {\n this.workflowProgressUnregister?.();\n this.workflowProgressUnregister = null;\n }\n }\n\n channelIsRunning(cfg: Config): boolean {\n const ids = listFeishuAccountIds(cfg);\n return ids.some((id) => {\n const a = resolveFeishuAccount(cfg, id);\n return a.enabled !== false && a.configured && this.abortControllers.has(id);\n });\n }\n\n async onConfigUpdated(cfg: Config): Promise<void> {\n const prev = this.cfg.channels?.feishu as unknown;\n const next = cfg.channels?.feishu as { enabled?: boolean } | undefined;\n const channelOff = !next || next.enabled !== true;\n\n if (channelOff) {\n this.cfg = cfg;\n await this.stop();\n return;\n }\n\n this.cfg = cfg;\n\n if (isDeepStrictEqual(prev, next) && this.channelIsRunning(cfg)) {\n return;\n }\n\n await this.stop();\n await this.start();\n }\n}\n\nexport const feishuPlugin = new FeishuChannelPlugin();\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../../../../src/utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../../../src/utils/logger.js";
|
|
3
|
+
import { formatFeishuOutboundText } from "../format.js";
|
|
3
4
|
import { resolveFeishuAccount } from "../state/accounts.js";
|
|
4
5
|
import { createFeishuClient } from "../transport/client/client.js";
|
|
5
6
|
import { getFeishuBindingByMessageId, recordFeishuMessageBinding } from "../state/message-bindings.js";
|
|
6
|
-
import { formatFeishuOutboundText } from "../format.js";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
8
|
//#region extensions/feishu/src/streaming/streaming-adapter.ts
|
|
9
9
|
init_logger();
|
|
@@ -7,8 +7,8 @@ import { createFeishuDedupe } from "../reliability/dedupe.js";
|
|
|
7
7
|
import { stripFeishuMentions } from "../text/mentions.js";
|
|
8
8
|
import { recordFeishuMessageBinding } from "../../state/message-bindings.js";
|
|
9
9
|
import crypto from "node:crypto";
|
|
10
|
+
import * as http$1 from "node:http";
|
|
10
11
|
import * as lark from "@larksuiteoapi/node-sdk";
|
|
11
|
-
import * as http from "node:http";
|
|
12
12
|
//#region extensions/feishu/src/transport/webhook/monitor.ts
|
|
13
13
|
init_logger();
|
|
14
14
|
const log = createLogger("FeishuWebhook");
|
|
@@ -223,7 +223,7 @@ function createFeishuWebhookMonitor(deps) {
|
|
|
223
223
|
loggerLevel: l.LoggerLevel.info
|
|
224
224
|
});
|
|
225
225
|
dispatcher.register({ "im.message.receive_v1": async (data) => await handleMessageReceive(data) });
|
|
226
|
-
const server = http.createServer();
|
|
226
|
+
const server = http$1.createServer();
|
|
227
227
|
async function handleRequest(req, res) {
|
|
228
228
|
if (req.method !== "POST") return text(res, 405, "Method Not Allowed");
|
|
229
229
|
if ((req.url ?? "").split("?")[0] !== path) return text(res, 404, "Not Found");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor.js","names":[],"sources":["../../../../../../extensions/feishu/src/transport/webhook/monitor.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport * as http from 'node:http';\n\nimport type { InboundMessage } from '@xopcai/xopc/channels/transport-types.js';\nimport * as lark from '@larksuiteoapi/node-sdk';\n\nimport type { Config } from '@xopcai/xopc/config/schema.js';\nimport type { ChannelSecurityContext } from '@xopcai/xopc/channels/plugin-types.js';\nimport { generateSessionKey } from '@xopcai/xopc/chat-commands/session-key.js';\nimport { createLogger } from '@xopcai/xopc/utils/logger.js';\n\nimport type { ResolvedFeishuAccount } from '../../state/accounts.js';\nimport { createFeishuDedupe } from '../reliability/dedupe.js';\nimport type { FeishuInboundWork } from '../reliability/inbound-pipeline.js';\nimport { stripFeishuMentions } from '../text/mentions.js';\nimport { recordFeishuMessageBinding } from '../../state/message-bindings.js';\nimport { sendFeishuPairingPromptIfNeeded } from '../../pairing/feishu-pairing-prompt.js';\nimport { createFeishuLarkSdkPinoLogger } from '../client/lark-sdk-logger.js';\n\nconst log = createLogger('FeishuWebhook');\n\nconst MAX_BODY_BYTES = 256 * 1024;\nconst BODY_TIMEOUT_MS = 2_000;\nconst RATE_LIMIT_WINDOW_MS = 60_000;\nconst RATE_LIMIT_MAX = 120;\nconst RATE_LIMIT_MAX_KEYS = 4096;\n\ntype RateKeyState = { windowStart: number; count: number };\nconst rateState = new Map<string, RateKeyState>();\n\nfunction pruneRateState(now: number) {\n for (const [k, v] of rateState.entries()) {\n if (now - v.windowStart > RATE_LIMIT_WINDOW_MS) {\n rateState.delete(k);\n }\n }\n if (rateState.size <= RATE_LIMIT_MAX_KEYS) return;\n const over = rateState.size - RATE_LIMIT_MAX_KEYS;\n let i = 0;\n for (const k of rateState.keys()) {\n rateState.delete(k);\n i++;\n if (i >= over) break;\n }\n}\n\nfunction isRateLimited(key: string, now: number): boolean {\n pruneRateState(now);\n const cur = rateState.get(key);\n if (!cur || now - cur.windowStart > RATE_LIMIT_WINDOW_MS) {\n rateState.set(key, { windowStart: now, count: 1 });\n return false;\n }\n cur.count += 1;\n return cur.count > RATE_LIMIT_MAX;\n}\n\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n try {\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\n } catch {\n return false;\n }\n}\n\nfunction signatureValid(headers: http.IncomingHttpHeaders, rawBody: string, encryptKey: string): boolean {\n const timestampHeader = headers['x-lark-request-timestamp'];\n const nonceHeader = headers['x-lark-request-nonce'];\n const signatureHeader = headers['x-lark-signature'];\n const timestamp = Array.isArray(timestampHeader) ? timestampHeader[0] : timestampHeader;\n const nonce = Array.isArray(nonceHeader) ? nonceHeader[0] : nonceHeader;\n const signature = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;\n if (!timestamp || !nonce || !signature) return false;\n if (typeof signature !== 'string' || signature.length < 32) return false;\n const computed = crypto.createHash('sha256').update(timestamp + nonce + encryptKey + rawBody).digest('hex');\n return safeEqual(computed, signature);\n}\n\nfunction readBody(\n req: http.IncomingMessage,\n): Promise<{ ok: true; body: string } | { ok: false; status: number; msg: string }> {\n return new Promise((resolve) => {\n let done = false;\n let bytes = 0;\n const chunks: Buffer[] = [];\n const t = setTimeout(() => {\n if (done) return;\n done = true;\n resolve({ ok: false, status: 408, msg: 'Request body timeout' });\n req.destroy();\n }, BODY_TIMEOUT_MS);\n\n req.on('data', (chunk: Buffer) => {\n if (done) return;\n bytes += chunk.length;\n if (bytes > MAX_BODY_BYTES) {\n done = true;\n clearTimeout(t);\n resolve({ ok: false, status: 413, msg: 'Payload too large' });\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n if (done) return;\n done = true;\n clearTimeout(t);\n resolve({ ok: true, body: Buffer.concat(chunks).toString('utf8') });\n });\n req.on('error', () => {\n if (done) return;\n done = true;\n clearTimeout(t);\n resolve({ ok: false, status: 400, msg: 'Bad Request' });\n });\n });\n}\n\nfunction json(res: http.ServerResponse, status: number, obj: unknown) {\n res.statusCode = status;\n res.setHeader('content-type', 'application/json; charset=utf-8');\n res.end(JSON.stringify(obj));\n}\n\nfunction text(res: http.ServerResponse, status: number, body: string) {\n res.statusCode = status;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n res.end(body);\n}\n\nexport interface FeishuWebhookMonitorDeps {\n account: ResolvedFeishuAccount;\n config: Config;\n enqueueInbound: (work: FeishuInboundWork) => Promise<void>;\n inboundDebounceDefaultMs: number;\n abortSignal: AbortSignal;\n security: {\n checkAccess: (ctx: ChannelSecurityContext) => { allowed: boolean; reason?: string } | undefined;\n };\n}\n\nexport function createFeishuWebhookMonitor(deps: FeishuWebhookMonitorDeps) {\n const { account, abortSignal, security, enqueueInbound, inboundDebounceDefaultMs } = deps;\n const dedupe = createFeishuDedupe();\n\n const encryptKey = (account.encryptKey ?? '').trim();\n const verificationToken = (account.verificationToken ?? '').trim();\n if (!encryptKey) throw new Error('Feishu webhook mode requires encryptKey');\n if (!verificationToken) throw new Error('Feishu webhook mode requires verificationToken');\n\n const host = (account.webhookHost ?? '127.0.0.1').trim() || '127.0.0.1';\n const port = account.webhookPort ?? 3000;\n const path = (account.webhookPath ?? '/feishu/events').trim() || '/feishu/events';\n const l = lark as any;\n const sdkLogger = createFeishuLarkSdkPinoLogger(account.accountId);\n\n function resolveTextDebounceMs(): number {\n if (typeof account.inboundDebounceMs === 'number' && Number.isFinite(account.inboundDebounceMs)) {\n return Math.max(0, Math.trunc(account.inboundDebounceMs));\n }\n return Math.max(0, Math.trunc(inboundDebounceDefaultMs));\n }\n\n async function pushText(inbound: InboundMessage): Promise<void> {\n const debounceMs = resolveTextDebounceMs();\n await enqueueInbound({\n kind: 'text',\n accountId: account.accountId,\n chatId: inbound.chat_id,\n debounceMs,\n inbound,\n });\n }\n\n async function handleMessageReceive(event: any): Promise<void> {\n const msg = event?.event?.message ?? event?.message ?? event?.data?.message;\n const sender = event?.event?.sender ?? event?.sender ?? event?.data?.sender;\n const chatId = msg?.chat_id ?? msg?.chatId ?? '';\n const messageId = msg?.message_id ?? msg?.messageId ?? '';\n const chatType = msg?.chat_type ?? msg?.chatType ?? '';\n\n const senderId =\n sender?.sender_id?.open_id ??\n sender?.sender_id?.user_id ??\n sender?.open_id ??\n sender?.user_id ??\n '';\n const senderName = sender?.sender_id?.name ?? sender?.sender_name ?? undefined;\n\n if (!chatId || !messageId || !senderId) return;\n if (!dedupe.claim(messageId)) return;\n\n const isGroup = chatType === 'group' || chatType === 'chat';\n const textRaw =\n msg?.content && typeof msg.content === 'string'\n ? safeJsonText(msg.content)\n : safeJsonText(msg?.body?.content);\n const normalizedText = stripFeishuMentions(textRaw ?? '').trim();\n if (!normalizedText) return;\n\n const threadId = msg?.thread_id ?? msg?.threadId ?? undefined;\n const sessionKey = generateSessionKey({\n source: 'feishu',\n chatId,\n senderId,\n isGroup,\n threadId: typeof threadId === 'string' && threadId.trim() ? threadId : undefined,\n accountId: account.accountId,\n });\n\n recordFeishuMessageBinding({\n messageId,\n sessionKey,\n accountId: account.accountId,\n chatId,\n senderId,\n isGroup,\n threadId: typeof threadId === 'string' && threadId.trim() ? threadId : undefined,\n });\n\n const access = security.checkAccess({\n accountId: account.accountId,\n chatId,\n senderId,\n senderName,\n isGroup,\n threadId,\n });\n if (access && !access.allowed) {\n if (!isGroup && access.reason === 'pairing-required') {\n await sendFeishuPairingPromptIfNeeded({\n account,\n messageId,\n threadId: typeof threadId === 'string' && threadId.trim() ? threadId : undefined,\n senderId,\n senderName,\n isGroup,\n });\n }\n return;\n }\n\n await pushText({\n channel: 'feishu',\n sender_id: senderId,\n chat_id: chatId,\n content: normalizedText,\n metadata: {\n sessionKey,\n accountId: account.accountId,\n messageId,\n threadId,\n isGroup,\n feishuEventType: 'im.message.receive_v1',\n raw: event,\n },\n });\n }\n\n const dispatcher = new l.EventDispatcher({\n verifyChallenge: false,\n encryptKey,\n verificationToken,\n logger: sdkLogger,\n loggerLevel: l.LoggerLevel.info,\n } as any);\n dispatcher.register({\n 'im.message.receive_v1': async (data: any) => await handleMessageReceive(data),\n });\n\n const server = http.createServer();\n\n async function handleRequest(req: http.IncomingMessage, res: http.ServerResponse) {\n if (req.method !== 'POST') return text(res, 405, 'Method Not Allowed');\n if ((req.url ?? '').split('?')[0] !== path) return text(res, 404, 'Not Found');\n\n const now = Date.now();\n const rateKey = `${account.accountId}:${path}:${req.socket.remoteAddress ?? 'unknown'}`;\n if (isRateLimited(rateKey, now)) return text(res, 429, 'Too Many Requests');\n\n const contentType = String(req.headers['content-type'] ?? '');\n if (!contentType.toLowerCase().includes('application/json')) return text(res, 415, 'Unsupported Media Type');\n\n const body = await readBody(req);\n if (body.ok === false) return text(res, body.status, body.msg);\n\n if (!signatureValid(req.headers, body.body, encryptKey)) return text(res, 401, 'Invalid signature');\n\n let payload: any;\n try {\n payload = JSON.parse(body.body);\n } catch {\n return text(res, 400, 'Invalid JSON');\n }\n\n const token = payload?.token ?? payload?.header?.token ?? payload?.event?.token;\n if (typeof token === 'string' && token.trim() && token.trim() !== verificationToken) {\n return text(res, 401, 'Invalid verification token');\n }\n\n const { isChallenge, challenge } = lark.generateChallenge(payload, { encryptKey });\n if (isChallenge) return json(res, 200, challenge);\n\n const envelope = Object.assign(Object.create({ headers: req.headers }), payload);\n const out = await dispatcher.invoke(envelope, { needCheck: false });\n if (!res.headersSent) return json(res, 200, out);\n }\n\n async function run(): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n server.on('request', (req, res) => {\n void handleRequest(req, res).catch((err) => {\n log.error({ err, accountId: account.accountId }, 'Feishu webhook handler error');\n if (!res.headersSent) text(res, 500, 'Internal Server Error');\n });\n });\n server.on('error', (err) => reject(err));\n server.listen(port, host, () => resolve());\n });\n\n log.info({ accountId: account.accountId, host, port, path }, 'Feishu webhook server listening');\n\n await new Promise<void>((resolve) => {\n if (abortSignal.aborted) {\n server.close();\n return resolve();\n }\n abortSignal.addEventListener(\n 'abort',\n () => {\n server.close();\n resolve();\n },\n { once: true },\n );\n });\n }\n\n return { run };\n}\n\nfunction safeJsonText(raw: unknown): string | undefined {\n if (typeof raw !== 'string' || !raw.trim()) return undefined;\n try {\n const parsed = JSON.parse(raw);\n const t =\n typeof parsed?.text === 'string'\n ? parsed.text\n : typeof parsed?.content === 'string'\n ? parsed.content\n : typeof parsed?.title === 'string'\n ? parsed.title\n : undefined;\n return typeof t === 'string' ? t : raw;\n } catch {\n return raw;\n }\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"monitor.js","names":["http"],"sources":["../../../../../../extensions/feishu/src/transport/webhook/monitor.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport * as http from 'node:http';\n\nimport type { InboundMessage } from '@xopcai/xopc/channels/transport-types.js';\nimport * as lark from '@larksuiteoapi/node-sdk';\n\nimport type { Config } from '@xopcai/xopc/config/schema.js';\nimport type { ChannelSecurityContext } from '@xopcai/xopc/channels/plugin-types.js';\nimport { generateSessionKey } from '@xopcai/xopc/chat-commands/session-key.js';\nimport { createLogger } from '@xopcai/xopc/utils/logger.js';\n\nimport type { ResolvedFeishuAccount } from '../../state/accounts.js';\nimport { createFeishuDedupe } from '../reliability/dedupe.js';\nimport type { FeishuInboundWork } from '../reliability/inbound-pipeline.js';\nimport { stripFeishuMentions } from '../text/mentions.js';\nimport { recordFeishuMessageBinding } from '../../state/message-bindings.js';\nimport { sendFeishuPairingPromptIfNeeded } from '../../pairing/feishu-pairing-prompt.js';\nimport { createFeishuLarkSdkPinoLogger } from '../client/lark-sdk-logger.js';\n\nconst log = createLogger('FeishuWebhook');\n\nconst MAX_BODY_BYTES = 256 * 1024;\nconst BODY_TIMEOUT_MS = 2_000;\nconst RATE_LIMIT_WINDOW_MS = 60_000;\nconst RATE_LIMIT_MAX = 120;\nconst RATE_LIMIT_MAX_KEYS = 4096;\n\ntype RateKeyState = { windowStart: number; count: number };\nconst rateState = new Map<string, RateKeyState>();\n\nfunction pruneRateState(now: number) {\n for (const [k, v] of rateState.entries()) {\n if (now - v.windowStart > RATE_LIMIT_WINDOW_MS) {\n rateState.delete(k);\n }\n }\n if (rateState.size <= RATE_LIMIT_MAX_KEYS) return;\n const over = rateState.size - RATE_LIMIT_MAX_KEYS;\n let i = 0;\n for (const k of rateState.keys()) {\n rateState.delete(k);\n i++;\n if (i >= over) break;\n }\n}\n\nfunction isRateLimited(key: string, now: number): boolean {\n pruneRateState(now);\n const cur = rateState.get(key);\n if (!cur || now - cur.windowStart > RATE_LIMIT_WINDOW_MS) {\n rateState.set(key, { windowStart: now, count: 1 });\n return false;\n }\n cur.count += 1;\n return cur.count > RATE_LIMIT_MAX;\n}\n\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n try {\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\n } catch {\n return false;\n }\n}\n\nfunction signatureValid(headers: http.IncomingHttpHeaders, rawBody: string, encryptKey: string): boolean {\n const timestampHeader = headers['x-lark-request-timestamp'];\n const nonceHeader = headers['x-lark-request-nonce'];\n const signatureHeader = headers['x-lark-signature'];\n const timestamp = Array.isArray(timestampHeader) ? timestampHeader[0] : timestampHeader;\n const nonce = Array.isArray(nonceHeader) ? nonceHeader[0] : nonceHeader;\n const signature = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;\n if (!timestamp || !nonce || !signature) return false;\n if (typeof signature !== 'string' || signature.length < 32) return false;\n const computed = crypto.createHash('sha256').update(timestamp + nonce + encryptKey + rawBody).digest('hex');\n return safeEqual(computed, signature);\n}\n\nfunction readBody(\n req: http.IncomingMessage,\n): Promise<{ ok: true; body: string } | { ok: false; status: number; msg: string }> {\n return new Promise((resolve) => {\n let done = false;\n let bytes = 0;\n const chunks: Buffer[] = [];\n const t = setTimeout(() => {\n if (done) return;\n done = true;\n resolve({ ok: false, status: 408, msg: 'Request body timeout' });\n req.destroy();\n }, BODY_TIMEOUT_MS);\n\n req.on('data', (chunk: Buffer) => {\n if (done) return;\n bytes += chunk.length;\n if (bytes > MAX_BODY_BYTES) {\n done = true;\n clearTimeout(t);\n resolve({ ok: false, status: 413, msg: 'Payload too large' });\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n if (done) return;\n done = true;\n clearTimeout(t);\n resolve({ ok: true, body: Buffer.concat(chunks).toString('utf8') });\n });\n req.on('error', () => {\n if (done) return;\n done = true;\n clearTimeout(t);\n resolve({ ok: false, status: 400, msg: 'Bad Request' });\n });\n });\n}\n\nfunction json(res: http.ServerResponse, status: number, obj: unknown) {\n res.statusCode = status;\n res.setHeader('content-type', 'application/json; charset=utf-8');\n res.end(JSON.stringify(obj));\n}\n\nfunction text(res: http.ServerResponse, status: number, body: string) {\n res.statusCode = status;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n res.end(body);\n}\n\nexport interface FeishuWebhookMonitorDeps {\n account: ResolvedFeishuAccount;\n config: Config;\n enqueueInbound: (work: FeishuInboundWork) => Promise<void>;\n inboundDebounceDefaultMs: number;\n abortSignal: AbortSignal;\n security: {\n checkAccess: (ctx: ChannelSecurityContext) => { allowed: boolean; reason?: string } | undefined;\n };\n}\n\nexport function createFeishuWebhookMonitor(deps: FeishuWebhookMonitorDeps) {\n const { account, abortSignal, security, enqueueInbound, inboundDebounceDefaultMs } = deps;\n const dedupe = createFeishuDedupe();\n\n const encryptKey = (account.encryptKey ?? '').trim();\n const verificationToken = (account.verificationToken ?? '').trim();\n if (!encryptKey) throw new Error('Feishu webhook mode requires encryptKey');\n if (!verificationToken) throw new Error('Feishu webhook mode requires verificationToken');\n\n const host = (account.webhookHost ?? '127.0.0.1').trim() || '127.0.0.1';\n const port = account.webhookPort ?? 3000;\n const path = (account.webhookPath ?? '/feishu/events').trim() || '/feishu/events';\n const l = lark as any;\n const sdkLogger = createFeishuLarkSdkPinoLogger(account.accountId);\n\n function resolveTextDebounceMs(): number {\n if (typeof account.inboundDebounceMs === 'number' && Number.isFinite(account.inboundDebounceMs)) {\n return Math.max(0, Math.trunc(account.inboundDebounceMs));\n }\n return Math.max(0, Math.trunc(inboundDebounceDefaultMs));\n }\n\n async function pushText(inbound: InboundMessage): Promise<void> {\n const debounceMs = resolveTextDebounceMs();\n await enqueueInbound({\n kind: 'text',\n accountId: account.accountId,\n chatId: inbound.chat_id,\n debounceMs,\n inbound,\n });\n }\n\n async function handleMessageReceive(event: any): Promise<void> {\n const msg = event?.event?.message ?? event?.message ?? event?.data?.message;\n const sender = event?.event?.sender ?? event?.sender ?? event?.data?.sender;\n const chatId = msg?.chat_id ?? msg?.chatId ?? '';\n const messageId = msg?.message_id ?? msg?.messageId ?? '';\n const chatType = msg?.chat_type ?? msg?.chatType ?? '';\n\n const senderId =\n sender?.sender_id?.open_id ??\n sender?.sender_id?.user_id ??\n sender?.open_id ??\n sender?.user_id ??\n '';\n const senderName = sender?.sender_id?.name ?? sender?.sender_name ?? undefined;\n\n if (!chatId || !messageId || !senderId) return;\n if (!dedupe.claim(messageId)) return;\n\n const isGroup = chatType === 'group' || chatType === 'chat';\n const textRaw =\n msg?.content && typeof msg.content === 'string'\n ? safeJsonText(msg.content)\n : safeJsonText(msg?.body?.content);\n const normalizedText = stripFeishuMentions(textRaw ?? '').trim();\n if (!normalizedText) return;\n\n const threadId = msg?.thread_id ?? msg?.threadId ?? undefined;\n const sessionKey = generateSessionKey({\n source: 'feishu',\n chatId,\n senderId,\n isGroup,\n threadId: typeof threadId === 'string' && threadId.trim() ? threadId : undefined,\n accountId: account.accountId,\n });\n\n recordFeishuMessageBinding({\n messageId,\n sessionKey,\n accountId: account.accountId,\n chatId,\n senderId,\n isGroup,\n threadId: typeof threadId === 'string' && threadId.trim() ? threadId : undefined,\n });\n\n const access = security.checkAccess({\n accountId: account.accountId,\n chatId,\n senderId,\n senderName,\n isGroup,\n threadId,\n });\n if (access && !access.allowed) {\n if (!isGroup && access.reason === 'pairing-required') {\n await sendFeishuPairingPromptIfNeeded({\n account,\n messageId,\n threadId: typeof threadId === 'string' && threadId.trim() ? threadId : undefined,\n senderId,\n senderName,\n isGroup,\n });\n }\n return;\n }\n\n await pushText({\n channel: 'feishu',\n sender_id: senderId,\n chat_id: chatId,\n content: normalizedText,\n metadata: {\n sessionKey,\n accountId: account.accountId,\n messageId,\n threadId,\n isGroup,\n feishuEventType: 'im.message.receive_v1',\n raw: event,\n },\n });\n }\n\n const dispatcher = new l.EventDispatcher({\n verifyChallenge: false,\n encryptKey,\n verificationToken,\n logger: sdkLogger,\n loggerLevel: l.LoggerLevel.info,\n } as any);\n dispatcher.register({\n 'im.message.receive_v1': async (data: any) => await handleMessageReceive(data),\n });\n\n const server = http.createServer();\n\n async function handleRequest(req: http.IncomingMessage, res: http.ServerResponse) {\n if (req.method !== 'POST') return text(res, 405, 'Method Not Allowed');\n if ((req.url ?? '').split('?')[0] !== path) return text(res, 404, 'Not Found');\n\n const now = Date.now();\n const rateKey = `${account.accountId}:${path}:${req.socket.remoteAddress ?? 'unknown'}`;\n if (isRateLimited(rateKey, now)) return text(res, 429, 'Too Many Requests');\n\n const contentType = String(req.headers['content-type'] ?? '');\n if (!contentType.toLowerCase().includes('application/json')) return text(res, 415, 'Unsupported Media Type');\n\n const body = await readBody(req);\n if (body.ok === false) return text(res, body.status, body.msg);\n\n if (!signatureValid(req.headers, body.body, encryptKey)) return text(res, 401, 'Invalid signature');\n\n let payload: any;\n try {\n payload = JSON.parse(body.body);\n } catch {\n return text(res, 400, 'Invalid JSON');\n }\n\n const token = payload?.token ?? payload?.header?.token ?? payload?.event?.token;\n if (typeof token === 'string' && token.trim() && token.trim() !== verificationToken) {\n return text(res, 401, 'Invalid verification token');\n }\n\n const { isChallenge, challenge } = lark.generateChallenge(payload, { encryptKey });\n if (isChallenge) return json(res, 200, challenge);\n\n const envelope = Object.assign(Object.create({ headers: req.headers }), payload);\n const out = await dispatcher.invoke(envelope, { needCheck: false });\n if (!res.headersSent) return json(res, 200, out);\n }\n\n async function run(): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n server.on('request', (req, res) => {\n void handleRequest(req, res).catch((err) => {\n log.error({ err, accountId: account.accountId }, 'Feishu webhook handler error');\n if (!res.headersSent) text(res, 500, 'Internal Server Error');\n });\n });\n server.on('error', (err) => reject(err));\n server.listen(port, host, () => resolve());\n });\n\n log.info({ accountId: account.accountId, host, port, path }, 'Feishu webhook server listening');\n\n await new Promise<void>((resolve) => {\n if (abortSignal.aborted) {\n server.close();\n return resolve();\n }\n abortSignal.addEventListener(\n 'abort',\n () => {\n server.close();\n resolve();\n },\n { once: true },\n );\n });\n }\n\n return { run };\n}\n\nfunction safeJsonText(raw: unknown): string | undefined {\n if (typeof raw !== 'string' || !raw.trim()) return undefined;\n try {\n const parsed = JSON.parse(raw);\n const t =\n typeof parsed?.text === 'string'\n ? parsed.text\n : typeof parsed?.content === 'string'\n ? parsed.content\n : typeof parsed?.title === 'string'\n ? parsed.title\n : undefined;\n return typeof t === 'string' ? t : raw;\n } catch {\n return raw;\n }\n}\n\n"],"mappings":"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"}
|
|
@@ -6,6 +6,72 @@
|
|
|
6
6
|
"kind": "tool",
|
|
7
7
|
"main": "src/index.ts",
|
|
8
8
|
"channels": ["feishu", "lark"],
|
|
9
|
+
"channelContributions": {
|
|
10
|
+
"feishu": {
|
|
11
|
+
"label": "Feishu",
|
|
12
|
+
"description": "Feishu/Lark messaging and workspace tools",
|
|
13
|
+
"docsPath": "/channels/feishu",
|
|
14
|
+
"order": 30,
|
|
15
|
+
"configPath": "channels.feishu",
|
|
16
|
+
"capabilities": {
|
|
17
|
+
"login": true,
|
|
18
|
+
"pairing": true,
|
|
19
|
+
"doctor": true,
|
|
20
|
+
"multiAccount": true,
|
|
21
|
+
"streaming": true,
|
|
22
|
+
"media": true
|
|
23
|
+
},
|
|
24
|
+
"configSchema": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"additionalProperties": true,
|
|
27
|
+
"properties": {
|
|
28
|
+
"enabled": { "type": "boolean", "default": false, "title": "Enabled" },
|
|
29
|
+
"accounts": { "type": "object", "additionalProperties": true, "title": "Accounts" },
|
|
30
|
+
"appId": { "type": "string", "title": "App ID" },
|
|
31
|
+
"appSecret": { "type": "string", "format": "password", "title": "App secret" },
|
|
32
|
+
"domain": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": ["feishu", "lark"],
|
|
35
|
+
"default": "feishu",
|
|
36
|
+
"title": "Domain"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"uiHints": {
|
|
41
|
+
"appSecret": { "sensitive": true },
|
|
42
|
+
"accounts.*.appSecret": { "sensitive": true },
|
|
43
|
+
"verificationToken": { "sensitive": true },
|
|
44
|
+
"encryptKey": { "sensitive": true }
|
|
45
|
+
},
|
|
46
|
+
"actions": {
|
|
47
|
+
"setup.start": { "label": "Set up by QR", "result": "qr" },
|
|
48
|
+
"setup.status": { "label": "Setup status", "result": "poll" },
|
|
49
|
+
"setup.manual": { "label": "Manual setup", "result": "form" },
|
|
50
|
+
"doctor.run": { "label": "Run doctor", "result": "diagnostics" }
|
|
51
|
+
},
|
|
52
|
+
"i18n": {
|
|
53
|
+
"zh": {
|
|
54
|
+
"label": "飞书 / Lark",
|
|
55
|
+
"description": "飞书 / Lark 消息通道与工作区工具",
|
|
56
|
+
"configSchema": {
|
|
57
|
+
"properties": {
|
|
58
|
+
"enabled": { "title": "启用" },
|
|
59
|
+
"accounts": { "title": "账号" },
|
|
60
|
+
"appId": { "title": "App ID" },
|
|
61
|
+
"appSecret": { "title": "App Secret" },
|
|
62
|
+
"domain": { "title": "域名" }
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"actions": {
|
|
66
|
+
"setup.start": { "label": "扫码配置" },
|
|
67
|
+
"setup.status": { "label": "配置状态" },
|
|
68
|
+
"setup.manual": { "label": "手动配置" },
|
|
69
|
+
"doctor.run": { "label": "诊断" }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
9
75
|
"activation": {
|
|
10
76
|
"onChannels": ["feishu", "lark"],
|
|
11
77
|
"onCapabilities": ["tool"]
|
|
@@ -15,4 +81,3 @@
|
|
|
15
81
|
"requiresRuntime": true
|
|
16
82
|
}
|
|
17
83
|
}
|
|
18
|
-
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { init_loader, loadConfig, saveConfig } from "../../../../src/config/loader.js";
|
|
2
|
+
//#region extensions/telegram/src/adapters/gateway-setup.ts
|
|
3
|
+
init_loader();
|
|
4
|
+
function isZh(locale) {
|
|
5
|
+
return locale?.toLowerCase().startsWith("zh") === true;
|
|
6
|
+
}
|
|
7
|
+
function readInput(input) {
|
|
8
|
+
return input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
9
|
+
}
|
|
10
|
+
function pickString(input) {
|
|
11
|
+
return typeof input === "string" ? input.trim() : "";
|
|
12
|
+
}
|
|
13
|
+
function pickDmPolicy(input) {
|
|
14
|
+
return input === "pairing" || input === "allowlist" || input === "disabled" ? input : "open";
|
|
15
|
+
}
|
|
16
|
+
function existingDefaultAccount(config) {
|
|
17
|
+
const account = ((config.channels?.telegram)?.accounts)?.default;
|
|
18
|
+
return account && typeof account === "object" && !Array.isArray(account) ? account : {};
|
|
19
|
+
}
|
|
20
|
+
function buildTelegramConfig(config, input) {
|
|
21
|
+
const existing = config.channels?.telegram ?? {};
|
|
22
|
+
const existingAccounts = existing.accounts ?? {};
|
|
23
|
+
const previousDefault = existingDefaultAccount(config);
|
|
24
|
+
const botToken = pickString(input.botToken) || pickString(previousDefault.botToken);
|
|
25
|
+
const apiRoot = pickString(input.apiRoot);
|
|
26
|
+
const proxy = pickString(input.proxy);
|
|
27
|
+
const dmPolicy = pickDmPolicy(input.dmPolicy ?? previousDefault.dmPolicy ?? existing.dmPolicy);
|
|
28
|
+
const defaultAccount = {
|
|
29
|
+
...previousDefault,
|
|
30
|
+
accountId: "default",
|
|
31
|
+
enabled: true,
|
|
32
|
+
botToken,
|
|
33
|
+
dmPolicy,
|
|
34
|
+
allowFrom: dmPolicy === "open" ? ["*"] : previousDefault.allowFrom ?? [],
|
|
35
|
+
groupPolicy: previousDefault.groupPolicy ?? existing.groupPolicy ?? "open",
|
|
36
|
+
replyToMode: previousDefault.replyToMode ?? existing.replyToMode ?? "off",
|
|
37
|
+
historyLimit: previousDefault.historyLimit ?? existing.historyLimit ?? 50,
|
|
38
|
+
textChunkLimit: previousDefault.textChunkLimit ?? existing.textChunkLimit ?? 4e3,
|
|
39
|
+
streaming: previousDefault.streaming ?? existing.streaming ?? { mode: "partial" }
|
|
40
|
+
};
|
|
41
|
+
if (apiRoot) defaultAccount.apiRoot = apiRoot;
|
|
42
|
+
if (proxy) defaultAccount.proxy = proxy;
|
|
43
|
+
const topAllowFrom = dmPolicy === "open" ? ["*"] : existing.allowFrom ?? [];
|
|
44
|
+
return {
|
|
45
|
+
...config,
|
|
46
|
+
channels: {
|
|
47
|
+
...config.channels,
|
|
48
|
+
telegram: {
|
|
49
|
+
...existing,
|
|
50
|
+
enabled: true,
|
|
51
|
+
dmPolicy,
|
|
52
|
+
allowFrom: topAllowFrom,
|
|
53
|
+
groupPolicy: existing.groupPolicy ?? "open",
|
|
54
|
+
replyToMode: existing.replyToMode ?? "off",
|
|
55
|
+
streaming: existing.streaming ?? { mode: "partial" },
|
|
56
|
+
historyLimit: existing.historyLimit ?? 50,
|
|
57
|
+
textChunkLimit: existing.textChunkLimit ?? 4e3,
|
|
58
|
+
...apiRoot ? { apiRoot } : {},
|
|
59
|
+
...proxy ? { proxy } : {},
|
|
60
|
+
accounts: {
|
|
61
|
+
...existingAccounts,
|
|
62
|
+
default: defaultAccount
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function formPayload(config, locale) {
|
|
69
|
+
const zh = isZh(locale);
|
|
70
|
+
const telegram = config.channels?.telegram ?? {};
|
|
71
|
+
const account = existingDefaultAccount(config);
|
|
72
|
+
return {
|
|
73
|
+
type: "form",
|
|
74
|
+
submitAction: "setup.save",
|
|
75
|
+
message: zh ? "填写 Bot Token 后保存即可启用 Telegram 私聊。群聊、多个账号、allowlist 等放在高级配置。" : "Enter a Bot Token and save. Private chat works by default; groups, multi-account, and allowlists live in Advanced configuration.",
|
|
76
|
+
schema: {
|
|
77
|
+
type: "object",
|
|
78
|
+
properties: {
|
|
79
|
+
botToken: {
|
|
80
|
+
type: "string",
|
|
81
|
+
title: zh ? "Bot Token" : "Bot Token",
|
|
82
|
+
format: "password"
|
|
83
|
+
},
|
|
84
|
+
dmPolicy: {
|
|
85
|
+
type: "string",
|
|
86
|
+
title: zh ? "私聊访问" : "Private chat access",
|
|
87
|
+
enum: [
|
|
88
|
+
"open",
|
|
89
|
+
"pairing",
|
|
90
|
+
"allowlist",
|
|
91
|
+
"disabled"
|
|
92
|
+
],
|
|
93
|
+
default: "open"
|
|
94
|
+
},
|
|
95
|
+
apiRoot: {
|
|
96
|
+
type: "string",
|
|
97
|
+
title: zh ? "API Root(可选)" : "API root (optional)",
|
|
98
|
+
placeholder: "https://api.telegram.org"
|
|
99
|
+
},
|
|
100
|
+
proxy: {
|
|
101
|
+
type: "string",
|
|
102
|
+
title: zh ? "代理(可选)" : "Proxy (optional)",
|
|
103
|
+
placeholder: "http://127.0.0.1:7897"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
required: ["botToken"]
|
|
107
|
+
},
|
|
108
|
+
values: {
|
|
109
|
+
botToken: pickString(account.botToken),
|
|
110
|
+
dmPolicy: pickDmPolicy(account.dmPolicy ?? telegram.dmPolicy ?? "open"),
|
|
111
|
+
apiRoot: pickString(account.apiRoot ?? telegram.apiRoot),
|
|
112
|
+
proxy: pickString(account.proxy ?? telegram.proxy)
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const telegramGatewaySetupActions = { async runAction({ actionId, input, locale }) {
|
|
117
|
+
const zh = isZh(locale);
|
|
118
|
+
if (actionId === "setup.start") return {
|
|
119
|
+
ok: true,
|
|
120
|
+
payload: formPayload(loadConfig(), locale)
|
|
121
|
+
};
|
|
122
|
+
if (actionId === "setup.save") {
|
|
123
|
+
const raw = readInput(input);
|
|
124
|
+
if (!pickString(raw.botToken)) return {
|
|
125
|
+
ok: false,
|
|
126
|
+
message: zh ? "Bot Token 为必填项。" : "Bot Token is required."
|
|
127
|
+
};
|
|
128
|
+
await saveConfig(buildTelegramConfig(loadConfig(), raw));
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
payload: {
|
|
132
|
+
type: "ok",
|
|
133
|
+
message: zh ? "Telegram 配置已保存。私聊现在默认可用。" : "Telegram configuration saved. Private chat is enabled by default.",
|
|
134
|
+
configChanged: true
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
message: `${zh ? "不支持的 Telegram 操作" : "Unsupported Telegram action"}: ${actionId}`
|
|
141
|
+
};
|
|
142
|
+
} };
|
|
143
|
+
//#endregion
|
|
144
|
+
export { telegramGatewaySetupActions };
|
|
145
|
+
|
|
146
|
+
//# sourceMappingURL=gateway-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-setup.js","names":[],"sources":["../../../../../extensions/telegram/src/adapters/gateway-setup.ts"],"sourcesContent":["import { loadConfig, saveConfig } from '@xopcai/xopc/config/loader.js';\nimport type { Config } from '@xopcai/xopc/config/schema.js';\nimport type { ChannelRuntimeActionAdapter } from '@xopcai/xopc/channels/plugins/types.adapters.js';\n\nfunction isZh(locale: string | undefined): boolean {\n return locale?.toLowerCase().startsWith('zh') === true;\n}\n\nfunction readInput(input: unknown): Record<string, unknown> {\n return input && typeof input === 'object' && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : {};\n}\n\nfunction pickString(input: unknown): string {\n return typeof input === 'string' ? input.trim() : '';\n}\n\nfunction pickDmPolicy(input: unknown): 'open' | 'pairing' | 'allowlist' | 'disabled' {\n return input === 'pairing' || input === 'allowlist' || input === 'disabled' ? input : 'open';\n}\n\nfunction existingDefaultAccount(config: Config): Record<string, unknown> {\n const telegram = config.channels?.telegram as Record<string, unknown> | undefined;\n const accounts = telegram?.accounts as Record<string, unknown> | undefined;\n const account = accounts?.default;\n return account && typeof account === 'object' && !Array.isArray(account)\n ? (account as Record<string, unknown>)\n : {};\n}\n\nfunction buildTelegramConfig(config: Config, input: Record<string, unknown>): Config {\n const existing = (config.channels?.telegram as Record<string, unknown> | undefined) ?? {};\n const existingAccounts = (existing.accounts as Record<string, unknown> | undefined) ?? {};\n const previousDefault = existingDefaultAccount(config);\n\n const botToken = pickString(input.botToken) || pickString(previousDefault.botToken);\n const apiRoot = pickString(input.apiRoot);\n const proxy = pickString(input.proxy);\n const dmPolicy = pickDmPolicy(input.dmPolicy ?? previousDefault.dmPolicy ?? existing.dmPolicy);\n\n const defaultAccount: Record<string, unknown> = {\n ...previousDefault,\n accountId: 'default',\n enabled: true,\n botToken,\n dmPolicy,\n allowFrom: dmPolicy === 'open' ? ['*'] : (previousDefault.allowFrom ?? []),\n groupPolicy: previousDefault.groupPolicy ?? existing.groupPolicy ?? 'open',\n replyToMode: previousDefault.replyToMode ?? existing.replyToMode ?? 'off',\n historyLimit: previousDefault.historyLimit ?? existing.historyLimit ?? 50,\n textChunkLimit: previousDefault.textChunkLimit ?? existing.textChunkLimit ?? 4000,\n streaming: previousDefault.streaming ?? existing.streaming ?? { mode: 'partial' },\n };\n\n if (apiRoot) defaultAccount.apiRoot = apiRoot;\n if (proxy) defaultAccount.proxy = proxy;\n\n const topAllowFrom = dmPolicy === 'open' ? ['*'] : (existing.allowFrom ?? []);\n\n return {\n ...config,\n channels: {\n ...config.channels,\n telegram: {\n ...existing,\n enabled: true,\n dmPolicy,\n allowFrom: topAllowFrom,\n groupPolicy: existing.groupPolicy ?? 'open',\n replyToMode: existing.replyToMode ?? 'off',\n streaming: existing.streaming ?? { mode: 'partial' },\n historyLimit: existing.historyLimit ?? 50,\n textChunkLimit: existing.textChunkLimit ?? 4000,\n ...(apiRoot ? { apiRoot } : {}),\n ...(proxy ? { proxy } : {}),\n accounts: {\n ...existingAccounts,\n default: defaultAccount,\n },\n },\n },\n };\n}\n\nfunction formPayload(config: Config, locale?: string) {\n const zh = isZh(locale);\n const telegram = (config.channels?.telegram as Record<string, unknown> | undefined) ?? {};\n const account = existingDefaultAccount(config);\n return {\n type: 'form' as const,\n submitAction: 'setup.save',\n message: zh\n ? '填写 Bot Token 后保存即可启用 Telegram 私聊。群聊、多个账号、allowlist 等放在高级配置。'\n : 'Enter a Bot Token and save. Private chat works by default; groups, multi-account, and allowlists live in Advanced configuration.',\n schema: {\n type: 'object',\n properties: {\n botToken: { type: 'string', title: zh ? 'Bot Token' : 'Bot Token', format: 'password' },\n dmPolicy: {\n type: 'string',\n title: zh ? '私聊访问' : 'Private chat access',\n enum: ['open', 'pairing', 'allowlist', 'disabled'],\n default: 'open',\n },\n apiRoot: {\n type: 'string',\n title: zh ? 'API Root(可选)' : 'API root (optional)',\n placeholder: 'https://api.telegram.org',\n },\n proxy: {\n type: 'string',\n title: zh ? '代理(可选)' : 'Proxy (optional)',\n placeholder: 'http://127.0.0.1:7897',\n },\n },\n required: ['botToken'],\n },\n values: {\n botToken: pickString(account.botToken),\n dmPolicy: pickDmPolicy(account.dmPolicy ?? telegram.dmPolicy ?? 'open'),\n apiRoot: pickString(account.apiRoot ?? telegram.apiRoot),\n proxy: pickString(account.proxy ?? telegram.proxy),\n },\n };\n}\n\nexport const telegramGatewaySetupActions: ChannelRuntimeActionAdapter = {\n async runAction({ actionId, input, locale }) {\n const zh = isZh(locale);\n if (actionId === 'setup.start') {\n return { ok: true, payload: formPayload(loadConfig(), locale) };\n }\n\n if (actionId === 'setup.save') {\n const raw = readInput(input);\n const botToken = pickString(raw.botToken);\n if (!botToken) {\n return { ok: false, message: zh ? 'Bot Token 为必填项。' : 'Bot Token is required.' };\n }\n await saveConfig(buildTelegramConfig(loadConfig(), raw));\n return {\n ok: true,\n payload: {\n type: 'ok',\n message: zh ? 'Telegram 配置已保存。私聊现在默认可用。' : 'Telegram configuration saved. Private chat is enabled by default.',\n configChanged: true,\n },\n };\n }\n\n return { ok: false, message: `${zh ? '不支持的 Telegram 操作' : 'Unsupported Telegram action'}: ${actionId}` };\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { evaluateAccess, resolveDmPolicy, resolveGroupPolicy } from "../../../../src/channels/security.js";
|
|
1
2
|
import { resolveStandardAllowFromPath } from "../../../../src/channels/pairing/paths.js";
|
|
2
3
|
import { readAllowFromIdsSync } from "../../../../src/channels/pairing/allow-from-file.js";
|
|
3
|
-
import { evaluateAccess, resolveDmPolicy, resolveGroupPolicy } from "../../../../src/channels/security.js";
|
|
4
4
|
//#region extensions/telegram/src/adapters/security-adapter.ts
|
|
5
5
|
function createTelegramSecurityAdapter() {
|
|
6
6
|
return {
|
|
@@ -97,8 +97,7 @@ function createTelegramCommandHandler(deps) {
|
|
|
97
97
|
const handleProviderSelect = async (ctx, providerId) => {
|
|
98
98
|
try {
|
|
99
99
|
const sessionKey = getSessionKeyFromCtx(ctx);
|
|
100
|
-
const
|
|
101
|
-
const defaultModel = typeof modelConfig === "string" ? modelConfig : modelConfig?.primary || getDefaultModelSync(config);
|
|
100
|
+
const defaultModel = (config.agents?.defaults?.models?.chat)?.primary || getDefaultModelSync(config);
|
|
102
101
|
const currentModel = getSessionModel(sessionKey) || defaultModel;
|
|
103
102
|
const models = getModelsForProvider(providerId);
|
|
104
103
|
if (models.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.js","names":[],"sources":["../../../../extensions/telegram/src/command-handler.ts"],"sourcesContent":["/**\n * Telegram Command Handler\n * \n * Handles Telegram-specific UI interactions (inline keyboards, callbacks).\n * Core commands (/new, /usage, /models, etc.) are handled by the unified command system.\n */\n\nimport type { Context } from 'grammy';\n\nimport type { TelegramAccountManager } from './account-manager.js';\nimport { createLogger } from '@xopcai/xopc/utils/logger.js';\nimport type { Config } from '@xopcai/xopc/config/index.js';\nimport { isProviderConfiguredSync } from '@xopcai/xopc/providers/index.js';\nimport { TelegramInlineKeyboards, type ProviderInfo } from './inline-keyboards.js';\nimport { getProviderDisplayName, getModelsByProvider, getDefaultModelSync, getAllProviders } from '@xopcai/xopc/providers/index.js';\nimport { generateSessionKey } from '@xopcai/xopc/chat-commands/session-key.js';\n\nconst log = createLogger('TelegramCommandHandler');\n\nexport interface TelegramCommandHandlerDeps {\n bus: any;\n config: Config;\n accountManager: TelegramAccountManager;\n getSessionModel: (sessionKey: string) => string | undefined;\n setSessionModel: (sessionKey: string, modelId: string) => void | Promise<void>;\n // Optional callbacks for inline keyboard handling\n showProviderModels?: (ctx: Context, providerId: string) => Promise<void>;\n showProvidersAgain?: (ctx: Context) => Promise<void>;\n handleCleanupConfirm?: (ctx: Context) => Promise<void>;\n}\n\nexport function createTelegramCommandHandler(deps: TelegramCommandHandlerDeps) {\n const { config, accountManager, getSessionModel, setSessionModel, bus } = deps;\n\n // ========== Helper Functions ==========\n\n const getAvailableProviders = (): ProviderInfo[] => {\n const allProviders = getAllProviders();\n const available: ProviderInfo[] = [];\n\n for (const providerId of allProviders) {\n if (isProviderConfiguredSync(providerId)) {\n available.push({ id: providerId, name: getProviderDisplayName(providerId) });\n }\n }\n\n if (available.length === 0) {\n available.push({ id: 'minimax', name: 'MiniMax' });\n }\n\n return available;\n };\n\n const getModelsForProvider = (providerId: string) => {\n const models = getModelsByProvider(providerId);\n \n if (models.length === 0) {\n return [{ id: `${providerId}/default`, name: 'default', provider: providerId }];\n }\n \n return models.map(m => ({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: m.provider,\n }));\n };\n\n // ========== Helper Functions ==========\n\n // Helper to get sessionKey from Telegram context\n const getSessionKeyFromCtx = (ctx: Context): string => {\n const chatId = String(ctx.chat?.id);\n const senderId = String(ctx.from?.id);\n const isGroup = ctx.chat?.type === 'group' || ctx.chat?.type === 'supergroup';\n const threadId =\n (ctx.message as { message_thread_id?: number })?.message_thread_id ??\n (ctx.callbackQuery?.message as { message_thread_id?: number } | undefined)?.message_thread_id;\n\n const accountId = accountManager.resolveAccountIdFromContext(ctx);\n\n return generateSessionKey({\n source: 'telegram',\n chatId,\n senderId,\n isGroup,\n threadId: threadId ? String(threadId) : undefined,\n accountId,\n });\n };\n\n // ========== Command Handlers ==========\n\n /**\n * /start - Show welcome message\n * Note: Other commands (/new, /usage, /models, etc.) are handled by the unified command system\n */\n const handleStart = async (ctx: Context): Promise<void> => {\n try {\n const providers = getAvailableProviders();\n const hasProviders = providers.length > 0;\n\n await ctx.reply(\n '👋 *Welcome to xopc!*\\n\\n' +\n 'I am your AI assistant. Here are the available commands:\\n\\n' +\n '🤖 *Model Selection*\\n' +\n '/models - List models (name + `provider/model` ref for /switch)\\n' +\n '/switch \\u003cprovider/model-id\\u003e - Same ref as shown in /models\\n\\n' +\n '📊 *Session Management*\\n' +\n '/new - Start a new session (archive current)\\n' +\n '/list - List all your sessions\\n' +\n '/usage - View token usage statistics\\n' +\n '/cleanup - Clean up old sessions\\n\\n' +\n '🔊 *Voice (TTS)*\\n' +\n '/tts - Show TTS settings\\n' +\n '/tts on|off - Enable/disable TTS\\n' +\n '/tts always|inbound|tagged|never - Set trigger mode\\n\\n' +\n '🛠️ *Skills*\\n' +\n '/skills reload - Reload all skills from disk\\n\\n' +\n '💡 *Tip*: Just send a message to start chatting!' +\n (hasProviders ? '' : '\\n\\n⚠️ *Note*: No LLM providers configured. Please set up API keys in your config.'),\n { parse_mode: 'Markdown' }\n );\n } catch (err) {\n log.error({ err }, 'Failed to handle start command');\n await ctx.reply('❌ Failed to show welcome message.');\n }\n };\n\n /**\n * /models - Show model selector with inline keyboard\n * Note: This provides a UI enhancement over the basic /models command\n */\n const handleModels = async (ctx: Context): Promise<void> => {\n try {\n const providers = getAvailableProviders();\n\n if (providers.length === 0) {\n await ctx.reply('❌ No providers available. Please check your configuration.');\n return;\n }\n\n await ctx.reply('🤖 Select a provider:', {\n reply_markup: TelegramInlineKeyboards.providerSelector(providers),\n });\n } catch (err) {\n log.error({ err }, 'Failed to show provider selector');\n await ctx.reply('❌ Failed to load providers. Please try again.');\n }\n };\n\n /**\n * /cleanup - Show cleanup confirmation dialog\n */\n const handleCleanup = async (ctx: Context): Promise<void> => {\n try {\n await ctx.reply(\n '🧹 *Session Cleanup*\\n\\n' +\n 'This will archive sessions that have been inactive for more than 30 days.\\n\\n' +\n 'Archived sessions can be restored later.',\n { parse_mode: 'Markdown', reply_markup: TelegramInlineKeyboards.cleanupConfirm() }\n );\n } catch (err) {\n log.error({ err }, 'Failed to show cleanup dialog');\n await ctx.reply('❌ Failed to initiate cleanup.');\n }\n };\n\n // ========== Callback Handlers (Inline Keyboard) ==========\n\n const handleProviderSelect = async (ctx: Context, providerId: string): Promise<void> => {\n try {\n const sessionKey = getSessionKeyFromCtx(ctx);\n const modelConfig = config.agents?.defaults?.model;\n const defaultModel = typeof modelConfig === 'string' ? modelConfig : modelConfig?.primary || getDefaultModelSync(config);\n const currentModel = getSessionModel(sessionKey) || defaultModel;\n\n const models = getModelsForProvider(providerId);\n \n if (models.length === 0) {\n await ctx.editMessageText('❌ No models available for this provider.');\n await ctx.answerCallbackQuery();\n return;\n }\n\n const keyboard = TelegramInlineKeyboards.modelSelector(models, currentModel);\n const providerName = getProviderDisplayName(providerId);\n \n await ctx.editMessageText(`🤖 Select a model from *${providerName}*:`, { \n reply_markup: keyboard,\n parse_mode: 'Markdown',\n });\n await ctx.answerCallbackQuery();\n } catch (err) {\n log.error({ err, providerId }, 'Failed to show provider models');\n await ctx.answerCallbackQuery('Failed to load models');\n }\n };\n\n const handleModelSelect = async (ctx: Context, modelId: string): Promise<void> => {\n try {\n const sessionKey = getSessionKeyFromCtx(ctx);\n await Promise.resolve(setSessionModel(sessionKey, modelId));\n\n const modelName = modelId.split('/').pop() || modelId;\n await ctx.editMessageText(\n `✅ Model switched to *${modelName}*\\n\\nThis model will be used for your next message.`,\n { parse_mode: 'Markdown' }\n );\n await ctx.answerCallbackQuery(`Switched to ${modelName}`);\n\n log.info({ sessionKey, modelId }, 'Model switched via Telegram');\n } catch (err) {\n log.error({ err }, 'Failed to handle model selection');\n await ctx.answerCallbackQuery('Failed to switch model');\n }\n };\n\n const handleShowProviders = async (ctx: Context): Promise<void> => {\n try {\n const providers = getAvailableProviders();\n\n await ctx.editMessageText('🤖 Select a provider:', {\n reply_markup: TelegramInlineKeyboards.providerSelector(providers),\n });\n await ctx.answerCallbackQuery();\n } catch (err) {\n log.error({ err }, 'Failed to show providers again');\n await ctx.answerCallbackQuery('Failed to go back');\n }\n };\n\n const handleCleanupConfirm = async (ctx: Context): Promise<void> => {\n try {\n await ctx.editMessageText('🧹 Cleaning up old sessions...');\n \n const chatId = String(ctx.chat?.id);\n\n await bus.publishInbound({\n channel: 'system',\n sender_id: 'telegram:cleanup',\n chat_id: chatId,\n content: '/cleanup --days 30 --force',\n });\n\n await ctx.editMessageText('✅ Cleanup initiated. Old sessions will be archived.');\n await ctx.answerCallbackQuery('Cleanup started');\n } catch (err) {\n log.error({ err }, 'Failed to execute cleanup');\n await ctx.editMessageText('❌ Cleanup failed. Please try again later.');\n await ctx.answerCallbackQuery('Cleanup failed');\n }\n };\n\n const handleCancel = async (ctx: Context): Promise<void> => {\n await ctx.editMessageText('Cancelled.');\n await ctx.answerCallbackQuery();\n };\n\n return {\n // Command handlers\n handleStart,\n handleModels,\n handleCleanup,\n // Callback handlers\n handleProviderSelect,\n handleModelSelect,\n handleShowProviders,\n handleCleanupConfirm,\n handleCancel,\n // Helpers\n getAvailableProviders,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"command-handler.js","names":[],"sources":["../../../../extensions/telegram/src/command-handler.ts"],"sourcesContent":["/**\n * Telegram Command Handler\n * \n * Handles Telegram-specific UI interactions (inline keyboards, callbacks).\n * Core commands (/new, /usage, /models, etc.) are handled by the unified command system.\n */\n\nimport type { Context } from 'grammy';\n\nimport type { TelegramAccountManager } from './account-manager.js';\nimport { createLogger } from '@xopcai/xopc/utils/logger.js';\nimport type { Config } from '@xopcai/xopc/config/index.js';\nimport { isProviderConfiguredSync } from '@xopcai/xopc/providers/index.js';\nimport { TelegramInlineKeyboards, type ProviderInfo } from './inline-keyboards.js';\nimport { getProviderDisplayName, getModelsByProvider, getDefaultModelSync, getAllProviders } from '@xopcai/xopc/providers/index.js';\nimport { generateSessionKey } from '@xopcai/xopc/chat-commands/session-key.js';\n\nconst log = createLogger('TelegramCommandHandler');\n\nexport interface TelegramCommandHandlerDeps {\n bus: any;\n config: Config;\n accountManager: TelegramAccountManager;\n getSessionModel: (sessionKey: string) => string | undefined;\n setSessionModel: (sessionKey: string, modelId: string) => void | Promise<void>;\n // Optional callbacks for inline keyboard handling\n showProviderModels?: (ctx: Context, providerId: string) => Promise<void>;\n showProvidersAgain?: (ctx: Context) => Promise<void>;\n handleCleanupConfirm?: (ctx: Context) => Promise<void>;\n}\n\nexport function createTelegramCommandHandler(deps: TelegramCommandHandlerDeps) {\n const { config, accountManager, getSessionModel, setSessionModel, bus } = deps;\n\n // ========== Helper Functions ==========\n\n const getAvailableProviders = (): ProviderInfo[] => {\n const allProviders = getAllProviders();\n const available: ProviderInfo[] = [];\n\n for (const providerId of allProviders) {\n if (isProviderConfiguredSync(providerId)) {\n available.push({ id: providerId, name: getProviderDisplayName(providerId) });\n }\n }\n\n if (available.length === 0) {\n available.push({ id: 'minimax', name: 'MiniMax' });\n }\n\n return available;\n };\n\n const getModelsForProvider = (providerId: string) => {\n const models = getModelsByProvider(providerId);\n \n if (models.length === 0) {\n return [{ id: `${providerId}/default`, name: 'default', provider: providerId }];\n }\n \n return models.map(m => ({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: m.provider,\n }));\n };\n\n // ========== Helper Functions ==========\n\n // Helper to get sessionKey from Telegram context\n const getSessionKeyFromCtx = (ctx: Context): string => {\n const chatId = String(ctx.chat?.id);\n const senderId = String(ctx.from?.id);\n const isGroup = ctx.chat?.type === 'group' || ctx.chat?.type === 'supergroup';\n const threadId =\n (ctx.message as { message_thread_id?: number })?.message_thread_id ??\n (ctx.callbackQuery?.message as { message_thread_id?: number } | undefined)?.message_thread_id;\n\n const accountId = accountManager.resolveAccountIdFromContext(ctx);\n\n return generateSessionKey({\n source: 'telegram',\n chatId,\n senderId,\n isGroup,\n threadId: threadId ? String(threadId) : undefined,\n accountId,\n });\n };\n\n // ========== Command Handlers ==========\n\n /**\n * /start - Show welcome message\n * Note: Other commands (/new, /usage, /models, etc.) are handled by the unified command system\n */\n const handleStart = async (ctx: Context): Promise<void> => {\n try {\n const providers = getAvailableProviders();\n const hasProviders = providers.length > 0;\n\n await ctx.reply(\n '👋 *Welcome to xopc!*\\n\\n' +\n 'I am your AI assistant. Here are the available commands:\\n\\n' +\n '🤖 *Model Selection*\\n' +\n '/models - List models (name + `provider/model` ref for /switch)\\n' +\n '/switch \\u003cprovider/model-id\\u003e - Same ref as shown in /models\\n\\n' +\n '📊 *Session Management*\\n' +\n '/new - Start a new session (archive current)\\n' +\n '/list - List all your sessions\\n' +\n '/usage - View token usage statistics\\n' +\n '/cleanup - Clean up old sessions\\n\\n' +\n '🔊 *Voice (TTS)*\\n' +\n '/tts - Show TTS settings\\n' +\n '/tts on|off - Enable/disable TTS\\n' +\n '/tts always|inbound|tagged|never - Set trigger mode\\n\\n' +\n '🛠️ *Skills*\\n' +\n '/skills reload - Reload all skills from disk\\n\\n' +\n '💡 *Tip*: Just send a message to start chatting!' +\n (hasProviders ? '' : '\\n\\n⚠️ *Note*: No LLM providers configured. Please set up API keys in your config.'),\n { parse_mode: 'Markdown' }\n );\n } catch (err) {\n log.error({ err }, 'Failed to handle start command');\n await ctx.reply('❌ Failed to show welcome message.');\n }\n };\n\n /**\n * /models - Show model selector with inline keyboard\n * Note: This provides a UI enhancement over the basic /models command\n */\n const handleModels = async (ctx: Context): Promise<void> => {\n try {\n const providers = getAvailableProviders();\n\n if (providers.length === 0) {\n await ctx.reply('❌ No providers available. Please check your configuration.');\n return;\n }\n\n await ctx.reply('🤖 Select a provider:', {\n reply_markup: TelegramInlineKeyboards.providerSelector(providers),\n });\n } catch (err) {\n log.error({ err }, 'Failed to show provider selector');\n await ctx.reply('❌ Failed to load providers. Please try again.');\n }\n };\n\n /**\n * /cleanup - Show cleanup confirmation dialog\n */\n const handleCleanup = async (ctx: Context): Promise<void> => {\n try {\n await ctx.reply(\n '🧹 *Session Cleanup*\\n\\n' +\n 'This will archive sessions that have been inactive for more than 30 days.\\n\\n' +\n 'Archived sessions can be restored later.',\n { parse_mode: 'Markdown', reply_markup: TelegramInlineKeyboards.cleanupConfirm() }\n );\n } catch (err) {\n log.error({ err }, 'Failed to show cleanup dialog');\n await ctx.reply('❌ Failed to initiate cleanup.');\n }\n };\n\n // ========== Callback Handlers (Inline Keyboard) ==========\n\n const handleProviderSelect = async (ctx: Context, providerId: string): Promise<void> => {\n try {\n const sessionKey = getSessionKeyFromCtx(ctx);\n const modelConfig = config.agents?.defaults?.models?.chat;\n const defaultModel = modelConfig?.primary || getDefaultModelSync(config);\n const currentModel = getSessionModel(sessionKey) || defaultModel;\n\n const models = getModelsForProvider(providerId);\n \n if (models.length === 0) {\n await ctx.editMessageText('❌ No models available for this provider.');\n await ctx.answerCallbackQuery();\n return;\n }\n\n const keyboard = TelegramInlineKeyboards.modelSelector(models, currentModel);\n const providerName = getProviderDisplayName(providerId);\n \n await ctx.editMessageText(`🤖 Select a model from *${providerName}*:`, { \n reply_markup: keyboard,\n parse_mode: 'Markdown',\n });\n await ctx.answerCallbackQuery();\n } catch (err) {\n log.error({ err, providerId }, 'Failed to show provider models');\n await ctx.answerCallbackQuery('Failed to load models');\n }\n };\n\n const handleModelSelect = async (ctx: Context, modelId: string): Promise<void> => {\n try {\n const sessionKey = getSessionKeyFromCtx(ctx);\n await Promise.resolve(setSessionModel(sessionKey, modelId));\n\n const modelName = modelId.split('/').pop() || modelId;\n await ctx.editMessageText(\n `✅ Model switched to *${modelName}*\\n\\nThis model will be used for your next message.`,\n { parse_mode: 'Markdown' }\n );\n await ctx.answerCallbackQuery(`Switched to ${modelName}`);\n\n log.info({ sessionKey, modelId }, 'Model switched via Telegram');\n } catch (err) {\n log.error({ err }, 'Failed to handle model selection');\n await ctx.answerCallbackQuery('Failed to switch model');\n }\n };\n\n const handleShowProviders = async (ctx: Context): Promise<void> => {\n try {\n const providers = getAvailableProviders();\n\n await ctx.editMessageText('🤖 Select a provider:', {\n reply_markup: TelegramInlineKeyboards.providerSelector(providers),\n });\n await ctx.answerCallbackQuery();\n } catch (err) {\n log.error({ err }, 'Failed to show providers again');\n await ctx.answerCallbackQuery('Failed to go back');\n }\n };\n\n const handleCleanupConfirm = async (ctx: Context): Promise<void> => {\n try {\n await ctx.editMessageText('🧹 Cleaning up old sessions...');\n \n const chatId = String(ctx.chat?.id);\n\n await bus.publishInbound({\n channel: 'system',\n sender_id: 'telegram:cleanup',\n chat_id: chatId,\n content: '/cleanup --days 30 --force',\n });\n\n await ctx.editMessageText('✅ Cleanup initiated. Old sessions will be archived.');\n await ctx.answerCallbackQuery('Cleanup started');\n } catch (err) {\n log.error({ err }, 'Failed to execute cleanup');\n await ctx.editMessageText('❌ Cleanup failed. Please try again later.');\n await ctx.answerCallbackQuery('Cleanup failed');\n }\n };\n\n const handleCancel = async (ctx: Context): Promise<void> => {\n await ctx.editMessageText('Cancelled.');\n await ctx.answerCallbackQuery();\n };\n\n return {\n // Command handlers\n handleStart,\n handleModels,\n handleCleanup,\n // Callback handlers\n handleProviderSelect,\n handleModelSelect,\n handleShowProviders,\n handleCleanupConfirm,\n handleCancel,\n // Helpers\n getAvailableProviders,\n };\n}\n"],"mappings":"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"}
|
|
@@ -69,7 +69,7 @@ var init_config_schema = __esmMin((() => {
|
|
|
69
69
|
"allowlist",
|
|
70
70
|
"open",
|
|
71
71
|
"disabled"
|
|
72
|
-
]).default("
|
|
72
|
+
]).default("open"),
|
|
73
73
|
groupPolicy: z.enum([
|
|
74
74
|
"open",
|
|
75
75
|
"disabled",
|
|
@@ -115,7 +115,7 @@ var init_config_schema = __esmMin((() => {
|
|
|
115
115
|
"allowlist",
|
|
116
116
|
"open",
|
|
117
117
|
"disabled"
|
|
118
|
-
]).default("
|
|
118
|
+
]).default("open"),
|
|
119
119
|
groupPolicy: z.enum([
|
|
120
120
|
"open",
|
|
121
121
|
"disabled",
|