@xopcai/xopc 0.0.127 → 0.0.129
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/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CgGgO4OV.js → agent-avatar-dicebear-DHzfg5D-.js} +1 -1
- package/dist/gateway/static/root/assets/agents-CMxKKFQD.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-ptk9c5BN.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-BnHQW7Hv.js → appearance-settings-bYeEj3IW.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-DdZvDf5B.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-5NXT7Zqv.js → archive-plugin-Dy6lsTHw.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DghwhYe0.js → attachment-load-qOtBYR6Y.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-DYmESgwl.js → automation-suggestion-card-BFH-RfaV.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-B8JTjkCr.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DSbPKdWX.js → binary-plugins-DJvi_thc.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CoZ-_np-.js → block-editor-DlMnizlt.js} +4 -4
- package/dist/gateway/static/root/assets/browser-settings-page-slHLiZgi.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-D4q7vHVJ.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Dng8Grpv.js +1 -0
- package/dist/gateway/static/root/assets/channel-recipient-api-BrW5Kcgc.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-KIsISXw0.js +1 -0
- package/dist/gateway/static/root/assets/{code-editor-gbRgS14t.js → code-editor--tMO38Tr.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-C5fx4Qs9.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-Jmdn6q47.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-npJ0Oh5p.js → desktop-pet-settings-B-u63N4e.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BR2ItBuf.js → directory-picker-path-field-8p1ehIHn.js} +1 -1
- package/dist/gateway/static/root/assets/dreaming-settings-CCkKP-I4.js +3 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-Tl0f1rNv.js → extension-debug-page-DJ1ABK95.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Ck7QuwE3.js → extension-page-CP9P2lGM.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-DnhU-tx0.js +1 -0
- package/dist/gateway/static/root/assets/fetch-BMjlW0g1.js +1 -0
- package/dist/gateway/static/root/assets/gateway-config-api-CjxDn46s.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-TING7224.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Yh8h3hkj.js → gateway-startup-retry-CY5W2Pp4.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-2lPbGfp3.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-DHWVRafk.js +4 -0
- package/dist/gateway/static/root/assets/goals-config-api-BqhuxG8P.js +1 -0
- package/dist/gateway/static/root/assets/goals-page-CMk-9ZYN.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-BHzOAU_l.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-BQIm0P3V.js +1 -0
- package/dist/gateway/static/root/assets/{html-workspace-editor-DV90ddkE.js → html-workspace-editor-COqmtESs.js} +1 -1
- package/dist/gateway/static/root/assets/index-C4k6QSXw.js +257 -0
- package/dist/gateway/static/root/assets/index-EKmpPvZj.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CfQrt_Rb.js → keyboard-shortcuts-settings-BrENZzM7.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-BiL302Ve.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-editor-BFOjBBla.js → markdown-editor-jD1LPiP-.js} +2 -2
- package/dist/gateway/static/root/assets/{markdown-split-BwiMdCf_.js → markdown-split-BYF4ReGM.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DhoizyZv.js → media-plugins-CpQDz-QJ.js} +1 -1
- package/dist/gateway/static/root/assets/messages-YzjnURPJ.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-CFPpl3Cq.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-BurgcdVZ.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-BAELRM_O.js +2 -0
- package/dist/gateway/static/root/assets/{page-tabs-DDC2t4Z8.js → page-tabs-RnYYOIWO.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BTmk-XDM.js → preview-open-alternatives-CTRt06Ri.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-iXX1Ceo2.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-GDVTFAY7.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-BUrbUnwv.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-DqU-yKIh.js → save-bar-controls-c4pZeikq.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-CUttkoSB.js → schedule-field-Cb6R7iuP.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CVSQA9nI.js → schema-form-BqET_hEP.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CiOreA2k.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-C-qvptlu.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-CK7ogS-P.js → settings-collapsible-section-DuOvqNsI.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-Bugp38Fa.js → settings-form-section-DptSsbWd.js} +1 -1
- package/dist/gateway/static/root/assets/settings-loading-skeleton-BlVfBCb9.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-DBRWwdhh.js → settings-page-layout-DVt69dJJ.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-xQx2Pkg5.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-DWB8VdLK.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-8m_ACH0z.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-CgxfhNxI.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BBFUOxmf.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-bo695odu.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-DJ6YuLqR.js → system-settings-panel-CW22OkZ4.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-B0T7N8Km.js → typed-models-lib-BqpGAKxV.js} +1 -1
- package/dist/gateway/static/root/assets/url-DFGNSBNT.js +1 -0
- package/dist/gateway/static/root/assets/use-channel-catalog-CPdJ0o0i.js +1 -0
- package/dist/gateway/static/root/assets/user-profile-settings-panel-CERVLuaW.js +1 -0
- package/dist/gateway/static/root/assets/{utils-CehXcWAY.js → utils-BnmysurA.js} +1 -1
- package/dist/gateway/static/root/assets/vendor-codemirror-C1WKjCk5.js +45 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-Jr3jvPcB.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-B-8rex4u.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-c4jeaohQ.js → workflow-run-setup-panel-Ci9GSPnS.js} +2 -2
- package/dist/gateway/static/root/assets/{workflow-start-dialog-ENRHjoqa.js → workflow-start-dialog-BhDj8pqH.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-Brb3UGvs.js +18 -0
- package/dist/gateway/static/root/index.html +7 -6
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +3 -0
- package/dist/src/agent/agent-manager.js +14 -6
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/capabilities/definitions.d.ts +14 -0
- package/dist/src/agent/capabilities/definitions.js +19 -0
- package/dist/src/agent/capabilities/definitions.js.map +1 -1
- package/dist/src/agent/goals/post-turn.js +23 -2
- package/dist/src/agent/goals/post-turn.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.d.ts +4 -0
- package/dist/src/agent/messaging/command-handler.js +6 -0
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/service.d.ts +2 -0
- package/dist/src/agent/service.js +23 -0
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/skills/hub-lock.d.ts +5 -5
- package/dist/src/agent/skills/hub-lock.js +12 -12
- package/dist/src/agent/skills/hub-lock.js.map +1 -1
- package/dist/src/agent/skills/hub-pull.d.ts +15 -0
- package/dist/src/agent/skills/hub-pull.js +299 -24
- package/dist/src/agent/skills/hub-pull.js.map +1 -1
- package/dist/src/agent/skills/index.js +4 -40
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/install-target.d.ts +3 -0
- package/dist/src/agent/skills/install-target.js +11 -0
- package/dist/src/agent/skills/install-target.js.map +1 -0
- package/dist/src/agent/skills/managed-store.d.ts +5 -3
- package/dist/src/agent/skills/managed-store.js +10 -9
- package/dist/src/agent/skills/managed-store.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +5 -3
- 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 +21 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +62 -6
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
- package/dist/src/agent/skills/marketplace/resolve-adapter.js +1 -1
- package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +2 -2
- package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -6
- package/dist/src/agent/skills/skill-manager.js.map +1 -1
- package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
- package/dist/src/agent/skills/workspace-skills-dir.js +5 -1
- package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -1
- package/dist/src/agent/tools/automation-tool.d.ts +6 -6
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +20 -20
- package/dist/src/agent/tools/composio-tool.d.ts +3 -3
- package/dist/src/agent/tools/desktop-pet-tool.d.ts +7 -7
- package/dist/src/agent/tools/factory.d.ts +3 -0
- package/dist/src/agent/tools/factory.js +6 -1
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/goal-tool.d.ts +16 -16
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/skill-install-tool.d.ts +28 -0
- package/dist/src/agent/tools/skill-install-tool.js +81 -0
- package/dist/src/agent/tools/skill-install-tool.js.map +1 -0
- package/dist/src/agent/tools/skill-manage-tool.js +3 -6
- package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
- package/dist/src/agent/tools/tool-manual-tool.d.ts +2 -2
- package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -5
- package/dist/src/automations/domain/types.d.ts +1 -0
- package/dist/src/automations/draft/automation-draft-service.js +1 -1
- package/dist/src/automations/service/automation-service.js +9 -0
- package/dist/src/automations/service/automation-service.js.map +1 -1
- package/dist/src/browser/schemas.d.ts +52 -52
- package/dist/src/capabilities/store-connector.d.ts +17 -0
- package/dist/src/capabilities/store-connector.js +191 -0
- package/dist/src/capabilities/store-connector.js.map +1 -0
- package/dist/src/chat-commands/builtins/skill.d.ts +1 -0
- package/dist/src/chat-commands/builtins/skill.js +132 -0
- package/dist/src/chat-commands/builtins/skill.js.map +1 -0
- package/dist/src/chat-commands/context.d.ts +3 -0
- package/dist/src/chat-commands/context.js +2 -0
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +17 -0
- package/dist/src/cli/command-loaders.js +1 -0
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +4 -0
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/connectors.d.ts +4 -0
- package/dist/src/cli/commands/connectors.js +96 -0
- package/dist/src/cli/commands/connectors.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/profile.js +1 -1
- package/dist/src/cli/commands/skills.js +1 -1
- package/dist/src/cli/commands/tunnel.js +1 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/index.js +1 -1
- package/dist/src/config/schema.js +2 -2
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/connectors/health.js +1 -1
- package/dist/src/connectors/install.js +3 -1
- package/dist/src/connectors/install.js.map +1 -1
- package/dist/src/connectors/materialize.js +2 -0
- package/dist/src/connectors/materialize.js.map +1 -1
- package/dist/src/connectors/types.d.ts +19 -1
- package/dist/src/extensions/install.js +1 -1
- package/dist/src/extensions/types/manifest.d.ts +1 -1
- package/dist/src/extensions/update.js +5 -3
- package/dist/src/extensions/update.js.map +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/mapper.js +5 -1
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/middleware/auth.d.ts +2 -2
- package/dist/src/gateway/hono/middleware/logger.d.ts +1 -1
- package/dist/src/gateway/hono/middleware/route-errors.d.ts +1 -1
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +2 -2
- package/dist/src/gateway/hono/routes/capabilities.d.ts +3 -0
- package/dist/src/gateway/hono/routes/capabilities.js +79 -0
- package/dist/src/gateway/hono/routes/capabilities.js.map +1 -0
- package/dist/src/gateway/hono/routes/commands-skills.js +81 -3
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +2 -2
- package/dist/src/gateway/hono/routes/goals.js +212 -3
- package/dist/src/gateway/hono/routes/goals.js.map +1 -1
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +1 -1
- package/dist/src/gateway/hono/routes/mobile.d.ts +3 -0
- package/dist/src/gateway/hono/routes/mobile.js +113 -0
- package/dist/src/gateway/hono/routes/mobile.js.map +1 -0
- package/dist/src/gateway/hono/routes/projects.js +17 -0
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +4 -1
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +3 -3
- package/dist/src/gateway/run-loop.js +1 -1
- package/dist/src/gateway/service/marketplace-service.d.ts +23 -1
- package/dist/src/gateway/service/marketplace-service.js +57 -6
- package/dist/src/gateway/service/marketplace-service.js.map +1 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +12 -2
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/goals/goal-contract-draft.d.ts +15 -0
- package/dist/src/goals/goal-contract-draft.js +114 -0
- package/dist/src/goals/goal-contract-draft.js.map +1 -0
- package/dist/src/goals/goal-evidence-review.d.ts +15 -0
- package/dist/src/goals/goal-evidence-review.js +91 -0
- package/dist/src/goals/goal-evidence-review.js.map +1 -0
- package/dist/src/goals/goal-runner.js +3 -1
- package/dist/src/goals/goal-runner.js.map +1 -1
- package/dist/src/goals/goal-service.d.ts +17 -1
- package/dist/src/goals/goal-service.js +44 -3
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/goals/goal-store.d.ts +18 -1
- package/dist/src/goals/goal-store.js +190 -1
- package/dist/src/goals/goal-store.js.map +1 -1
- package/dist/src/goals/index.d.ts +4 -0
- package/dist/src/goals/index.js +3 -1
- package/dist/src/goals/types.d.ts +42 -0
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/mobile/notification-service.d.ts +8 -0
- package/dist/src/mobile/notification-service.js +139 -0
- package/dist/src/mobile/notification-service.js.map +1 -0
- package/dist/src/mobile/notification-store.d.ts +28 -0
- package/dist/src/mobile/notification-store.js +134 -0
- package/dist/src/mobile/notification-store.js.map +1 -0
- package/dist/src/mobile/notification-types.d.ts +37 -0
- package/dist/src/mobile/notification-types.js +11 -0
- package/dist/src/mobile/notification-types.js.map +1 -0
- package/dist/src/storage/sqlite/migrations/026_goal_contracts.sql +10 -0
- package/dist/src/storage/sqlite/migrations/027_mobile_notifications.sql +43 -0
- package/dist/src/storage/sqlite/migrations/028_goal_evidence_requirements.sql +47 -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/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +44 -0
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/package.json +1 -1
- package/skills/THIRD_PARTY_NOTICES.md +16 -0
- package/skills/creative/algorithmic-art/SKILL.md +37 -0
- package/skills/creative/algorithmic-art/templates/generator-template.js +27 -0
- package/skills/creative/algorithmic-art/templates/viewer.html +27 -0
- package/skills/documents/doc-coauthoring/SKILL.md +40 -0
- package/skills/documents/doc-coauthoring/references/reader-review.md +9 -0
- package/skills/documents/docx/SKILL.md +40 -0
- package/skills/documents/docx/references/editing-checklist.md +8 -0
- package/skills/documents/docx/scripts/inspect_ooxml.py +36 -0
- package/skills/documents/docx/scripts/render_docx.py +33 -0
- package/skills/documents/pdf/SKILL.md +47 -0
- package/skills/documents/pdf/references/operations.md +16 -0
- package/skills/documents/pdf/scripts/inspect_pdf.py +41 -0
- package/skills/documents/pdf/scripts/render_pdf.py +32 -0
- package/skills/documents/pptx/SKILL.md +41 -0
- package/skills/documents/pptx/references/qa-checklist.md +6 -0
- package/skills/documents/pptx/scripts/inspect_ooxml.py +34 -0
- package/skills/documents/pptx/scripts/render_pptx.py +33 -0
- package/skills/engineering/define-goal/SKILL.md +41 -0
- package/skills/engineering/define-goal/references/objective-rubric.md +12 -0
- package/dist/gateway/static/root/assets/agents-k59l7NMb.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-DeQsTsyy.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-BG9b4abG.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-De8mVutL.js +0 -4
- package/dist/gateway/static/root/assets/browser-settings-page-C_ZRa4LF.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-hny224j-.js +0 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Drc0qLsw.js +0 -1
- package/dist/gateway/static/root/assets/channel-recipient-api-DAlOHxKJ.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CA20zBV9.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-qMyMB5te.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-XG6Vb_fZ.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-CkUZ997f.js +0 -3
- package/dist/gateway/static/root/assets/extension-settings-page-3RMhQtZ3.js +0 -1
- package/dist/gateway/static/root/assets/fetch-pg2ErdAk.js +0 -1
- package/dist/gateway/static/root/assets/gateway-config-api-DbG97ia2.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-B8cyqKk-.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-DmeW7Zz3.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DrTyGbVD.js +0 -1
- package/dist/gateway/static/root/assets/goals-config-api-CxCWGIBB.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-DV1bJhIh.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-9DrfOkP5.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-KaDpZrv0.js +0 -1
- package/dist/gateway/static/root/assets/index-C2F0Clvm.js +0 -256
- package/dist/gateway/static/root/assets/index-COQSX5d_.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-C9dpiNTF.js +0 -2
- package/dist/gateway/static/root/assets/messages-DmnbiNxU.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-zdCdmBmH.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-MpGeFfPt.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-DYCM3yd2.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-Cu0ElRnS.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-DakNaUjZ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DYKjt7L9.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CcGHDsz1.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CuFdeKNu.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-0AJoUvxi.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-D6a_hEk7.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-BtsuETKF.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-CcEFT7S9.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BcN_RuTD.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BbRZZZA5.js +0 -2
- package/dist/gateway/static/root/assets/use-channel-catalog-C6vrxdzZ.js +0 -1
- package/dist/gateway/static/root/assets/user-profile-settings-panel-DZ0nKMgj.js +0 -1
- package/dist/gateway/static/root/assets/vendor-codemirror-BvNgyE1Q.js +0 -45
- package/dist/gateway/static/root/assets/voice-api-key-field-2QKflCx8.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-DfJnuWq1.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BJwwFTm_.js +0 -18
|
@@ -184,60 +184,24 @@ function loadSkills(options) {
|
|
|
184
184
|
if (builtinDir) {
|
|
185
185
|
const discovered = discoverSkills(builtinDir, "builtin");
|
|
186
186
|
diagnostics.push(...discovered.diagnostics);
|
|
187
|
-
for (const skill of discovered.skills)
|
|
188
|
-
const existing = skillMap.get(skill.name);
|
|
189
|
-
if (existing) diagnostics.push({
|
|
190
|
-
type: "collision",
|
|
191
|
-
skillName: skill.name,
|
|
192
|
-
message: `Skill "${skill.name}" collision: ${existing.source} overrides ${skill.source}`,
|
|
193
|
-
path: skill.filePath
|
|
194
|
-
});
|
|
195
|
-
else skillMap.set(skill.name, skill);
|
|
196
|
-
}
|
|
187
|
+
for (const skill of discovered.skills) if (!skillMap.has(skill.name)) skillMap.set(skill.name, skill);
|
|
197
188
|
}
|
|
198
189
|
const globalDirs = [options.globalDir, join(resolveStateDir(), "skills")].filter((d) => !!d && existsSync(d));
|
|
199
190
|
for (const dir of globalDirs) {
|
|
200
191
|
const discovered = discoverSkills(dir, "global");
|
|
201
192
|
diagnostics.push(...discovered.diagnostics);
|
|
202
|
-
for (const skill of discovered.skills)
|
|
203
|
-
const existing = skillMap.get(skill.name);
|
|
204
|
-
if (existing) diagnostics.push({
|
|
205
|
-
type: "collision",
|
|
206
|
-
skillName: skill.name,
|
|
207
|
-
message: `Skill "${skill.name}" collision: ${skill.source} overrides ${existing.source}`,
|
|
208
|
-
path: skill.filePath
|
|
209
|
-
});
|
|
210
|
-
skillMap.set(skill.name, skill);
|
|
211
|
-
}
|
|
193
|
+
for (const skill of discovered.skills) skillMap.set(skill.name, skill);
|
|
212
194
|
}
|
|
213
195
|
if (workspaceDir) {
|
|
214
196
|
const discovered = discoverSkills(resolveWorkspaceSkillsDir(workspaceDir), "workspace");
|
|
215
197
|
diagnostics.push(...discovered.diagnostics);
|
|
216
198
|
const workspaceSkills = discovered.skills;
|
|
217
|
-
for (const skill of workspaceSkills)
|
|
218
|
-
const existing = skillMap.get(skill.name);
|
|
219
|
-
if (existing) diagnostics.push({
|
|
220
|
-
type: "collision",
|
|
221
|
-
skillName: skill.name,
|
|
222
|
-
message: `Skill "${skill.name}" collision: ${skill.source} overrides ${existing.source}`,
|
|
223
|
-
path: skill.filePath
|
|
224
|
-
});
|
|
225
|
-
skillMap.set(skill.name, skill);
|
|
226
|
-
}
|
|
199
|
+
for (const skill of workspaceSkills) skillMap.set(skill.name, skill);
|
|
227
200
|
}
|
|
228
201
|
for (const extraDir of extraDirs) if (existsSync(extraDir)) {
|
|
229
202
|
const discovered = discoverSkills(extraDir, "global");
|
|
230
203
|
diagnostics.push(...discovered.diagnostics);
|
|
231
|
-
for (const skill of discovered.skills)
|
|
232
|
-
const existing = skillMap.get(skill.name);
|
|
233
|
-
if (existing) diagnostics.push({
|
|
234
|
-
type: "collision",
|
|
235
|
-
skillName: skill.name,
|
|
236
|
-
message: `Skill "${skill.name}" collision: ${existing.source} overrides ${skill.source}`,
|
|
237
|
-
path: skill.filePath
|
|
238
|
-
});
|
|
239
|
-
else skillMap.set(skill.name, skill);
|
|
240
|
-
}
|
|
204
|
+
for (const skill of discovered.skills) if (!skillMap.has(skill.name)) skillMap.set(skill.name, skill);
|
|
241
205
|
}
|
|
242
206
|
const skillsConfig = createSkillConfigManager(resolveStateDir()).load();
|
|
243
207
|
const merged = Array.from(skillMap.values());
|
|
@@ -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 { resolveWorkspaceSkillsDir } from './workspace-skills-dir.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(\n dir: string,\n source: 'builtin' | 'workspace' | 'global',\n): { skills: Skill[]; diagnostics: SkillDiagnostic[] } {\n const skills: Skill[] = [];\n const diagnostics: SkillDiagnostic[] = [];\n if (!existsSync(dir)) return { skills, diagnostics };\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, diagnostic } = loadSkillFromFile(skillMdPath, source, dir);\n if (diagnostic) diagnostics.push(diagnostic);\n if (skill) skills.push(skill);\n }\n\n scan(fullPath, subIgnoredPaths);\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n diagnostics.push({\n type: 'error',\n message: `Failed to scan skills directory: ${message}`,\n path: currentDir,\n });\n }\n }\n\n scan(dir, loadIgnoreRules(dir, dir));\n return { skills, diagnostics };\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(\n filePath: string,\n source: 'builtin' | 'workspace' | 'global',\n rootDir?: string,\n): { skill: Skill | null; diagnostic?: SkillDiagnostic } {\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()) {\n return {\n skill: null,\n diagnostic: {\n type: 'error',\n skillName: name,\n message: `Skill \"${name}\" is missing a description`,\n path: filePath,\n },\n };\n }\n\n // Derive category from directory path: .xopc/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 skill: {\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 };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n skill: null,\n diagnostic: {\n type: 'error',\n message: `Failed to load skill file: ${message}`,\n path: filePath,\n },\n };\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 const discovered = discoverSkills(builtinDir, 'builtin');\n diagnostics.push(...discovered.diagnostics);\n for (const skill of discovered.skills) {\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 const discovered = discoverSkills(dir, 'global');\n diagnostics.push(...discovered.diagnostics);\n for (const skill of discovered.skills) {\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 discovered = discoverSkills(resolveWorkspaceSkillsDir(workspaceDir), 'workspace');\n diagnostics.push(...discovered.diagnostics);\n const workspaceSkills = discovered.skills;\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 const discovered = discoverSkills(extraDir, 'global');\n diagnostics.push(...discovered.diagnostics);\n for (const skill of discovered.skills) {\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 { resolveWorkspaceSkillsDir } from './workspace-skills-dir.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(\n dir: string,\n source: 'builtin' | 'workspace' | 'global',\n): { skills: Skill[]; diagnostics: SkillDiagnostic[] } {\n const skills: Skill[] = [];\n const diagnostics: SkillDiagnostic[] = [];\n if (!existsSync(dir)) return { skills, diagnostics };\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, diagnostic } = loadSkillFromFile(skillMdPath, source, dir);\n if (diagnostic) diagnostics.push(diagnostic);\n if (skill) skills.push(skill);\n }\n\n scan(fullPath, subIgnoredPaths);\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n diagnostics.push({\n type: 'error',\n message: `Failed to scan skills directory: ${message}`,\n path: currentDir,\n });\n }\n }\n\n scan(dir, loadIgnoreRules(dir, dir));\n return { skills, diagnostics };\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(\n filePath: string,\n source: 'builtin' | 'workspace' | 'global',\n rootDir?: string,\n): { skill: Skill | null; diagnostic?: SkillDiagnostic } {\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()) {\n return {\n skill: null,\n diagnostic: {\n type: 'error',\n skillName: name,\n message: `Skill \"${name}\" is missing a description`,\n path: filePath,\n },\n };\n }\n\n // Derive category from directory path: .xopc/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 skill: {\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 };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n skill: null,\n diagnostic: {\n type: 'error',\n message: `Failed to load skill file: ${message}`,\n path: filePath,\n },\n };\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 const discovered = discoverSkills(builtinDir, 'builtin');\n diagnostics.push(...discovered.diagnostics);\n for (const skill of discovered.skills) {\n if (!skillMap.has(skill.name)) {\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 const discovered = discoverSkills(dir, 'global');\n diagnostics.push(...discovered.diagnostics);\n for (const skill of discovered.skills) {\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 discovered = discoverSkills(resolveWorkspaceSkillsDir(workspaceDir), 'workspace');\n diagnostics.push(...discovered.diagnostics);\n const workspaceSkills = discovered.skills;\n for (const skill of workspaceSkills) {\n skillMap.set(skill.name, skill);\n }\n }\n\n // Scan extra directories\n for (const extraDir of extraDirs) {\n if (existsSync(extraDir)) {\n const discovered = discoverSkills(extraDir, 'global');\n diagnostics.push(...discovered.diagnostics);\n for (const skill of discovered.skills) {\n if (!skillMap.has(skill.name)) {\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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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/agent/skills/install-target.ts
|
|
2
|
+
function normalizeSkillInstallTarget(value) {
|
|
3
|
+
return value === "global" ? "global" : "workspace";
|
|
4
|
+
}
|
|
5
|
+
function isSkillInstallTarget(value) {
|
|
6
|
+
return value === "workspace" || value === "global";
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { isSkillInstallTarget, normalizeSkillInstallTarget };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=install-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-target.js","names":[],"sources":["../../../../src/agent/skills/install-target.ts"],"sourcesContent":["export type SkillInstallTarget = 'workspace' | 'global';\n\nexport function normalizeSkillInstallTarget(value: unknown): SkillInstallTarget {\n return value === 'global' ? 'global' : 'workspace';\n}\n\nexport function isSkillInstallTarget(value: unknown): value is SkillInstallTarget {\n return value === 'workspace' || value === 'global';\n}\n"],"mappings":";AAEA,SAAgB,4BAA4B,OAAoC;AAC9E,QAAO,UAAU,WAAW,WAAW;;AAGzC,SAAgB,qBAAqB,OAA6C;AAChF,QAAO,UAAU,eAAe,UAAU"}
|
|
@@ -19,13 +19,13 @@ export interface ManagedSkillListItem {
|
|
|
19
19
|
hub?: SkillHubLockEntry;
|
|
20
20
|
}
|
|
21
21
|
export declare function listManagedSkillDirs(): ManagedSkillListItem[];
|
|
22
|
-
export declare function deleteManagedSkill(skillId: string): void;
|
|
22
|
+
export declare function deleteManagedSkill(skillId: string, rootDir?: string): void;
|
|
23
23
|
export declare function getManagedSkillDir(skillId: string): string;
|
|
24
|
-
export declare function assertManagedSkillDestination(skillId: string): {
|
|
24
|
+
export declare function assertManagedSkillDestination(skillId: string, rootDir?: string): {
|
|
25
25
|
root: string;
|
|
26
26
|
destDir: string;
|
|
27
27
|
};
|
|
28
|
-
export declare function prepareManagedSkillTempDir(skillId: string): {
|
|
28
|
+
export declare function prepareManagedSkillTempDir(skillId: string, rootDir?: string): {
|
|
29
29
|
root: string;
|
|
30
30
|
destDir: string;
|
|
31
31
|
tempDir: string;
|
|
@@ -34,6 +34,7 @@ export declare function promoteManagedSkillTempDir(params: {
|
|
|
34
34
|
skillId: string;
|
|
35
35
|
tempDir: string;
|
|
36
36
|
overwrite?: boolean;
|
|
37
|
+
rootDir?: string;
|
|
37
38
|
}): {
|
|
38
39
|
skillId: string;
|
|
39
40
|
path: string;
|
|
@@ -45,6 +46,7 @@ export declare function promoteManagedSkillTempDir(params: {
|
|
|
45
46
|
export declare function installSkillFromZip(buffer: Buffer, options: {
|
|
46
47
|
skillId?: string;
|
|
47
48
|
overwrite?: boolean;
|
|
49
|
+
rootDir?: string;
|
|
48
50
|
}): {
|
|
49
51
|
skillId: string;
|
|
50
52
|
path: string;
|
|
@@ -87,9 +87,9 @@ function listManagedSkillDirs() {
|
|
|
87
87
|
out.sort((a, b) => a.id.localeCompare(b.id));
|
|
88
88
|
return out;
|
|
89
89
|
}
|
|
90
|
-
function deleteManagedSkill(skillId) {
|
|
90
|
+
function deleteManagedSkill(skillId, rootDir = resolveSkillsDir()) {
|
|
91
91
|
if (!isValidSkillId(skillId)) throw new Error("Invalid skill id");
|
|
92
|
-
const root =
|
|
92
|
+
const root = resolve(rootDir);
|
|
93
93
|
const dir = resolve(join(root, skillId));
|
|
94
94
|
const rootResolved = resolve(root);
|
|
95
95
|
if (!dir.startsWith(rootResolved + sep) && dir !== rootResolved) throw new Error("Invalid path");
|
|
@@ -112,9 +112,9 @@ function getManagedSkillDir(skillId) {
|
|
|
112
112
|
if (!isValidSkillId(skillId)) throw new Error("Invalid skill id");
|
|
113
113
|
return join(resolveSkillsDir(), skillId);
|
|
114
114
|
}
|
|
115
|
-
function assertManagedSkillDestination(skillId) {
|
|
115
|
+
function assertManagedSkillDestination(skillId, rootDir = resolveSkillsDir()) {
|
|
116
116
|
if (!isValidSkillId(skillId)) throw new Error(`Invalid skill id "${skillId}" (letters, digits, ._-; max 63 chars after first)`);
|
|
117
|
-
const root =
|
|
117
|
+
const root = resolve(rootDir);
|
|
118
118
|
mkdirSync(root, { recursive: true });
|
|
119
119
|
const destDir = join(root, skillId);
|
|
120
120
|
const destResolved = resolve(destDir);
|
|
@@ -125,8 +125,8 @@ function assertManagedSkillDestination(skillId) {
|
|
|
125
125
|
destDir
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
-
function prepareManagedSkillTempDir(skillId) {
|
|
129
|
-
const { root, destDir } = assertManagedSkillDestination(skillId);
|
|
128
|
+
function prepareManagedSkillTempDir(skillId, rootDir) {
|
|
129
|
+
const { root, destDir } = assertManagedSkillDestination(skillId, rootDir);
|
|
130
130
|
const tempDir = createTransientManagedDir(root, TEMP_PREFIX, skillId);
|
|
131
131
|
mkdirSync(tempDir, { recursive: true });
|
|
132
132
|
return {
|
|
@@ -136,7 +136,7 @@ function prepareManagedSkillTempDir(skillId) {
|
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
function promoteManagedSkillTempDir(params) {
|
|
139
|
-
const { root, destDir } = assertManagedSkillDestination(params.skillId);
|
|
139
|
+
const { root, destDir } = assertManagedSkillDestination(params.skillId, params.rootDir);
|
|
140
140
|
const tempResolved = resolve(params.tempDir);
|
|
141
141
|
const rootResolved = resolve(root);
|
|
142
142
|
if (!tempResolved.startsWith(rootResolved + sep)) throw new Error("Invalid temporary skill directory");
|
|
@@ -199,7 +199,7 @@ function installSkillFromZip(buffer, options) {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
if (!targetId || !isValidSkillId(targetId)) throw new Error("Could not determine skill id: use a folder named with the skill id, pass skillId, or set name: in SKILL.md (letters, digits, ._-)");
|
|
202
|
-
const { destDir, tempDir } = prepareManagedSkillTempDir(targetId);
|
|
202
|
+
const { destDir, tempDir } = prepareManagedSkillTempDir(targetId, options.rootDir);
|
|
203
203
|
const tempResolved = resolve(tempDir);
|
|
204
204
|
try {
|
|
205
205
|
if (existsSync(destDir) && !options.overwrite) throw new Error(`Skill "${targetId}" already exists. Pass overwrite to replace.`);
|
|
@@ -222,7 +222,8 @@ function installSkillFromZip(buffer, options) {
|
|
|
222
222
|
return promoteManagedSkillTempDir({
|
|
223
223
|
skillId: targetId,
|
|
224
224
|
tempDir,
|
|
225
|
-
overwrite: options.overwrite
|
|
225
|
+
overwrite: options.overwrite,
|
|
226
|
+
rootDir: options.rootDir
|
|
226
227
|
});
|
|
227
228
|
} catch (err) {
|
|
228
229
|
rmSync(tempDir, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"managed-store.js","names":[],"sources":["../../../../src/agent/skills/managed-store.ts"],"sourcesContent":["/**\n * Managed skills live under ~/.xopc/skills (see resolveSkillsDir).\n * Install/update/delete via zip or folder operations; used by gateway API.\n */\n\nimport AdmZip from 'adm-zip';\nimport {\n existsSync,\n mkdirSync,\n renameSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { resolveSkillsDir } from '../../config/paths.js';\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { loadSkillsLock, type SkillHubLockEntry } from './hub-lock.js';\n\nexport const MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\n\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst TEMP_PREFIX = '.tmp-';\nconst TRASH_PREFIX = '.trash-';\n\nexport function isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\nexport function isManagedSkillTransientDirName(name: string): boolean {\n return name.startsWith(TEMP_PREFIX) || name.startsWith(TRASH_PREFIX);\n}\n\n/** True when `baseDir` is the global managed skills root or a direct child folder. */\nexport function isUnderManagedSkillsDir(baseDir: string): boolean {\n const b = resolve(baseDir);\n const r = resolve(resolveSkillsDir());\n return b === r || b.startsWith(r + sep);\n}\n\nfunction isSafeZipPath(name: string): boolean {\n if (!name) return false;\n const normalized = name.replace(/\\\\/g, '/');\n if (normalized.includes('..')) return false;\n if (normalized.startsWith('/') || /^\\w:/.test(normalized)) return false;\n for (const p of normalized.split('/')) {\n if (p === '..') return false;\n }\n return true;\n}\n\n/** macOS/Windows noise; not part of the skill tree. */\nexport function isIgnorableZipEntry(name: string): boolean {\n const n = name.replace(/\\\\/g, '/');\n if (n.startsWith('__MACOSX/')) return true;\n const segments = n.split('/').filter(Boolean);\n for (const s of segments) {\n if (s === '.DS_Store' || s === 'Thumbs.db' || s === 'desktop.ini') return true;\n if (s.startsWith('._')) return true;\n }\n return false;\n}\n\nexport interface ManagedSkillListItem {\n id: string;\n name: string;\n description: string;\n path: string;\n /** Set when this folder was installed via `skills hub pull` / lock file. */\n hub?: SkillHubLockEntry;\n}\n\nfunction readSkillMdMeta(skillMdPath: string): { name: string; description: string } {\n try {\n const raw = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter } = parseFrontmatter(raw);\n return {\n name: (frontmatter.name as string) || '',\n description: (frontmatter.description as string)?.trim() || '',\n };\n } catch {\n return { name: '', description: '' };\n }\n}\n\nexport function listManagedSkillDirs(): ManagedSkillListItem[] {\n const root = resolveSkillsDir();\n mkdirSync(root, { recursive: true });\n const lock = loadSkillsLock();\n let dirNames: string[];\n try {\n dirNames = readdirSync(root, { withFileTypes: true })\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => e.name);\n } catch {\n return [];\n }\n const out: ManagedSkillListItem[] = [];\n for (const id of dirNames) {\n if (!isValidSkillId(id)) continue;\n const skillMd = join(root, id, 'SKILL.md');\n if (!existsSync(skillMd)) continue;\n const meta = readSkillMdMeta(skillMd);\n const hub = lock.entries[id];\n out.push({\n id,\n name: meta.name || id,\n description: meta.description || '',\n path: join(root, id),\n ...(hub ? { hub } : {}),\n });\n }\n out.sort((a, b) => a.id.localeCompare(b.id));\n return out;\n}\n\nexport function deleteManagedSkill(skillId: string): void {\n if (!isValidSkillId(skillId)) {\n throw new Error('Invalid skill id');\n }\n const root = resolveSkillsDir();\n const dir = resolve(join(root, skillId));\n const rootResolved = resolve(root);\n if (!dir.startsWith(rootResolved + sep) && dir !== rootResolved) {\n throw new Error('Invalid path');\n }\n if (!existsSync(join(dir, 'SKILL.md'))) {\n throw new Error('Skill not found');\n }\n const trashDir = createTransientManagedDir(root, TRASH_PREFIX, skillId);\n renameSync(dir, trashDir);\n rmSync(trashDir, { recursive: true, force: true });\n}\n\nfunction createTransientManagedDir(root: string, prefix: string, skillId: string): string {\n for (let i = 0; i < 100; i += 1) {\n const suffix = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}-${i}`;\n const dir = join(root, `${prefix}${skillId}-${suffix}`);\n if (!existsSync(dir)) return dir;\n }\n throw new Error('Could not allocate temporary skill directory');\n}\n\nexport function getManagedSkillDir(skillId: string): string {\n if (!isValidSkillId(skillId)) {\n throw new Error('Invalid skill id');\n }\n return join(resolveSkillsDir(), skillId);\n}\n\nexport function assertManagedSkillDestination(skillId: string): { root: string; destDir: string } {\n if (!isValidSkillId(skillId)) {\n throw new Error(`Invalid skill id \"${skillId}\" (letters, digits, ._-; max 63 chars after first)`);\n }\n const root = resolveSkillsDir();\n mkdirSync(root, { recursive: true });\n const destDir = join(root, skillId);\n const destResolved = resolve(destDir);\n const rootResolved = resolve(root);\n if (!destResolved.startsWith(rootResolved + sep) && destResolved !== rootResolved) {\n throw new Error('Invalid destination path');\n }\n return { root, destDir };\n}\n\nexport function prepareManagedSkillTempDir(skillId: string): { root: string; destDir: string; tempDir: string } {\n const { root, destDir } = assertManagedSkillDestination(skillId);\n const tempDir = createTransientManagedDir(root, TEMP_PREFIX, skillId);\n mkdirSync(tempDir, { recursive: true });\n return { root, destDir, tempDir };\n}\n\nexport function promoteManagedSkillTempDir(params: {\n skillId: string;\n tempDir: string;\n overwrite?: boolean;\n}): { skillId: string; path: string } {\n const { root, destDir } = assertManagedSkillDestination(params.skillId);\n const tempResolved = resolve(params.tempDir);\n const rootResolved = resolve(root);\n if (!tempResolved.startsWith(rootResolved + sep)) {\n throw new Error('Invalid temporary skill directory');\n }\n if (!existsSync(join(params.tempDir, 'SKILL.md'))) {\n throw new Error('Installed tree is missing SKILL.md');\n }\n\n if (existsSync(destDir)) {\n if (!params.overwrite) {\n throw new Error(`Skill \"${params.skillId}\" already exists. Pass overwrite to replace.`);\n }\n const trashDir = createTransientManagedDir(root, TRASH_PREFIX, params.skillId);\n renameSync(destDir, trashDir);\n try {\n renameSync(params.tempDir, destDir);\n } catch (err) {\n renameSync(trashDir, destDir);\n throw err;\n }\n rmSync(trashDir, { recursive: true, force: true });\n } else {\n renameSync(params.tempDir, destDir);\n }\n\n return { skillId: params.skillId, path: destDir };\n}\n\nfunction inferStripPrefix(primary: string): string {\n const parts = primary.split('/').filter(Boolean);\n if (parts.length === 1 && parts[0].toLowerCase() === 'skill.md') {\n return '';\n }\n return primary.slice(0, -'SKILL.md'.length);\n}\n\n/**\n * Install or replace a skill from a zip buffer. Layout: either `SKILL.md` at archive root\n * or a single top-level folder containing `SKILL.md` (optionally nested one level).\n */\nexport function installSkillFromZip(\n buffer: Buffer,\n options: { skillId?: string; overwrite?: boolean },\n): { skillId: string; path: string } {\n if (buffer.length > MAX_SKILL_ZIP_BYTES) {\n throw new Error(`Zip exceeds maximum size (${MAX_SKILL_ZIP_BYTES} bytes)`);\n }\n\n const zip = new AdmZip(buffer);\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName));\n\n const safeEntries = entries.filter((e) => isSafeZipPath(e.entryName));\n if (safeEntries.length === 0) {\n throw new Error('Zip is empty or invalid');\n }\n\n const names = safeEntries.map((e) => e.entryName.replace(/\\\\/g, '/'));\n const skillMdPaths = names.filter((n) => /(^|\\/)SKILL\\.md$/i.test(n));\n if (skillMdPaths.length === 0) {\n throw new Error('Zip must contain at least one SKILL.md');\n }\n\n const shallow = skillMdPaths.filter((p) => p.split('/').filter(Boolean).length <= 2);\n if (shallow.length === 0) {\n throw new Error(\n 'SKILL.md is nested too deeply; use a zip with SKILL.md at archive root or one folder (e.g. my-skill/SKILL.md)',\n );\n }\n\n shallow.sort((a, b) => a.length - b.length);\n const stripPrefix = inferStripPrefix(shallow[0]);\n\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n const outside = names.filter((n) => !n.startsWith(prefixNorm) && !isIgnorableZipEntry(n));\n if (outside.length > 0) {\n throw new Error(\n `Invalid zip: expected all skill files under \"${prefixNorm.replace(/\\/$/, '')}/\", but found \"${outside[0]}\". ` +\n 'Put SKILL.md and assets in one folder, or zip that folder only.',\n );\n }\n }\n\n let targetId = options.skillId?.trim();\n if (!targetId) {\n if (stripPrefix) {\n const first = stripPrefix.replace(/\\/$/, '').split('/')[0];\n targetId = first || '';\n }\n if (!targetId) {\n const skillName = shallow.find((n) => /(^|\\/)SKILL\\.md$/i.test(n)) || '';\n const entry = zip.getEntry(skillName);\n if (!entry) throw new Error('SKILL.md missing');\n const raw = entry.getData().toString('utf-8');\n const { frontmatter } = parseFrontmatter(raw);\n targetId = String(frontmatter.name || '').trim();\n }\n }\n\n if (!targetId || !isValidSkillId(targetId)) {\n throw new Error(\n 'Could not determine skill id: use a folder named with the skill id, pass skillId, or set name: in SKILL.md (letters, digits, ._-)',\n );\n }\n\n const { destDir, tempDir } = prepareManagedSkillTempDir(targetId);\n const tempResolved = resolve(tempDir);\n try {\n if (existsSync(destDir) && !options.overwrite) {\n throw new Error(`Skill \"${targetId}\" already exists. Pass overwrite to replace.`);\n }\n\n for (const e of safeEntries) {\n const norm = e.entryName.replace(/\\\\/g, '/');\n let rel: string;\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n if (!norm.startsWith(prefixNorm)) continue;\n rel = norm.slice(prefixNorm.length).replace(/^\\//, '');\n } else {\n rel = norm;\n }\n if (!rel || rel.includes('..')) continue;\n\n const targetPath = join(tempDir, rel);\n const resolvedTarget = resolve(targetPath);\n if (!resolvedTarget.startsWith(tempResolved + sep) && resolvedTarget !== tempResolved) {\n continue;\n }\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, e.getData());\n }\n\n if (!existsSync(join(tempDir, 'SKILL.md'))) {\n throw new Error('Extracted content is missing SKILL.md');\n }\n\n return promoteManagedSkillTempDir({\n skillId: targetId,\n tempDir,\n overwrite: options.overwrite,\n });\n } catch (err) {\n rmSync(tempDir, { recursive: true, force: true });\n throw err;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"managed-store.js","names":[],"sources":["../../../../src/agent/skills/managed-store.ts"],"sourcesContent":["/**\n * Managed skills live under ~/.xopc/skills (see resolveSkillsDir).\n * Install/update/delete via zip or folder operations; used by gateway API.\n */\n\nimport AdmZip from 'adm-zip';\nimport {\n existsSync,\n mkdirSync,\n renameSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { resolveSkillsDir } from '../../config/paths.js';\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { loadSkillsLock, type SkillHubLockEntry } from './hub-lock.js';\n\nexport const MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\n\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst TEMP_PREFIX = '.tmp-';\nconst TRASH_PREFIX = '.trash-';\n\nexport function isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\nexport function isManagedSkillTransientDirName(name: string): boolean {\n return name.startsWith(TEMP_PREFIX) || name.startsWith(TRASH_PREFIX);\n}\n\n/** True when `baseDir` is the global managed skills root or a direct child folder. */\nexport function isUnderManagedSkillsDir(baseDir: string): boolean {\n const b = resolve(baseDir);\n const r = resolve(resolveSkillsDir());\n return b === r || b.startsWith(r + sep);\n}\n\nfunction isSafeZipPath(name: string): boolean {\n if (!name) return false;\n const normalized = name.replace(/\\\\/g, '/');\n if (normalized.includes('..')) return false;\n if (normalized.startsWith('/') || /^\\w:/.test(normalized)) return false;\n for (const p of normalized.split('/')) {\n if (p === '..') return false;\n }\n return true;\n}\n\n/** macOS/Windows noise; not part of the skill tree. */\nexport function isIgnorableZipEntry(name: string): boolean {\n const n = name.replace(/\\\\/g, '/');\n if (n.startsWith('__MACOSX/')) return true;\n const segments = n.split('/').filter(Boolean);\n for (const s of segments) {\n if (s === '.DS_Store' || s === 'Thumbs.db' || s === 'desktop.ini') return true;\n if (s.startsWith('._')) return true;\n }\n return false;\n}\n\nexport interface ManagedSkillListItem {\n id: string;\n name: string;\n description: string;\n path: string;\n /** Set when this folder was installed via `skills hub pull` / lock file. */\n hub?: SkillHubLockEntry;\n}\n\nfunction readSkillMdMeta(skillMdPath: string): { name: string; description: string } {\n try {\n const raw = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter } = parseFrontmatter(raw);\n return {\n name: (frontmatter.name as string) || '',\n description: (frontmatter.description as string)?.trim() || '',\n };\n } catch {\n return { name: '', description: '' };\n }\n}\n\nexport function listManagedSkillDirs(): ManagedSkillListItem[] {\n const root = resolveSkillsDir();\n mkdirSync(root, { recursive: true });\n const lock = loadSkillsLock();\n let dirNames: string[];\n try {\n dirNames = readdirSync(root, { withFileTypes: true })\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => e.name);\n } catch {\n return [];\n }\n const out: ManagedSkillListItem[] = [];\n for (const id of dirNames) {\n if (!isValidSkillId(id)) continue;\n const skillMd = join(root, id, 'SKILL.md');\n if (!existsSync(skillMd)) continue;\n const meta = readSkillMdMeta(skillMd);\n const hub = lock.entries[id];\n out.push({\n id,\n name: meta.name || id,\n description: meta.description || '',\n path: join(root, id),\n ...(hub ? { hub } : {}),\n });\n }\n out.sort((a, b) => a.id.localeCompare(b.id));\n return out;\n}\n\nexport function deleteManagedSkill(skillId: string, rootDir = resolveSkillsDir()): void {\n if (!isValidSkillId(skillId)) {\n throw new Error('Invalid skill id');\n }\n const root = resolve(rootDir);\n const dir = resolve(join(root, skillId));\n const rootResolved = resolve(root);\n if (!dir.startsWith(rootResolved + sep) && dir !== rootResolved) {\n throw new Error('Invalid path');\n }\n if (!existsSync(join(dir, 'SKILL.md'))) {\n throw new Error('Skill not found');\n }\n const trashDir = createTransientManagedDir(root, TRASH_PREFIX, skillId);\n renameSync(dir, trashDir);\n rmSync(trashDir, { recursive: true, force: true });\n}\n\nfunction createTransientManagedDir(root: string, prefix: string, skillId: string): string {\n for (let i = 0; i < 100; i += 1) {\n const suffix = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}-${i}`;\n const dir = join(root, `${prefix}${skillId}-${suffix}`);\n if (!existsSync(dir)) return dir;\n }\n throw new Error('Could not allocate temporary skill directory');\n}\n\nexport function getManagedSkillDir(skillId: string): string {\n if (!isValidSkillId(skillId)) {\n throw new Error('Invalid skill id');\n }\n return join(resolveSkillsDir(), skillId);\n}\n\nexport function assertManagedSkillDestination(\n skillId: string,\n rootDir = resolveSkillsDir(),\n): { root: string; destDir: string } {\n if (!isValidSkillId(skillId)) {\n throw new Error(`Invalid skill id \"${skillId}\" (letters, digits, ._-; max 63 chars after first)`);\n }\n const root = resolve(rootDir);\n mkdirSync(root, { recursive: true });\n const destDir = join(root, skillId);\n const destResolved = resolve(destDir);\n const rootResolved = resolve(root);\n if (!destResolved.startsWith(rootResolved + sep) && destResolved !== rootResolved) {\n throw new Error('Invalid destination path');\n }\n return { root, destDir };\n}\n\nexport function prepareManagedSkillTempDir(\n skillId: string,\n rootDir?: string,\n): { root: string; destDir: string; tempDir: string } {\n const { root, destDir } = assertManagedSkillDestination(skillId, rootDir);\n const tempDir = createTransientManagedDir(root, TEMP_PREFIX, skillId);\n mkdirSync(tempDir, { recursive: true });\n return { root, destDir, tempDir };\n}\n\nexport function promoteManagedSkillTempDir(params: {\n skillId: string;\n tempDir: string;\n overwrite?: boolean;\n rootDir?: string;\n}): { skillId: string; path: string } {\n const { root, destDir } = assertManagedSkillDestination(params.skillId, params.rootDir);\n const tempResolved = resolve(params.tempDir);\n const rootResolved = resolve(root);\n if (!tempResolved.startsWith(rootResolved + sep)) {\n throw new Error('Invalid temporary skill directory');\n }\n if (!existsSync(join(params.tempDir, 'SKILL.md'))) {\n throw new Error('Installed tree is missing SKILL.md');\n }\n\n if (existsSync(destDir)) {\n if (!params.overwrite) {\n throw new Error(`Skill \"${params.skillId}\" already exists. Pass overwrite to replace.`);\n }\n const trashDir = createTransientManagedDir(root, TRASH_PREFIX, params.skillId);\n renameSync(destDir, trashDir);\n try {\n renameSync(params.tempDir, destDir);\n } catch (err) {\n renameSync(trashDir, destDir);\n throw err;\n }\n rmSync(trashDir, { recursive: true, force: true });\n } else {\n renameSync(params.tempDir, destDir);\n }\n\n return { skillId: params.skillId, path: destDir };\n}\n\nfunction inferStripPrefix(primary: string): string {\n const parts = primary.split('/').filter(Boolean);\n if (parts.length === 1 && parts[0].toLowerCase() === 'skill.md') {\n return '';\n }\n return primary.slice(0, -'SKILL.md'.length);\n}\n\n/**\n * Install or replace a skill from a zip buffer. Layout: either `SKILL.md` at archive root\n * or a single top-level folder containing `SKILL.md` (optionally nested one level).\n */\nexport function installSkillFromZip(\n buffer: Buffer,\n options: { skillId?: string; overwrite?: boolean; rootDir?: string },\n): { skillId: string; path: string } {\n if (buffer.length > MAX_SKILL_ZIP_BYTES) {\n throw new Error(`Zip exceeds maximum size (${MAX_SKILL_ZIP_BYTES} bytes)`);\n }\n\n const zip = new AdmZip(buffer);\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName));\n\n const safeEntries = entries.filter((e) => isSafeZipPath(e.entryName));\n if (safeEntries.length === 0) {\n throw new Error('Zip is empty or invalid');\n }\n\n const names = safeEntries.map((e) => e.entryName.replace(/\\\\/g, '/'));\n const skillMdPaths = names.filter((n) => /(^|\\/)SKILL\\.md$/i.test(n));\n if (skillMdPaths.length === 0) {\n throw new Error('Zip must contain at least one SKILL.md');\n }\n\n const shallow = skillMdPaths.filter((p) => p.split('/').filter(Boolean).length <= 2);\n if (shallow.length === 0) {\n throw new Error(\n 'SKILL.md is nested too deeply; use a zip with SKILL.md at archive root or one folder (e.g. my-skill/SKILL.md)',\n );\n }\n\n shallow.sort((a, b) => a.length - b.length);\n const stripPrefix = inferStripPrefix(shallow[0]);\n\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n const outside = names.filter((n) => !n.startsWith(prefixNorm) && !isIgnorableZipEntry(n));\n if (outside.length > 0) {\n throw new Error(\n `Invalid zip: expected all skill files under \"${prefixNorm.replace(/\\/$/, '')}/\", but found \"${outside[0]}\". ` +\n 'Put SKILL.md and assets in one folder, or zip that folder only.',\n );\n }\n }\n\n let targetId = options.skillId?.trim();\n if (!targetId) {\n if (stripPrefix) {\n const first = stripPrefix.replace(/\\/$/, '').split('/')[0];\n targetId = first || '';\n }\n if (!targetId) {\n const skillName = shallow.find((n) => /(^|\\/)SKILL\\.md$/i.test(n)) || '';\n const entry = zip.getEntry(skillName);\n if (!entry) throw new Error('SKILL.md missing');\n const raw = entry.getData().toString('utf-8');\n const { frontmatter } = parseFrontmatter(raw);\n targetId = String(frontmatter.name || '').trim();\n }\n }\n\n if (!targetId || !isValidSkillId(targetId)) {\n throw new Error(\n 'Could not determine skill id: use a folder named with the skill id, pass skillId, or set name: in SKILL.md (letters, digits, ._-)',\n );\n }\n\n const { destDir, tempDir } = prepareManagedSkillTempDir(targetId, options.rootDir);\n const tempResolved = resolve(tempDir);\n try {\n if (existsSync(destDir) && !options.overwrite) {\n throw new Error(`Skill \"${targetId}\" already exists. Pass overwrite to replace.`);\n }\n\n for (const e of safeEntries) {\n const norm = e.entryName.replace(/\\\\/g, '/');\n let rel: string;\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n if (!norm.startsWith(prefixNorm)) continue;\n rel = norm.slice(prefixNorm.length).replace(/^\\//, '');\n } else {\n rel = norm;\n }\n if (!rel || rel.includes('..')) continue;\n\n const targetPath = join(tempDir, rel);\n const resolvedTarget = resolve(targetPath);\n if (!resolvedTarget.startsWith(tempResolved + sep) && resolvedTarget !== tempResolved) {\n continue;\n }\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, e.getData());\n }\n\n if (!existsSync(join(tempDir, 'SKILL.md'))) {\n throw new Error('Extracted content is missing SKILL.md');\n }\n\n return promoteManagedSkillTempDir({\n skillId: targetId,\n tempDir,\n overwrite: options.overwrite,\n rootDir: options.rootDir,\n });\n } catch (err) {\n rmSync(tempDir, { recursive: true, force: true });\n throw err;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { registerMarketplaceAdapter } from "../../registry.js";
|
|
2
|
-
import { downloadSkillZipBuffer, fetchMarketplacePackageDetail, listSkillPackages, resolveSkillZipDownloadUrl, resolveSkillsStoreBaseUrl, skillIdForMarketplaceInstall } from "./store-api-client.js";
|
|
2
|
+
import { downloadSkillZipBuffer, fetchMarketplacePackageDetail, listSkillPackages, resolveSkillZipDownloadUrl, resolveSkillsStoreBaseUrl, skillIdForMarketplaceInstall, verifyStoreArtifactSha256 } from "./store-api-client.js";
|
|
3
3
|
import { buildSkillMarkdownPreviewFromRaw } from "../../../skill-markdown-preview-from-raw.js";
|
|
4
4
|
//#region src/agent/skills/marketplace/adapters/store/adapter.ts
|
|
5
5
|
const storeMarketplaceAdapter = {
|
|
@@ -31,9 +31,11 @@ const storeMarketplaceAdapter = {
|
|
|
31
31
|
},
|
|
32
32
|
async downloadPackage(config, packageName, version) {
|
|
33
33
|
const base = resolveSkillsStoreBaseUrl(config);
|
|
34
|
-
const { downloadUrl, version: resolvedVersion } = await resolveSkillZipDownloadUrl(base, packageName, version);
|
|
34
|
+
const { downloadUrl, version: resolvedVersion, sha256 } = await resolveSkillZipDownloadUrl(base, packageName, version);
|
|
35
|
+
const buffer = await downloadSkillZipBuffer(base, downloadUrl);
|
|
36
|
+
verifyStoreArtifactSha256(buffer, sha256);
|
|
35
37
|
return {
|
|
36
|
-
buffer
|
|
38
|
+
buffer,
|
|
37
39
|
skillId: skillIdForMarketplaceInstall(packageName) ?? packageName,
|
|
38
40
|
version: resolvedVersion
|
|
39
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/store/adapter.ts"],"sourcesContent":["import { buildSkillMarkdownPreviewFromRaw } from '../../../skill-markdown-preview-from-raw.js';\nimport {\n downloadSkillZipBuffer,\n fetchMarketplacePackageDetail,\n listSkillPackages,\n resolveSkillZipDownloadUrl,\n resolveSkillsStoreBaseUrl,\n skillIdForMarketplaceInstall,\n} from './store-api-client.js';\n\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\nexport const storeMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'store',\n\n async listCategories(_config) {\n return [];\n },\n\n async listPackages(config, params) {\n const base = resolveSkillsStoreBaseUrl(config);\n const response = await listSkillPackages(base, params);\n return {\n items: response.items,\n meta: response.meta,\n provider: 'store',\n };\n },\n\n async getPackageDetail(config, packageName) {\n const base = resolveSkillsStoreBaseUrl(config);\n const detail = await fetchMarketplacePackageDetail(base, packageName);\n const readme = detail.readme?.trim();\n if (!readme) {\n throw new Error(`Store skill package [${packageName}] did not include readme`);\n }\n return {\n ...detail,\n readme,\n provider: 'store',\n skillDocPreview: buildSkillMarkdownPreviewFromRaw(readme, {\n name: detail.name,\n description: detail.description,\n }),\n };\n },\n\n async downloadPackage(config, packageName, version) {\n const base = resolveSkillsStoreBaseUrl(config);\n const { downloadUrl, version: resolvedVersion } = await resolveSkillZipDownloadUrl(\n base,\n packageName,\n version,\n );\n const buffer = await downloadSkillZipBuffer(base, downloadUrl);\n return {\n buffer,\n skillId: skillIdForMarketplaceInstall(packageName) ?? packageName,\n version: resolvedVersion,\n };\n },\n};\n\n// Self-register into the dynamic marketplace adapter registry.\nregisterMarketplaceAdapter({\n adapter: storeMarketplaceAdapter,\n displayName: 'XOPC Store',\n});\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/store/adapter.ts"],"sourcesContent":["import { buildSkillMarkdownPreviewFromRaw } from '../../../skill-markdown-preview-from-raw.js';\nimport {\n downloadSkillZipBuffer,\n fetchMarketplacePackageDetail,\n listSkillPackages,\n resolveSkillZipDownloadUrl,\n resolveSkillsStoreBaseUrl,\n skillIdForMarketplaceInstall,\n verifyStoreArtifactSha256,\n} from './store-api-client.js';\n\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\nexport const storeMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'store',\n\n async listCategories(_config) {\n return [];\n },\n\n async listPackages(config, params) {\n const base = resolveSkillsStoreBaseUrl(config);\n const response = await listSkillPackages(base, params);\n return {\n items: response.items,\n meta: response.meta,\n provider: 'store',\n };\n },\n\n async getPackageDetail(config, packageName) {\n const base = resolveSkillsStoreBaseUrl(config);\n const detail = await fetchMarketplacePackageDetail(base, packageName);\n const readme = detail.readme?.trim();\n if (!readme) {\n throw new Error(`Store skill package [${packageName}] did not include readme`);\n }\n return {\n ...detail,\n readme,\n provider: 'store',\n skillDocPreview: buildSkillMarkdownPreviewFromRaw(readme, {\n name: detail.name,\n description: detail.description,\n }),\n };\n },\n\n async downloadPackage(config, packageName, version) {\n const base = resolveSkillsStoreBaseUrl(config);\n const { downloadUrl, version: resolvedVersion, sha256 } = await resolveSkillZipDownloadUrl(\n base,\n packageName,\n version,\n );\n const buffer = await downloadSkillZipBuffer(base, downloadUrl);\n verifyStoreArtifactSha256(buffer, sha256);\n return {\n buffer,\n skillId: skillIdForMarketplaceInstall(packageName) ?? packageName,\n version: resolvedVersion,\n };\n },\n};\n\n// Self-register into the dynamic marketplace adapter registry.\nregisterMarketplaceAdapter({\n adapter: storeMarketplaceAdapter,\n displayName: 'XOPC Store',\n});\n"],"mappings":";;;;AAcA,MAAa,0BAAoD;CAC/D,IAAI;CAEJ,MAAM,eAAe,SAAS;AAC5B,SAAO,EAAE;;CAGX,MAAM,aAAa,QAAQ,QAAQ;EAEjC,MAAM,WAAW,MAAM,kBADV,0BAA0B,OACM,EAAE,OAAO;AACtD,SAAO;GACL,OAAO,SAAS;GAChB,MAAM,SAAS;GACf,UAAU;GACX;;CAGH,MAAM,iBAAiB,QAAQ,aAAa;EAE1C,MAAM,SAAS,MAAM,8BADR,0BAA0B,OACgB,EAAE,YAAY;EACrE,MAAM,SAAS,OAAO,QAAQ,MAAM;AACpC,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,wBAAwB,YAAY,0BAA0B;AAEhF,SAAO;GACL,GAAG;GACH;GACA,UAAU;GACV,iBAAiB,iCAAiC,QAAQ;IACxD,MAAM,OAAO;IACb,aAAa,OAAO;IACrB,CAAC;GACH;;CAGH,MAAM,gBAAgB,QAAQ,aAAa,SAAS;EAClD,MAAM,OAAO,0BAA0B,OAAO;EAC9C,MAAM,EAAE,aAAa,SAAS,iBAAiB,WAAW,MAAM,2BAC9D,MACA,aACA,QACD;EACD,MAAM,SAAS,MAAM,uBAAuB,MAAM,YAAY;AAC9D,4BAA0B,QAAQ,OAAO;AACzC,SAAO;GACL;GACA,SAAS,6BAA6B,YAAY,IAAI;GACtD,SAAS;GACV;;CAEJ;AAGD,2BAA2B;CACzB,SAAS;CACT,aAAa;CACd,CAAC"}
|
|
@@ -70,6 +70,8 @@ export declare function getStoreOrigin(baseUrl: string): string;
|
|
|
70
70
|
*/
|
|
71
71
|
export declare function assertDownloadUrlAllowed(downloadUrl: string, storeBaseUrl: string): URL;
|
|
72
72
|
export declare function listSkillPackages(storeBaseUrl: string, params: SkillsStoreListParams): Promise<SkillsStoreListResponse>;
|
|
73
|
+
/** Public connector catalog exposed by xopc-store. */
|
|
74
|
+
export declare function listConnectorPackages(storeBaseUrl: string, params: SkillsStoreListParams): Promise<SkillsStoreListResponse>;
|
|
73
75
|
/** GET /api/v1/packages/:name — published skill package (public). */
|
|
74
76
|
export interface MarketplacePackageDetail {
|
|
75
77
|
id: string;
|
|
@@ -88,12 +90,28 @@ export interface MarketplacePackageDetail {
|
|
|
88
90
|
publishedAt: string;
|
|
89
91
|
};
|
|
90
92
|
}
|
|
93
|
+
export interface StoreConnectorPackageDetail {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
type: 'connector';
|
|
97
|
+
description: string;
|
|
98
|
+
latestVersion: {
|
|
99
|
+
version: string;
|
|
100
|
+
manifest: unknown;
|
|
101
|
+
downloadUrl: string;
|
|
102
|
+
sha256: string | null;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export declare function fetchStoreConnectorPackageDetail(storeBaseUrl: string, packageName: string, version?: string): Promise<StoreConnectorPackageDetail>;
|
|
91
106
|
export declare function fetchMarketplacePackageDetail(storeBaseUrl: string, packageName: string): Promise<MarketplacePackageDetail>;
|
|
92
107
|
export declare function resolveSkillZipDownloadUrl(storeBaseUrl: string, packageName: string, version?: string): Promise<{
|
|
93
108
|
downloadUrl: string;
|
|
94
109
|
version: string;
|
|
110
|
+
sha256?: string;
|
|
95
111
|
}>;
|
|
96
|
-
|
|
112
|
+
/** Verify Store-provided immutable artifact digest before any local installation. */
|
|
113
|
+
export declare function verifyStoreArtifactSha256(buffer: Buffer, expected: string | null | undefined): void;
|
|
114
|
+
export declare function downloadSkillZipBuffer(storeBaseUrl: string, downloadUrl: string, expectedSha256?: string): Promise<Buffer>;
|
|
97
115
|
/** GET /api/v1/packages/:name — subset used for extension installs. */
|
|
98
116
|
export interface StorePublishedPackageHead {
|
|
99
117
|
name: string;
|
|
@@ -110,8 +128,10 @@ export declare function resolveExtensionZipDownloadUrl(storeBaseUrl: string, pac
|
|
|
110
128
|
downloadUrl: string;
|
|
111
129
|
version: string;
|
|
112
130
|
integrity?: string;
|
|
131
|
+
sha256?: string;
|
|
113
132
|
}>;
|
|
114
133
|
export declare function downloadExtensionStoreZipBuffer(storeBaseUrl: string, downloadUrl: string): Promise<Buffer>;
|
|
134
|
+
export declare function downloadConnectorStoreZipBuffer(storeBaseUrl: string, downloadUrl: string): Promise<Buffer>;
|
|
115
135
|
export declare function skillIdForMarketplaceInstall(packageName: string): string | undefined;
|
|
116
136
|
/**
|
|
117
137
|
* Unified marketplace list response (adapter fills `provider`).
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { MAX_SKILL_ZIP_BYTES, isValidSkillId } from "../../../managed-store.js";
|
|
2
2
|
import { MAX_EXTENSION_STORE_ZIP_BYTES } from "../../../../../extensions/store-zip-limits.js";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
3
4
|
//#region src/agent/skills/marketplace/adapters/store/store-api-client.ts
|
|
5
|
+
/**
|
|
6
|
+
* HTTP client for the public xopc-store-compatible REST API (packages list, detail, zip download).
|
|
7
|
+
* Used by the store marketplace adapter and SSRF-safe download helpers.
|
|
8
|
+
*
|
|
9
|
+
* Facade: {@link ../../../skills-marketplace.js}.
|
|
10
|
+
*/
|
|
4
11
|
const DEFAULT_STORE_BASE = "https://store.xopc.ai";
|
|
5
12
|
function resolveSkillsStoreBaseUrl(config) {
|
|
6
13
|
const env = process.env.XOPC_SKILLS_STORE_URL?.trim();
|
|
@@ -87,6 +94,34 @@ async function listSkillPackages(storeBaseUrl, params) {
|
|
|
87
94
|
if (params.category?.trim()) sp.set("category", params.category.trim());
|
|
88
95
|
return fetchJson(`${base}/api/v1/packages?${sp.toString()}`);
|
|
89
96
|
}
|
|
97
|
+
/** Public connector catalog exposed by xopc-store. */
|
|
98
|
+
async function listConnectorPackages(storeBaseUrl, params) {
|
|
99
|
+
const base = normalizeBaseUrl(storeBaseUrl);
|
|
100
|
+
const sp = new URLSearchParams();
|
|
101
|
+
sp.set("type", "connector");
|
|
102
|
+
if (params.q?.trim()) sp.set("q", params.q.trim());
|
|
103
|
+
if (params.page != null) sp.set("page", String(params.page));
|
|
104
|
+
if (params.pageSize != null) sp.set("pageSize", String(params.pageSize));
|
|
105
|
+
if (params.sort) sp.set("sort", params.sort);
|
|
106
|
+
if (params.category?.trim()) sp.set("category", params.category.trim());
|
|
107
|
+
return fetchJson(`${base}/api/v1/packages?${sp.toString()}`);
|
|
108
|
+
}
|
|
109
|
+
async function fetchStoreConnectorPackageDetail(storeBaseUrl, packageName, version) {
|
|
110
|
+
const base = normalizeBaseUrl(storeBaseUrl);
|
|
111
|
+
const enc = encodeURIComponent(packageName.trim());
|
|
112
|
+
const pkg = await fetchJson(`${base}/api/v1/packages/${enc}`);
|
|
113
|
+
if (pkg.type !== "connector") throw new Error(`Package "${packageName}" has type "${pkg.type}" (expected connector).`);
|
|
114
|
+
if (!version?.trim() || version.trim() === pkg.latestVersion.version) {
|
|
115
|
+
assertDownloadUrlAllowed(pkg.latestVersion.downloadUrl, base);
|
|
116
|
+
return pkg;
|
|
117
|
+
}
|
|
118
|
+
const detail = await fetchJson(`${base}/api/v1/packages/${enc}/versions/${encodeURIComponent(version.trim())}`);
|
|
119
|
+
assertDownloadUrlAllowed(detail.downloadUrl, base);
|
|
120
|
+
return {
|
|
121
|
+
...pkg,
|
|
122
|
+
latestVersion: detail
|
|
123
|
+
};
|
|
124
|
+
}
|
|
90
125
|
async function fetchMarketplacePackageDetail(storeBaseUrl, packageName) {
|
|
91
126
|
return fetchJson(`${normalizeBaseUrl(storeBaseUrl)}/api/v1/packages/${encodeURIComponent(packageName.trim())}`);
|
|
92
127
|
}
|
|
@@ -99,7 +134,8 @@ async function resolveSkillZipDownloadUrl(storeBaseUrl, packageName, version) {
|
|
|
99
134
|
assertDownloadUrlAllowed(detail.downloadUrl, base);
|
|
100
135
|
return {
|
|
101
136
|
downloadUrl: detail.downloadUrl,
|
|
102
|
-
version: detail.version
|
|
137
|
+
version: detail.version,
|
|
138
|
+
...detail.sha256 ? { sha256: detail.sha256 } : {}
|
|
103
139
|
};
|
|
104
140
|
}
|
|
105
141
|
const pkg = await fetchJson(`${base}/api/v1/packages/${enc}`);
|
|
@@ -107,10 +143,16 @@ async function resolveSkillZipDownloadUrl(storeBaseUrl, packageName, version) {
|
|
|
107
143
|
assertDownloadUrlAllowed(pkg.latestVersion.downloadUrl, base);
|
|
108
144
|
return {
|
|
109
145
|
downloadUrl: pkg.latestVersion.downloadUrl,
|
|
110
|
-
version: pkg.latestVersion.version
|
|
146
|
+
version: pkg.latestVersion.version,
|
|
147
|
+
...pkg.latestVersion.sha256 ? { sha256: pkg.latestVersion.sha256 } : {}
|
|
111
148
|
};
|
|
112
149
|
}
|
|
113
|
-
|
|
150
|
+
/** Verify Store-provided immutable artifact digest before any local installation. */
|
|
151
|
+
function verifyStoreArtifactSha256(buffer, expected) {
|
|
152
|
+
if (!expected || !/^[a-f0-9]{64}$/i.test(expected)) throw new Error("Store version is missing a valid SHA-256 checksum");
|
|
153
|
+
if (createHash("sha256").update(buffer).digest("hex") !== expected.toLowerCase()) throw new Error("Store artifact checksum verification failed");
|
|
154
|
+
}
|
|
155
|
+
async function downloadSkillZipBuffer(storeBaseUrl, downloadUrl, expectedSha256) {
|
|
114
156
|
assertDownloadUrlAllowed(downloadUrl, normalizeBaseUrl(storeBaseUrl));
|
|
115
157
|
const res = await fetch(downloadUrl, { redirect: "follow" });
|
|
116
158
|
if (!res.ok) throw new Error(`Failed to download skill archive (${res.status})`);
|
|
@@ -122,6 +164,7 @@ async function downloadSkillZipBuffer(storeBaseUrl, downloadUrl) {
|
|
|
122
164
|
const ab = await res.arrayBuffer();
|
|
123
165
|
const buf = Buffer.from(ab);
|
|
124
166
|
if (buf.length > 15728640) throw new Error(`Zip exceeds maximum size (${MAX_SKILL_ZIP_BYTES} bytes)`);
|
|
167
|
+
if (expectedSha256 !== void 0) verifyStoreArtifactSha256(buf, expectedSha256);
|
|
125
168
|
return buf;
|
|
126
169
|
}
|
|
127
170
|
async function resolveExtensionZipDownloadUrl(storeBaseUrl, packageName, version) {
|
|
@@ -136,7 +179,8 @@ async function resolveExtensionZipDownloadUrl(storeBaseUrl, packageName, version
|
|
|
136
179
|
return {
|
|
137
180
|
downloadUrl: detail.downloadUrl,
|
|
138
181
|
version: detail.version,
|
|
139
|
-
integrity: detail.integrity ?? detail.checksum ?? detail.sha256
|
|
182
|
+
integrity: detail.integrity ?? detail.checksum ?? detail.sha256,
|
|
183
|
+
...detail.sha256 ? { sha256: detail.sha256 } : {}
|
|
140
184
|
};
|
|
141
185
|
}
|
|
142
186
|
const lv = meta.latestVersion;
|
|
@@ -145,7 +189,8 @@ async function resolveExtensionZipDownloadUrl(storeBaseUrl, packageName, version
|
|
|
145
189
|
return {
|
|
146
190
|
downloadUrl: lv.downloadUrl,
|
|
147
191
|
version: lv.version,
|
|
148
|
-
integrity: lv.integrity ?? lv.checksum ?? lv.sha256
|
|
192
|
+
integrity: lv.integrity ?? lv.checksum ?? lv.sha256,
|
|
193
|
+
...lv.sha256 ? { sha256: lv.sha256 } : {}
|
|
149
194
|
};
|
|
150
195
|
}
|
|
151
196
|
async function downloadExtensionStoreZipBuffer(storeBaseUrl, downloadUrl) {
|
|
@@ -162,12 +207,23 @@ async function downloadExtensionStoreZipBuffer(storeBaseUrl, downloadUrl) {
|
|
|
162
207
|
if (buf.length > 10485760) throw new Error(`Zip exceeds maximum size (${MAX_EXTENSION_STORE_ZIP_BYTES} bytes)`);
|
|
163
208
|
return buf;
|
|
164
209
|
}
|
|
210
|
+
async function downloadConnectorStoreZipBuffer(storeBaseUrl, downloadUrl) {
|
|
211
|
+
assertDownloadUrlAllowed(downloadUrl, normalizeBaseUrl(storeBaseUrl));
|
|
212
|
+
const res = await fetch(downloadUrl, { redirect: "error" });
|
|
213
|
+
if (!res.ok) throw new Error(`Failed to download connector archive (${res.status})`);
|
|
214
|
+
const maxBytes = 1024 * 1024;
|
|
215
|
+
const len = res.headers.get("content-length");
|
|
216
|
+
if (len && Number(len) > maxBytes) throw new Error(`Connector archive exceeds maximum size (${maxBytes} bytes)`);
|
|
217
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
218
|
+
if (buf.length > maxBytes) throw new Error(`Connector archive exceeds maximum size (${maxBytes} bytes)`);
|
|
219
|
+
return buf;
|
|
220
|
+
}
|
|
165
221
|
function skillIdForMarketplaceInstall(packageName) {
|
|
166
222
|
const trimmed = packageName.trim();
|
|
167
223
|
if (!trimmed) return void 0;
|
|
168
224
|
return isValidSkillId(trimmed) ? trimmed : void 0;
|
|
169
225
|
}
|
|
170
226
|
//#endregion
|
|
171
|
-
export { MAX_EXTENSION_STORE_ZIP_BYTES, assertDownloadUrlAllowed, downloadExtensionStoreZipBuffer, downloadSkillZipBuffer, fetchMarketplacePackageDetail, getStoreOrigin, listSkillPackages, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl, resolveSkillZipDownloadUrl, resolveSkillsStoreBaseUrl, skillIdForMarketplaceInstall };
|
|
227
|
+
export { MAX_EXTENSION_STORE_ZIP_BYTES, assertDownloadUrlAllowed, downloadConnectorStoreZipBuffer, downloadExtensionStoreZipBuffer, downloadSkillZipBuffer, fetchMarketplacePackageDetail, fetchStoreConnectorPackageDetail, getStoreOrigin, listConnectorPackages, listSkillPackages, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl, resolveSkillZipDownloadUrl, resolveSkillsStoreBaseUrl, skillIdForMarketplaceInstall, verifyStoreArtifactSha256 };
|
|
172
228
|
|
|
173
229
|
//# sourceMappingURL=store-api-client.js.map
|