@xopcai/xopc 0.0.103 → 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 +7 -4
- package/README.zh-CN.md +7 -4
- 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 +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/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-C5RmwmTT.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-CWm8hTXZ.js → dist-C6vclgEL.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BzYgTkS9.js → extension-debug-page-D4JYAbsX.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BmTZH6gL.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-CMoWY2Si.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-BjdQjHwk.js → logs-page-DsjtTjBy.js} +2 -2
- package/dist/gateway/static/root/assets/{note-detail-page-8Er4197b.js → note-detail-page-B2V7RhgD.js} +43 -43
- package/dist/gateway/static/root/assets/{note-time-CF3vf1jm.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-C7qA7y0J.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-Tvr5Mtq5.js → share-preview-page-DOFy0FNt.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-DmTsrs_a.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-HTvJlFLL.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-CeBkAjP7.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/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/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.js +10 -5
- package/dist/src/auth/credentials.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/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/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 +1 -1
- 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 +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 +7 -4
- 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.js +8 -5
- 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/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/heartbeat/service.js +1 -1
- 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/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/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/heartbeat/index.js +1 -1
- package/dist/src/mcp/channel-bridge.js +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 +1 -1
- package/dist/src/providers/index.js +18 -7
- package/dist/src/providers/index.js.map +1 -1
- 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-BwXkia_W.js +0 -222
- package/dist/gateway/static/root/assets/channels-settings-tlOTdaXw.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-D4XjqwqC.js +0 -8
- package/dist/gateway/static/root/assets/cron-api-DcmfGuj0.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-CijJ4G6F.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-CyJk_G64.js +0 -1
- package/dist/gateway/static/root/assets/field-primitives-C4GpxsDo.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-CLD0Gpi3.js +0 -1
- package/dist/gateway/static/root/assets/index-0HmunJW9.js +0 -4845
- package/dist/gateway/static/root/assets/index-Bk75Phrd.css +0 -1
- package/dist/gateway/static/root/assets/notes-page-BBnTh0uI.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B0riYK7j.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DiP_WHu_.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-1ZPhcCZ9.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-BQ1hllKD.js +0 -2
- package/dist/gateway/static/root/assets/url-F3_D_6zZ.js +0 -3
- package/dist/gateway/static/root/assets/utils-CPr3FBh2.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-BkbDl6dH.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-D059ysoF.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/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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../../../src/agent/skills/config.ts"],"sourcesContent":["/**\n * Skill Configuration Manager\n * \n * Handles skill-specific configuration and environment variables.\n *\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport { writeTextAtomicSync } from '../../infra/write-file-atomic.js';\nimport type { SkillConfig, SkillsConfig, Skill } from './types.js';\n\nconst log = createLogger('SkillConfig');\n\n/**\n * Resolve skill configuration from multiple sources\n * \n * Priority (highest to lowest):\n * 1. Environment variable overrides (XOPC_SKILL_<NAME>_<KEY>)\n * 2. Config file entries\n * 3. Skill defaults\n */\nexport function resolveSkillConfig(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): SkillConfig {\n const config: SkillConfig = {};\n\n // Start with config file entries\n const entryConfig = skillsConfig?.entries?.[skill.name];\n if (entryConfig) {\n config.enabled = entryConfig.enabled;\n config.apiKey = entryConfig.apiKey;\n config.env = entryConfig.env ? { ...entryConfig.env } : undefined;\n config.config = entryConfig.config ? { ...entryConfig.config } : undefined;\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n \n // Check for enabled override\n const enabledEnv = process.env[`${envPrefix}_ENABLED`];\n if (enabledEnv !== undefined) {\n config.enabled = enabledEnv.toLowerCase() === 'true' || enabledEnv === '1';\n }\n\n // Check for API key override\n const apiKeyEnv = process.env[`${envPrefix}_API_KEY`];\n if (apiKeyEnv) {\n config.apiKey = apiKeyEnv;\n }\n\n // Check for environment variable overrides\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n if (!config.env) {\n config.env = {};\n }\n config.env[envKey] = value;\n }\n }\n\n return config;\n}\n\n/**\n * Apply environment variable overrides to a skill's environment\n */\nexport function applySkillEnvOverrides(\n skill: Skill,\n baseEnv: Record<string, string> = {},\n skillConfig?: SkillConfig\n): Record<string, string> {\n const env: Record<string, string> = { ...baseEnv };\n\n // Apply config env\n if (skillConfig?.env) {\n for (const [key, value] of Object.entries(skillConfig.env)) {\n env[key] = value;\n }\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n env[envKey] = value;\n }\n }\n\n return env;\n}\n\n/**\n * Get the effective environment for a skill\n */\nexport function getSkillEnvironment(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): Record<string, string> {\n const config = resolveSkillConfig(skill, skillsConfig);\n return applySkillEnvOverrides(skill, process.env as Record<string, string>, config);\n}\n\n/**\n * Skill configuration file manager\n */\nexport interface SkillConfigFile {\n /** Path to the config file */\n configPath: string;\n /** Load configuration */\n load: () => SkillsConfig;\n /** Save configuration */\n save: (config: SkillsConfig) => void;\n /** Get skill-specific config */\n getSkillConfig: (skillName: string) => SkillConfig | undefined;\n /** Update skill configuration */\n updateSkillConfig: (skillName: string, config: Partial<SkillConfig>) => void;\n /** Enable/disable a skill */\n setSkillEnabled: (skillName: string, enabled: boolean) => void;\n /** Set skill API key */\n setSkillApiKey: (skillName: string, apiKey: string) => void;\n}\n\n/**\n * Create a skill configuration file manager\n */\nexport function createSkillConfigManager(configDir: string): SkillConfigFile {\n const configPath = join(configDir, 'skills.json');\n\n function loadConfig(): SkillsConfig {\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n return JSON.parse(content);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ error: err, errorMessage: em, path: configPath }, `Skills config load failed, using defaults: ${em}`);\n return {};\n }\n }\n\n function saveConfig(config: SkillsConfig): void {\n try {\n writeTextAtomicSync(configPath, JSON.stringify(config, null, 2));\n log.info('Saved skills config');\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ error: err, errorMessage: em, path: configPath }, `Failed to save skills config: ${em}`);\n }\n }\n\n return {\n configPath,\n\n load: loadConfig,\n\n save: saveConfig,\n\n getSkillConfig: (skillName: string) => {\n const config = loadConfig();\n return config.entries?.[skillName];\n },\n\n updateSkillConfig: (skillName: string, updates: Partial<SkillConfig>) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n ...updates,\n };\n\n saveConfig(config);\n },\n\n setSkillEnabled: (skillName: string, enabled: boolean) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n enabled,\n };\n\n saveConfig(config);\n log.info({ skillName, enabled }, 'Updated skill enabled state');\n },\n\n setSkillApiKey: (skillName: string, apiKey: string) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n apiKey,\n };\n\n saveConfig(config);\n log.info({ skillName }, 'Updated skill API key');\n },\n };\n}\n\n/**\n * Check if a skill is enabled\n */\nexport function isSkillEnabled(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): boolean {\n const config = resolveSkillConfig(skill, skillsConfig);\n \n // Explicitly disabled\n if (config.enabled === false) {\n return false;\n }\n\n // Check if skill has requirements that are not met\n const requires = skill.metadata.xopc?.requires || skill.metadata.requires;\n if (requires?.bins) {\n const { hasBinary } = require('./installer.js');\n for (const bin of requires.bins) {\n if (!hasBinary(bin)) {\n log.debug({ skill: skill.name, bin }, 'Skill requirement not met');\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Validate skill configuration\n */\nexport function validateSkillConfig(config: SkillsConfig): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n if (config.toolGating !== undefined && typeof config.toolGating !== 'boolean') {\n errors.push('toolGating must be a boolean');\n }\n\n if (\n config.agentWritePolicy !== undefined &&\n config.agentWritePolicy !== 'global' &&\n config.agentWritePolicy !== 'workspace' &&\n config.agentWritePolicy !== 'both'\n ) {\n errors.push('agentWritePolicy must be \"global\", \"workspace\", or \"both\"');\n }\n\n // Validate limits\n const limits = config.limits;\n if (limits) {\n if (limits.maxCandidatesPerRoot !== undefined && limits.maxCandidatesPerRoot < 1) {\n errors.push('limits.maxCandidatesPerRoot must be at least 1');\n }\n if (limits.maxSkillsLoadedPerSource !== undefined && limits.maxSkillsLoadedPerSource < 1) {\n errors.push('limits.maxSkillsLoadedPerSource must be at least 1');\n }\n if (limits.maxSkillsInPrompt !== undefined && limits.maxSkillsInPrompt < 1) {\n errors.push('limits.maxSkillsInPrompt must be at least 1');\n }\n }\n\n // Validate entries\n if (config.entries) {\n for (const [skillName, skillConfig] of Object.entries(config.entries)) {\n if (skillConfig.apiKey && typeof skillConfig.apiKey !== 'string') {\n errors.push(`entries.${skillName}.apiKey must be a string`);\n }\n if (skillConfig.env && typeof skillConfig.env !== 'object') {\n errors.push(`entries.${skillName}.env must be an object`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../../../src/agent/skills/config.ts"],"sourcesContent":["/**\n * Skill Configuration Manager\n * \n * Handles skill-specific configuration and environment variables.\n *\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport { writeTextAtomicSync } from '../../infra/write-file-atomic.js';\nimport { hasBinary } from './installer.js';\nimport type { SkillConfig, SkillsConfig, Skill } from './types.js';\n\nconst log = createLogger('SkillConfig');\n\n/**\n * Resolve skill configuration from multiple sources\n * \n * Priority (highest to lowest):\n * 1. Environment variable overrides (XOPC_SKILL_<NAME>_<KEY>)\n * 2. Config file entries\n * 3. Skill defaults\n */\nexport function resolveSkillConfig(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): SkillConfig {\n const config: SkillConfig = {};\n\n // Start with config file entries\n const entryConfig = skillsConfig?.entries?.[skill.name];\n if (entryConfig) {\n config.enabled = entryConfig.enabled;\n config.apiKey = entryConfig.apiKey;\n config.env = entryConfig.env ? { ...entryConfig.env } : undefined;\n config.config = entryConfig.config ? { ...entryConfig.config } : undefined;\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n \n // Check for enabled override\n const enabledEnv = process.env[`${envPrefix}_ENABLED`];\n if (enabledEnv !== undefined) {\n config.enabled = enabledEnv.toLowerCase() === 'true' || enabledEnv === '1';\n }\n\n // Check for API key override\n const apiKeyEnv = process.env[`${envPrefix}_API_KEY`];\n if (apiKeyEnv) {\n config.apiKey = apiKeyEnv;\n }\n\n // Check for environment variable overrides\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n if (!config.env) {\n config.env = {};\n }\n config.env[envKey] = value;\n }\n }\n\n return config;\n}\n\n/**\n * Apply environment variable overrides to a skill's environment\n */\nexport function applySkillEnvOverrides(\n skill: Skill,\n baseEnv: Record<string, string> = {},\n skillConfig?: SkillConfig\n): Record<string, string> {\n const env: Record<string, string> = { ...baseEnv };\n\n // Apply config env\n if (skillConfig?.env) {\n for (const [key, value] of Object.entries(skillConfig.env)) {\n env[key] = value;\n }\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n env[envKey] = value;\n }\n }\n\n return env;\n}\n\n/**\n * Get the effective environment for a skill\n */\nexport function getSkillEnvironment(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): Record<string, string> {\n const config = resolveSkillConfig(skill, skillsConfig);\n return applySkillEnvOverrides(skill, process.env as Record<string, string>, config);\n}\n\n/**\n * Skill configuration file manager\n */\nexport interface SkillConfigFile {\n /** Path to the config file */\n configPath: string;\n /** Load configuration */\n load: () => SkillsConfig;\n /** Save configuration */\n save: (config: SkillsConfig) => void;\n /** Get skill-specific config */\n getSkillConfig: (skillName: string) => SkillConfig | undefined;\n /** Update skill configuration */\n updateSkillConfig: (skillName: string, config: Partial<SkillConfig>) => void;\n /** Enable/disable a skill */\n setSkillEnabled: (skillName: string, enabled: boolean) => void;\n /** Set skill API key */\n setSkillApiKey: (skillName: string, apiKey: string) => void;\n}\n\n/**\n * Create a skill configuration file manager\n */\nexport function createSkillConfigManager(configDir: string): SkillConfigFile {\n const configPath = join(configDir, 'skills.json');\n\n function loadConfig(): SkillsConfig {\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n return JSON.parse(content);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ error: err, errorMessage: em, path: configPath }, `Skills config load failed, using defaults: ${em}`);\n return {};\n }\n }\n\n function saveConfig(config: SkillsConfig): void {\n try {\n writeTextAtomicSync(configPath, JSON.stringify(config, null, 2));\n log.info('Saved skills config');\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ error: err, errorMessage: em, path: configPath }, `Failed to save skills config: ${em}`);\n }\n }\n\n return {\n configPath,\n\n load: loadConfig,\n\n save: saveConfig,\n\n getSkillConfig: (skillName: string) => {\n const config = loadConfig();\n return config.entries?.[skillName];\n },\n\n updateSkillConfig: (skillName: string, updates: Partial<SkillConfig>) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n ...updates,\n };\n\n saveConfig(config);\n },\n\n setSkillEnabled: (skillName: string, enabled: boolean) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n enabled,\n };\n\n saveConfig(config);\n log.info({ skillName, enabled }, 'Updated skill enabled state');\n },\n\n setSkillApiKey: (skillName: string, apiKey: string) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n apiKey,\n };\n\n saveConfig(config);\n log.info({ skillName }, 'Updated skill API key');\n },\n };\n}\n\n/**\n * Check if a skill is enabled\n */\nexport function isSkillEnabled(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): boolean {\n const config = resolveSkillConfig(skill, skillsConfig);\n \n // Explicitly disabled\n if (config.enabled === false) {\n return false;\n }\n\n // Check if skill has requirements that are not met\n const requires = skill.metadata.xopc?.requires || skill.metadata.requires;\n if (requires?.bins) {\n for (const bin of requires.bins) {\n if (!hasBinary(bin)) {\n log.debug({ skill: skill.name, bin }, 'Skill requirement not met');\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Validate skill configuration\n */\nexport function validateSkillConfig(config: SkillsConfig): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n if (config.toolGating !== undefined && typeof config.toolGating !== 'boolean') {\n errors.push('toolGating must be a boolean');\n }\n\n if (\n config.agentWritePolicy !== undefined &&\n config.agentWritePolicy !== 'global' &&\n config.agentWritePolicy !== 'workspace' &&\n config.agentWritePolicy !== 'both'\n ) {\n errors.push('agentWritePolicy must be \"global\", \"workspace\", or \"both\"');\n }\n\n // Validate limits\n const limits = config.limits;\n if (limits) {\n if (limits.maxCandidatesPerRoot !== undefined && limits.maxCandidatesPerRoot < 1) {\n errors.push('limits.maxCandidatesPerRoot must be at least 1');\n }\n if (limits.maxSkillsLoadedPerSource !== undefined && limits.maxSkillsLoadedPerSource < 1) {\n errors.push('limits.maxSkillsLoadedPerSource must be at least 1');\n }\n if (limits.maxSkillsInPrompt !== undefined && limits.maxSkillsInPrompt < 1) {\n errors.push('limits.maxSkillsInPrompt must be at least 1');\n }\n }\n\n // Validate entries\n if (config.entries) {\n for (const [skillName, skillConfig] of Object.entries(config.entries)) {\n if (skillConfig.apiKey && typeof skillConfig.apiKey !== 'string') {\n errors.push(`entries.${skillName}.apiKey must be a string`);\n }\n if (skillConfig.env && typeof skillConfig.env !== 'object') {\n errors.push(`entries.${skillName}.env must be an object`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { Skill } from './types.js';
|
|
5
5
|
import type { SkillsConfig } from './types.js';
|
|
6
6
|
export interface FormatSkillsForPromptOptions {
|
|
7
|
+
/** Explicit skill names visible in this context. Omitted means all enabled skills; empty means no visible skills. */
|
|
7
8
|
skillAllowlist?: string[];
|
|
8
9
|
/** When set (including empty array), applies tool gating from skill frontmatter. */
|
|
9
10
|
registeredToolNames?: string[];
|
|
@@ -6,10 +6,11 @@ import { skillVisibleForRegisteredTools } from "./skill-tool-gating.js";
|
|
|
6
6
|
*/
|
|
7
7
|
function selectSkillsVisibleInPrompt(skills, skillsConfig, options) {
|
|
8
8
|
let list = skills;
|
|
9
|
-
if (options?.skillAllowlist
|
|
9
|
+
if (options?.skillAllowlist !== void 0) {
|
|
10
|
+
if (options.skillAllowlist.length === 0) return [];
|
|
10
11
|
const allow = new Set(options.skillAllowlist.map((s) => s.toLowerCase()));
|
|
11
12
|
list = list.filter((s) => allow.has(s.name.toLowerCase()));
|
|
12
|
-
}
|
|
13
|
+
}
|
|
13
14
|
list = list.filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig));
|
|
14
15
|
if (skillsConfig?.toolGating !== false && options?.registeredToolNames !== void 0) {
|
|
15
16
|
const at = new Set(options.registeredToolNames);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-skills-prompt.js","names":[],"sources":["../../../../src/agent/skills/format-skills-prompt.ts"],"sourcesContent":["/**\n * Build `<available_skills>` XML block for the system prompt.\n */\n\nimport { isSkillEnabled } from './config.js';\nimport { skillVisibleForRegisteredTools } from './skill-tool-gating.js';\nimport type { Skill } from './types.js';\nimport type { SkillsConfig } from './types.js';\n\nexport interface FormatSkillsForPromptOptions {\n skillAllowlist?: string[];\n /** When set (including empty array), applies tool gating from skill frontmatter. */\n registeredToolNames?: string[];\n}\n\nexport function selectSkillsVisibleInPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): Skill[] {\n let list = skills;\n\n if (options?.skillAllowlist
|
|
1
|
+
{"version":3,"file":"format-skills-prompt.js","names":[],"sources":["../../../../src/agent/skills/format-skills-prompt.ts"],"sourcesContent":["/**\n * Build `<available_skills>` XML block for the system prompt.\n */\n\nimport { isSkillEnabled } from './config.js';\nimport { skillVisibleForRegisteredTools } from './skill-tool-gating.js';\nimport type { Skill } from './types.js';\nimport type { SkillsConfig } from './types.js';\n\nexport interface FormatSkillsForPromptOptions {\n /** Explicit skill names visible in this context. Omitted means all enabled skills; empty means no visible skills. */\n skillAllowlist?: string[];\n /** When set (including empty array), applies tool gating from skill frontmatter. */\n registeredToolNames?: string[];\n}\n\nexport function selectSkillsVisibleInPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): Skill[] {\n let list = skills;\n\n if (options?.skillAllowlist !== undefined) {\n if (options.skillAllowlist.length === 0) {\n return [];\n }\n const allow = new Set(options.skillAllowlist.map((s) => s.toLowerCase()));\n list = list.filter((s) => allow.has(s.name.toLowerCase()));\n }\n\n list = list.filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig));\n\n if (skillsConfig?.toolGating !== false && options?.registeredToolNames !== undefined) {\n const at = new Set(options.registeredToolNames);\n list = list.filter((s) => skillVisibleForRegisteredTools(s, at));\n }\n\n return list;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction formatSkillXmlMetadataOnly(skill: Skill): string {\n const emoji = skill.metadata.emoji || '';\n const emojiStr = emoji ? `${emoji} ` : '';\n\n return [\n ' <skill>',\n ` <name>${escapeXml(skill.name)}</name>`,\n ` <description>${emojiStr}${escapeXml(skill.description)}</description>`,\n ' </skill>',\n ].join('\\n');\n}\n\nexport function formatSkillsForPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): string {\n const visibleSkills = selectSkillsVisibleInPrompt(skills, skillsConfig, options);\n if (visibleSkills.length === 0) return '';\n\n const lines = [\n '\\n\\n<available_skills>',\n 'Skills are folders of instructions, scripts, and resources.',\n 'Use skills_list to browse; use skill_view(name) for SKILL.md or skill_view(name, path) for references/, templates/, scripts/, or assets/.',\n '',\n ];\n\n for (const skill of visibleSkills) {\n lines.push(formatSkillXmlMetadataOnly(skill));\n }\n\n lines.push('</available_skills>');\n return lines.join('\\n');\n}\n"],"mappings":";;;;;;AAgBA,SAAgB,4BACd,QACA,cACA,SACS;CACT,IAAI,OAAO;AAEX,KAAI,SAAS,mBAAmB,KAAA,GAAW;AACzC,MAAI,QAAQ,eAAe,WAAW,EACpC,QAAO,EAAE;EAEX,MAAM,QAAQ,IAAI,IAAI,QAAQ,eAAe,KAAK,MAAM,EAAE,aAAa,CAAC,CAAC;AACzE,SAAO,KAAK,QAAQ,MAAM,MAAM,IAAI,EAAE,KAAK,aAAa,CAAC,CAAC;;AAG5D,QAAO,KAAK,QAAQ,MAAM,CAAC,EAAE,0BAA0B,eAAe,GAAG,aAAa,CAAC;AAEvF,KAAI,cAAc,eAAe,SAAS,SAAS,wBAAwB,KAAA,GAAW;EACpF,MAAM,KAAK,IAAI,IAAI,QAAQ,oBAAoB;AAC/C,SAAO,KAAK,QAAQ,MAAM,+BAA+B,GAAG,GAAG,CAAC;;AAGlE,QAAO;;AAGT,SAAS,UAAU,KAAqB;AACtC,QAAO,IACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,SAAS;;AAG5B,SAAS,2BAA2B,OAAsB;CACxD,MAAM,QAAQ,MAAM,SAAS,SAAS;CACtC,MAAM,WAAW,QAAQ,GAAG,MAAM,KAAK;AAEvC,QAAO;EACL;EACA,aAAa,UAAU,MAAM,KAAK,CAAC;EACnC,oBAAoB,WAAW,UAAU,MAAM,YAAY,CAAC;EAC5D;EACD,CAAC,KAAK,KAAK;;AAGd,SAAgB,sBACd,QACA,cACA,SACQ;CACR,MAAM,gBAAgB,4BAA4B,QAAQ,cAAc,QAAQ;AAChF,KAAI,cAAc,WAAW,EAAG,QAAO;CAEvC,MAAM,QAAQ;EACZ;EACA;EACA;EACA;EACD;AAED,MAAK,MAAM,SAAS,cAClB,OAAM,KAAK,2BAA2B,MAAM,CAAC;AAG/C,OAAM,KAAK,sBAAsB;AACjC,QAAO,MAAM,KAAK,KAAK"}
|
|
@@ -7,8 +7,8 @@ import { computeSkillTreeHashSync } from "./hub-hash.js";
|
|
|
7
7
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { basename, join, normalize, resolve, sep } from "node:path";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
10
|
import { execFileSync } from "node:child_process";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { fetch } from "undici";
|
|
13
13
|
//#region src/agent/skills/hub-pull.ts
|
|
14
14
|
/**
|
|
@@ -3,20 +3,19 @@ import { init_logger } from "../../utils/logger.js";
|
|
|
3
3
|
import { resolveStateDir } from "../../config/paths-state.js";
|
|
4
4
|
import { init_paths } from "../../config/paths.js";
|
|
5
5
|
import { parseFrontmatter } from "../../markdown/frontmatter.js";
|
|
6
|
-
import { findInstallSpec, getDefaultInstallerPreferences, hasBinary,
|
|
6
|
+
import { findInstallSpec, getDefaultInstallerPreferences, hasBinary, installSkill } from "./installer.js";
|
|
7
7
|
import { applySkillEnvOverrides, createSkillConfigManager, getSkillEnvironment, isSkillEnabled, resolveSkillConfig, validateSkillConfig } from "./config.js";
|
|
8
|
+
import { collectSkillInstallWarnings, formatScanSummary, scanSkillDirectory } from "./scanner.js";
|
|
8
9
|
import { parseSkillToolConditions } from "./skill-tool-gating.js";
|
|
9
10
|
import { parseRequiredEnvVarNames } from "./required-env-vars.js";
|
|
10
|
-
import { parseSkillMetadata } from "./parse-skill-metadata.js";
|
|
11
|
-
import { collectSkillInstallWarnings, formatScanSummary, scanSkillDirectory } from "./scanner.js";
|
|
12
11
|
import { formatSkillsForPrompt } from "./format-skills-prompt.js";
|
|
12
|
+
import { parseSkillMetadata } from "./parse-skill-metadata.js";
|
|
13
13
|
import { SkillTestFramework, SkillTestRunner, formatTestResults, formatTestResultsJson, formatTestResultsTap } from "./test-framework.js";
|
|
14
14
|
import { basename, dirname, join, relative, sep } from "path";
|
|
15
15
|
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
16
16
|
//#region src/agent/skills/index.ts
|
|
17
17
|
init_paths();
|
|
18
18
|
init_logger();
|
|
19
|
-
init_installer();
|
|
20
19
|
const log = createLogger("SkillLoader");
|
|
21
20
|
const IGNORE_FILES = [
|
|
22
21
|
".gitignore",
|
|
@@ -98,13 +97,27 @@ function discoverSkills(dir, source) {
|
|
|
98
97
|
scan(dir, loadIgnoreRules(dir, dir));
|
|
99
98
|
return skills;
|
|
100
99
|
}
|
|
100
|
+
function deriveDescriptionFromMarkdown(content) {
|
|
101
|
+
let fallbackHeading = "";
|
|
102
|
+
for (const rawLine of content.split(/\r?\n/)) {
|
|
103
|
+
const line = rawLine.trim();
|
|
104
|
+
if (!line) continue;
|
|
105
|
+
const heading = line.match(/^#{1,6}\s+(.+)$/);
|
|
106
|
+
if (heading) {
|
|
107
|
+
fallbackHeading ||= heading[1]?.trim() ?? "";
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
return line.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/[*_`~]/g, "").trim() || void 0;
|
|
111
|
+
}
|
|
112
|
+
return fallbackHeading || void 0;
|
|
113
|
+
}
|
|
101
114
|
function loadSkillFromFile(filePath, source, rootDir) {
|
|
102
115
|
try {
|
|
103
116
|
const { frontmatter, content } = parseFrontmatter(readFileSync(filePath, "utf-8"));
|
|
104
117
|
const skillDir = dirname(filePath);
|
|
105
118
|
const parentDirName = basename(skillDir);
|
|
106
119
|
const name = frontmatter.name || parentDirName;
|
|
107
|
-
const description = frontmatter.description;
|
|
120
|
+
const description = frontmatter.description?.trim() || deriveDescriptionFromMarkdown(content);
|
|
108
121
|
if (!description?.trim()) return null;
|
|
109
122
|
let category;
|
|
110
123
|
if (rootDir) {
|
|
@@ -112,6 +125,8 @@ function loadSkillFromFile(filePath, source, rootDir) {
|
|
|
112
125
|
if (segments.length > 1) category = segments[0];
|
|
113
126
|
}
|
|
114
127
|
const metadata = parseSkillMetadata(frontmatter);
|
|
128
|
+
metadata.name ||= name;
|
|
129
|
+
metadata.description ||= description.trim();
|
|
115
130
|
const toolConditions = parseSkillToolConditions(frontmatter);
|
|
116
131
|
const requiredEnvVarNames = parseRequiredEnvVarNames(frontmatter);
|
|
117
132
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/agent/skills/index.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'fs';\nimport { basename, dirname, join, relative, sep } from 'path';\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { createSkillConfigManager, isSkillEnabled } from './config.js';\nimport { formatSkillsForPrompt } from './format-skills-prompt.js';\nimport { parseRequiredEnvVarNames } from './required-env-vars.js';\nimport { parseSkillMetadata } from './parse-skill-metadata.js';\nimport { parseSkillToolConditions } from './skill-tool-gating.js';\nimport type { Skill, SkillDiagnostic, LoadSkillsResult, SkillConfig, SkillsConfig } from './types.js';\n\nconst log = createLogger('SkillLoader');\n\nconst IGNORE_FILES = ['.gitignore', '.ignore', '.fdignore'];\n\nfunction toPosixPath(p: string): string {\n return p.split(sep).join('/');\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n if (trimmed.startsWith('#') && !trimmed.startsWith('\\\\#')) return null;\n\n let pattern = line;\n let negated = false;\n\n if (pattern.startsWith('!')) {\n negated = true;\n pattern = pattern.slice(1);\n } else if (pattern.startsWith('\\\\!')) {\n pattern = pattern.slice(1);\n }\n\n if (pattern.startsWith('/')) {\n pattern = pattern.slice(1);\n }\n\n const prefixed = prefix ? `${prefix}${pattern}` : pattern;\n return negated ? `!${prefixed}` : prefixed;\n}\n\nfunction loadIgnoreRules(dir: string, rootDir: string): Set<string> {\n const ignoredPaths = new Set<string>();\n const relativeDir = relative(rootDir, dir);\n const prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : '';\n\n for (const filename of IGNORE_FILES) {\n const ignorePath = join(dir, filename);\n if (!existsSync(ignorePath)) continue;\n\n try {\n const content = readFileSync(ignorePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const pattern = prefixIgnorePattern(line, prefix);\n if (pattern) {\n const fullPattern = pattern.startsWith('!')\n ? `!${prefix}${pattern.slice(1)}`\n : `${prefix}${pattern}`;\n ignoredPaths.add(fullPattern);\n }\n }\n } catch {}\n }\n\n return ignoredPaths;\n}\n\nfunction shouldIgnore(path: string, ignoredPaths: Set<string>): boolean {\n for (const pattern of ignoredPaths) {\n if (pattern.startsWith('!')) {\n const positive = pattern.slice(1);\n if (path === positive || path.startsWith(`${positive}/`)) {\n return false;\n }\n } else {\n if (path === pattern || path.startsWith(`${pattern}/`)) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction discoverSkills(dir: string, source: 'builtin' | 'workspace' | 'global'): Skill[] {\n const skills: Skill[] = [];\n if (!existsSync(dir)) return skills;\n\n function scan(currentDir: string, currentIgnoredPaths: Set<string>) {\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n\n const fullPath = join(currentDir, entry.name);\n const relPath = toPosixPath(relative(dir, fullPath));\n\n if (shouldIgnore(relPath, currentIgnoredPaths)) continue;\n\n if (entry.isDirectory()) {\n const skillMdPath = join(fullPath, 'SKILL.md');\n const skillRelPath = `${relPath}/`;\n\n const subIgnoredPaths = new Set(currentIgnoredPaths);\n const subIgnoreFile = join(fullPath, '.gitignore');\n if (existsSync(subIgnoreFile)) {\n const subRules = loadIgnoreRules(fullPath, dir);\n for (const rule of subRules) {\n subIgnoredPaths.add(`${skillRelPath}${rule}`);\n }\n }\n\n if (existsSync(skillMdPath) && !shouldIgnore(skillRelPath, currentIgnoredPaths)) {\n const skill = loadSkillFromFile(skillMdPath, source, dir);\n if (skill) skills.push(skill);\n }\n\n scan(fullPath, subIgnoredPaths);\n }\n }\n } catch {}\n }\n\n scan(dir, loadIgnoreRules(dir, dir));\n return skills;\n}\n\nfunction loadSkillFromFile(filePath: string, source: 'builtin' | 'workspace' | 'global', rootDir?: string): Skill | null {\n try {\n const rawContent = readFileSync(filePath, 'utf-8');\n const { frontmatter, content } = parseFrontmatter(rawContent);\n const skillDir = dirname(filePath);\n const parentDirName = basename(skillDir);\n\n const name = (frontmatter.name as string | undefined) || parentDirName;\n const description = frontmatter.description as string | undefined;\n if (!description?.trim()) return null;\n\n // Derive category from directory path: skills/creative/algorithmic-art → 'creative'\n // Only assign a category when the skill is nested at least two levels below rootDir.\n let category: string | undefined;\n if (rootDir) {\n const relDir = toPosixPath(relative(rootDir, skillDir));\n const segments = relDir.split('/');\n if (segments.length > 1) {\n category = segments[0];\n }\n }\n\n const metadata = parseSkillMetadata(frontmatter);\n const toolConditions = parseSkillToolConditions(frontmatter);\n const requiredEnvVarNames = parseRequiredEnvVarNames(frontmatter);\n\n return {\n name,\n description: description.trim(),\n category,\n filePath,\n baseDir: skillDir,\n source,\n disableModelInvocation: frontmatter['disable-model-invocation'] === true,\n metadata,\n toolConditions,\n requiredEnvVarNames: requiredEnvVarNames.length > 0 ? requiredEnvVarNames : undefined,\n content,\n };\n } catch {\n return null;\n }\n}\n\nexport function loadSkills(options: {\n workspaceDir?: string;\n globalDir?: string;\n builtinDir?: string;\n extraDirs?: string[];\n}): LoadSkillsResult {\n const { workspaceDir, builtinDir, extraDirs = [] } = options;\n\n const skillMap = new Map<string, Skill>();\n const diagnostics: SkillDiagnostic[] = [];\n\n if (builtinDir) {\n for (const skill of discoverSkills(builtinDir, 'builtin')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n\n const globalDirs = [\n options.globalDir,\n join(resolveStateDir(), 'skills'),\n ].filter((d): d is string => !!d && existsSync(d));\n\n for (const dir of globalDirs) {\n for (const skill of discoverSkills(dir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n // Global must win over bundled when names match (Workspace > Global > Bundled).\n skillMap.set(skill.name, skill);\n }\n }\n\n if (workspaceDir) {\n const workspaceSkills = discoverSkills(join(workspaceDir, 'skills'), 'workspace');\n for (const skill of workspaceSkills) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n skillMap.set(skill.name, skill);\n }\n }\n\n // Scan extra directories\n for (const extraDir of extraDirs) {\n if (existsSync(extraDir)) {\n for (const skill of discoverSkills(extraDir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n }\n\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n const merged = Array.from(skillMap.values());\n\n return {\n skills: merged,\n prompt: formatSkillsForPrompt(merged, skillsConfig),\n diagnostics,\n };\n}\n\nexport interface SkillLoader {\n init: (workspace: string, builtin: string | null) => LoadSkillsResult;\n load: () => LoadSkillsResult;\n reload: () => LoadSkillsResult;\n /** Recompute `<available_skills>` from disk-loaded skills and current ~/.xopc/skills.json (no filesystem rescan). */\n refreshPromptFromConfig: () => void;\n getSkills: () => Skill[];\n getPrompt: () => string;\n getDiagnostics: () => SkillDiagnostic[];\n getLastLoadTime: () => number;\n getSkillByName: (name: string) => Skill | undefined;\n getEnabledSkills: (config?: Record<string, SkillConfig>) => Skill[];\n}\n\nexport function createSkillLoader(): SkillLoader {\n let cachedSkills: Skill[] = [];\n let cachedPrompt: string = '';\n let cachedDiagnostics: SkillDiagnostic[] = [];\n let lastLoadTime = 0;\n let workspaceDir: string | undefined;\n let builtinDir: string | undefined;\n let extraDirs: string[] = [];\n\n function updateCache(result: LoadSkillsResult): LoadSkillsResult {\n cachedSkills = result.skills;\n cachedPrompt = result.prompt;\n cachedDiagnostics = result.diagnostics;\n lastLoadTime = Date.now();\n return result;\n }\n\n return {\n init: (workspace: string, builtin: string | null) => {\n workspaceDir = workspace;\n builtinDir = builtin || undefined;\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n load: () => {\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n reload: () => {\n log.info('Reloading skills');\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n\n refreshPromptFromConfig: () => {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n cachedPrompt = formatSkillsForPrompt(cachedSkills, skillsConfig);\n lastLoadTime = Date.now();\n },\n\n getSkills: () => cachedSkills,\n getPrompt: () => cachedPrompt,\n getDiagnostics: () => cachedDiagnostics,\n getLastLoadTime: () => lastLoadTime,\n \n getSkillByName: (name: string) => {\n return cachedSkills.find(s => s.name === name);\n },\n \n getEnabledSkills: (entries?: Record<string, SkillConfig>) => {\n const skillsConfig: SkillsConfig =\n entries !== undefined ? { entries } : createSkillConfigManager(resolveStateDir()).load();\n return cachedSkills.filter(\n (skill) => !skill.disableModelInvocation && isSkillEnabled(skill, skillsConfig),\n );\n },\n };\n}\n\n// `SkillManager` + sibling types removed from this barrel — `skill-manager.ts`\n// imports `createSkillLoader` from THIS file, so re-exporting it back here\n// formed a circular cycle. External callers should import directly from\n// `./skill-manager.js`.\n\n// Re-export types for convenience\nexport type { \n Skill, \n SkillMetadata, \n SkillConfig,\n SkillInstallSpec,\n SkillInstallResult,\n SkillInstallRequest,\n LoadSkillsResult,\n // Note: SkillDiagnostic is re-exported from skill-manager.ts above\n SkillSnapshot,\n} from './types.js';\n\n// Re-export installer\nexport { \n installSkill, \n findInstallSpec,\n hasBinary,\n getDefaultInstallerPreferences,\n type InstallerPreferences,\n type InstallContext,\n} from './installer.js';\n\n// Re-export scanner\nexport {\n scanSkillDirectory,\n formatScanSummary,\n collectSkillInstallWarnings,\n type ScanSummary,\n type SecurityFinding,\n type Severity,\n} from './scanner.js';\n\n// Re-export config manager\nexport {\n resolveSkillConfig,\n applySkillEnvOverrides,\n getSkillEnvironment,\n createSkillConfigManager,\n isSkillEnabled,\n validateSkillConfig,\n type SkillConfigFile,\n} from './config.js';\n\n// `watcher.ts` re-exports removed — it imports `SkillLoader` from THIS file, so\n// re-exporting back here formed a circular cycle. External callers should\n// import directly from `./watcher.js`.\n\n// Re-export test framework\nexport {\n SkillTestFramework,\n SkillTestRunner,\n formatTestResults,\n formatTestResultsJson,\n formatTestResultsTap,\n type TestResult,\n type TestStatus,\n type SkillTestReport,\n type TestOptions,\n type TestRunnerOptions,\n} from './test-framework.js';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/agent/skills/index.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'fs';\nimport { basename, dirname, join, relative, sep } from 'path';\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { createSkillConfigManager, isSkillEnabled } from './config.js';\nimport { formatSkillsForPrompt } from './format-skills-prompt.js';\nimport { parseRequiredEnvVarNames } from './required-env-vars.js';\nimport { parseSkillMetadata } from './parse-skill-metadata.js';\nimport { parseSkillToolConditions } from './skill-tool-gating.js';\nimport type { Skill, SkillDiagnostic, LoadSkillsResult, SkillConfig, SkillsConfig } from './types.js';\n\nconst log = createLogger('SkillLoader');\n\nconst IGNORE_FILES = ['.gitignore', '.ignore', '.fdignore'];\n\nfunction toPosixPath(p: string): string {\n return p.split(sep).join('/');\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n if (trimmed.startsWith('#') && !trimmed.startsWith('\\\\#')) return null;\n\n let pattern = line;\n let negated = false;\n\n if (pattern.startsWith('!')) {\n negated = true;\n pattern = pattern.slice(1);\n } else if (pattern.startsWith('\\\\!')) {\n pattern = pattern.slice(1);\n }\n\n if (pattern.startsWith('/')) {\n pattern = pattern.slice(1);\n }\n\n const prefixed = prefix ? `${prefix}${pattern}` : pattern;\n return negated ? `!${prefixed}` : prefixed;\n}\n\nfunction loadIgnoreRules(dir: string, rootDir: string): Set<string> {\n const ignoredPaths = new Set<string>();\n const relativeDir = relative(rootDir, dir);\n const prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : '';\n\n for (const filename of IGNORE_FILES) {\n const ignorePath = join(dir, filename);\n if (!existsSync(ignorePath)) continue;\n\n try {\n const content = readFileSync(ignorePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const pattern = prefixIgnorePattern(line, prefix);\n if (pattern) {\n const fullPattern = pattern.startsWith('!')\n ? `!${prefix}${pattern.slice(1)}`\n : `${prefix}${pattern}`;\n ignoredPaths.add(fullPattern);\n }\n }\n } catch {}\n }\n\n return ignoredPaths;\n}\n\nfunction shouldIgnore(path: string, ignoredPaths: Set<string>): boolean {\n for (const pattern of ignoredPaths) {\n if (pattern.startsWith('!')) {\n const positive = pattern.slice(1);\n if (path === positive || path.startsWith(`${positive}/`)) {\n return false;\n }\n } else {\n if (path === pattern || path.startsWith(`${pattern}/`)) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction discoverSkills(dir: string, source: 'builtin' | 'workspace' | 'global'): Skill[] {\n const skills: Skill[] = [];\n if (!existsSync(dir)) return skills;\n\n function scan(currentDir: string, currentIgnoredPaths: Set<string>) {\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n\n const fullPath = join(currentDir, entry.name);\n const relPath = toPosixPath(relative(dir, fullPath));\n\n if (shouldIgnore(relPath, currentIgnoredPaths)) continue;\n\n if (entry.isDirectory()) {\n const skillMdPath = join(fullPath, 'SKILL.md');\n const skillRelPath = `${relPath}/`;\n\n const subIgnoredPaths = new Set(currentIgnoredPaths);\n const subIgnoreFile = join(fullPath, '.gitignore');\n if (existsSync(subIgnoreFile)) {\n const subRules = loadIgnoreRules(fullPath, dir);\n for (const rule of subRules) {\n subIgnoredPaths.add(`${skillRelPath}${rule}`);\n }\n }\n\n if (existsSync(skillMdPath) && !shouldIgnore(skillRelPath, currentIgnoredPaths)) {\n const skill = loadSkillFromFile(skillMdPath, source, dir);\n if (skill) skills.push(skill);\n }\n\n scan(fullPath, subIgnoredPaths);\n }\n }\n } catch {}\n }\n\n scan(dir, loadIgnoreRules(dir, dir));\n return skills;\n}\n\nfunction deriveDescriptionFromMarkdown(content: string): string | undefined {\n let fallbackHeading = '';\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line) continue;\n\n const heading = line.match(/^#{1,6}\\s+(.+)$/);\n if (heading) {\n fallbackHeading ||= heading[1]?.trim() ?? '';\n continue;\n }\n\n return line\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/[*_`~]/g, '')\n .trim() || undefined;\n }\n\n return fallbackHeading || undefined;\n}\n\nfunction loadSkillFromFile(filePath: string, source: 'builtin' | 'workspace' | 'global', rootDir?: string): Skill | null {\n try {\n const rawContent = readFileSync(filePath, 'utf-8');\n const { frontmatter, content } = parseFrontmatter(rawContent);\n const skillDir = dirname(filePath);\n const parentDirName = basename(skillDir);\n\n const name = (frontmatter.name as string | undefined) || parentDirName;\n const description =\n (frontmatter.description as string | undefined)?.trim() || deriveDescriptionFromMarkdown(content);\n if (!description?.trim()) return null;\n\n // Derive category from directory path: skills/creative/algorithmic-art → 'creative'\n // Only assign a category when the skill is nested at least two levels below rootDir.\n let category: string | undefined;\n if (rootDir) {\n const relDir = toPosixPath(relative(rootDir, skillDir));\n const segments = relDir.split('/');\n if (segments.length > 1) {\n category = segments[0];\n }\n }\n\n const metadata = parseSkillMetadata(frontmatter);\n metadata.name ||= name;\n metadata.description ||= description.trim();\n const toolConditions = parseSkillToolConditions(frontmatter);\n const requiredEnvVarNames = parseRequiredEnvVarNames(frontmatter);\n\n return {\n name,\n description: description.trim(),\n category,\n filePath,\n baseDir: skillDir,\n source,\n disableModelInvocation: frontmatter['disable-model-invocation'] === true,\n metadata,\n toolConditions,\n requiredEnvVarNames: requiredEnvVarNames.length > 0 ? requiredEnvVarNames : undefined,\n content,\n };\n } catch {\n return null;\n }\n}\n\nexport function loadSkills(options: {\n workspaceDir?: string;\n globalDir?: string;\n builtinDir?: string;\n extraDirs?: string[];\n}): LoadSkillsResult {\n const { workspaceDir, builtinDir, extraDirs = [] } = options;\n\n const skillMap = new Map<string, Skill>();\n const diagnostics: SkillDiagnostic[] = [];\n\n if (builtinDir) {\n for (const skill of discoverSkills(builtinDir, 'builtin')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n\n const globalDirs = [\n options.globalDir,\n join(resolveStateDir(), 'skills'),\n ].filter((d): d is string => !!d && existsSync(d));\n\n for (const dir of globalDirs) {\n for (const skill of discoverSkills(dir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n // Global must win over bundled when names match (Workspace > Global > Bundled).\n skillMap.set(skill.name, skill);\n }\n }\n\n if (workspaceDir) {\n const workspaceSkills = discoverSkills(join(workspaceDir, 'skills'), 'workspace');\n for (const skill of workspaceSkills) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n skillMap.set(skill.name, skill);\n }\n }\n\n // Scan extra directories\n for (const extraDir of extraDirs) {\n if (existsSync(extraDir)) {\n for (const skill of discoverSkills(extraDir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n }\n\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n const merged = Array.from(skillMap.values());\n\n return {\n skills: merged,\n prompt: formatSkillsForPrompt(merged, skillsConfig),\n diagnostics,\n };\n}\n\nexport interface SkillLoader {\n init: (workspace: string, builtin: string | null) => LoadSkillsResult;\n load: () => LoadSkillsResult;\n reload: () => LoadSkillsResult;\n /** Recompute `<available_skills>` from disk-loaded skills and current ~/.xopc/skills.json (no filesystem rescan). */\n refreshPromptFromConfig: () => void;\n getSkills: () => Skill[];\n getPrompt: () => string;\n getDiagnostics: () => SkillDiagnostic[];\n getLastLoadTime: () => number;\n getSkillByName: (name: string) => Skill | undefined;\n getEnabledSkills: (config?: Record<string, SkillConfig>) => Skill[];\n}\n\nexport function createSkillLoader(): SkillLoader {\n let cachedSkills: Skill[] = [];\n let cachedPrompt: string = '';\n let cachedDiagnostics: SkillDiagnostic[] = [];\n let lastLoadTime = 0;\n let workspaceDir: string | undefined;\n let builtinDir: string | undefined;\n let extraDirs: string[] = [];\n\n function updateCache(result: LoadSkillsResult): LoadSkillsResult {\n cachedSkills = result.skills;\n cachedPrompt = result.prompt;\n cachedDiagnostics = result.diagnostics;\n lastLoadTime = Date.now();\n return result;\n }\n\n return {\n init: (workspace: string, builtin: string | null) => {\n workspaceDir = workspace;\n builtinDir = builtin || undefined;\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n load: () => {\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n reload: () => {\n log.info('Reloading skills');\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n\n refreshPromptFromConfig: () => {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n cachedPrompt = formatSkillsForPrompt(cachedSkills, skillsConfig);\n lastLoadTime = Date.now();\n },\n\n getSkills: () => cachedSkills,\n getPrompt: () => cachedPrompt,\n getDiagnostics: () => cachedDiagnostics,\n getLastLoadTime: () => lastLoadTime,\n \n getSkillByName: (name: string) => {\n return cachedSkills.find(s => s.name === name);\n },\n \n getEnabledSkills: (entries?: Record<string, SkillConfig>) => {\n const skillsConfig: SkillsConfig =\n entries !== undefined ? { entries } : createSkillConfigManager(resolveStateDir()).load();\n return cachedSkills.filter(\n (skill) => !skill.disableModelInvocation && isSkillEnabled(skill, skillsConfig),\n );\n },\n };\n}\n\n// `SkillManager` + sibling types removed from this barrel — `skill-manager.ts`\n// imports `createSkillLoader` from THIS file, so re-exporting it back here\n// formed a circular cycle. External callers should import directly from\n// `./skill-manager.js`.\n\n// Re-export types for convenience\nexport type { \n Skill, \n SkillMetadata, \n SkillConfig,\n SkillInstallSpec,\n SkillInstallResult,\n SkillInstallRequest,\n LoadSkillsResult,\n // Note: SkillDiagnostic is re-exported from skill-manager.ts above\n SkillSnapshot,\n} from './types.js';\n\n// Re-export installer\nexport { \n installSkill, \n findInstallSpec,\n hasBinary,\n getDefaultInstallerPreferences,\n type InstallerPreferences,\n type InstallContext,\n} from './installer.js';\n\n// Re-export scanner\nexport {\n scanSkillDirectory,\n formatScanSummary,\n collectSkillInstallWarnings,\n type ScanSummary,\n type SecurityFinding,\n type Severity,\n} from './scanner.js';\n\n// Re-export config manager\nexport {\n resolveSkillConfig,\n applySkillEnvOverrides,\n getSkillEnvironment,\n createSkillConfigManager,\n isSkillEnabled,\n validateSkillConfig,\n type SkillConfigFile,\n} from './config.js';\n\n// `watcher.ts` re-exports removed — it imports `SkillLoader` from THIS file, so\n// re-exporting back here formed a circular cycle. External callers should\n// import directly from `./watcher.js`.\n\n// Re-export test framework\nexport {\n SkillTestFramework,\n SkillTestRunner,\n formatTestResults,\n formatTestResultsJson,\n formatTestResultsTap,\n type TestResult,\n type TestStatus,\n type SkillTestReport,\n type TestOptions,\n type TestRunnerOptions,\n} from './test-framework.js';\n"],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { __esmMin, __exportAll, __require } from "../../../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
-
import { join } from "path";
|
|
5
|
-
import { existsSync } from "fs";
|
|
3
|
+
import { delimiter, join } from "path";
|
|
4
|
+
import { accessSync, constants, existsSync } from "fs";
|
|
6
5
|
import { promisify } from "util";
|
|
7
6
|
import { exec } from "child_process";
|
|
8
7
|
//#region src/agent/skills/installer.ts
|
|
@@ -12,29 +11,24 @@ import { exec } from "child_process";
|
|
|
12
11
|
* Handles installation of skill dependencies via various package managers.
|
|
13
12
|
*
|
|
14
13
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
hasBinary: () => hasBinary,
|
|
19
|
-
installSkill: () => installSkill,
|
|
20
|
-
resolveBrewExecutable: () => resolveBrewExecutable
|
|
21
|
-
});
|
|
14
|
+
init_logger();
|
|
15
|
+
const execAsync = promisify(exec);
|
|
16
|
+
const log = createLogger("SkillInstaller");
|
|
22
17
|
/**
|
|
23
18
|
* Check if a binary exists
|
|
24
19
|
*/
|
|
25
20
|
function hasBinary(name) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
if (!name || name.includes("/") || name.includes("\\")) return false;
|
|
22
|
+
const pathEntries = (process.env.PATH || "").split(delimiter).filter(Boolean);
|
|
23
|
+
const extensions = process.platform === "win32" ? (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean) : [""];
|
|
24
|
+
for (const dir of pathEntries) for (const ext of extensions) {
|
|
25
|
+
const candidate = join(dir, `${name}${ext}`);
|
|
30
26
|
try {
|
|
31
|
-
|
|
32
|
-
execSync(`which ${name}`, { stdio: "ignore" });
|
|
27
|
+
accessSync(candidate, constants.X_OK);
|
|
33
28
|
return true;
|
|
34
|
-
} catch {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
29
|
+
} catch {}
|
|
37
30
|
}
|
|
31
|
+
return false;
|
|
38
32
|
}
|
|
39
33
|
/**
|
|
40
34
|
* Resolve brew executable path
|
|
@@ -347,14 +341,7 @@ function getDefaultInstallerPreferences() {
|
|
|
347
341
|
nodeManager: "pnpm"
|
|
348
342
|
};
|
|
349
343
|
}
|
|
350
|
-
var execAsync, log;
|
|
351
|
-
var init_installer = __esmMin((() => {
|
|
352
|
-
init_logger();
|
|
353
|
-
execAsync = promisify(exec);
|
|
354
|
-
log = createLogger("SkillInstaller");
|
|
355
|
-
}));
|
|
356
344
|
//#endregion
|
|
357
|
-
|
|
358
|
-
export { findInstallSpec, getDefaultInstallerPreferences, hasBinary, init_installer, installSkill, installer_exports, resolveBrewExecutable };
|
|
345
|
+
export { findInstallSpec, getDefaultInstallerPreferences, hasBinary, installSkill, resolveBrewExecutable };
|
|
359
346
|
|
|
360
347
|
//# sourceMappingURL=installer.js.map
|
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,UAAU,MAAuB;AAC/C,KAAI;EACF,MAAM,EAAE,UAAA,UAAkB,QAAQ;AAClC,SAAO,CAAC,CAAC,MAAM,KAAK,MAAM,EAAE,SAAS,MAAM,CAAC;SACtC;AAEN,MAAI;GACF,MAAM,EAAE,aAAA,UAAqB,gBAAgB;AAC7C,YAAS,SAAS,QAAQ,EAAE,OAAO,UAAU,CAAC;AAC9C,UAAO;UACD;AACN,UAAO;;;;;;;AAQb,SAAgB,wBAA4C;AAM1D,MAAK,MAAM,aAAa,CAJtB,0BACA,sBAGgC,CAChC,KAAI,WAAW,UAAU,CACvB,QAAO;;;;;AAUb,SAAS,wBAAwB,aAAqB,SAAwD;AAC5G,SAAQ,SAAR;EACE,KAAK,OACH,QAAO;GAAC;GAAQ;GAAO;GAAM;GAAoB;GAAY;EAC/D,KAAK,OACH,QAAO;GAAC;GAAQ;GAAU;GAAO;GAAoB;GAAY;EACnE,KAAK,MACH,QAAO;GAAC;GAAO;GAAO;GAAM;GAAoB;GAAY;EAC9D,QACE,QAAO;GAAC;GAAO;GAAW;GAAM;GAAoB;GAAY;;;;;;AAOtE,SAAS,oBAAoB,MAAwB,OAGnD;AACA,SAAQ,KAAK,MAAb;EACE,KAAK;AACH,OAAI,CAAC,KAAK,QACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAwB;AAEtD,UAAO,EAAE,MAAM;IAAC;IAAQ;IAAW,KAAK;IAAQ,EAAE;EAGpD,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;AACH,OAAI,CAAC,KAAK,QACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAwB;AAEtD,UAAO,EACL,MAAM,wBAAwB,KAAK,SAAS,MAAM,YAAY,EAC/D;EAGH,KAAK;AACH,OAAI,CAAC,KAAK,OACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAqB;AAEnD,UAAO,EAAE,MAAM;IAAC;IAAM;IAAW,KAAK;IAAO,EAAE;EAGjD,KAAK;AACH,OAAI,CAAC,KAAK,QACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAsB;AAEpD,UAAO,EAAE,MAAM;IAAC;IAAM;IAAQ;IAAW,KAAK;IAAQ,EAAE;EAG1D,KAAK,WACH,QAAO;GAAE,MAAM;GAAM,OAAO;GAAuC;EAGrE;AAC6B,QAAK;AAChC,UAAO;IAAE,MAAM;IAAM,OAAO,0BAA0B,KAAK;IAAQ;;;;;;AAQzE,eAAe,sBACb,MACA,WACA,KACkE;CAClE,MAAM,CAAC,KAAK,GAAG,QAAQ;AAEvB,KAAI;EACF,MAAM,EAAE,QAAQ,WAAW,MAAM,UAAU,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,IAAI;GACrE,SAAS;GACT;GACA,WAAW,KAAK,OAAO;GACxB,CAAC;AAEF,SAAO;GACL,MAAM;GACN,QAAQ,OAAO,UAAU;GACzB,QAAQ,OAAO,UAAU;GAC1B;UACM,KAAc;AACrB,MAAI,eAAe,OAAO;GACxB,MAAM,YAAY;AAClB,UAAO;IACL,MAAM,UAAU,QAAQ;IACxB,QAAQ,UAAU,QAAQ,UAAU,IAAI;IACxC,QAAQ,UAAU,QAAQ,UAAU,IAAI;IACzC;;AAGH,SAAO;GACL,MAAM;GACN,QAAQ;GACR,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GACzD;;;;;;AAOL,eAAe,kBAAkB,WAA4D;AAC3F,KAAI,UAAU,KAAK,CACjB;CAIF,MAAM,UAAU,uBAAuB;AACvC,KAAI,CAAC,QACH,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ;EACR,QAAQ;EACR,MAAM;EACP;CAGH,MAAM,SAAS,MAAM,sBAAsB;EAAC;EAAS;EAAW;EAAK,EAAE,UAAU;AACjF,KAAI,OAAO,SAAS,EAClB;AAGF,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,MAAM,OAAO;EACd;;;;;AAMH,eAAe,kBAAkB,WAA4D;AAC3F,KAAI,UAAU,KAAK,CACjB;CAGF,MAAM,UAAU,uBAAuB;AACvC,KAAI,SAAS;EACX,MAAM,SAAS,MAAM,sBAAsB;GAAC;GAAS;GAAW;GAAK,EAAE,UAAU;AACjF,MAAI,OAAO,SAAS,EAClB;AAGF,SAAO;GACL,IAAI;GACJ,SAAS;GACT,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,MAAM,OAAO;GACd;;AAIH,KAAI,UAAU,UAAU,EAAE;EACxB,MAAM,SAAS,QAAQ,UAAU,KAAK;EACtC,MAAM,SAAS,SACX;GAAC;GAAW;GAAW;GAAM;GAAY,GACzC;GAAC;GAAQ;GAAW;GAAW;GAAM;GAAY;AAGrD,MAAI,CAAC,OACH,OAAM,sBAAsB;GAAC;GAAQ;GAAW;GAAU;GAAM,EAAE,KAAK,IAAI,WAAW,IAAM,CAAC;EAG/F,MAAM,SAAS,MAAM,sBAAsB,QAAQ,UAAU;AAC7D,MAAI,OAAO,SAAS,EAClB;AAGF,SAAO;GACL,IAAI;GACJ,SAAS;GACT,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,MAAM,OAAO;GACd;;AAGH,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ;EACR,QAAQ;EACR,MAAM;EACP;;;;;AAMH,SAAS,qBAAqB,QAKP;AACrB,QAAO;EACL,IAAI;EACJ,SAAS,OAAO;EAChB,QAAQ,OAAO,QAAQ,MAAM,IAAI;EACjC,QAAQ,OAAO,QAAQ,MAAM,IAAI;EACjC,MAAM,OAAO,QAAQ;EACtB;;;;;AAMH,SAAS,qBAAqB,QAAqF;AACjH,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ,OAAO,OAAO,MAAM;EAC5B,QAAQ,OAAO,OAAO,MAAM;EAC5B,MAAM,OAAO;EACd;;;;;AAMH,SAAgB,gBAAgB,OAAmB,WAAiD;CAClG,MAAM,QAAQ,MAAM,SAAS,WAAW,EAAE;AAE1C,MAAK,MAAM,CAAC,OAAO,SAAS,MAAM,SAAS,CAEzC,MADW,KAAK,MAAM,GAAG,KAAK,KAAK,GAAG,aAC3B,UACT,QAAO;;;;;AAUb,eAAsB,aAAa,KAAkD;CACnF,MAAM,EAAE,aAAa,WAAW,gBAAgB;AAEhD,KAAI,KAAK;EAAE,OAAO,IAAI,WAAW,MAAM;EAAM,MAAM,YAAY;EAAM,EAAE,8BAA8B;AAGrG,KAAI,YAAY,SAAS,WACvB,QAAO,qBAAqB,EAC1B,SAAS,0CACV,CAAC;AAIJ,KAAI,YAAY,SAAS,MAAM;EAC7B,MAAM,YAAY,MAAM,kBAAkB,UAAU;AACpD,MAAI,UACF,QAAO;;AAIX,KAAI,YAAY,SAAS,MAAM;EAC7B,MAAM,YAAY,MAAM,kBAAkB,UAAU;AACpD,MAAI,UACF,QAAO;;CAKX,MAAM,UAAU,oBAAoB,aAAa,YAAY;AAC7D,KAAI,QAAQ,MACV,QAAO,qBAAqB,EAC1B,SAAS,QAAQ,OAClB,CAAC;AAGJ,KAAI,CAAC,QAAQ,KACX,QAAO,qBAAqB,EAC1B,SAAS,2BACV,CAAC;CAIJ,IAAI,OAAO,CAAC,GAAG,QAAQ,KAAK;AAC5B,KAAI,YAAY,SAAS,QAAQ;EAC/B,MAAM,UAAU,uBAAuB;AACvC,MAAI,CAAC,QAKH,QAAO,qBAAqB,EAC1B,SAAS,wBALE,QAAQ,aAAa,UAC9B,mGACA,gEAIH,CAAC;AAEJ,OAAK,KAAK;;CAIZ,IAAI;AACJ,KAAI,YAAY,SAAS,MAAM;EAC7B,MAAM,UAAU,uBAAuB;AACvC,MAAI,QACF,KAAI;GACF,MAAM,EAAE,WAAW,MAAM,UAAU,GAAG,QAAQ,WAAW;GACzD,MAAM,SAAS,OAAO,MAAM;AAC5B,OAAI,OACF,OAAM;IAAE,GAAG,QAAQ;IAAK,OAAO,KAAK,QAAQ,MAAM;IAAE;UAEhD;;CAOZ,MAAM,SAAS,MAAM,sBAAsB,MAAM,WAAW,IAAI;AAEhE,KAAI,OAAO,SAAS,GAAG;AACrB,MAAI,KAAK,EAAE,OAAO,IAAI,WAAW,MAAM,MAAM,EAAE,0CAA0C;AACzF,SAAO,qBAAqB,OAAO;;AAGrC,KAAI,KAAK;EACP,OAAO,IAAI,WAAW,MAAM;EAC5B,QAAQ,OAAO;EAChB,EAAE,uCAAuC;AAE1C,QAAO,qBAAqB;EAC1B,SAAS,OAAO,UAAU,sCAAsC,OAAO;EACvE,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,MAAM,OAAO;EACd,CAAC;;;;;AAMJ,SAAgB,iCAAuD;AACrE,QAAO;EACL,YAAY;EACZ,aAAa;EACd;;;;cA1ZkD;AAG/C,aAAY,UAAU,KAAK;AAE3B,OAAM,aAAa,iBAAiB"}
|
|
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":";;;;;;;;;;;;;aAWqD;AAGrD,MAAM,YAAY,UAAU,KAAK;AAEjC,MAAM,MAAM,aAAa,iBAAiB;;;;AAkB1C,SAAgB,UAAU,MAAuB;AAC/C,KAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,KAAK,CACpD,QAAO;CAGT,MAAM,eAAe,QAAQ,IAAI,QAAQ,IAAI,MAAM,UAAU,CAAC,OAAO,QAAQ;CAC7E,MAAM,aAAa,QAAQ,aAAa,WACnC,QAAQ,IAAI,WAAW,uBAAuB,MAAM,IAAI,CAAC,OAAO,QAAQ,GACzE,CAAC,GAAG;AAER,MAAK,MAAM,OAAO,YAChB,MAAK,MAAM,OAAO,YAAY;EAC5B,MAAM,YAAY,KAAK,KAAK,GAAG,OAAO,MAAM;AAC5C,MAAI;AACF,cAAW,WAAW,UAAU,KAAK;AACrC,UAAO;UACD;;AAMZ,QAAO;;;;;AAMT,SAAgB,wBAA4C;AAM1D,MAAK,MAAM,aAAa,CAJtB,0BACA,sBAGgC,CAChC,KAAI,WAAW,UAAU,CACvB,QAAO;;;;;AAUb,SAAS,wBAAwB,aAAqB,SAAwD;AAC5G,SAAQ,SAAR;EACE,KAAK,OACH,QAAO;GAAC;GAAQ;GAAO;GAAM;GAAoB;GAAY;EAC/D,KAAK,OACH,QAAO;GAAC;GAAQ;GAAU;GAAO;GAAoB;GAAY;EACnE,KAAK,MACH,QAAO;GAAC;GAAO;GAAO;GAAM;GAAoB;GAAY;EAC9D,QACE,QAAO;GAAC;GAAO;GAAW;GAAM;GAAoB;GAAY;;;;;;AAOtE,SAAS,oBAAoB,MAAwB,OAGnD;AACA,SAAQ,KAAK,MAAb;EACE,KAAK;AACH,OAAI,CAAC,KAAK,QACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAwB;AAEtD,UAAO,EAAE,MAAM;IAAC;IAAQ;IAAW,KAAK;IAAQ,EAAE;EAGpD,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;AACH,OAAI,CAAC,KAAK,QACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAwB;AAEtD,UAAO,EACL,MAAM,wBAAwB,KAAK,SAAS,MAAM,YAAY,EAC/D;EAGH,KAAK;AACH,OAAI,CAAC,KAAK,OACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAqB;AAEnD,UAAO,EAAE,MAAM;IAAC;IAAM;IAAW,KAAK;IAAO,EAAE;EAGjD,KAAK;AACH,OAAI,CAAC,KAAK,QACR,QAAO;IAAE,MAAM;IAAM,OAAO;IAAsB;AAEpD,UAAO,EAAE,MAAM;IAAC;IAAM;IAAQ;IAAW,KAAK;IAAQ,EAAE;EAG1D,KAAK,WACH,QAAO;GAAE,MAAM;GAAM,OAAO;GAAuC;EAGrE;AAC6B,QAAK;AAChC,UAAO;IAAE,MAAM;IAAM,OAAO,0BAA0B,KAAK;IAAQ;;;;;;AAQzE,eAAe,sBACb,MACA,WACA,KACkE;CAClE,MAAM,CAAC,KAAK,GAAG,QAAQ;AAEvB,KAAI;EACF,MAAM,EAAE,QAAQ,WAAW,MAAM,UAAU,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,IAAI;GACrE,SAAS;GACT;GACA,WAAW,KAAK,OAAO;GACxB,CAAC;AAEF,SAAO;GACL,MAAM;GACN,QAAQ,OAAO,UAAU;GACzB,QAAQ,OAAO,UAAU;GAC1B;UACM,KAAc;AACrB,MAAI,eAAe,OAAO;GACxB,MAAM,YAAY;AAClB,UAAO;IACL,MAAM,UAAU,QAAQ;IACxB,QAAQ,UAAU,QAAQ,UAAU,IAAI;IACxC,QAAQ,UAAU,QAAQ,UAAU,IAAI;IACzC;;AAGH,SAAO;GACL,MAAM;GACN,QAAQ;GACR,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GACzD;;;;;;AAOL,eAAe,kBAAkB,WAA4D;AAC3F,KAAI,UAAU,KAAK,CACjB;CAIF,MAAM,UAAU,uBAAuB;AACvC,KAAI,CAAC,QACH,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ;EACR,QAAQ;EACR,MAAM;EACP;CAGH,MAAM,SAAS,MAAM,sBAAsB;EAAC;EAAS;EAAW;EAAK,EAAE,UAAU;AACjF,KAAI,OAAO,SAAS,EAClB;AAGF,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,MAAM,OAAO;EACd;;;;;AAMH,eAAe,kBAAkB,WAA4D;AAC3F,KAAI,UAAU,KAAK,CACjB;CAGF,MAAM,UAAU,uBAAuB;AACvC,KAAI,SAAS;EACX,MAAM,SAAS,MAAM,sBAAsB;GAAC;GAAS;GAAW;GAAK,EAAE,UAAU;AACjF,MAAI,OAAO,SAAS,EAClB;AAGF,SAAO;GACL,IAAI;GACJ,SAAS;GACT,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,MAAM,OAAO;GACd;;AAIH,KAAI,UAAU,UAAU,EAAE;EACxB,MAAM,SAAS,QAAQ,UAAU,KAAK;EACtC,MAAM,SAAS,SACX;GAAC;GAAW;GAAW;GAAM;GAAY,GACzC;GAAC;GAAQ;GAAW;GAAW;GAAM;GAAY;AAGrD,MAAI,CAAC,OACH,OAAM,sBAAsB;GAAC;GAAQ;GAAW;GAAU;GAAM,EAAE,KAAK,IAAI,WAAW,IAAM,CAAC;EAG/F,MAAM,SAAS,MAAM,sBAAsB,QAAQ,UAAU;AAC7D,MAAI,OAAO,SAAS,EAClB;AAGF,SAAO;GACL,IAAI;GACJ,SAAS;GACT,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,MAAM,OAAO;GACd;;AAGH,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ;EACR,QAAQ;EACR,MAAM;EACP;;;;;AAMH,SAAS,qBAAqB,QAKP;AACrB,QAAO;EACL,IAAI;EACJ,SAAS,OAAO;EAChB,QAAQ,OAAO,QAAQ,MAAM,IAAI;EACjC,QAAQ,OAAO,QAAQ,MAAM,IAAI;EACjC,MAAM,OAAO,QAAQ;EACtB;;;;;AAMH,SAAS,qBAAqB,QAAqF;AACjH,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ,OAAO,OAAO,MAAM;EAC5B,QAAQ,OAAO,OAAO,MAAM;EAC5B,MAAM,OAAO;EACd;;;;;AAMH,SAAgB,gBAAgB,OAAmB,WAAiD;CAClG,MAAM,QAAQ,MAAM,SAAS,WAAW,EAAE;AAE1C,MAAK,MAAM,CAAC,OAAO,SAAS,MAAM,SAAS,CAEzC,MADW,KAAK,MAAM,GAAG,KAAK,KAAK,GAAG,aAC3B,UACT,QAAO;;;;;AAUb,eAAsB,aAAa,KAAkD;CACnF,MAAM,EAAE,aAAa,WAAW,gBAAgB;AAEhD,KAAI,KAAK;EAAE,OAAO,IAAI,WAAW,MAAM;EAAM,MAAM,YAAY;EAAM,EAAE,8BAA8B;AAGrG,KAAI,YAAY,SAAS,WACvB,QAAO,qBAAqB,EAC1B,SAAS,0CACV,CAAC;AAIJ,KAAI,YAAY,SAAS,MAAM;EAC7B,MAAM,YAAY,MAAM,kBAAkB,UAAU;AACpD,MAAI,UACF,QAAO;;AAIX,KAAI,YAAY,SAAS,MAAM;EAC7B,MAAM,YAAY,MAAM,kBAAkB,UAAU;AACpD,MAAI,UACF,QAAO;;CAKX,MAAM,UAAU,oBAAoB,aAAa,YAAY;AAC7D,KAAI,QAAQ,MACV,QAAO,qBAAqB,EAC1B,SAAS,QAAQ,OAClB,CAAC;AAGJ,KAAI,CAAC,QAAQ,KACX,QAAO,qBAAqB,EAC1B,SAAS,2BACV,CAAC;CAIJ,IAAI,OAAO,CAAC,GAAG,QAAQ,KAAK;AAC5B,KAAI,YAAY,SAAS,QAAQ;EAC/B,MAAM,UAAU,uBAAuB;AACvC,MAAI,CAAC,QAKH,QAAO,qBAAqB,EAC1B,SAAS,wBALE,QAAQ,aAAa,UAC9B,mGACA,gEAIH,CAAC;AAEJ,OAAK,KAAK;;CAIZ,IAAI;AACJ,KAAI,YAAY,SAAS,MAAM;EAC7B,MAAM,UAAU,uBAAuB;AACvC,MAAI,QACF,KAAI;GACF,MAAM,EAAE,WAAW,MAAM,UAAU,GAAG,QAAQ,WAAW;GACzD,MAAM,SAAS,OAAO,MAAM;AAC5B,OAAI,OACF,OAAM;IAAE,GAAG,QAAQ;IAAK,OAAO,KAAK,QAAQ,MAAM;IAAE;UAEhD;;CAOZ,MAAM,SAAS,MAAM,sBAAsB,MAAM,WAAW,IAAI;AAEhE,KAAI,OAAO,SAAS,GAAG;AACrB,MAAI,KAAK,EAAE,OAAO,IAAI,WAAW,MAAM,MAAM,EAAE,0CAA0C;AACzF,SAAO,qBAAqB,OAAO;;AAGrC,KAAI,KAAK;EACP,OAAO,IAAI,WAAW,MAAM;EAC5B,QAAQ,OAAO;EAChB,EAAE,uCAAuC;AAE1C,QAAO,qBAAqB;EAC1B,SAAS,OAAO,UAAU,sCAAsC,OAAO;EACvE,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,MAAM,OAAO;EACd,CAAC;;;;;AAMJ,SAAgB,iCAAuD;AACrE,QAAO;EACL,YAAY;EACZ,aAAa;EACd"}
|
|
@@ -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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"}
|