@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":"installer.js","names":[],"sources":["../../../../src/agent/skills/installer.ts"],"sourcesContent":["/**\n * Skill Installer\n * \n * Handles installation of skill dependencies via various package managers.\n *\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillEntry, SkillInstallResult, SkillInstallSpec } from './types.js';\n\nconst execAsync = promisify(exec);\n\nconst log = createLogger('SkillInstaller');\n\nexport interface InstallerPreferences {\n preferBrew: boolean;\n nodeManager: 'pnpm' | 'npm' | 'yarn' | 'bun';\n}\n\nexport interface InstallContext {\n workspaceDir: string;\n skillEntry: SkillEntry;\n installSpec: SkillInstallSpec;\n timeoutMs: number;\n preferences: InstallerPreferences;\n}\n\n/**\n * Check if a binary exists\n */\nexport function hasBinary(name: string): boolean {\n try {\n const { which } = require('which');\n return !!which.sync(name, { nothrow: true });\n } catch {\n // Fallback: try to execute the command\n try {\n const { execSync } = require('child_process');\n execSync(`which ${name}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Resolve brew executable path\n */\nexport function resolveBrewExecutable(): string | undefined {\n const candidates = [\n '/opt/homebrew/bin/brew',\n '/usr/local/bin/brew',\n ];\n \n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n \n return undefined;\n}\n\n/**\n * Build install command for Node.js packages\n */\nfunction buildNodeInstallCommand(packageName: string, manager: InstallerPreferences['nodeManager']): string[] {\n switch (manager) {\n case 'pnpm':\n return ['pnpm', 'add', '-g', '--ignore-scripts', packageName];\n case 'yarn':\n return ['yarn', 'global', 'add', '--ignore-scripts', packageName];\n case 'bun':\n return ['bun', 'add', '-g', '--ignore-scripts', packageName];\n default:\n return ['npm', 'install', '-g', '--ignore-scripts', packageName];\n }\n}\n\n/**\n * Build install command from spec\n */\nfunction buildInstallCommand(spec: SkillInstallSpec, prefs: InstallerPreferences): {\n argv: string[] | null;\n error?: string;\n} {\n switch (spec.kind) {\n case 'brew': {\n if (!spec.formula) {\n return { argv: null, error: 'Missing brew formula' };\n }\n return { argv: ['brew', 'install', spec.formula] };\n }\n \n case 'pnpm':\n case 'npm':\n case 'yarn':\n case 'bun': {\n if (!spec.package) {\n return { argv: null, error: 'Missing package name' };\n }\n return {\n argv: buildNodeInstallCommand(spec.package, prefs.nodeManager),\n };\n }\n \n case 'go': {\n if (!spec.module) {\n return { argv: null, error: 'Missing go module' };\n }\n return { argv: ['go', 'install', spec.module] };\n }\n \n case 'uv': {\n if (!spec.package) {\n return { argv: null, error: 'Missing uv package' };\n }\n return { argv: ['uv', 'tool', 'install', spec.package] };\n }\n \n case 'download': {\n return { argv: null, error: 'Download install handled separately' };\n }\n \n default: {\n const _exhaustive: never = spec.kind;\n return { argv: null, error: `Unsupported installer: ${spec.kind}` };\n }\n }\n}\n\n/**\n * Run command with timeout\n */\nasync function runCommandWithTimeout(\n argv: string[],\n timeoutMs: number,\n env?: NodeJS.ProcessEnv\n): Promise<{ code: number | null; stdout: string; stderr: string }> {\n const [cmd, ...args] = argv;\n \n try {\n const { stdout, stderr } = await execAsync(`${cmd} ${args.join(' ')}`, {\n timeout: timeoutMs,\n env,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n \n return {\n code: 0,\n stdout: stdout.toString(),\n stderr: stderr.toString(),\n };\n } catch (err: unknown) {\n if (err instanceof Error) {\n const execError = err as Error & { code?: number; stdout?: string; stderr?: string };\n return {\n code: execError.code ?? null,\n stdout: execError.stdout?.toString() ?? '',\n stderr: execError.stderr?.toString() ?? '',\n };\n }\n \n return {\n code: null,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Ensure uv is installed\n */\nasync function ensureUvInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('uv')) {\n return undefined;\n }\n \n // Try to install via brew\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n return {\n ok: false,\n message: 'uv not installed — install manually: https://docs.astral.sh/uv/getting-started/installation/',\n stdout: '',\n stderr: '',\n code: null,\n };\n }\n \n const result = await runCommandWithTimeout([brewExe, 'install', 'uv'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install uv (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n}\n\n/**\n * Ensure Go is installed\n */\nasync function ensureGoInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('go')) {\n return undefined;\n }\n \n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n const result = await runCommandWithTimeout([brewExe, 'install', 'go'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install go (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n // Try apt-get on Linux\n if (hasBinary('apt-get')) {\n const isRoot = process.getuid?.() === 0;\n const aptCmd = isRoot \n ? ['apt-get', 'install', '-y', 'golang-go']\n : ['sudo', 'apt-get', 'install', '-y', 'golang-go'];\n \n // Update package index first\n if (!isRoot) {\n await runCommandWithTimeout(['sudo', 'apt-get', 'update', '-qq'], Math.min(timeoutMs, 30000));\n }\n \n const result = await runCommandWithTimeout(aptCmd, timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'go not installed — automatic install via apt failed. Install manually: https://go.dev/doc/install',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n return {\n ok: false,\n message: 'go not installed — install manually: https://go.dev/doc/install',\n stdout: '',\n stderr: '',\n code: null,\n };\n}\n\n/**\n * Create install failure result\n */\nfunction createInstallFailure(params: {\n message: string;\n stdout?: string;\n stderr?: string;\n code?: number | null;\n}): SkillInstallResult {\n return {\n ok: false,\n message: params.message,\n stdout: params.stdout?.trim() ?? '',\n stderr: params.stderr?.trim() ?? '',\n code: params.code ?? null,\n };\n}\n\n/**\n * Create install success result\n */\nfunction createInstallSuccess(result: { code: number | null; stdout: string; stderr: string }): SkillInstallResult {\n return {\n ok: true,\n message: 'Installed',\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n code: result.code,\n };\n}\n\n/**\n * Find install spec by ID\n */\nexport function findInstallSpec(entry: SkillEntry, installId: string): SkillInstallSpec | undefined {\n const specs = entry.metadata.install ?? [];\n \n for (const [index, spec] of specs.entries()) {\n const id = spec.id ?? `${spec.kind}-${index}`;\n if (id === installId) {\n return spec;\n }\n }\n \n return undefined;\n}\n\n/**\n * Install a skill dependency\n */\nexport async function installSkill(ctx: InstallContext): Promise<SkillInstallResult> {\n const { installSpec, timeoutMs, preferences } = ctx;\n \n log.info({ skill: ctx.skillEntry.skill.name, kind: installSpec.kind }, 'Installing skill dependency');\n \n // Handle download installer separately\n if (installSpec.kind === 'download') {\n return createInstallFailure({\n message: 'Download installer not yet implemented',\n });\n }\n \n // Check and install prerequisites\n if (installSpec.kind === 'uv') {\n const uvFailure = await ensureUvInstalled(timeoutMs);\n if (uvFailure) {\n return uvFailure;\n }\n }\n \n if (installSpec.kind === 'go') {\n const goFailure = await ensureGoInstalled(timeoutMs);\n if (goFailure) {\n return goFailure;\n }\n }\n \n // Build install command\n const command = buildInstallCommand(installSpec, preferences);\n if (command.error) {\n return createInstallFailure({\n message: command.error,\n });\n }\n \n if (!command.argv) {\n return createInstallFailure({\n message: 'Invalid install command',\n });\n }\n \n // Resolve brew executable\n let argv = [...command.argv];\n if (installSpec.kind === 'brew') {\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n const hint = process.platform === 'linux'\n ? 'Homebrew is not installed. Install it from https://brew.sh or use your system package manager.'\n : 'Homebrew is not installed. Install it from https://brew.sh';\n \n return createInstallFailure({\n message: `brew not installed — ${hint}`,\n });\n }\n argv[0] = brewExe;\n }\n \n // Set up environment for go installations\n let env: NodeJS.ProcessEnv | undefined;\n if (installSpec.kind === 'go') {\n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n try {\n const { stdout } = await execAsync(`${brewExe} --prefix`);\n const prefix = stdout.trim();\n if (prefix) {\n env = { ...process.env, GOBIN: join(prefix, 'bin') };\n }\n } catch {\n // Use default GOBIN\n }\n }\n }\n \n // Execute install command\n const result = await runCommandWithTimeout(argv, timeoutMs, env);\n \n if (result.code === 0) {\n log.info({ skill: ctx.skillEntry.skill.name }, 'Skill dependency installed successfully');\n return createInstallSuccess(result);\n }\n \n log.warn({ \n skill: ctx.skillEntry.skill.name, \n stderr: result.stderr \n }, 'Skill dependency installation failed');\n \n return createInstallFailure({\n message: result.stderr || `Installation failed with exit code ${result.code}`,\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n });\n}\n\n/**\n * Get default installer preferences from config\n */\nexport function getDefaultInstallerPreferences(): InstallerPreferences {\n return {\n preferBrew: true,\n nodeManager: 'pnpm', // Default to pnpm as per project guidelines\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"installer.js","names":[],"sources":["../../../../src/agent/skills/installer.ts"],"sourcesContent":["/**\n * Skill Installer\n * \n * Handles installation of skill dependencies via various package managers.\n *\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { accessSync, constants, existsSync } from 'fs';\nimport { delimiter, join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillEntry, SkillInstallResult, SkillInstallSpec } from './types.js';\n\nconst execAsync = promisify(exec);\n\nconst log = createLogger('SkillInstaller');\n\nexport interface InstallerPreferences {\n preferBrew: boolean;\n nodeManager: 'pnpm' | 'npm' | 'yarn' | 'bun';\n}\n\nexport interface InstallContext {\n workspaceDir: string;\n skillEntry: SkillEntry;\n installSpec: SkillInstallSpec;\n timeoutMs: number;\n preferences: InstallerPreferences;\n}\n\n/**\n * Check if a binary exists\n */\nexport function hasBinary(name: string): boolean {\n if (!name || name.includes('/') || name.includes('\\\\')) {\n return false;\n }\n\n const pathEntries = (process.env.PATH || '').split(delimiter).filter(Boolean);\n const extensions = process.platform === 'win32'\n ? (process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM').split(';').filter(Boolean)\n : [''];\n\n for (const dir of pathEntries) {\n for (const ext of extensions) {\n const candidate = join(dir, `${name}${ext}`);\n try {\n accessSync(candidate, constants.X_OK);\n return true;\n } catch {\n // Continue searching PATH.\n }\n }\n }\n\n return false;\n}\n\n/**\n * Resolve brew executable path\n */\nexport function resolveBrewExecutable(): string | undefined {\n const candidates = [\n '/opt/homebrew/bin/brew',\n '/usr/local/bin/brew',\n ];\n \n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n \n return undefined;\n}\n\n/**\n * Build install command for Node.js packages\n */\nfunction buildNodeInstallCommand(packageName: string, manager: InstallerPreferences['nodeManager']): string[] {\n switch (manager) {\n case 'pnpm':\n return ['pnpm', 'add', '-g', '--ignore-scripts', packageName];\n case 'yarn':\n return ['yarn', 'global', 'add', '--ignore-scripts', packageName];\n case 'bun':\n return ['bun', 'add', '-g', '--ignore-scripts', packageName];\n default:\n return ['npm', 'install', '-g', '--ignore-scripts', packageName];\n }\n}\n\n/**\n * Build install command from spec\n */\nfunction buildInstallCommand(spec: SkillInstallSpec, prefs: InstallerPreferences): {\n argv: string[] | null;\n error?: string;\n} {\n switch (spec.kind) {\n case 'brew': {\n if (!spec.formula) {\n return { argv: null, error: 'Missing brew formula' };\n }\n return { argv: ['brew', 'install', spec.formula] };\n }\n \n case 'pnpm':\n case 'npm':\n case 'yarn':\n case 'bun': {\n if (!spec.package) {\n return { argv: null, error: 'Missing package name' };\n }\n return {\n argv: buildNodeInstallCommand(spec.package, prefs.nodeManager),\n };\n }\n \n case 'go': {\n if (!spec.module) {\n return { argv: null, error: 'Missing go module' };\n }\n return { argv: ['go', 'install', spec.module] };\n }\n \n case 'uv': {\n if (!spec.package) {\n return { argv: null, error: 'Missing uv package' };\n }\n return { argv: ['uv', 'tool', 'install', spec.package] };\n }\n \n case 'download': {\n return { argv: null, error: 'Download install handled separately' };\n }\n \n default: {\n const _exhaustive: never = spec.kind;\n return { argv: null, error: `Unsupported installer: ${spec.kind}` };\n }\n }\n}\n\n/**\n * Run command with timeout\n */\nasync function runCommandWithTimeout(\n argv: string[],\n timeoutMs: number,\n env?: NodeJS.ProcessEnv\n): Promise<{ code: number | null; stdout: string; stderr: string }> {\n const [cmd, ...args] = argv;\n \n try {\n const { stdout, stderr } = await execAsync(`${cmd} ${args.join(' ')}`, {\n timeout: timeoutMs,\n env,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n \n return {\n code: 0,\n stdout: stdout.toString(),\n stderr: stderr.toString(),\n };\n } catch (err: unknown) {\n if (err instanceof Error) {\n const execError = err as Error & { code?: number; stdout?: string; stderr?: string };\n return {\n code: execError.code ?? null,\n stdout: execError.stdout?.toString() ?? '',\n stderr: execError.stderr?.toString() ?? '',\n };\n }\n \n return {\n code: null,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Ensure uv is installed\n */\nasync function ensureUvInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('uv')) {\n return undefined;\n }\n \n // Try to install via brew\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n return {\n ok: false,\n message: 'uv not installed — install manually: https://docs.astral.sh/uv/getting-started/installation/',\n stdout: '',\n stderr: '',\n code: null,\n };\n }\n \n const result = await runCommandWithTimeout([brewExe, 'install', 'uv'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install uv (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n}\n\n/**\n * Ensure Go is installed\n */\nasync function ensureGoInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('go')) {\n return undefined;\n }\n \n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n const result = await runCommandWithTimeout([brewExe, 'install', 'go'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install go (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n // Try apt-get on Linux\n if (hasBinary('apt-get')) {\n const isRoot = process.getuid?.() === 0;\n const aptCmd = isRoot \n ? ['apt-get', 'install', '-y', 'golang-go']\n : ['sudo', 'apt-get', 'install', '-y', 'golang-go'];\n \n // Update package index first\n if (!isRoot) {\n await runCommandWithTimeout(['sudo', 'apt-get', 'update', '-qq'], Math.min(timeoutMs, 30000));\n }\n \n const result = await runCommandWithTimeout(aptCmd, timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'go not installed — automatic install via apt failed. Install manually: https://go.dev/doc/install',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n return {\n ok: false,\n message: 'go not installed — install manually: https://go.dev/doc/install',\n stdout: '',\n stderr: '',\n code: null,\n };\n}\n\n/**\n * Create install failure result\n */\nfunction createInstallFailure(params: {\n message: string;\n stdout?: string;\n stderr?: string;\n code?: number | null;\n}): SkillInstallResult {\n return {\n ok: false,\n message: params.message,\n stdout: params.stdout?.trim() ?? '',\n stderr: params.stderr?.trim() ?? '',\n code: params.code ?? null,\n };\n}\n\n/**\n * Create install success result\n */\nfunction createInstallSuccess(result: { code: number | null; stdout: string; stderr: string }): SkillInstallResult {\n return {\n ok: true,\n message: 'Installed',\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n code: result.code,\n };\n}\n\n/**\n * Find install spec by ID\n */\nexport function findInstallSpec(entry: SkillEntry, installId: string): SkillInstallSpec | undefined {\n const specs = entry.metadata.install ?? [];\n \n for (const [index, spec] of specs.entries()) {\n const id = spec.id ?? `${spec.kind}-${index}`;\n if (id === installId) {\n return spec;\n }\n }\n \n return undefined;\n}\n\n/**\n * Install a skill dependency\n */\nexport async function installSkill(ctx: InstallContext): Promise<SkillInstallResult> {\n const { installSpec, timeoutMs, preferences } = ctx;\n \n log.info({ skill: ctx.skillEntry.skill.name, kind: installSpec.kind }, 'Installing skill dependency');\n \n // Handle download installer separately\n if (installSpec.kind === 'download') {\n return createInstallFailure({\n message: 'Download installer not yet implemented',\n });\n }\n \n // Check and install prerequisites\n if (installSpec.kind === 'uv') {\n const uvFailure = await ensureUvInstalled(timeoutMs);\n if (uvFailure) {\n return uvFailure;\n }\n }\n \n if (installSpec.kind === 'go') {\n const goFailure = await ensureGoInstalled(timeoutMs);\n if (goFailure) {\n return goFailure;\n }\n }\n \n // Build install command\n const command = buildInstallCommand(installSpec, preferences);\n if (command.error) {\n return createInstallFailure({\n message: command.error,\n });\n }\n \n if (!command.argv) {\n return createInstallFailure({\n message: 'Invalid install command',\n });\n }\n \n // Resolve brew executable\n let argv = [...command.argv];\n if (installSpec.kind === 'brew') {\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n const hint = process.platform === 'linux'\n ? 'Homebrew is not installed. Install it from https://brew.sh or use your system package manager.'\n : 'Homebrew is not installed. Install it from https://brew.sh';\n \n return createInstallFailure({\n message: `brew not installed — ${hint}`,\n });\n }\n argv[0] = brewExe;\n }\n \n // Set up environment for go installations\n let env: NodeJS.ProcessEnv | undefined;\n if (installSpec.kind === 'go') {\n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n try {\n const { stdout } = await execAsync(`${brewExe} --prefix`);\n const prefix = stdout.trim();\n if (prefix) {\n env = { ...process.env, GOBIN: join(prefix, 'bin') };\n }\n } catch {\n // Use default GOBIN\n }\n }\n }\n \n // Execute install command\n const result = await runCommandWithTimeout(argv, timeoutMs, env);\n \n if (result.code === 0) {\n log.info({ skill: ctx.skillEntry.skill.name }, 'Skill dependency installed successfully');\n return createInstallSuccess(result);\n }\n \n log.warn({ \n skill: ctx.skillEntry.skill.name, \n stderr: result.stderr \n }, 'Skill dependency installation failed');\n \n return createInstallFailure({\n message: result.stderr || `Installation failed with exit code ${result.code}`,\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n });\n}\n\n/**\n * Get default installer preferences from config\n */\nexport function getDefaultInstallerPreferences(): InstallerPreferences {\n return {\n preferBrew: true,\n nodeManager: 'pnpm', // Default to pnpm as per project guidelines\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { registerMarketplaceAdapter } from "../../registry.js";
|
|
2
|
+
import { buildSkillMarkdownPreviewFromRaw } from "../../../skill-markdown-preview-from-raw.js";
|
|
2
3
|
//#region src/agent/skills/marketplace/adapters/clawhub/adapter.ts
|
|
4
|
+
/**
|
|
5
|
+
* ClawHub (clawhub.ai) skills marketplace adapter.
|
|
6
|
+
*/
|
|
3
7
|
const DEFAULT_CLAWHUB_BASE = "https://clawhub.ai";
|
|
4
8
|
const MAX_CLAWHUB_FILE_BYTES = 512 * 1024;
|
|
5
9
|
const MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;
|
|
@@ -274,12 +278,18 @@ const clawHubMarketplaceAdapter = {
|
|
|
274
278
|
if (!readme) readme = fallbackReadmeMarkdown(detail);
|
|
275
279
|
const changelog = detail.latestVersion.changelog?.trim();
|
|
276
280
|
if (changelog) readme = `${readme}\n\n---\n\n## Changelog\n\n${changelog}`;
|
|
281
|
+
const description = detail.skill.summary || "";
|
|
282
|
+
const skillDocPreview = buildSkillMarkdownPreviewFromRaw(readme, {
|
|
283
|
+
name: slug,
|
|
284
|
+
description
|
|
285
|
+
});
|
|
277
286
|
return {
|
|
278
287
|
id: slug,
|
|
279
288
|
name: slug,
|
|
280
289
|
type: "skill",
|
|
281
|
-
description
|
|
290
|
+
description,
|
|
282
291
|
readme,
|
|
292
|
+
skillDocPreview,
|
|
283
293
|
downloads: detail.skill.stats.downloads,
|
|
284
294
|
author: {
|
|
285
295
|
username: detail.owner.handle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/clawhub/adapter.ts"],"sourcesContent":["/**\n * ClawHub (clawhub.ai) skills marketplace adapter.\n */\n\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_CLAWHUB_BASE = 'https://clawhub.ai';\nconst MAX_CLAWHUB_FILE_BYTES = 512 * 1024;\nconst MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst LIST_BATCH_SIZE = 200;\n\nconst DEFAULT_CACHE_MS = 5 * 60 * 1000;\nconst MAX_LIST_CACHE_KEYS = 24;\nconst MAX_DETAIL_CACHE_KEYS = 48;\n\n// ─── Inline helpers ──────────────────────────────────────────────────────────\n\nfunction isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\nfunction resolveClawHubBaseUrl(): string {\n const env = process.env.CLAWHUB_REGISTRY?.trim();\n if (env) {\n try {\n return new URL(env).toString().replace(/\\/$/, '');\n } catch {\n // fall through\n }\n }\n return DEFAULT_CLAWHUB_BASE;\n}\n\n// ─── ClawHub API types ───────────────────────────────────────────────────────\n\ninterface ClawHubSkillListItem {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n}\n\ninterface ClawHubSkillListResponse {\n items: ClawHubSkillListItem[];\n nextCursor: string | null;\n}\n\ninterface ClawHubSearchResultItem {\n score: number;\n slug: string;\n displayName: string;\n summary: string;\n version: string | null;\n updatedAt: number;\n ownerHandle: string;\n owner: {\n handle: string;\n displayName: string;\n image: string | null;\n };\n}\n\ninterface ClawHubSearchResponse {\n results: ClawHubSearchResultItem[];\n}\n\ninterface ClawHubSkillDetail {\n skill: {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n };\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n owner: {\n handle: string;\n userId: string;\n displayName: string;\n image: string | null;\n };\n moderation: {\n isSuspicious: boolean;\n isMalwareBlocked: boolean;\n verdict: string;\n } | null;\n}\n\ninterface ClawHubVersionFile {\n path: string;\n size: number;\n sha256: string;\n contentType: string;\n}\n\ninterface ClawHubVersionDetail {\n skill: { slug: string; displayName: string };\n version: {\n version: string;\n createdAt: number;\n changelog: string | null;\n changelogSource: string | null;\n license: string | null;\n files: ClawHubVersionFile[];\n security: {\n status: string;\n hasWarnings: boolean;\n hasScanResult: boolean;\n } | null;\n };\n}\n\ntype ClawHubListSort = 'updated' | 'newest' | 'downloads' | 'stars' | 'trending';\n\ninterface ClawHubListParams {\n limit?: number;\n cursor?: string;\n sort?: ClawHubListSort;\n}\n\n// ─── ClawHub HTTP helpers ────────────────────────────────────────────────────\n\nasync function clawHubFetch(path: string, init?: { signal?: AbortSignal }): Promise<Response> {\n const base = resolveClawHubBaseUrl();\n const url = `${base}${path}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n signal: init?.signal,\n });\n return res as unknown as Response;\n}\n\nfunction assertOk(res: Response, context: string): void {\n if (!res.ok) {\n throw new Error(`ClawHub ${context} failed (${res.status})`);\n }\n}\n\nasync function listClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const sp = new URLSearchParams();\n if (params?.limit) sp.set('limit', String(params.limit));\n if (params?.cursor) sp.set('cursor', params.cursor);\n if (params?.sort) sp.set('sort', params.sort);\n sp.set('nonSuspiciousOnly', 'true');\n const qs = sp.toString();\n const res = await clawHubFetch(`/api/v1/skills${qs ? `?${qs}` : ''}`);\n assertOk(res, 'list skills');\n return (await res.json()) as ClawHubSkillListResponse;\n}\n\nasync function searchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const sp = new URLSearchParams({ q: query, nonSuspiciousOnly: 'true' });\n if (limit) sp.set('limit', String(limit));\n const res = await clawHubFetch(`/api/v1/search?${sp.toString()}`);\n assertOk(res, 'search');\n return (await res.json()) as ClawHubSearchResponse;\n}\n\nasync function getClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const enc = encodeURIComponent(slug.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}`);\n assertOk(res, `skill detail [${slug}]`);\n return (await res.json()) as ClawHubSkillDetail;\n}\n\nasync function getClawHubVersionDetail(slug: string, version: string): Promise<ClawHubVersionDetail> {\n const enc = encodeURIComponent(slug.trim());\n const ver = encodeURIComponent(version.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}/versions/${ver}`);\n assertOk(res, `version detail [${slug}@${version}]`);\n return (await res.json()) as ClawHubVersionDetail;\n}\n\nasync function getClawHubSkillFileText(slug: string, filePath: string, version?: string): Promise<string> {\n const enc = encodeURIComponent(slug.trim());\n const sp = new URLSearchParams({ path: filePath });\n if (version?.trim()) sp.set('version', version.trim());\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/skills/${enc}/file?${sp.toString()}`;\n const res = await fetch(url, { headers: { Accept: 'text/markdown,text/plain,*/*' } });\n if (!res.ok) {\n throw new Error(`ClawHub file fetch [${slug}/${filePath}] failed (${res.status})`);\n }\n const text = await res.text();\n return text.length > MAX_CLAWHUB_FILE_BYTES ? text.slice(0, MAX_CLAWHUB_FILE_BYTES) : text;\n}\n\nasync function downloadClawHubSkillZip(\n slug: string,\n version?: string,\n): Promise<{ buffer: Buffer; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n const sp = version?.trim() ? `?version=${encodeURIComponent(version.trim())}` : '';\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/packages/${enc}/download${sp}`;\n const res = await fetch(url, { redirect: 'follow' });\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`ClawHub download [${slug}] failed (${res.status}): ${body.slice(0, 200)}`);\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('zip') && !contentType.includes('octet-stream')) {\n throw new Error(`ClawHub download [${slug}] unexpected content-type: ${contentType}`);\n }\n const arrayBuf = await res.arrayBuffer();\n if (arrayBuf.byteLength > MAX_SKILL_ZIP_BYTES) {\n throw new Error(\n `ClawHub download [${slug}] exceeds size limit (${arrayBuf.byteLength} > ${MAX_SKILL_ZIP_BYTES})`,\n );\n }\n return { buffer: Buffer.from(arrayBuf), version: version?.trim() || 'latest' };\n}\n\nfunction pickClawHubDocFilePath(files: ClawHubVersionFile[]): string | null {\n const rows = files.map((f) => ({\n path: f.path.replace(/\\\\/g, '/'),\n base: f.path.replace(/\\\\/g, '/').split('/').pop()?.toLowerCase() ?? '',\n }));\n const find = (name: string) => rows.find((r) => r.base === name.toLowerCase());\n const skillMd = find('SKILL.md') ?? find('skill.md');\n if (skillMd) return skillMd.path;\n const readme = find('README.md') ?? find('readme.md');\n if (readme) return readme.path;\n return null;\n}\n\n// ─── In-memory TTL cache ─────────────────────────────────────────────────────\n\ntype CacheEntry<T> = { value: T; expiresAt: number };\n\nfunction cacheTtlMs(): number {\n const raw = process.env.XOPC_CLAWHUB_CACHE_MS?.trim();\n if (raw === '0' || raw === 'false') return 0;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_CACHE_MS;\n return parsed;\n}\n\nfunction getFresh<T>(entry: CacheEntry<T> | undefined): T | undefined {\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\nfunction evictOldest<T>(map: Map<string, CacheEntry<T>>): void {\n const first = map.keys().next().value;\n if (first !== undefined) map.delete(first);\n}\n\nconst listCache = new Map<string, CacheEntry<ClawHubSkillListResponse>>();\nconst searchCache = new Map<string, CacheEntry<ClawHubSearchResponse>>();\nconst detailCache = new Map<string, CacheEntry<ClawHubSkillDetail>>();\n\nasync function cachedListClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const ttl = cacheTtlMs();\n const key = JSON.stringify(params ?? {});\n if (ttl > 0) {\n const hit = getFresh(listCache.get(key));\n if (hit) return hit;\n }\n const value = await listClawHubSkills(params);\n if (ttl > 0) {\n while (listCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(listCache);\n listCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedSearchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const ttl = cacheTtlMs();\n const key = `${query}::${limit ?? ''}`;\n if (ttl > 0) {\n const hit = getFresh(searchCache.get(key));\n if (hit) return hit;\n }\n const value = await searchClawHubSkills(query, limit);\n if (ttl > 0) {\n while (searchCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(searchCache);\n searchCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedGetClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const ttl = cacheTtlMs();\n const key = slug.trim();\n if (ttl > 0) {\n const hit = getFresh(detailCache.get(key));\n if (hit) return hit;\n }\n const value = await getClawHubSkillDetail(slug);\n if (ttl > 0) {\n while (detailCache.size >= MAX_DETAIL_CACHE_KEYS) evictOldest(detailCache);\n detailCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\n// ─── Adapter conversion helpers ──────────────────────────────────────────────\n\ninterface PackageListItem {\n id: string;\n name: string;\n type: string;\n description: string;\n downloads: number;\n author: { username: string; avatarUrl: string | null };\n latestVersion?: string;\n updatedAt: string;\n categories?: string[];\n stars?: number;\n sourceLabel?: string;\n}\n\nfunction convertListItemToPackageItem(item: ClawHubSkillListItem): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: item.stats.downloads,\n author: { username: 'clawhub', avatarUrl: null },\n latestVersion: item.latestVersion?.version ?? item.tags.latest ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: item.metadata?.os ?? [],\n stars: item.stats.stars,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction convertSearchResultToPackageItem(\n item: ClawHubSearchResultItem,\n enrichment?: ClawHubSkillListItem,\n): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: enrichment?.stats.downloads ?? 0,\n author: {\n username: item.owner?.handle ?? item.ownerHandle ?? 'clawhub',\n avatarUrl: item.owner?.image ?? null,\n },\n latestVersion: item.version ?? enrichment?.latestVersion?.version ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: enrichment?.metadata?.os ?? [],\n stars: enrichment?.stats.stars ?? 0,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction mapSortParam(sort?: string): ClawHubListSort | undefined {\n if (sort === 'downloads') return 'downloads';\n if (sort === 'newest') return 'newest';\n return undefined;\n}\n\nfunction fallbackReadmeMarkdown(detail: {\n skill: { slug: string; displayName: string; summary: string };\n latestVersion: { version: string };\n}): string {\n const title = detail.skill.displayName || detail.skill.slug;\n const body = detail.skill.summary || '_No description._';\n return `## ${title}\\n\\n**${detail.skill.slug}** · v${detail.latestVersion.version}\\n\\n${body}`;\n}\n\nexport const clawHubMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'clawhub',\n\n async listCategories() {\n return [];\n },\n\n async listPackages(_config, params) {\n const pageSize = params.pageSize ?? 20;\n const page = params.page ?? 1;\n\n if (params.q?.trim()) {\n // Search results from /search omit downloads/stars/metadata. We pull the cached list\n // snapshot in parallel and merge by slug — costs nothing when the list cache is hot\n // (which it is after any preceding browse), and adds at most one round-trip on a cold\n // cache. We still tolerate a list-fetch failure: enrichment becomes a no-op.\n const [searchResponse, listSettled] = await Promise.allSettled([\n cachedSearchClawHubSkills(params.q.trim(), LIST_BATCH_SIZE),\n cachedListClawHubSkills({ limit: LIST_BATCH_SIZE }),\n ]);\n if (searchResponse.status === 'rejected') throw searchResponse.reason;\n const enrichmentBySlug = new Map<string, ClawHubSkillListItem>();\n if (listSettled.status === 'fulfilled') {\n for (const it of listSettled.value.items) enrichmentBySlug.set(it.slug, it);\n }\n let rows = searchResponse.value.results.map((r) =>\n convertSearchResultToPackageItem(r, enrichmentBySlug.get(r.slug)),\n );\n if (params.sort === 'downloads') {\n rows = [...rows].sort((a, b) => b.downloads - a.downloads);\n } else if (params.sort === 'newest') {\n rows = [...rows].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n }\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n }\n\n const sort = mapSortParam(params.sort);\n const listResponse = await cachedListClawHubSkills({ limit: LIST_BATCH_SIZE, sort });\n const rows = listResponse.items.map(convertListItemToPackageItem);\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n },\n\n async getPackageDetail(_config, packageName) {\n const detail = await cachedGetClawHubSkillDetail(packageName);\n const slug = detail.skill.slug;\n const version = detail.latestVersion.version;\n\n let readme: string | null = null;\n\n try {\n const versionDetail = await getClawHubVersionDetail(slug, version);\n const docPath = pickClawHubDocFilePath(versionDetail.version.files);\n if (docPath) {\n const rawText = await getClawHubSkillFileText(slug, docPath, version);\n const trimmed = rawText.trim();\n if (trimmed) readme = trimmed;\n }\n } catch {\n // version detail or file fetch failed — use fallback\n }\n\n if (!readme) {\n readme = fallbackReadmeMarkdown(detail);\n }\n\n const changelog = detail.latestVersion.changelog?.trim();\n if (changelog) {\n readme = `${readme}\\n\\n---\\n\\n## Changelog\\n\\n${changelog}`;\n }\n\n return {\n id: slug,\n name: slug,\n type: 'skill',\n description: detail.skill.summary || '',\n readme,\n downloads: detail.skill.stats.downloads,\n author: {\n username: detail.owner.handle,\n avatarUrl: detail.owner.image,\n },\n latestVersion: {\n version: detail.latestVersion.version,\n changelog: detail.latestVersion.changelog,\n publishedAt: String(detail.latestVersion.createdAt),\n },\n provider: 'clawhub',\n };\n },\n\n async downloadPackage(_config, packageName, version) {\n const slug = packageName.trim();\n const result = await downloadClawHubSkillZip(slug, version);\n return {\n buffer: result.buffer,\n skillId: isValidSkillId(slug) ? slug : 'unknown',\n version: result.version,\n };\n },\n};\n\nregisterMarketplaceAdapter({\n adapter: clawHubMarketplaceAdapter,\n displayName: 'ClawHub',\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/clawhub/adapter.ts"],"sourcesContent":["/**\n * ClawHub (clawhub.ai) skills marketplace adapter.\n */\n\nimport { buildSkillMarkdownPreviewFromRaw } from '../../../skill-markdown-preview-from-raw.js';\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_CLAWHUB_BASE = 'https://clawhub.ai';\nconst MAX_CLAWHUB_FILE_BYTES = 512 * 1024;\nconst MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst LIST_BATCH_SIZE = 200;\n\nconst DEFAULT_CACHE_MS = 5 * 60 * 1000;\nconst MAX_LIST_CACHE_KEYS = 24;\nconst MAX_DETAIL_CACHE_KEYS = 48;\n\n// ─── Inline helpers ──────────────────────────────────────────────────────────\n\nfunction isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\nfunction resolveClawHubBaseUrl(): string {\n const env = process.env.CLAWHUB_REGISTRY?.trim();\n if (env) {\n try {\n return new URL(env).toString().replace(/\\/$/, '');\n } catch {\n // fall through\n }\n }\n return DEFAULT_CLAWHUB_BASE;\n}\n\n// ─── ClawHub API types ───────────────────────────────────────────────────────\n\ninterface ClawHubSkillListItem {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n}\n\ninterface ClawHubSkillListResponse {\n items: ClawHubSkillListItem[];\n nextCursor: string | null;\n}\n\ninterface ClawHubSearchResultItem {\n score: number;\n slug: string;\n displayName: string;\n summary: string;\n version: string | null;\n updatedAt: number;\n ownerHandle: string;\n owner: {\n handle: string;\n displayName: string;\n image: string | null;\n };\n}\n\ninterface ClawHubSearchResponse {\n results: ClawHubSearchResultItem[];\n}\n\ninterface ClawHubSkillDetail {\n skill: {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n };\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n owner: {\n handle: string;\n userId: string;\n displayName: string;\n image: string | null;\n };\n moderation: {\n isSuspicious: boolean;\n isMalwareBlocked: boolean;\n verdict: string;\n } | null;\n}\n\ninterface ClawHubVersionFile {\n path: string;\n size: number;\n sha256: string;\n contentType: string;\n}\n\ninterface ClawHubVersionDetail {\n skill: { slug: string; displayName: string };\n version: {\n version: string;\n createdAt: number;\n changelog: string | null;\n changelogSource: string | null;\n license: string | null;\n files: ClawHubVersionFile[];\n security: {\n status: string;\n hasWarnings: boolean;\n hasScanResult: boolean;\n } | null;\n };\n}\n\ntype ClawHubListSort = 'updated' | 'newest' | 'downloads' | 'stars' | 'trending';\n\ninterface ClawHubListParams {\n limit?: number;\n cursor?: string;\n sort?: ClawHubListSort;\n}\n\n// ─── ClawHub HTTP helpers ────────────────────────────────────────────────────\n\nasync function clawHubFetch(path: string, init?: { signal?: AbortSignal }): Promise<Response> {\n const base = resolveClawHubBaseUrl();\n const url = `${base}${path}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n signal: init?.signal,\n });\n return res as unknown as Response;\n}\n\nfunction assertOk(res: Response, context: string): void {\n if (!res.ok) {\n throw new Error(`ClawHub ${context} failed (${res.status})`);\n }\n}\n\nasync function listClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const sp = new URLSearchParams();\n if (params?.limit) sp.set('limit', String(params.limit));\n if (params?.cursor) sp.set('cursor', params.cursor);\n if (params?.sort) sp.set('sort', params.sort);\n sp.set('nonSuspiciousOnly', 'true');\n const qs = sp.toString();\n const res = await clawHubFetch(`/api/v1/skills${qs ? `?${qs}` : ''}`);\n assertOk(res, 'list skills');\n return (await res.json()) as ClawHubSkillListResponse;\n}\n\nasync function searchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const sp = new URLSearchParams({ q: query, nonSuspiciousOnly: 'true' });\n if (limit) sp.set('limit', String(limit));\n const res = await clawHubFetch(`/api/v1/search?${sp.toString()}`);\n assertOk(res, 'search');\n return (await res.json()) as ClawHubSearchResponse;\n}\n\nasync function getClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const enc = encodeURIComponent(slug.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}`);\n assertOk(res, `skill detail [${slug}]`);\n return (await res.json()) as ClawHubSkillDetail;\n}\n\nasync function getClawHubVersionDetail(slug: string, version: string): Promise<ClawHubVersionDetail> {\n const enc = encodeURIComponent(slug.trim());\n const ver = encodeURIComponent(version.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}/versions/${ver}`);\n assertOk(res, `version detail [${slug}@${version}]`);\n return (await res.json()) as ClawHubVersionDetail;\n}\n\nasync function getClawHubSkillFileText(slug: string, filePath: string, version?: string): Promise<string> {\n const enc = encodeURIComponent(slug.trim());\n const sp = new URLSearchParams({ path: filePath });\n if (version?.trim()) sp.set('version', version.trim());\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/skills/${enc}/file?${sp.toString()}`;\n const res = await fetch(url, { headers: { Accept: 'text/markdown,text/plain,*/*' } });\n if (!res.ok) {\n throw new Error(`ClawHub file fetch [${slug}/${filePath}] failed (${res.status})`);\n }\n const text = await res.text();\n return text.length > MAX_CLAWHUB_FILE_BYTES ? text.slice(0, MAX_CLAWHUB_FILE_BYTES) : text;\n}\n\nasync function downloadClawHubSkillZip(\n slug: string,\n version?: string,\n): Promise<{ buffer: Buffer; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n const sp = version?.trim() ? `?version=${encodeURIComponent(version.trim())}` : '';\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/packages/${enc}/download${sp}`;\n const res = await fetch(url, { redirect: 'follow' });\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`ClawHub download [${slug}] failed (${res.status}): ${body.slice(0, 200)}`);\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('zip') && !contentType.includes('octet-stream')) {\n throw new Error(`ClawHub download [${slug}] unexpected content-type: ${contentType}`);\n }\n const arrayBuf = await res.arrayBuffer();\n if (arrayBuf.byteLength > MAX_SKILL_ZIP_BYTES) {\n throw new Error(\n `ClawHub download [${slug}] exceeds size limit (${arrayBuf.byteLength} > ${MAX_SKILL_ZIP_BYTES})`,\n );\n }\n return { buffer: Buffer.from(arrayBuf), version: version?.trim() || 'latest' };\n}\n\nfunction pickClawHubDocFilePath(files: ClawHubVersionFile[]): string | null {\n const rows = files.map((f) => ({\n path: f.path.replace(/\\\\/g, '/'),\n base: f.path.replace(/\\\\/g, '/').split('/').pop()?.toLowerCase() ?? '',\n }));\n const find = (name: string) => rows.find((r) => r.base === name.toLowerCase());\n const skillMd = find('SKILL.md') ?? find('skill.md');\n if (skillMd) return skillMd.path;\n const readme = find('README.md') ?? find('readme.md');\n if (readme) return readme.path;\n return null;\n}\n\n// ─── In-memory TTL cache ─────────────────────────────────────────────────────\n\ntype CacheEntry<T> = { value: T; expiresAt: number };\n\nfunction cacheTtlMs(): number {\n const raw = process.env.XOPC_CLAWHUB_CACHE_MS?.trim();\n if (raw === '0' || raw === 'false') return 0;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_CACHE_MS;\n return parsed;\n}\n\nfunction getFresh<T>(entry: CacheEntry<T> | undefined): T | undefined {\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\nfunction evictOldest<T>(map: Map<string, CacheEntry<T>>): void {\n const first = map.keys().next().value;\n if (first !== undefined) map.delete(first);\n}\n\nconst listCache = new Map<string, CacheEntry<ClawHubSkillListResponse>>();\nconst searchCache = new Map<string, CacheEntry<ClawHubSearchResponse>>();\nconst detailCache = new Map<string, CacheEntry<ClawHubSkillDetail>>();\n\nasync function cachedListClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const ttl = cacheTtlMs();\n const key = JSON.stringify(params ?? {});\n if (ttl > 0) {\n const hit = getFresh(listCache.get(key));\n if (hit) return hit;\n }\n const value = await listClawHubSkills(params);\n if (ttl > 0) {\n while (listCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(listCache);\n listCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedSearchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const ttl = cacheTtlMs();\n const key = `${query}::${limit ?? ''}`;\n if (ttl > 0) {\n const hit = getFresh(searchCache.get(key));\n if (hit) return hit;\n }\n const value = await searchClawHubSkills(query, limit);\n if (ttl > 0) {\n while (searchCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(searchCache);\n searchCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedGetClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const ttl = cacheTtlMs();\n const key = slug.trim();\n if (ttl > 0) {\n const hit = getFresh(detailCache.get(key));\n if (hit) return hit;\n }\n const value = await getClawHubSkillDetail(slug);\n if (ttl > 0) {\n while (detailCache.size >= MAX_DETAIL_CACHE_KEYS) evictOldest(detailCache);\n detailCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\n// ─── Adapter conversion helpers ──────────────────────────────────────────────\n\ninterface PackageListItem {\n id: string;\n name: string;\n type: string;\n description: string;\n downloads: number;\n author: { username: string; avatarUrl: string | null };\n latestVersion?: string;\n updatedAt: string;\n categories?: string[];\n stars?: number;\n sourceLabel?: string;\n}\n\nfunction convertListItemToPackageItem(item: ClawHubSkillListItem): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: item.stats.downloads,\n author: { username: 'clawhub', avatarUrl: null },\n latestVersion: item.latestVersion?.version ?? item.tags.latest ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: item.metadata?.os ?? [],\n stars: item.stats.stars,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction convertSearchResultToPackageItem(\n item: ClawHubSearchResultItem,\n enrichment?: ClawHubSkillListItem,\n): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: enrichment?.stats.downloads ?? 0,\n author: {\n username: item.owner?.handle ?? item.ownerHandle ?? 'clawhub',\n avatarUrl: item.owner?.image ?? null,\n },\n latestVersion: item.version ?? enrichment?.latestVersion?.version ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: enrichment?.metadata?.os ?? [],\n stars: enrichment?.stats.stars ?? 0,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction mapSortParam(sort?: string): ClawHubListSort | undefined {\n if (sort === 'downloads') return 'downloads';\n if (sort === 'newest') return 'newest';\n return undefined;\n}\n\nfunction fallbackReadmeMarkdown(detail: {\n skill: { slug: string; displayName: string; summary: string };\n latestVersion: { version: string };\n}): string {\n const title = detail.skill.displayName || detail.skill.slug;\n const body = detail.skill.summary || '_No description._';\n return `## ${title}\\n\\n**${detail.skill.slug}** · v${detail.latestVersion.version}\\n\\n${body}`;\n}\n\nexport const clawHubMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'clawhub',\n\n async listCategories() {\n return [];\n },\n\n async listPackages(_config, params) {\n const pageSize = params.pageSize ?? 20;\n const page = params.page ?? 1;\n\n if (params.q?.trim()) {\n // Search results from /search omit downloads/stars/metadata. We pull the cached list\n // snapshot in parallel and merge by slug — costs nothing when the list cache is hot\n // (which it is after any preceding browse), and adds at most one round-trip on a cold\n // cache. We still tolerate a list-fetch failure: enrichment becomes a no-op.\n const [searchResponse, listSettled] = await Promise.allSettled([\n cachedSearchClawHubSkills(params.q.trim(), LIST_BATCH_SIZE),\n cachedListClawHubSkills({ limit: LIST_BATCH_SIZE }),\n ]);\n if (searchResponse.status === 'rejected') throw searchResponse.reason;\n const enrichmentBySlug = new Map<string, ClawHubSkillListItem>();\n if (listSettled.status === 'fulfilled') {\n for (const it of listSettled.value.items) enrichmentBySlug.set(it.slug, it);\n }\n let rows = searchResponse.value.results.map((r) =>\n convertSearchResultToPackageItem(r, enrichmentBySlug.get(r.slug)),\n );\n if (params.sort === 'downloads') {\n rows = [...rows].sort((a, b) => b.downloads - a.downloads);\n } else if (params.sort === 'newest') {\n rows = [...rows].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n }\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n }\n\n const sort = mapSortParam(params.sort);\n const listResponse = await cachedListClawHubSkills({ limit: LIST_BATCH_SIZE, sort });\n const rows = listResponse.items.map(convertListItemToPackageItem);\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n },\n\n async getPackageDetail(_config, packageName) {\n const detail = await cachedGetClawHubSkillDetail(packageName);\n const slug = detail.skill.slug;\n const version = detail.latestVersion.version;\n\n let readme: string | null = null;\n\n try {\n const versionDetail = await getClawHubVersionDetail(slug, version);\n const docPath = pickClawHubDocFilePath(versionDetail.version.files);\n if (docPath) {\n const rawText = await getClawHubSkillFileText(slug, docPath, version);\n const trimmed = rawText.trim();\n if (trimmed) readme = trimmed;\n }\n } catch {\n // version detail or file fetch failed — use fallback\n }\n\n if (!readme) {\n readme = fallbackReadmeMarkdown(detail);\n }\n\n const changelog = detail.latestVersion.changelog?.trim();\n if (changelog) {\n readme = `${readme}\\n\\n---\\n\\n## Changelog\\n\\n${changelog}`;\n }\n\n const description = detail.skill.summary || '';\n const skillDocPreview = buildSkillMarkdownPreviewFromRaw(readme, {\n name: slug,\n description,\n });\n\n return {\n id: slug,\n name: slug,\n type: 'skill',\n description,\n readme,\n skillDocPreview,\n downloads: detail.skill.stats.downloads,\n author: {\n username: detail.owner.handle,\n avatarUrl: detail.owner.image,\n },\n latestVersion: {\n version: detail.latestVersion.version,\n changelog: detail.latestVersion.changelog,\n publishedAt: String(detail.latestVersion.createdAt),\n },\n provider: 'clawhub',\n };\n },\n\n async downloadPackage(_config, packageName, version) {\n const slug = packageName.trim();\n const result = await downloadClawHubSkillZip(slug, version);\n return {\n buffer: result.buffer,\n skillId: isValidSkillId(slug) ? slug : 'unknown',\n version: result.version,\n };\n },\n};\n\nregisterMarketplaceAdapter({\n adapter: clawHubMarketplaceAdapter,\n displayName: 'ClawHub',\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { registerMarketplaceAdapter } from "../../registry.js";
|
|
2
|
+
import { buildSkillMarkdownPreviewFromRaw } from "../../../skill-markdown-preview-from-raw.js";
|
|
2
3
|
import { sortMarketplaceCategories } from "../../marketplace-category-order.js";
|
|
3
4
|
import { basename } from "node:path";
|
|
4
5
|
//#region src/agent/skills/marketplace/adapters/skillhub/adapter.ts
|
|
@@ -334,12 +335,19 @@ function packageDetailFromCuratedSkill(skill) {
|
|
|
334
335
|
const version = (skill.version ?? "").trim() || "1.0.0";
|
|
335
336
|
const categories = (skill.categories ?? []).map((c) => String(c).trim()).filter(Boolean);
|
|
336
337
|
const sourceLabel = sourceLabelFromHomepage(skill.homepage);
|
|
338
|
+
const name = (skill.name ?? slug).trim() || slug;
|
|
339
|
+
const description = (skill.description ?? "").trim();
|
|
340
|
+
const readme = curatedSkillFallbackReadmeMarkdown(skill);
|
|
337
341
|
return {
|
|
338
342
|
id: slug,
|
|
339
|
-
name
|
|
343
|
+
name,
|
|
340
344
|
type: "skill",
|
|
341
|
-
description
|
|
342
|
-
readme
|
|
345
|
+
description,
|
|
346
|
+
readme,
|
|
347
|
+
skillDocPreview: buildSkillMarkdownPreviewFromRaw(readme, {
|
|
348
|
+
name,
|
|
349
|
+
description
|
|
350
|
+
}),
|
|
343
351
|
downloads: typeof skill.downloads === "number" ? skill.downloads : 0,
|
|
344
352
|
author: {
|
|
345
353
|
username: sourceLabel?.toLowerCase() ?? "skillhub",
|
|
@@ -761,12 +769,18 @@ const skillHubMarketplaceAdapter = {
|
|
|
761
769
|
readme = trimmed;
|
|
762
770
|
if (changelog?.trim() && !isPipelineOnlyChangelog(changelog)) readme = `${trimmed}\n\n---\n\n## Changelog\n\n${changelog.trim()}`;
|
|
763
771
|
}
|
|
772
|
+
const description = detail.skill.summary_zh || detail.skill.summary;
|
|
773
|
+
const skillDocPreview = buildSkillMarkdownPreviewFromRaw(readme, {
|
|
774
|
+
name: detail.skill.slug,
|
|
775
|
+
description
|
|
776
|
+
});
|
|
764
777
|
return {
|
|
765
778
|
id: detail.skill.slug,
|
|
766
779
|
name: detail.skill.slug,
|
|
767
780
|
type: "skill",
|
|
768
|
-
description
|
|
781
|
+
description,
|
|
769
782
|
readme,
|
|
783
|
+
skillDocPreview,
|
|
770
784
|
downloads: detail.skill.stats.downloads,
|
|
771
785
|
author: {
|
|
772
786
|
username: detail.owner.handle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/skillhub/adapter.ts"],"sourcesContent":["/**\n * SkillHub (skillhub.cn) skills marketplace adapter.\n */\n\nimport { basename } from 'node:path';\n\nimport type { MarketplaceCategoryOption } from '../store/store-api-client.js';\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { sortMarketplaceCategories } from '../../marketplace-category-order.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst SKILLHUB_API_BASE = 'https://api.skillhub.cn';\nconst MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\nconst MAX_SKILLHUB_README_BYTES = 512 * 1024;\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst REGISTRY_SKILL_BATCH_CHUNK = 80;\n\nconst DEFAULT_SKILLS_INDEX_URL = 'https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/skills.json';\nconst DEFAULT_SEARCH_URL = 'https://lightmake.site/api/v1/search';\nconst DEFAULT_PRIMARY_DOWNLOAD_TEMPLATE = 'https://lightmake.site/api/v1/download?slug={slug}';\nconst DEFAULT_FALLBACK_DOWNLOAD_TEMPLATE =\n 'https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/skills/{slug}.zip';\nconst DEFAULT_ALLOWED_DOWNLOAD_HOSTS = new Set([\n 'lightmake.site',\n 'api.skillhub.cn',\n 'skillhub-1388575217.cos.ap-guangzhou.myqcloud.com',\n]);\nconst LIGHTMAKE_SEARCH_MAX = 100;\nconst SKILLSET_DISCOVERY_PAGE_CAP = 25;\nconst MAX_DEFAULT_SLUGS = 200;\n\nconst DEFAULT_CACHE_MS = 5 * 60 * 1000;\nconst MAX_BATCH_CACHE_KEYS = 48;\n\n// ─── Inline helpers ──────────────────────────────────────────────────────────\n\nfunction isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\n// ─── SkillHub registry types ─────────────────────────────────────────────────\n\ninterface SkillHubSkill {\n slug: string;\n displayName: string;\n summary: string;\n summary_zh?: string;\n category: string;\n iconUrl: string | null;\n source: string;\n labels: { requires_api_key?: string };\n stats: {\n downloads: number;\n installs: number;\n stars: number;\n comments: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n tags: Record<string, string>;\n}\n\ninterface SkillHubSkillDetail {\n skill: SkillHubSkill;\n latestVersion: {\n version: string;\n changelog: string | null;\n createdAt: number;\n securityReports?: {\n keen?: { status: string; statusText: string; reportUrl?: string };\n sanbu?: { status: string; statusText: string; reportUrl?: string };\n };\n };\n owner: { handle: string; displayName: string; image: string | null };\n}\n\ninterface SkillHubFile { path: string; sha256: string; size: number }\n\ninterface SkillHubRegistryCategoryItem {\n key: string;\n name: string;\n nameEn: string;\n sortOrder: number;\n active: boolean;\n}\n\ninterface SkillHubSkillset {\n id: number;\n slug: string;\n displayName: string;\n summary: string;\n scene: string;\n subScene: string;\n content: string;\n skillSlugs: string[];\n skillCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\n// ─── Ecosystem types ─────────────────────────────────────────────────────────\n\ninterface EcosystemUrls {\n skillsIndexUrl: string;\n searchUrl: string;\n primaryDownloadTemplate: string;\n fallbackDownloadTemplate: string;\n}\n\ninterface CuratedIndexSkill {\n rank?: number;\n slug: string;\n name?: string;\n description?: string;\n version?: string;\n homepage?: string;\n downloads?: number;\n stars?: number;\n score?: number;\n categories?: string[];\n}\n\ninterface CuratedIndex {\n total?: number;\n skills: CuratedIndexSkill[];\n}\n\ninterface LightmakeSearchHit {\n slug: string;\n displayName?: string;\n name?: string;\n summary?: string;\n description?: string;\n description_zh?: string;\n version?: string;\n downloads?: number;\n installs?: number;\n stars?: number;\n owner_name?: string;\n category?: string;\n score?: number;\n updatedAt?: number;\n updated_at?: number;\n /** Origin registry label from Lightmake (e.g. clawhub, community). Detail/download still go\n * through api.skillhub.cn for synced skills. */\n source?: string;\n}\n\ninterface PackageListItem {\n id: string;\n name: string;\n type: string;\n description: string;\n downloads: number;\n author: { username: string; avatarUrl: string | null };\n latestVersion?: string;\n updatedAt: string;\n categories?: string[];\n stars?: number;\n sourceLabel?: string;\n}\n\n// ─── Registry HTTP helpers ───────────────────────────────────────────────────\n\nasync function registryFetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, {\n ...init,\n headers: { Accept: 'application/json', ...(init?.headers as Record<string, string> | undefined) },\n });\n const text = await res.text();\n if (!res.ok) {\n let msg = `SkillHub request failed (${res.status})`;\n try {\n const j = JSON.parse(text) as { message?: string; error?: string };\n if (j.message) msg = j.message;\n else if (j.error) msg = j.error;\n } catch { if (text) msg = text.slice(0, 200); }\n throw new Error(msg);\n }\n try { return JSON.parse(text) as T; }\n catch { throw new Error('SkillHub returned invalid JSON'); }\n}\n\nfunction basenameSkillPath(p: string): string {\n const norm = p.replace(/\\\\/g, '/');\n const parts = norm.split('/');\n return parts[parts.length - 1] || norm;\n}\n\nfunction pickSkillHubDocFilePath(files: SkillHubFile[]): string | null {\n const rows = files.map((f) => ({\n path: f.path.replace(/\\\\/g, '/'),\n base: basenameSkillPath(f.path).toLowerCase(),\n }));\n const firstBase = (name: string) => rows.find((r) => r.base === name.toLowerCase());\n const skillMd = firstBase('SKILL.md') ?? firstBase('skill.md');\n if (skillMd) return skillMd.path;\n const readme = firstBase('README.md') ?? firstBase('readme.md');\n if (readme) return readme.path;\n const how = firstBase('HOW_TO_USE.md');\n if (how) return how.path;\n return null;\n}\n\nfunction assertSkillHubReadmeResponseUrl(finalUrl: string): void {\n let u: URL;\n try { u = new URL(finalUrl); } catch { throw new Error('Invalid SkillHub file response URL'); }\n if (u.protocol !== 'https:') throw new Error('SkillHub file response must use HTTPS');\n const host = u.hostname.toLowerCase();\n if (host === 'api.skillhub.cn') return;\n if (host.endsWith('.myqcloud.com')) return;\n throw new Error('SkillHub file redirect host is not allowlisted');\n}\n\nasync function getSkillHubSkillFileText(slug: string, filePath: string, version?: string): Promise<string> {\n const enc = encodeURIComponent(slug.trim());\n const normPath = filePath.replace(/\\\\/g, '/');\n const sp = new URLSearchParams({ path: normPath });\n if (version?.trim()) sp.set('version', version.trim());\n const url = `${SKILLHUB_API_BASE}/api/v1/skills/${enc}/file?${sp.toString()}`;\n const res = await fetch(url, { redirect: 'follow', headers: { Accept: 'text/markdown,text/plain,*/*' } });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n let msg = `SkillHub file request failed (${res.status})`;\n try {\n const j = JSON.parse(text) as { message?: string; error?: string };\n if (typeof j.message === 'string') msg = j.message;\n else if (typeof j.error === 'string') msg = j.error;\n } catch { if (text) msg = text.slice(0, 200); }\n throw new Error(msg);\n }\n assertSkillHubReadmeResponseUrl(res.url);\n const len = res.headers.get('content-length');\n if (len) {\n const n = Number(len);\n if (Number.isFinite(n) && n > MAX_SKILLHUB_README_BYTES) throw new Error(`SkillHub file exceeds max size`);\n }\n const ab = await res.arrayBuffer();\n if (ab.byteLength > MAX_SKILLHUB_README_BYTES) throw new Error(`SkillHub file exceeds max size`);\n return new TextDecoder('utf-8').decode(ab);\n}\n\nasync function getSkillHubSkill(slug: string): Promise<SkillHubSkillDetail> {\n return registryFetchJson<SkillHubSkillDetail>(`${SKILLHUB_API_BASE}/api/v1/skills/${encodeURIComponent(slug.trim())}`);\n}\n\nasync function getSkillHubSkillFiles(slug: string, version?: string): Promise<{ files: SkillHubFile[]; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n const sp = version ? `?version=${encodeURIComponent(version)}` : '';\n return registryFetchJson<{ files: SkillHubFile[]; version: string }>(`${SKILLHUB_API_BASE}/api/v1/skills/${enc}/files${sp}`);\n}\n\nasync function downloadSkillHubZipBuffer(slug: string, version?: string): Promise<{ buffer: Buffer; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n let url = `${SKILLHUB_API_BASE}/api/v1/download?slug=${enc}`;\n if (version?.trim()) url += `&version=${encodeURIComponent(version.trim())}`;\n const res = await fetch(url, { redirect: 'follow' });\n if (!res.ok) throw new Error(`Failed to download skill archive (${res.status})`);\n const len = res.headers.get('content-length');\n if (len) { const n = Number(len); if (Number.isFinite(n) && n > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`); }\n const ab = await res.arrayBuffer();\n const buf = Buffer.from(ab);\n if (buf.length > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`);\n let resolvedVersion = version ?? '1.0.0';\n if (!version?.trim()) {\n try { resolvedVersion = (await getSkillHubSkillFiles(slug)).version; } catch { /* keep default */ }\n }\n return { buffer: buf, version: resolvedVersion };\n}\n\nasync function batchGetSkillHubSkills(slugs: string[]): Promise<SkillHubSkillDetail[]> {\n if (slugs.length === 0) return [];\n const response = await registryFetchJson<{ count: number; items: SkillHubSkillDetail[]; missing: string[] }>(\n `${SKILLHUB_API_BASE}/api/v1/skills/batch`,\n { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ slugs }) },\n );\n return response.items ?? [];\n}\n\nasync function listSkillHubRegistryCategories(): Promise<SkillHubRegistryCategoryItem[]> {\n const raw = await registryFetchJson<{ count?: number; items?: SkillHubRegistryCategoryItem[] }>(\n `${SKILLHUB_API_BASE}/api/v1/categories`,\n );\n const items = Array.isArray(raw.items) ? raw.items : [];\n return items.filter((c) => c && typeof c.key === 'string' && c.key.trim().length > 0 && c.active !== false);\n}\n\nasync function listSkillHubSkillsets(opts: { page?: number; pageSize?: number; keyword?: string; scene?: string } = {}): Promise<{ skillSets: SkillHubSkillset[]; total: number }> {\n const page = opts.page ?? 1;\n const pageSize = opts.pageSize ?? 20;\n const sp = new URLSearchParams({ page: String(page), pageSize: String(pageSize) });\n if (opts.keyword?.trim()) sp.set('keyword', opts.keyword.trim());\n if (opts.scene?.trim()) sp.set('scene', opts.scene.trim());\n return registryFetchJson<{ skillSets: SkillHubSkillset[]; total: number }>(`${SKILLHUB_API_BASE}/api/v1/skillsets?${sp.toString()}`);\n}\n\nasync function getDefaultSkillSlugs(): Promise<string[]> {\n const slugs = new Set<string>();\n let page = 1;\n const pageSize = 50;\n let total = Infinity;\n while (page <= SKILLSET_DISCOVERY_PAGE_CAP && slugs.size < MAX_DEFAULT_SLUGS) {\n const response = await listSkillHubSkillsets({ page, pageSize });\n total = response.total;\n for (const skillset of response.skillSets) {\n for (const slug of skillset.skillSlugs) slugs.add(slug);\n }\n if (page * pageSize >= total) break;\n page += 1;\n }\n return Array.from(slugs).slice(0, MAX_DEFAULT_SLUGS);\n}\n\nasync function searchSkillHubSkills(query: string, maxSlugs = 200): Promise<{ slugs: string[]; total: number }> {\n const keyword = query.trim();\n if (!keyword) return { slugs: [], total: 0 };\n const slugs: string[] = [];\n const seen = new Set<string>();\n let page = 1;\n const batchSize = 50;\n while (page <= SKILLSET_DISCOVERY_PAGE_CAP) {\n const response = await listSkillHubSkillsets({ page, pageSize: batchSize, keyword });\n for (const skillset of response.skillSets) {\n for (const slug of skillset.skillSlugs) {\n if (!seen.has(slug)) { seen.add(slug); slugs.push(slug); }\n }\n }\n if (page * batchSize >= response.total) break;\n page += 1;\n }\n const capped = slugs.slice(0, maxSlugs);\n return { slugs: capped, total: capped.length };\n}\n\n// ─── Ecosystem helpers ───────────────────────────────────────────────────────\n\nfunction templateWithSlug(template: string, slug: string): string {\n const raw = template.trim();\n if (!raw) return '';\n if (raw.includes('{slug}')) return raw.replaceAll('{slug}', encodeURIComponent(slug.trim()));\n const base = raw.replace(/\\/$/, '');\n return `${base}/${encodeURIComponent(slug.trim())}.zip`;\n}\n\nfunction hostFromTemplate(template: string): string | undefined {\n const t = templateWithSlug(template, 'x');\n try { return new URL(t).hostname.toLowerCase(); } catch { return undefined; }\n}\n\nfunction resolveSkillHubEcosystemUrls(): EcosystemUrls {\n return {\n skillsIndexUrl: process.env.XOPC_SKILLHUB_SKILLS_INDEX_URL?.trim() || DEFAULT_SKILLS_INDEX_URL,\n searchUrl: process.env.XOPC_SKILLHUB_SEARCH_URL?.trim() || DEFAULT_SEARCH_URL,\n primaryDownloadTemplate: process.env.XOPC_SKILLHUB_PRIMARY_DOWNLOAD_TEMPLATE?.trim() || DEFAULT_PRIMARY_DOWNLOAD_TEMPLATE,\n fallbackDownloadTemplate: process.env.XOPC_SKILLHUB_FALLBACK_DOWNLOAD_TEMPLATE?.trim() || DEFAULT_FALLBACK_DOWNLOAD_TEMPLATE,\n };\n}\n\nfunction allowedDownloadHosts(urls: EcosystemUrls): Set<string> {\n const hosts = new Set(DEFAULT_ALLOWED_DOWNLOAD_HOSTS);\n for (const h of [hostFromTemplate(urls.primaryDownloadTemplate), hostFromTemplate(urls.fallbackDownloadTemplate)]) { if (h) hosts.add(h); }\n try { hosts.add(new URL(urls.skillsIndexUrl).hostname.toLowerCase()); } catch { /* ignore */ }\n try { hosts.add(new URL(urls.searchUrl).hostname.toLowerCase()); } catch { /* ignore */ }\n return hosts;\n}\n\nfunction assertSkillHubDownloadUrlAllowed(downloadUrl: string, urls: EcosystemUrls): URL {\n let u: URL;\n try { u = new URL(downloadUrl); } catch { throw new Error('Invalid SkillHub download URL'); }\n if (u.protocol !== 'https:') throw new Error('SkillHub download URL must use HTTPS');\n if (!allowedDownloadHosts(urls).has(u.hostname.toLowerCase())) throw new Error('SkillHub download URL host is not allowlisted');\n return u;\n}\n\nasync function ecoFetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, { ...init, headers: { Accept: 'application/json', ...init?.headers } });\n const text = await res.text();\n if (!res.ok) {\n let msg = `SkillHub ecosystem request failed (${res.status})`;\n try { const j = JSON.parse(text) as { message?: string; error?: string }; if (j.message) msg = j.message; else if (j.error) msg = j.error; } catch { if (text) msg = text.slice(0, 200); }\n throw new Error(msg);\n }\n try { return JSON.parse(text) as T; } catch { throw new Error('SkillHub ecosystem returned invalid JSON'); }\n}\n\nasync function fetchSkillHubCuratedIndex(urls: EcosystemUrls): Promise<CuratedIndex> {\n const raw = await ecoFetchJson<unknown>(urls.skillsIndexUrl);\n if (Array.isArray(raw)) return { skills: raw as CuratedIndexSkill[] };\n if (raw && typeof raw === 'object' && Array.isArray((raw as CuratedIndex).skills)) return raw as CuratedIndex;\n throw new Error('SkillHub index JSON must be an object with a skills array');\n}\n\nfunction sourceLabelFromHomepage(homepage?: string): string | undefined {\n const h = homepage?.trim().toLowerCase() ?? '';\n if (h.includes('clawhub')) return 'ClawHub';\n if (h.includes('skillhub')) return 'SkillHub';\n return undefined;\n}\n\nfunction curatedSkillsToPackageItems(skills: CuratedIndexSkill[]): PackageListItem[] {\n return skills.map((s) => ({\n id: s.slug,\n name: (s.name ?? s.slug).trim() || s.slug,\n type: 'skill',\n description: (s.description ?? '').trim(),\n downloads: typeof s.downloads === 'number' ? s.downloads : 0,\n author: { username: 'skillhub', avatarUrl: null },\n latestVersion: (s.version ?? '').trim() || undefined,\n updatedAt: String(s.rank ?? s.score ?? 0),\n categories: (s.categories ?? []).map((c) => String(c).trim()).filter(Boolean),\n stars: typeof s.stars === 'number' ? s.stars : undefined,\n sourceLabel: sourceLabelFromHomepage(s.homepage),\n }));\n}\n\nasync function findCuratedIndexSkill(slug: string): Promise<CuratedIndexSkill | null> {\n const want = slug.trim();\n if (!want) return null;\n const ecoUrls = resolveSkillHubEcosystemUrls();\n try {\n const idx = await cachedFetchSkillHubCuratedIndex(ecoUrls);\n return idx.skills.find((s) => s.slug?.trim() === want) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction curatedSkillFallbackReadmeMarkdown(skill: CuratedIndexSkill): string {\n const title = (skill.name ?? skill.slug).trim() || skill.slug;\n const desc = (skill.description ?? '').trim() || '_No description._';\n const version = (skill.version ?? '').trim() || '1.0.0';\n return `## ${title}\\n\\n**${skill.slug}** · v${version}\\n\\n${desc}`;\n}\n\nfunction packageDetailFromCuratedSkill(skill: CuratedIndexSkill) {\n const slug = skill.slug.trim();\n const version = (skill.version ?? '').trim() || '1.0.0';\n const categories = (skill.categories ?? []).map((c) => String(c).trim()).filter(Boolean);\n const sourceLabel = sourceLabelFromHomepage(skill.homepage);\n return {\n id: slug,\n name: (skill.name ?? slug).trim() || slug,\n type: 'skill',\n description: (skill.description ?? '').trim(),\n readme: curatedSkillFallbackReadmeMarkdown(skill),\n downloads: typeof skill.downloads === 'number' ? skill.downloads : 0,\n author: {\n username: sourceLabel?.toLowerCase() ?? 'skillhub',\n avatarUrl: null,\n },\n latestVersion: {\n version,\n changelog: null,\n publishedAt: String(skill.rank ?? skill.score ?? 0),\n },\n provider: 'skillhub',\n skillHubInfo: {\n category: categories[0] ?? '',\n installs: 0,\n stars: typeof skill.stars === 'number' ? skill.stars : 0,\n },\n };\n}\n\nfunction lightmakeHitToPackageItem(hit: LightmakeSearchHit): PackageListItem {\n const slug = String(hit.slug || '').trim();\n const desc = (hit.summary ?? hit.description_zh ?? hit.description ?? '').trim() || '';\n const updated = hit.updatedAt ?? hit.updated_at ?? 0;\n const cat = hit.category?.trim();\n return {\n id: slug,\n name: (hit.displayName ?? hit.name ?? slug).trim() || slug,\n type: 'skill',\n description: desc,\n downloads: typeof hit.downloads === 'number' ? hit.downloads : 0,\n author: { username: (hit.owner_name ?? 'skillhub').trim() || 'skillhub', avatarUrl: null },\n latestVersion: (hit.version ?? '').trim() || undefined,\n updatedAt: String(updated),\n categories: cat ? [cat] : [],\n stars: typeof hit.stars === 'number' ? hit.stars : undefined,\n sourceLabel: sourceLabelFromSkillSource(hit.source) ?? 'Lightmake',\n };\n}\n\nasync function searchSkillHubLightmake(urls: EcosystemUrls, query: string, limit: number, timeoutMs = 4000): Promise<PackageListItem[]> {\n const q = query.trim().toLowerCase();\n if (!q) return [];\n const search = new URL(urls.searchUrl);\n if (search.protocol !== 'https:') throw new Error('SkillHub search URL must use HTTPS');\n search.searchParams.set('q', q);\n search.searchParams.set('limit', String(Math.max(1, Math.min(LIGHTMAKE_SEARCH_MAX, limit))));\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const raw = await ecoFetchJson<{ results?: LightmakeSearchHit[] }>(search.toString(), { signal: controller.signal });\n const results = raw.results;\n if (!Array.isArray(results)) return [];\n const out: PackageListItem[] = [];\n for (const item of results) {\n if (!item || typeof item !== 'object') continue;\n const hit = item as LightmakeSearchHit;\n const slug = String(hit.slug ?? '').trim();\n if (!slug) continue;\n out.push(lightmakeHitToPackageItem(hit));\n }\n return out;\n } finally { clearTimeout(timer); }\n}\n\nasync function downloadSkillHubZipFromAllowlistedUrl(urls: EcosystemUrls, downloadUrl: string): Promise<Buffer> {\n const normalized = assertSkillHubDownloadUrlAllowed(downloadUrl, urls);\n const res = await fetch(normalized.toString(), { redirect: 'follow' });\n if (!res.ok) throw new Error(`Failed to download skill archive (${res.status})`);\n const len = res.headers.get('content-length');\n if (len) { const n = Number(len); if (Number.isFinite(n) && n > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`); }\n const ab = await res.arrayBuffer();\n const buf = Buffer.from(ab);\n if (buf.length > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`);\n return buf;\n}\n\nasync function downloadSkillHubZipFromEcosystem(urls: EcosystemUrls, slug: string): Promise<Buffer> {\n const primary = templateWithSlug(urls.primaryDownloadTemplate, slug);\n const fallback = templateWithSlug(urls.fallbackDownloadTemplate, slug);\n const candidates = [primary, fallback].filter(Boolean);\n const seen = new Set<string>();\n let lastErr: Error | undefined;\n for (const url of candidates) {\n if (seen.has(url)) continue;\n seen.add(url);\n try { return await downloadSkillHubZipFromAllowlistedUrl(urls, url); }\n catch (e) { lastErr = e instanceof Error ? e : new Error(String(e)); }\n }\n throw lastErr ?? new Error('SkillHub ecosystem download failed');\n}\n\n// ─── In-memory TTL cache ─────────────────────────────────────────────────────\n\ntype CacheEntry<T> = { value: T; expiresAt: number };\n\nfunction cacheTtlMs(): number {\n const raw = process.env.XOPC_SKILLHUB_CACHE_MS?.trim();\n if (raw === '0' || raw === 'false') return 0;\n const n = Number(raw);\n if (!Number.isFinite(n) || n < 0) return DEFAULT_CACHE_MS;\n return n;\n}\n\nfunction getFresh<T>(entry: CacheEntry<T> | undefined): T | undefined {\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\nconst curatedByIndexUrl = new Map<string, CacheEntry<CuratedIndex>>();\nlet defaultSlugsEntry: CacheEntry<string[]> | undefined;\nlet registryCategoriesEntry: CacheEntry<SkillHubRegistryCategoryItem[]> | undefined;\nconst batchBySlugsKey = new Map<string, CacheEntry<SkillHubSkillDetail[]>>();\nconst lightmakeSearchByQuery = new Map<string, CacheEntry<PackageListItem[]>>();\n\nfunction evictOldestBatchKey(): void {\n const first = batchBySlugsKey.keys().next().value;\n if (first !== undefined) batchBySlugsKey.delete(first);\n}\n\nfunction evictOldestSearchKey(): void {\n const first = lightmakeSearchByQuery.keys().next().value;\n if (first !== undefined) lightmakeSearchByQuery.delete(first);\n}\n\nfunction batchSlugsCacheKey(slugs: string[]): string {\n if (slugs.length === 0) return '';\n return [...slugs].sort().join('\\n');\n}\n\nasync function cachedFetchSkillHubCuratedIndex(urls: EcosystemUrls): Promise<CuratedIndex> {\n const ttl = cacheTtlMs();\n const key = urls.skillsIndexUrl;\n if (ttl > 0) { const hit = getFresh(curatedByIndexUrl.get(key)); if (hit) return hit; }\n const value = await fetchSkillHubCuratedIndex(urls);\n if (ttl > 0) curatedByIndexUrl.set(key, { value, expiresAt: Date.now() + ttl });\n return value;\n}\n\nasync function cachedGetDefaultSkillSlugs(): Promise<string[]> {\n const ttl = cacheTtlMs();\n if (ttl > 0) { const hit = getFresh(defaultSlugsEntry); if (hit) return hit; }\n const value = await getDefaultSkillSlugs();\n if (ttl > 0) defaultSlugsEntry = { value, expiresAt: Date.now() + ttl };\n return value;\n}\n\nasync function cachedListSkillHubRegistryCategories(): Promise<SkillHubRegistryCategoryItem[]> {\n const ttl = cacheTtlMs();\n if (ttl > 0) { const hit = getFresh(registryCategoriesEntry); if (hit) return hit; }\n const value = await listSkillHubRegistryCategories();\n if (ttl > 0) registryCategoriesEntry = { value, expiresAt: Date.now() + ttl };\n return value;\n}\n\nasync function cachedBatchGetSkillHubSkills(slugs: string[]): Promise<SkillHubSkillDetail[]> {\n if (slugs.length === 0) return [];\n const ttl = cacheTtlMs();\n const key = batchSlugsCacheKey(slugs);\n if (ttl > 0) { const hit = getFresh(batchBySlugsKey.get(key)); if (hit) return hit; }\n const value = await batchGetSkillHubSkills(slugs);\n if (ttl > 0) {\n while (batchBySlugsKey.size >= MAX_BATCH_CACHE_KEYS) evictOldestBatchKey();\n batchBySlugsKey.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedSearchSkillHubLightmake(\n urls: EcosystemUrls,\n query: string,\n limit: number,\n): Promise<PackageListItem[]> {\n const q = query.trim().toLowerCase();\n if (!q) return [];\n const ttl = cacheTtlMs();\n const key = `${urls.searchUrl}|${q}|${limit}`;\n if (ttl > 0) { const hit = getFresh(lightmakeSearchByQuery.get(key)); if (hit) return hit; }\n const value = await searchSkillHubLightmake(urls, q, limit);\n if (ttl > 0) {\n while (lightmakeSearchByQuery.size >= MAX_BATCH_CACHE_KEYS) evictOldestSearchKey();\n lightmakeSearchByQuery.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\n// ─── Adapter conversion helpers ──────────────────────────────────────────────\n\nfunction humanizeRegistryCategoryKey(slug: string): string {\n return slug.replace(/_/g, '-').split('-').filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' ');\n}\n\nfunction sourceLabelFromSkillSource(source: string | undefined): string | undefined {\n const s = source?.trim();\n if (!s) return undefined;\n const lower = s.toLowerCase();\n if (lower === 'clawhub') return 'ClawHub';\n if (lower === 'lightmake') return 'Lightmake';\n if (lower === 'skillhub') return 'SkillHub';\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction filterByCategory(rows: PackageListItem[], category?: string): PackageListItem[] {\n const want = category?.trim();\n if (!want) return rows;\n return rows.filter((r) => (r.categories ?? []).includes(want));\n}\n\nasync function collectRegistryCategoryKeysFromSlugs(slugs: string[]): Promise<Set<string>> {\n const used = new Set<string>();\n for (let i = 0; i < slugs.length; i += REGISTRY_SKILL_BATCH_CHUNK) {\n const chunk = slugs.slice(i, i + REGISTRY_SKILL_BATCH_CHUNK);\n const details = await cachedBatchGetSkillHubSkills(chunk);\n for (const d of details) {\n const k = d.skill.category?.trim();\n if (k) used.add(k);\n }\n }\n return used;\n}\n\nfunction isPipelineOnlyChangelog(text: string | null | undefined): boolean {\n if (!text?.trim()) return true;\n return /^synced by skillhub pipeline\\.?$/i.test(text.trim());\n}\n\nfunction skillHubFallbackReadmeMarkdown(detail: { skill: SkillHubSkill; latestVersion: { version: string } }): string {\n const s = detail.skill;\n const title = s.displayName?.trim() || s.slug;\n const zh = s.summary_zh?.trim();\n const en = s.summary?.trim();\n const body = zh && en && zh !== en ? `${zh}\\n\\n${en}` : zh || en || '_No description._';\n return `## ${title}\\n\\n**${s.slug}** · v${detail.latestVersion.version}\\n\\n${body}`;\n}\n\nfunction convertSkillHubToPackageListItem(detail: SkillHubSkill): PackageListItem {\n const cat = detail.category?.trim();\n return {\n id: detail.slug,\n name: detail.displayName?.trim() || detail.slug,\n type: 'skill',\n description: detail.summary_zh || detail.summary,\n downloads: detail.stats.downloads,\n author: { username: detail.source || 'skillhub', avatarUrl: null },\n latestVersion: detail.tags.latest || '1.0.0',\n updatedAt: String(detail.updatedAt),\n categories: cat ? [cat] : [],\n stars: detail.stats.stars,\n sourceLabel: sourceLabelFromSkillSource(detail.source),\n };\n}\n\nexport const skillHubMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'skillhub',\n\n async listCategories(_config) {\n const sortByLabel = (a: MarketplaceCategoryOption, b: MarketplaceCategoryOption) =>\n a.label.localeCompare(b.label, 'zh-Hans-CN', { sensitivity: 'base' });\n const ecoUrls = resolveSkillHubEcosystemUrls();\n try {\n const idx = await cachedFetchSkillHubCuratedIndex(ecoUrls);\n if (idx.skills?.length) {\n const map = new Map<string, MarketplaceCategoryOption>();\n for (const s of idx.skills) {\n for (const raw of s.categories ?? []) {\n const label = String(raw).trim();\n if (label) map.set(label, { id: label, label });\n }\n }\n return sortMarketplaceCategories(\n Array.from(map.values()).filter((c) => c.id.trim() && c.label.trim()),\n sortByLabel,\n );\n }\n } catch { /* fall through: registry-backed catalog */ }\n try {\n const [taxonomy, slugs] = await Promise.all([\n cachedListSkillHubRegistryCategories(),\n cachedGetDefaultSkillSlugs(),\n ]);\n const usedKeys = await collectRegistryCategoryKeysFromSlugs(slugs);\n const taxByKey = new Map(taxonomy.map((t) => [t.key, t] as const));\n const options: MarketplaceCategoryOption[] = [];\n for (const key of usedKeys) {\n const t = taxByKey.get(key);\n const label = t?.name?.trim() || t?.nameEn?.trim() || humanizeRegistryCategoryKey(key).trim();\n if (!label) continue;\n options.push({ id: key, label });\n }\n return sortMarketplaceCategories(options, (a, b) => {\n const oa = taxByKey.get(a.id)?.sortOrder ?? 999;\n const ob = taxByKey.get(b.id)?.sortOrder ?? 999;\n if (oa !== ob) return oa - ob;\n return sortByLabel(a, b);\n });\n } catch { return []; }\n },\n\n async listPackages(_config, params) {\n const pageSize = params.pageSize ?? 20;\n const page = params.page ?? 1;\n const ecoUrls = resolveSkillHubEcosystemUrls();\n\n if (params.q?.trim()) {\n const q = params.q.trim();\n let rows: PackageListItem[] = [];\n try {\n rows = await cachedSearchSkillHubLightmake(ecoUrls, q, 100);\n } catch {\n // Lightmake unavailable — fall back to the registry skillset scan. We do NOT run this\n // when Lightmake returned zero hits: that would queue ~40 sequential HTTP calls just to\n // confirm \"no results\", and the empty state UI is the better answer for the user.\n try {\n const searchResult = await searchSkillHubSkills(q, 200);\n const details = await cachedBatchGetSkillHubSkills(searchResult.slugs);\n rows = details.map((d) => convertSkillHubToPackageListItem(d.skill));\n } catch {\n rows = [];\n }\n }\n rows = filterByCategory(rows, params.category);\n if (params.sort === 'downloads') rows = [...rows].sort((a, b) => b.downloads - a.downloads);\n else if (params.sort === 'newest') rows = [...rows].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n }\n\n try {\n const idx = await cachedFetchSkillHubCuratedIndex(ecoUrls);\n let skills = [...idx.skills].filter((s) => s.slug?.trim());\n if (skills.length > 0) {\n if (params.category?.trim()) {\n const want = params.category.trim();\n skills = skills.filter((s) => (s.categories ?? []).some((x) => String(x).trim() === want));\n }\n if (params.sort === 'downloads') skills.sort((a, b) => (b.downloads ?? 0) - (a.downloads ?? 0));\n else if (params.sort === 'newest') skills.sort((a, b) => (a.rank ?? 999) - (b.rank ?? 999));\n const rows = curatedSkillsToPackageItems(skills);\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n }\n } catch { /* fall through */ }\n\n const slugs = await cachedGetDefaultSkillSlugs();\n if (params.category?.trim()) {\n const details = await cachedBatchGetSkillHubSkills(slugs);\n let allItems = details.map((d) => convertSkillHubToPackageListItem(d.skill));\n allItems = filterByCategory(allItems, params.category);\n if (params.sort === 'downloads') allItems = [...allItems].sort((a, b) => b.downloads - a.downloads);\n else if (params.sort === 'newest') allItems = [...allItems].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n const total = allItems.length;\n const start = (page - 1) * pageSize;\n const items = allItems.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n }\n\n const total = slugs.length;\n const start = (page - 1) * pageSize;\n const paginatedSlugs = slugs.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n const details = await cachedBatchGetSkillHubSkills(paginatedSlugs);\n const items = details.map((d) => convertSkillHubToPackageListItem(d.skill));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n },\n\n async getPackageDetail(_config, packageName) {\n const slug = packageName.trim();\n let detail: SkillHubSkillDetail;\n try {\n detail = await getSkillHubSkill(slug);\n } catch (registryErr) {\n const curated = await findCuratedIndexSkill(slug);\n if (curated) return packageDetailFromCuratedSkill(curated);\n throw registryErr;\n }\n const version = detail.latestVersion.version;\n const changelog = detail.latestVersion.changelog;\n\n let readme: string | null = null;\n let docPath: string | null = null;\n try {\n const { files } = await getSkillHubSkillFiles(slug, version);\n docPath = pickSkillHubDocFilePath(files);\n if (docPath) readme = await getSkillHubSkillFileText(slug, docPath, version);\n } catch { readme = null; }\n\n const trimmed = readme?.trim() ?? '';\n const docBase = docPath ? basename(docPath.replace(/\\\\/g, '/')).toLowerCase() : '';\n const isSkillMd = docBase === 'skill.md';\n\n if (!trimmed) {\n readme = skillHubFallbackReadmeMarkdown(detail);\n } else if (isSkillMd) {\n readme = trimmed;\n if (changelog?.trim() && !isPipelineOnlyChangelog(changelog)) {\n readme = `${trimmed}\\n\\n---\\n\\n## Changelog\\n\\n${changelog.trim()}`;\n }\n } else {\n readme = trimmed;\n if (changelog?.trim() && !isPipelineOnlyChangelog(changelog)) {\n readme = `${trimmed}\\n\\n---\\n\\n## Changelog\\n\\n${changelog.trim()}`;\n }\n }\n\n return {\n id: detail.skill.slug,\n name: detail.skill.slug,\n type: 'skill',\n description: detail.skill.summary_zh || detail.skill.summary,\n readme,\n downloads: detail.skill.stats.downloads,\n author: {\n username: detail.owner.handle,\n avatarUrl: detail.owner.image,\n },\n latestVersion: {\n version: detail.latestVersion.version,\n changelog: detail.latestVersion.changelog,\n publishedAt: String(detail.latestVersion.createdAt),\n },\n provider: 'skillhub',\n skillHubInfo: {\n category: detail.skill.category,\n installs: detail.skill.stats.installs,\n stars: detail.skill.stats.stars,\n securityReports: detail.latestVersion.securityReports,\n },\n };\n },\n\n async downloadPackage(_config, packageName, version) {\n const slug = packageName.trim();\n if (version?.trim()) {\n const { buffer, version: resolvedVersion } = await downloadSkillHubZipBuffer(slug, version);\n return { buffer, skillId: isValidSkillId(slug) ? slug : 'unknown', version: resolvedVersion };\n }\n const ecoUrls = resolveSkillHubEcosystemUrls();\n try {\n const buffer = await downloadSkillHubZipFromEcosystem(ecoUrls, slug);\n let resolvedVersion = '1.0.0';\n try { resolvedVersion = (await getSkillHubSkillFiles(slug)).version; } catch { /* keep default */ }\n return { buffer, skillId: isValidSkillId(slug) ? slug : 'unknown', version: resolvedVersion };\n } catch {\n const { buffer, version: resolvedVersion } = await downloadSkillHubZipBuffer(slug);\n return { buffer, skillId: isValidSkillId(slug) ? slug : 'unknown', version: resolvedVersion };\n }\n },\n};\n\nregisterMarketplaceAdapter({\n adapter: skillHubMarketplaceAdapter,\n displayName: 'SkillHub',\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/skillhub/adapter.ts"],"sourcesContent":["/**\n * SkillHub (skillhub.cn) skills marketplace adapter.\n */\n\nimport { basename } from 'node:path';\n\nimport { buildSkillMarkdownPreviewFromRaw } from '../../../skill-markdown-preview-from-raw.js';\nimport type { MarketplaceCategoryOption } from '../store/store-api-client.js';\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { sortMarketplaceCategories } from '../../marketplace-category-order.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst SKILLHUB_API_BASE = 'https://api.skillhub.cn';\nconst MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\nconst MAX_SKILLHUB_README_BYTES = 512 * 1024;\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst REGISTRY_SKILL_BATCH_CHUNK = 80;\n\nconst DEFAULT_SKILLS_INDEX_URL = 'https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/skills.json';\nconst DEFAULT_SEARCH_URL = 'https://lightmake.site/api/v1/search';\nconst DEFAULT_PRIMARY_DOWNLOAD_TEMPLATE = 'https://lightmake.site/api/v1/download?slug={slug}';\nconst DEFAULT_FALLBACK_DOWNLOAD_TEMPLATE =\n 'https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/skills/{slug}.zip';\nconst DEFAULT_ALLOWED_DOWNLOAD_HOSTS = new Set([\n 'lightmake.site',\n 'api.skillhub.cn',\n 'skillhub-1388575217.cos.ap-guangzhou.myqcloud.com',\n]);\nconst LIGHTMAKE_SEARCH_MAX = 100;\nconst SKILLSET_DISCOVERY_PAGE_CAP = 25;\nconst MAX_DEFAULT_SLUGS = 200;\n\nconst DEFAULT_CACHE_MS = 5 * 60 * 1000;\nconst MAX_BATCH_CACHE_KEYS = 48;\n\n// ─── Inline helpers ──────────────────────────────────────────────────────────\n\nfunction isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\n// ─── SkillHub registry types ─────────────────────────────────────────────────\n\ninterface SkillHubSkill {\n slug: string;\n displayName: string;\n summary: string;\n summary_zh?: string;\n category: string;\n iconUrl: string | null;\n source: string;\n labels: { requires_api_key?: string };\n stats: {\n downloads: number;\n installs: number;\n stars: number;\n comments: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n tags: Record<string, string>;\n}\n\ninterface SkillHubSkillDetail {\n skill: SkillHubSkill;\n latestVersion: {\n version: string;\n changelog: string | null;\n createdAt: number;\n securityReports?: {\n keen?: { status: string; statusText: string; reportUrl?: string };\n sanbu?: { status: string; statusText: string; reportUrl?: string };\n };\n };\n owner: { handle: string; displayName: string; image: string | null };\n}\n\ninterface SkillHubFile { path: string; sha256: string; size: number }\n\ninterface SkillHubRegistryCategoryItem {\n key: string;\n name: string;\n nameEn: string;\n sortOrder: number;\n active: boolean;\n}\n\ninterface SkillHubSkillset {\n id: number;\n slug: string;\n displayName: string;\n summary: string;\n scene: string;\n subScene: string;\n content: string;\n skillSlugs: string[];\n skillCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\n// ─── Ecosystem types ─────────────────────────────────────────────────────────\n\ninterface EcosystemUrls {\n skillsIndexUrl: string;\n searchUrl: string;\n primaryDownloadTemplate: string;\n fallbackDownloadTemplate: string;\n}\n\ninterface CuratedIndexSkill {\n rank?: number;\n slug: string;\n name?: string;\n description?: string;\n version?: string;\n homepage?: string;\n downloads?: number;\n stars?: number;\n score?: number;\n categories?: string[];\n}\n\ninterface CuratedIndex {\n total?: number;\n skills: CuratedIndexSkill[];\n}\n\ninterface LightmakeSearchHit {\n slug: string;\n displayName?: string;\n name?: string;\n summary?: string;\n description?: string;\n description_zh?: string;\n version?: string;\n downloads?: number;\n installs?: number;\n stars?: number;\n owner_name?: string;\n category?: string;\n score?: number;\n updatedAt?: number;\n updated_at?: number;\n /** Origin registry label from Lightmake (e.g. clawhub, community). Detail/download still go\n * through api.skillhub.cn for synced skills. */\n source?: string;\n}\n\ninterface PackageListItem {\n id: string;\n name: string;\n type: string;\n description: string;\n downloads: number;\n author: { username: string; avatarUrl: string | null };\n latestVersion?: string;\n updatedAt: string;\n categories?: string[];\n stars?: number;\n sourceLabel?: string;\n}\n\n// ─── Registry HTTP helpers ───────────────────────────────────────────────────\n\nasync function registryFetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, {\n ...init,\n headers: { Accept: 'application/json', ...(init?.headers as Record<string, string> | undefined) },\n });\n const text = await res.text();\n if (!res.ok) {\n let msg = `SkillHub request failed (${res.status})`;\n try {\n const j = JSON.parse(text) as { message?: string; error?: string };\n if (j.message) msg = j.message;\n else if (j.error) msg = j.error;\n } catch { if (text) msg = text.slice(0, 200); }\n throw new Error(msg);\n }\n try { return JSON.parse(text) as T; }\n catch { throw new Error('SkillHub returned invalid JSON'); }\n}\n\nfunction basenameSkillPath(p: string): string {\n const norm = p.replace(/\\\\/g, '/');\n const parts = norm.split('/');\n return parts[parts.length - 1] || norm;\n}\n\nfunction pickSkillHubDocFilePath(files: SkillHubFile[]): string | null {\n const rows = files.map((f) => ({\n path: f.path.replace(/\\\\/g, '/'),\n base: basenameSkillPath(f.path).toLowerCase(),\n }));\n const firstBase = (name: string) => rows.find((r) => r.base === name.toLowerCase());\n const skillMd = firstBase('SKILL.md') ?? firstBase('skill.md');\n if (skillMd) return skillMd.path;\n const readme = firstBase('README.md') ?? firstBase('readme.md');\n if (readme) return readme.path;\n const how = firstBase('HOW_TO_USE.md');\n if (how) return how.path;\n return null;\n}\n\nfunction assertSkillHubReadmeResponseUrl(finalUrl: string): void {\n let u: URL;\n try { u = new URL(finalUrl); } catch { throw new Error('Invalid SkillHub file response URL'); }\n if (u.protocol !== 'https:') throw new Error('SkillHub file response must use HTTPS');\n const host = u.hostname.toLowerCase();\n if (host === 'api.skillhub.cn') return;\n if (host.endsWith('.myqcloud.com')) return;\n throw new Error('SkillHub file redirect host is not allowlisted');\n}\n\nasync function getSkillHubSkillFileText(slug: string, filePath: string, version?: string): Promise<string> {\n const enc = encodeURIComponent(slug.trim());\n const normPath = filePath.replace(/\\\\/g, '/');\n const sp = new URLSearchParams({ path: normPath });\n if (version?.trim()) sp.set('version', version.trim());\n const url = `${SKILLHUB_API_BASE}/api/v1/skills/${enc}/file?${sp.toString()}`;\n const res = await fetch(url, { redirect: 'follow', headers: { Accept: 'text/markdown,text/plain,*/*' } });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n let msg = `SkillHub file request failed (${res.status})`;\n try {\n const j = JSON.parse(text) as { message?: string; error?: string };\n if (typeof j.message === 'string') msg = j.message;\n else if (typeof j.error === 'string') msg = j.error;\n } catch { if (text) msg = text.slice(0, 200); }\n throw new Error(msg);\n }\n assertSkillHubReadmeResponseUrl(res.url);\n const len = res.headers.get('content-length');\n if (len) {\n const n = Number(len);\n if (Number.isFinite(n) && n > MAX_SKILLHUB_README_BYTES) throw new Error(`SkillHub file exceeds max size`);\n }\n const ab = await res.arrayBuffer();\n if (ab.byteLength > MAX_SKILLHUB_README_BYTES) throw new Error(`SkillHub file exceeds max size`);\n return new TextDecoder('utf-8').decode(ab);\n}\n\nasync function getSkillHubSkill(slug: string): Promise<SkillHubSkillDetail> {\n return registryFetchJson<SkillHubSkillDetail>(`${SKILLHUB_API_BASE}/api/v1/skills/${encodeURIComponent(slug.trim())}`);\n}\n\nasync function getSkillHubSkillFiles(slug: string, version?: string): Promise<{ files: SkillHubFile[]; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n const sp = version ? `?version=${encodeURIComponent(version)}` : '';\n return registryFetchJson<{ files: SkillHubFile[]; version: string }>(`${SKILLHUB_API_BASE}/api/v1/skills/${enc}/files${sp}`);\n}\n\nasync function downloadSkillHubZipBuffer(slug: string, version?: string): Promise<{ buffer: Buffer; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n let url = `${SKILLHUB_API_BASE}/api/v1/download?slug=${enc}`;\n if (version?.trim()) url += `&version=${encodeURIComponent(version.trim())}`;\n const res = await fetch(url, { redirect: 'follow' });\n if (!res.ok) throw new Error(`Failed to download skill archive (${res.status})`);\n const len = res.headers.get('content-length');\n if (len) { const n = Number(len); if (Number.isFinite(n) && n > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`); }\n const ab = await res.arrayBuffer();\n const buf = Buffer.from(ab);\n if (buf.length > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`);\n let resolvedVersion = version ?? '1.0.0';\n if (!version?.trim()) {\n try { resolvedVersion = (await getSkillHubSkillFiles(slug)).version; } catch { /* keep default */ }\n }\n return { buffer: buf, version: resolvedVersion };\n}\n\nasync function batchGetSkillHubSkills(slugs: string[]): Promise<SkillHubSkillDetail[]> {\n if (slugs.length === 0) return [];\n const response = await registryFetchJson<{ count: number; items: SkillHubSkillDetail[]; missing: string[] }>(\n `${SKILLHUB_API_BASE}/api/v1/skills/batch`,\n { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ slugs }) },\n );\n return response.items ?? [];\n}\n\nasync function listSkillHubRegistryCategories(): Promise<SkillHubRegistryCategoryItem[]> {\n const raw = await registryFetchJson<{ count?: number; items?: SkillHubRegistryCategoryItem[] }>(\n `${SKILLHUB_API_BASE}/api/v1/categories`,\n );\n const items = Array.isArray(raw.items) ? raw.items : [];\n return items.filter((c) => c && typeof c.key === 'string' && c.key.trim().length > 0 && c.active !== false);\n}\n\nasync function listSkillHubSkillsets(opts: { page?: number; pageSize?: number; keyword?: string; scene?: string } = {}): Promise<{ skillSets: SkillHubSkillset[]; total: number }> {\n const page = opts.page ?? 1;\n const pageSize = opts.pageSize ?? 20;\n const sp = new URLSearchParams({ page: String(page), pageSize: String(pageSize) });\n if (opts.keyword?.trim()) sp.set('keyword', opts.keyword.trim());\n if (opts.scene?.trim()) sp.set('scene', opts.scene.trim());\n return registryFetchJson<{ skillSets: SkillHubSkillset[]; total: number }>(`${SKILLHUB_API_BASE}/api/v1/skillsets?${sp.toString()}`);\n}\n\nasync function getDefaultSkillSlugs(): Promise<string[]> {\n const slugs = new Set<string>();\n let page = 1;\n const pageSize = 50;\n let total = Infinity;\n while (page <= SKILLSET_DISCOVERY_PAGE_CAP && slugs.size < MAX_DEFAULT_SLUGS) {\n const response = await listSkillHubSkillsets({ page, pageSize });\n total = response.total;\n for (const skillset of response.skillSets) {\n for (const slug of skillset.skillSlugs) slugs.add(slug);\n }\n if (page * pageSize >= total) break;\n page += 1;\n }\n return Array.from(slugs).slice(0, MAX_DEFAULT_SLUGS);\n}\n\nasync function searchSkillHubSkills(query: string, maxSlugs = 200): Promise<{ slugs: string[]; total: number }> {\n const keyword = query.trim();\n if (!keyword) return { slugs: [], total: 0 };\n const slugs: string[] = [];\n const seen = new Set<string>();\n let page = 1;\n const batchSize = 50;\n while (page <= SKILLSET_DISCOVERY_PAGE_CAP) {\n const response = await listSkillHubSkillsets({ page, pageSize: batchSize, keyword });\n for (const skillset of response.skillSets) {\n for (const slug of skillset.skillSlugs) {\n if (!seen.has(slug)) { seen.add(slug); slugs.push(slug); }\n }\n }\n if (page * batchSize >= response.total) break;\n page += 1;\n }\n const capped = slugs.slice(0, maxSlugs);\n return { slugs: capped, total: capped.length };\n}\n\n// ─── Ecosystem helpers ───────────────────────────────────────────────────────\n\nfunction templateWithSlug(template: string, slug: string): string {\n const raw = template.trim();\n if (!raw) return '';\n if (raw.includes('{slug}')) return raw.replaceAll('{slug}', encodeURIComponent(slug.trim()));\n const base = raw.replace(/\\/$/, '');\n return `${base}/${encodeURIComponent(slug.trim())}.zip`;\n}\n\nfunction hostFromTemplate(template: string): string | undefined {\n const t = templateWithSlug(template, 'x');\n try { return new URL(t).hostname.toLowerCase(); } catch { return undefined; }\n}\n\nfunction resolveSkillHubEcosystemUrls(): EcosystemUrls {\n return {\n skillsIndexUrl: process.env.XOPC_SKILLHUB_SKILLS_INDEX_URL?.trim() || DEFAULT_SKILLS_INDEX_URL,\n searchUrl: process.env.XOPC_SKILLHUB_SEARCH_URL?.trim() || DEFAULT_SEARCH_URL,\n primaryDownloadTemplate: process.env.XOPC_SKILLHUB_PRIMARY_DOWNLOAD_TEMPLATE?.trim() || DEFAULT_PRIMARY_DOWNLOAD_TEMPLATE,\n fallbackDownloadTemplate: process.env.XOPC_SKILLHUB_FALLBACK_DOWNLOAD_TEMPLATE?.trim() || DEFAULT_FALLBACK_DOWNLOAD_TEMPLATE,\n };\n}\n\nfunction allowedDownloadHosts(urls: EcosystemUrls): Set<string> {\n const hosts = new Set(DEFAULT_ALLOWED_DOWNLOAD_HOSTS);\n for (const h of [hostFromTemplate(urls.primaryDownloadTemplate), hostFromTemplate(urls.fallbackDownloadTemplate)]) { if (h) hosts.add(h); }\n try { hosts.add(new URL(urls.skillsIndexUrl).hostname.toLowerCase()); } catch { /* ignore */ }\n try { hosts.add(new URL(urls.searchUrl).hostname.toLowerCase()); } catch { /* ignore */ }\n return hosts;\n}\n\nfunction assertSkillHubDownloadUrlAllowed(downloadUrl: string, urls: EcosystemUrls): URL {\n let u: URL;\n try { u = new URL(downloadUrl); } catch { throw new Error('Invalid SkillHub download URL'); }\n if (u.protocol !== 'https:') throw new Error('SkillHub download URL must use HTTPS');\n if (!allowedDownloadHosts(urls).has(u.hostname.toLowerCase())) throw new Error('SkillHub download URL host is not allowlisted');\n return u;\n}\n\nasync function ecoFetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, { ...init, headers: { Accept: 'application/json', ...init?.headers } });\n const text = await res.text();\n if (!res.ok) {\n let msg = `SkillHub ecosystem request failed (${res.status})`;\n try { const j = JSON.parse(text) as { message?: string; error?: string }; if (j.message) msg = j.message; else if (j.error) msg = j.error; } catch { if (text) msg = text.slice(0, 200); }\n throw new Error(msg);\n }\n try { return JSON.parse(text) as T; } catch { throw new Error('SkillHub ecosystem returned invalid JSON'); }\n}\n\nasync function fetchSkillHubCuratedIndex(urls: EcosystemUrls): Promise<CuratedIndex> {\n const raw = await ecoFetchJson<unknown>(urls.skillsIndexUrl);\n if (Array.isArray(raw)) return { skills: raw as CuratedIndexSkill[] };\n if (raw && typeof raw === 'object' && Array.isArray((raw as CuratedIndex).skills)) return raw as CuratedIndex;\n throw new Error('SkillHub index JSON must be an object with a skills array');\n}\n\nfunction sourceLabelFromHomepage(homepage?: string): string | undefined {\n const h = homepage?.trim().toLowerCase() ?? '';\n if (h.includes('clawhub')) return 'ClawHub';\n if (h.includes('skillhub')) return 'SkillHub';\n return undefined;\n}\n\nfunction curatedSkillsToPackageItems(skills: CuratedIndexSkill[]): PackageListItem[] {\n return skills.map((s) => ({\n id: s.slug,\n name: (s.name ?? s.slug).trim() || s.slug,\n type: 'skill',\n description: (s.description ?? '').trim(),\n downloads: typeof s.downloads === 'number' ? s.downloads : 0,\n author: { username: 'skillhub', avatarUrl: null },\n latestVersion: (s.version ?? '').trim() || undefined,\n updatedAt: String(s.rank ?? s.score ?? 0),\n categories: (s.categories ?? []).map((c) => String(c).trim()).filter(Boolean),\n stars: typeof s.stars === 'number' ? s.stars : undefined,\n sourceLabel: sourceLabelFromHomepage(s.homepage),\n }));\n}\n\nasync function findCuratedIndexSkill(slug: string): Promise<CuratedIndexSkill | null> {\n const want = slug.trim();\n if (!want) return null;\n const ecoUrls = resolveSkillHubEcosystemUrls();\n try {\n const idx = await cachedFetchSkillHubCuratedIndex(ecoUrls);\n return idx.skills.find((s) => s.slug?.trim() === want) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction curatedSkillFallbackReadmeMarkdown(skill: CuratedIndexSkill): string {\n const title = (skill.name ?? skill.slug).trim() || skill.slug;\n const desc = (skill.description ?? '').trim() || '_No description._';\n const version = (skill.version ?? '').trim() || '1.0.0';\n return `## ${title}\\n\\n**${skill.slug}** · v${version}\\n\\n${desc}`;\n}\n\nfunction packageDetailFromCuratedSkill(skill: CuratedIndexSkill) {\n const slug = skill.slug.trim();\n const version = (skill.version ?? '').trim() || '1.0.0';\n const categories = (skill.categories ?? []).map((c) => String(c).trim()).filter(Boolean);\n const sourceLabel = sourceLabelFromHomepage(skill.homepage);\n const name = (skill.name ?? slug).trim() || slug;\n const description = (skill.description ?? '').trim();\n const readme = curatedSkillFallbackReadmeMarkdown(skill);\n return {\n id: slug,\n name,\n type: 'skill',\n description,\n readme,\n skillDocPreview: buildSkillMarkdownPreviewFromRaw(readme, { name, description }),\n downloads: typeof skill.downloads === 'number' ? skill.downloads : 0,\n author: {\n username: sourceLabel?.toLowerCase() ?? 'skillhub',\n avatarUrl: null,\n },\n latestVersion: {\n version,\n changelog: null,\n publishedAt: String(skill.rank ?? skill.score ?? 0),\n },\n provider: 'skillhub',\n skillHubInfo: {\n category: categories[0] ?? '',\n installs: 0,\n stars: typeof skill.stars === 'number' ? skill.stars : 0,\n },\n };\n}\n\nfunction lightmakeHitToPackageItem(hit: LightmakeSearchHit): PackageListItem {\n const slug = String(hit.slug || '').trim();\n const desc = (hit.summary ?? hit.description_zh ?? hit.description ?? '').trim() || '';\n const updated = hit.updatedAt ?? hit.updated_at ?? 0;\n const cat = hit.category?.trim();\n return {\n id: slug,\n name: (hit.displayName ?? hit.name ?? slug).trim() || slug,\n type: 'skill',\n description: desc,\n downloads: typeof hit.downloads === 'number' ? hit.downloads : 0,\n author: { username: (hit.owner_name ?? 'skillhub').trim() || 'skillhub', avatarUrl: null },\n latestVersion: (hit.version ?? '').trim() || undefined,\n updatedAt: String(updated),\n categories: cat ? [cat] : [],\n stars: typeof hit.stars === 'number' ? hit.stars : undefined,\n sourceLabel: sourceLabelFromSkillSource(hit.source) ?? 'Lightmake',\n };\n}\n\nasync function searchSkillHubLightmake(urls: EcosystemUrls, query: string, limit: number, timeoutMs = 4000): Promise<PackageListItem[]> {\n const q = query.trim().toLowerCase();\n if (!q) return [];\n const search = new URL(urls.searchUrl);\n if (search.protocol !== 'https:') throw new Error('SkillHub search URL must use HTTPS');\n search.searchParams.set('q', q);\n search.searchParams.set('limit', String(Math.max(1, Math.min(LIGHTMAKE_SEARCH_MAX, limit))));\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const raw = await ecoFetchJson<{ results?: LightmakeSearchHit[] }>(search.toString(), { signal: controller.signal });\n const results = raw.results;\n if (!Array.isArray(results)) return [];\n const out: PackageListItem[] = [];\n for (const item of results) {\n if (!item || typeof item !== 'object') continue;\n const hit = item as LightmakeSearchHit;\n const slug = String(hit.slug ?? '').trim();\n if (!slug) continue;\n out.push(lightmakeHitToPackageItem(hit));\n }\n return out;\n } finally { clearTimeout(timer); }\n}\n\nasync function downloadSkillHubZipFromAllowlistedUrl(urls: EcosystemUrls, downloadUrl: string): Promise<Buffer> {\n const normalized = assertSkillHubDownloadUrlAllowed(downloadUrl, urls);\n const res = await fetch(normalized.toString(), { redirect: 'follow' });\n if (!res.ok) throw new Error(`Failed to download skill archive (${res.status})`);\n const len = res.headers.get('content-length');\n if (len) { const n = Number(len); if (Number.isFinite(n) && n > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`); }\n const ab = await res.arrayBuffer();\n const buf = Buffer.from(ab);\n if (buf.length > MAX_SKILL_ZIP_BYTES) throw new Error(`Zip exceeds max size`);\n return buf;\n}\n\nasync function downloadSkillHubZipFromEcosystem(urls: EcosystemUrls, slug: string): Promise<Buffer> {\n const primary = templateWithSlug(urls.primaryDownloadTemplate, slug);\n const fallback = templateWithSlug(urls.fallbackDownloadTemplate, slug);\n const candidates = [primary, fallback].filter(Boolean);\n const seen = new Set<string>();\n let lastErr: Error | undefined;\n for (const url of candidates) {\n if (seen.has(url)) continue;\n seen.add(url);\n try { return await downloadSkillHubZipFromAllowlistedUrl(urls, url); }\n catch (e) { lastErr = e instanceof Error ? e : new Error(String(e)); }\n }\n throw lastErr ?? new Error('SkillHub ecosystem download failed');\n}\n\n// ─── In-memory TTL cache ─────────────────────────────────────────────────────\n\ntype CacheEntry<T> = { value: T; expiresAt: number };\n\nfunction cacheTtlMs(): number {\n const raw = process.env.XOPC_SKILLHUB_CACHE_MS?.trim();\n if (raw === '0' || raw === 'false') return 0;\n const n = Number(raw);\n if (!Number.isFinite(n) || n < 0) return DEFAULT_CACHE_MS;\n return n;\n}\n\nfunction getFresh<T>(entry: CacheEntry<T> | undefined): T | undefined {\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\nconst curatedByIndexUrl = new Map<string, CacheEntry<CuratedIndex>>();\nlet defaultSlugsEntry: CacheEntry<string[]> | undefined;\nlet registryCategoriesEntry: CacheEntry<SkillHubRegistryCategoryItem[]> | undefined;\nconst batchBySlugsKey = new Map<string, CacheEntry<SkillHubSkillDetail[]>>();\nconst lightmakeSearchByQuery = new Map<string, CacheEntry<PackageListItem[]>>();\n\nfunction evictOldestBatchKey(): void {\n const first = batchBySlugsKey.keys().next().value;\n if (first !== undefined) batchBySlugsKey.delete(first);\n}\n\nfunction evictOldestSearchKey(): void {\n const first = lightmakeSearchByQuery.keys().next().value;\n if (first !== undefined) lightmakeSearchByQuery.delete(first);\n}\n\nfunction batchSlugsCacheKey(slugs: string[]): string {\n if (slugs.length === 0) return '';\n return [...slugs].sort().join('\\n');\n}\n\nasync function cachedFetchSkillHubCuratedIndex(urls: EcosystemUrls): Promise<CuratedIndex> {\n const ttl = cacheTtlMs();\n const key = urls.skillsIndexUrl;\n if (ttl > 0) { const hit = getFresh(curatedByIndexUrl.get(key)); if (hit) return hit; }\n const value = await fetchSkillHubCuratedIndex(urls);\n if (ttl > 0) curatedByIndexUrl.set(key, { value, expiresAt: Date.now() + ttl });\n return value;\n}\n\nasync function cachedGetDefaultSkillSlugs(): Promise<string[]> {\n const ttl = cacheTtlMs();\n if (ttl > 0) { const hit = getFresh(defaultSlugsEntry); if (hit) return hit; }\n const value = await getDefaultSkillSlugs();\n if (ttl > 0) defaultSlugsEntry = { value, expiresAt: Date.now() + ttl };\n return value;\n}\n\nasync function cachedListSkillHubRegistryCategories(): Promise<SkillHubRegistryCategoryItem[]> {\n const ttl = cacheTtlMs();\n if (ttl > 0) { const hit = getFresh(registryCategoriesEntry); if (hit) return hit; }\n const value = await listSkillHubRegistryCategories();\n if (ttl > 0) registryCategoriesEntry = { value, expiresAt: Date.now() + ttl };\n return value;\n}\n\nasync function cachedBatchGetSkillHubSkills(slugs: string[]): Promise<SkillHubSkillDetail[]> {\n if (slugs.length === 0) return [];\n const ttl = cacheTtlMs();\n const key = batchSlugsCacheKey(slugs);\n if (ttl > 0) { const hit = getFresh(batchBySlugsKey.get(key)); if (hit) return hit; }\n const value = await batchGetSkillHubSkills(slugs);\n if (ttl > 0) {\n while (batchBySlugsKey.size >= MAX_BATCH_CACHE_KEYS) evictOldestBatchKey();\n batchBySlugsKey.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedSearchSkillHubLightmake(\n urls: EcosystemUrls,\n query: string,\n limit: number,\n): Promise<PackageListItem[]> {\n const q = query.trim().toLowerCase();\n if (!q) return [];\n const ttl = cacheTtlMs();\n const key = `${urls.searchUrl}|${q}|${limit}`;\n if (ttl > 0) { const hit = getFresh(lightmakeSearchByQuery.get(key)); if (hit) return hit; }\n const value = await searchSkillHubLightmake(urls, q, limit);\n if (ttl > 0) {\n while (lightmakeSearchByQuery.size >= MAX_BATCH_CACHE_KEYS) evictOldestSearchKey();\n lightmakeSearchByQuery.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\n// ─── Adapter conversion helpers ──────────────────────────────────────────────\n\nfunction humanizeRegistryCategoryKey(slug: string): string {\n return slug.replace(/_/g, '-').split('-').filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' ');\n}\n\nfunction sourceLabelFromSkillSource(source: string | undefined): string | undefined {\n const s = source?.trim();\n if (!s) return undefined;\n const lower = s.toLowerCase();\n if (lower === 'clawhub') return 'ClawHub';\n if (lower === 'lightmake') return 'Lightmake';\n if (lower === 'skillhub') return 'SkillHub';\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction filterByCategory(rows: PackageListItem[], category?: string): PackageListItem[] {\n const want = category?.trim();\n if (!want) return rows;\n return rows.filter((r) => (r.categories ?? []).includes(want));\n}\n\nasync function collectRegistryCategoryKeysFromSlugs(slugs: string[]): Promise<Set<string>> {\n const used = new Set<string>();\n for (let i = 0; i < slugs.length; i += REGISTRY_SKILL_BATCH_CHUNK) {\n const chunk = slugs.slice(i, i + REGISTRY_SKILL_BATCH_CHUNK);\n const details = await cachedBatchGetSkillHubSkills(chunk);\n for (const d of details) {\n const k = d.skill.category?.trim();\n if (k) used.add(k);\n }\n }\n return used;\n}\n\nfunction isPipelineOnlyChangelog(text: string | null | undefined): boolean {\n if (!text?.trim()) return true;\n return /^synced by skillhub pipeline\\.?$/i.test(text.trim());\n}\n\nfunction skillHubFallbackReadmeMarkdown(detail: { skill: SkillHubSkill; latestVersion: { version: string } }): string {\n const s = detail.skill;\n const title = s.displayName?.trim() || s.slug;\n const zh = s.summary_zh?.trim();\n const en = s.summary?.trim();\n const body = zh && en && zh !== en ? `${zh}\\n\\n${en}` : zh || en || '_No description._';\n return `## ${title}\\n\\n**${s.slug}** · v${detail.latestVersion.version}\\n\\n${body}`;\n}\n\nfunction convertSkillHubToPackageListItem(detail: SkillHubSkill): PackageListItem {\n const cat = detail.category?.trim();\n return {\n id: detail.slug,\n name: detail.displayName?.trim() || detail.slug,\n type: 'skill',\n description: detail.summary_zh || detail.summary,\n downloads: detail.stats.downloads,\n author: { username: detail.source || 'skillhub', avatarUrl: null },\n latestVersion: detail.tags.latest || '1.0.0',\n updatedAt: String(detail.updatedAt),\n categories: cat ? [cat] : [],\n stars: detail.stats.stars,\n sourceLabel: sourceLabelFromSkillSource(detail.source),\n };\n}\n\nexport const skillHubMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'skillhub',\n\n async listCategories(_config) {\n const sortByLabel = (a: MarketplaceCategoryOption, b: MarketplaceCategoryOption) =>\n a.label.localeCompare(b.label, 'zh-Hans-CN', { sensitivity: 'base' });\n const ecoUrls = resolveSkillHubEcosystemUrls();\n try {\n const idx = await cachedFetchSkillHubCuratedIndex(ecoUrls);\n if (idx.skills?.length) {\n const map = new Map<string, MarketplaceCategoryOption>();\n for (const s of idx.skills) {\n for (const raw of s.categories ?? []) {\n const label = String(raw).trim();\n if (label) map.set(label, { id: label, label });\n }\n }\n return sortMarketplaceCategories(\n Array.from(map.values()).filter((c) => c.id.trim() && c.label.trim()),\n sortByLabel,\n );\n }\n } catch { /* fall through: registry-backed catalog */ }\n try {\n const [taxonomy, slugs] = await Promise.all([\n cachedListSkillHubRegistryCategories(),\n cachedGetDefaultSkillSlugs(),\n ]);\n const usedKeys = await collectRegistryCategoryKeysFromSlugs(slugs);\n const taxByKey = new Map(taxonomy.map((t) => [t.key, t] as const));\n const options: MarketplaceCategoryOption[] = [];\n for (const key of usedKeys) {\n const t = taxByKey.get(key);\n const label = t?.name?.trim() || t?.nameEn?.trim() || humanizeRegistryCategoryKey(key).trim();\n if (!label) continue;\n options.push({ id: key, label });\n }\n return sortMarketplaceCategories(options, (a, b) => {\n const oa = taxByKey.get(a.id)?.sortOrder ?? 999;\n const ob = taxByKey.get(b.id)?.sortOrder ?? 999;\n if (oa !== ob) return oa - ob;\n return sortByLabel(a, b);\n });\n } catch { return []; }\n },\n\n async listPackages(_config, params) {\n const pageSize = params.pageSize ?? 20;\n const page = params.page ?? 1;\n const ecoUrls = resolveSkillHubEcosystemUrls();\n\n if (params.q?.trim()) {\n const q = params.q.trim();\n let rows: PackageListItem[] = [];\n try {\n rows = await cachedSearchSkillHubLightmake(ecoUrls, q, 100);\n } catch {\n // Lightmake unavailable — fall back to the registry skillset scan. We do NOT run this\n // when Lightmake returned zero hits: that would queue ~40 sequential HTTP calls just to\n // confirm \"no results\", and the empty state UI is the better answer for the user.\n try {\n const searchResult = await searchSkillHubSkills(q, 200);\n const details = await cachedBatchGetSkillHubSkills(searchResult.slugs);\n rows = details.map((d) => convertSkillHubToPackageListItem(d.skill));\n } catch {\n rows = [];\n }\n }\n rows = filterByCategory(rows, params.category);\n if (params.sort === 'downloads') rows = [...rows].sort((a, b) => b.downloads - a.downloads);\n else if (params.sort === 'newest') rows = [...rows].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n }\n\n try {\n const idx = await cachedFetchSkillHubCuratedIndex(ecoUrls);\n let skills = [...idx.skills].filter((s) => s.slug?.trim());\n if (skills.length > 0) {\n if (params.category?.trim()) {\n const want = params.category.trim();\n skills = skills.filter((s) => (s.categories ?? []).some((x) => String(x).trim() === want));\n }\n if (params.sort === 'downloads') skills.sort((a, b) => (b.downloads ?? 0) - (a.downloads ?? 0));\n else if (params.sort === 'newest') skills.sort((a, b) => (a.rank ?? 999) - (b.rank ?? 999));\n const rows = curatedSkillsToPackageItems(skills);\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n }\n } catch { /* fall through */ }\n\n const slugs = await cachedGetDefaultSkillSlugs();\n if (params.category?.trim()) {\n const details = await cachedBatchGetSkillHubSkills(slugs);\n let allItems = details.map((d) => convertSkillHubToPackageListItem(d.skill));\n allItems = filterByCategory(allItems, params.category);\n if (params.sort === 'downloads') allItems = [...allItems].sort((a, b) => b.downloads - a.downloads);\n else if (params.sort === 'newest') allItems = [...allItems].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n const total = allItems.length;\n const start = (page - 1) * pageSize;\n const items = allItems.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n }\n\n const total = slugs.length;\n const start = (page - 1) * pageSize;\n const paginatedSlugs = slugs.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n const details = await cachedBatchGetSkillHubSkills(paginatedSlugs);\n const items = details.map((d) => convertSkillHubToPackageListItem(d.skill));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'skillhub' };\n },\n\n async getPackageDetail(_config, packageName) {\n const slug = packageName.trim();\n let detail: SkillHubSkillDetail;\n try {\n detail = await getSkillHubSkill(slug);\n } catch (registryErr) {\n const curated = await findCuratedIndexSkill(slug);\n if (curated) return packageDetailFromCuratedSkill(curated);\n throw registryErr;\n }\n const version = detail.latestVersion.version;\n const changelog = detail.latestVersion.changelog;\n\n let readme: string | null = null;\n let docPath: string | null = null;\n try {\n const { files } = await getSkillHubSkillFiles(slug, version);\n docPath = pickSkillHubDocFilePath(files);\n if (docPath) readme = await getSkillHubSkillFileText(slug, docPath, version);\n } catch { readme = null; }\n\n const trimmed = readme?.trim() ?? '';\n const docBase = docPath ? basename(docPath.replace(/\\\\/g, '/')).toLowerCase() : '';\n const isSkillMd = docBase === 'skill.md';\n\n if (!trimmed) {\n readme = skillHubFallbackReadmeMarkdown(detail);\n } else if (isSkillMd) {\n readme = trimmed;\n if (changelog?.trim() && !isPipelineOnlyChangelog(changelog)) {\n readme = `${trimmed}\\n\\n---\\n\\n## Changelog\\n\\n${changelog.trim()}`;\n }\n } else {\n readme = trimmed;\n if (changelog?.trim() && !isPipelineOnlyChangelog(changelog)) {\n readme = `${trimmed}\\n\\n---\\n\\n## Changelog\\n\\n${changelog.trim()}`;\n }\n }\n\n const description = detail.skill.summary_zh || detail.skill.summary;\n const skillDocPreview = buildSkillMarkdownPreviewFromRaw(readme, {\n name: detail.skill.slug,\n description,\n });\n\n return {\n id: detail.skill.slug,\n name: detail.skill.slug,\n type: 'skill',\n description,\n readme,\n skillDocPreview,\n downloads: detail.skill.stats.downloads,\n author: {\n username: detail.owner.handle,\n avatarUrl: detail.owner.image,\n },\n latestVersion: {\n version: detail.latestVersion.version,\n changelog: detail.latestVersion.changelog,\n publishedAt: String(detail.latestVersion.createdAt),\n },\n provider: 'skillhub',\n skillHubInfo: {\n category: detail.skill.category,\n installs: detail.skill.stats.installs,\n stars: detail.skill.stats.stars,\n securityReports: detail.latestVersion.securityReports,\n },\n };\n },\n\n async downloadPackage(_config, packageName, version) {\n const slug = packageName.trim();\n if (version?.trim()) {\n const { buffer, version: resolvedVersion } = await downloadSkillHubZipBuffer(slug, version);\n return { buffer, skillId: isValidSkillId(slug) ? slug : 'unknown', version: resolvedVersion };\n }\n const ecoUrls = resolveSkillHubEcosystemUrls();\n try {\n const buffer = await downloadSkillHubZipFromEcosystem(ecoUrls, slug);\n let resolvedVersion = '1.0.0';\n try { resolvedVersion = (await getSkillHubSkillFiles(slug)).version; } catch { /* keep default */ }\n return { buffer, skillId: isValidSkillId(slug) ? slug : 'unknown', version: resolvedVersion };\n } catch {\n const { buffer, version: resolvedVersion } = await downloadSkillHubZipBuffer(slug);\n return { buffer, skillId: isValidSkillId(slug) ? slug : 'unknown', version: resolvedVersion };\n }\n },\n};\n\nregisterMarketplaceAdapter({\n adapter: skillHubMarketplaceAdapter,\n displayName: 'SkillHub',\n});\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerMarketplaceAdapter } from "../../registry.js";
|
|
2
2
|
import { downloadSkillZipBuffer, fetchMarketplacePackageDetail, listSkillPackages, resolveSkillZipDownloadUrl, resolveSkillsStoreBaseUrl, skillIdForMarketplaceInstall } from "./store-api-client.js";
|
|
3
|
+
import { buildSkillMarkdownPreviewFromRaw } from "../../../skill-markdown-preview-from-raw.js";
|
|
3
4
|
//#region src/agent/skills/marketplace/adapters/store/adapter.ts
|
|
4
5
|
const storeMarketplaceAdapter = {
|
|
5
6
|
id: "store",
|
|
@@ -15,9 +16,17 @@ const storeMarketplaceAdapter = {
|
|
|
15
16
|
};
|
|
16
17
|
},
|
|
17
18
|
async getPackageDetail(config, packageName) {
|
|
19
|
+
const detail = await fetchMarketplacePackageDetail(resolveSkillsStoreBaseUrl(config), packageName);
|
|
20
|
+
const readme = detail.readme?.trim();
|
|
21
|
+
if (!readme) throw new Error(`Store skill package [${packageName}] did not include readme`);
|
|
18
22
|
return {
|
|
19
|
-
...
|
|
20
|
-
|
|
23
|
+
...detail,
|
|
24
|
+
readme,
|
|
25
|
+
provider: "store",
|
|
26
|
+
skillDocPreview: buildSkillMarkdownPreviewFromRaw(readme, {
|
|
27
|
+
name: detail.name,
|
|
28
|
+
description: detail.description
|
|
29
|
+
})
|
|
21
30
|
};
|
|
22
31
|
},
|
|
23
32
|
async downloadPackage(config, packageName, version) {
|