@skaile/workspaces 4.35.0 → 4.37.0
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/CHANGELOG.md +42 -0
- package/dist/app-sdk/index.js +1 -1
- package/dist/{asset-feeds-NL3526ZV.js → asset-feeds-KTRFFJYM.js} +10 -10
- package/dist/{asset-feeds-NL3526ZV.js.map → asset-feeds-KTRFFJYM.js.map} +1 -1
- package/dist/asset-manager/catalog-deployer.js +5 -5
- package/dist/asset-manager/index.js +10 -10
- package/dist/asset-manager/installer.js +7 -7
- package/dist/asset-manager/renderers.js +2 -2
- package/dist/asset-manager/src/index.d.ts +18 -0
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/mcp-config.d.ts.map +1 -1
- package/dist/bridge/drivers/claude-sdk.js +14 -11
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +7 -7
- package/dist/bridge/drivers/continue.js +8 -8
- package/dist/bridge/drivers/echo.js +3 -3
- package/dist/bridge/drivers/gemini.js +6 -6
- package/dist/bridge/drivers/goose.js +8 -8
- package/dist/bridge/drivers/omp.js +9 -6
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +8 -8
- package/dist/bridge/drivers/qwen.js +6 -6
- package/dist/bridge/index.js +11 -11
- package/dist/bridge/src/drivers/claude-sdk.d.ts +1 -0
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp.d.ts +3 -2
- package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
- package/dist/bridge/src/types.d.ts +8 -0
- package/dist/bridge/src/types.d.ts.map +1 -1
- package/dist/{chunk-TGE33MKN.js → chunk-2D3C4AJP.js} +4 -2
- package/dist/chunk-2D3C4AJP.js.map +1 -0
- package/dist/{chunk-ZWTCXL3H.js → chunk-2QYQOJ2F.js} +3 -3
- package/dist/{chunk-ZWTCXL3H.js.map → chunk-2QYQOJ2F.js.map} +1 -1
- package/dist/{chunk-T3YUSWVK.js → chunk-3SUWLY3H.js} +3 -3
- package/dist/{chunk-T3YUSWVK.js.map → chunk-3SUWLY3H.js.map} +1 -1
- package/dist/{chunk-Q6NDQ6BH.js → chunk-5JAO4MXA.js} +3 -3
- package/dist/{chunk-Q6NDQ6BH.js.map → chunk-5JAO4MXA.js.map} +1 -1
- package/dist/{chunk-NVQLE4MK.js → chunk-5SGS5SN2.js} +4 -4
- package/dist/{chunk-NVQLE4MK.js.map → chunk-5SGS5SN2.js.map} +1 -1
- package/dist/{chunk-RHESVS7V.js → chunk-7YCPY6NC.js} +6 -6
- package/dist/{chunk-RHESVS7V.js.map → chunk-7YCPY6NC.js.map} +1 -1
- package/dist/{chunk-N2UGG6WV.js → chunk-A5RRXBLI.js} +5 -5
- package/dist/{chunk-N2UGG6WV.js.map → chunk-A5RRXBLI.js.map} +1 -1
- package/dist/{chunk-DOF77WEV.js → chunk-BSIHJZKN.js} +6 -6
- package/dist/{chunk-DOF77WEV.js.map → chunk-BSIHJZKN.js.map} +1 -1
- package/dist/{chunk-VOXFI3XS.js → chunk-DFZDL62S.js} +4 -4
- package/dist/{chunk-VOXFI3XS.js.map → chunk-DFZDL62S.js.map} +1 -1
- package/dist/{chunk-XTOTP7MJ.js → chunk-ENXE4BKS.js} +2 -2
- package/dist/{chunk-XTOTP7MJ.js.map → chunk-ENXE4BKS.js.map} +1 -1
- package/dist/{chunk-3ELIPWCH.js → chunk-FJYOQMXT.js} +4 -4
- package/dist/{chunk-3ELIPWCH.js.map → chunk-FJYOQMXT.js.map} +1 -1
- package/dist/{chunk-7HJ6SFFF.js → chunk-FLGLODDF.js} +3 -3
- package/dist/{chunk-7HJ6SFFF.js.map → chunk-FLGLODDF.js.map} +1 -1
- package/dist/{chunk-TGJIX77V.js → chunk-FZFCOQTI.js} +3 -3
- package/dist/{chunk-TGJIX77V.js.map → chunk-FZFCOQTI.js.map} +1 -1
- package/dist/{chunk-P2DLXBZK.js → chunk-H3KXUUYQ.js} +4 -4
- package/dist/{chunk-P2DLXBZK.js.map → chunk-H3KXUUYQ.js.map} +1 -1
- package/dist/{chunk-AKO6XHGV.js → chunk-KN5Y5BXK.js} +5 -5
- package/dist/{chunk-AKO6XHGV.js.map → chunk-KN5Y5BXK.js.map} +1 -1
- package/dist/{chunk-QJOOD3OV.js → chunk-L7R52OOV.js} +3 -3
- package/dist/{chunk-QJOOD3OV.js.map → chunk-L7R52OOV.js.map} +1 -1
- package/dist/{chunk-TB3LJ6NA.js → chunk-MDBAEEY5.js} +3 -3
- package/dist/{chunk-TB3LJ6NA.js.map → chunk-MDBAEEY5.js.map} +1 -1
- package/dist/{chunk-TUTVTGMG.js → chunk-MIRWAK5C.js} +4 -4
- package/dist/{chunk-TUTVTGMG.js.map → chunk-MIRWAK5C.js.map} +1 -1
- package/dist/{chunk-C3256F2F.js → chunk-MRS5YHPI.js} +3 -3
- package/dist/{chunk-C3256F2F.js.map → chunk-MRS5YHPI.js.map} +1 -1
- package/dist/{chunk-7LBPHRRP.js → chunk-NFECHLV6.js} +3 -3
- package/dist/{chunk-7LBPHRRP.js.map → chunk-NFECHLV6.js.map} +1 -1
- package/dist/{chunk-LX3FKVLL.js → chunk-NTASYPDN.js} +3 -3
- package/dist/{chunk-LX3FKVLL.js.map → chunk-NTASYPDN.js.map} +1 -1
- package/dist/{chunk-7IH3RKKK.js → chunk-OEBAXTQ4.js} +3 -3
- package/dist/{chunk-7IH3RKKK.js.map → chunk-OEBAXTQ4.js.map} +1 -1
- package/dist/{chunk-7LZJRVKJ.js → chunk-OKGUDNDT.js} +94 -16
- package/dist/chunk-OKGUDNDT.js.map +1 -0
- package/dist/{chunk-Z2QI42YH.js → chunk-OPBGV4DX.js} +30 -9
- package/dist/chunk-OPBGV4DX.js.map +1 -0
- package/dist/{chunk-T762W5CI.js → chunk-QABZZROM.js} +3 -3
- package/dist/{chunk-T762W5CI.js.map → chunk-QABZZROM.js.map} +1 -1
- package/dist/{chunk-LRCSWOZO.js → chunk-QKXDRBLL.js} +5 -3
- package/dist/chunk-QKXDRBLL.js.map +1 -0
- package/dist/{chunk-66A35U4V.js → chunk-R2SYODNK.js} +64 -8
- package/dist/chunk-R2SYODNK.js.map +1 -0
- package/dist/{chunk-TTITGVXV.js → chunk-RZXP5ZER.js} +3 -3
- package/dist/{chunk-TTITGVXV.js.map → chunk-RZXP5ZER.js.map} +1 -1
- package/dist/{chunk-DHLE66FV.js → chunk-S63H4HDH.js} +8 -4
- package/dist/chunk-S63H4HDH.js.map +1 -0
- package/dist/{chunk-J4ANCOQ4.js → chunk-SGMCSVTO.js} +7 -7
- package/dist/{chunk-J4ANCOQ4.js.map → chunk-SGMCSVTO.js.map} +1 -1
- package/dist/{chunk-IGNY4C6K.js → chunk-SOFPA4S4.js} +7 -7
- package/dist/{chunk-IGNY4C6K.js.map → chunk-SOFPA4S4.js.map} +1 -1
- package/dist/{chunk-2FBPAR2V.js → chunk-SQ7IN7KR.js} +3 -2
- package/dist/chunk-SQ7IN7KR.js.map +1 -0
- package/dist/{chunk-GORUF3YZ.js → chunk-U4CNCL7Q.js} +10 -10
- package/dist/{chunk-GORUF3YZ.js.map → chunk-U4CNCL7Q.js.map} +1 -1
- package/dist/{chunk-75LXFKQR.js → chunk-UFBURH6K.js} +4 -4
- package/dist/{chunk-75LXFKQR.js.map → chunk-UFBURH6K.js.map} +1 -1
- package/dist/{chunk-AO7TCPOS.js → chunk-USJWXEXS.js} +311 -32
- package/dist/chunk-USJWXEXS.js.map +1 -0
- package/dist/{chunk-GKTFGCQZ.js → chunk-UTZEHXYT.js} +3 -3
- package/dist/{chunk-GKTFGCQZ.js.map → chunk-UTZEHXYT.js.map} +1 -1
- package/dist/{chunk-JS7DCCDA.js → chunk-V2OQ3BI6.js} +4 -4
- package/dist/chunk-V2OQ3BI6.js.map +1 -0
- package/dist/{chunk-5YXKEM7Q.js → chunk-VCLN2IUM.js} +5 -5
- package/dist/{chunk-5YXKEM7Q.js.map → chunk-VCLN2IUM.js.map} +1 -1
- package/dist/{chunk-JRIU5GA7.js → chunk-VRFKCF3R.js} +4 -4
- package/dist/{chunk-JRIU5GA7.js.map → chunk-VRFKCF3R.js.map} +1 -1
- package/dist/{chunk-MTWZ7KHZ.js → chunk-WQULDAH2.js} +11 -2
- package/dist/chunk-WQULDAH2.js.map +1 -0
- package/dist/{chunk-IFUQ6XBQ.js → chunk-WTBXGJCD.js} +207 -19
- package/dist/chunk-WTBXGJCD.js.map +1 -0
- package/dist/{chunk-7ERHZQ7O.js → chunk-XN7DAZB7.js} +3 -3
- package/dist/{chunk-7ERHZQ7O.js.map → chunk-XN7DAZB7.js.map} +1 -1
- package/dist/{chunk-24X2GGSC.js → chunk-YU433JEL.js} +6 -6
- package/dist/{chunk-24X2GGSC.js.map → chunk-YU433JEL.js.map} +1 -1
- package/dist/cli/index.js +72 -64
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts +7 -0
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/connector.d.ts.map +1 -1
- package/dist/connectors/config.js +3 -3
- package/dist/connectors/index.js +15 -15
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/connectors/src/connector-types.d.ts +7 -0
- package/dist/connectors/src/connector-types.d.ts.map +1 -1
- package/dist/connectors/src/materialized-connectors.d.ts.map +1 -1
- package/dist/connectors-shared/index.js +2 -2
- package/dist/core/index.js +4 -4
- package/dist/core/manifest.js +1 -1
- package/dist/core/runtime-assets.js +3 -3
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +7 -0
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +2 -2
- package/dist/deploy/index.js +4 -4
- package/dist/discovery/index.js +3 -3
- package/dist/{ensure-sources-DVPPPCBS.js → ensure-sources-IGU65O72.js} +13 -13
- package/dist/{ensure-sources-DVPPPCBS.js.map → ensure-sources-IGU65O72.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +15 -15
- package/dist/factory-assets/connectors/deploy.js +15 -15
- package/dist/factory-assets/connectors/devserver.js +15 -15
- package/dist/factory-assets/connectors/flow/adapter.js +15 -15
- package/dist/factory-assets/connectors/flow/engine.js +5 -5
- package/dist/factory-assets/connectors/flow/run-flow.js +17 -17
- package/dist/factory-assets/connectors/flow.js +15 -15
- package/dist/factory-assets/connectors/git/CONNECTOR.md +1 -0
- package/dist/factory-assets/connectors/git/driver.d.ts +29 -0
- package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git.js +15 -15
- package/dist/factory-assets/connectors/gmail.js +15 -15
- package/dist/factory-assets/connectors/googledrive.js +15 -15
- package/dist/factory-assets/connectors/local.js +15 -15
- package/dist/factory-assets/connectors/mattermost.js +15 -15
- package/dist/factory-assets/connectors/memory.js +15 -15
- package/dist/factory-assets/connectors/minio.js +15 -15
- package/dist/factory-assets/connectors/postgres.js +15 -15
- package/dist/factory-assets/connectors/s3.js +15 -15
- package/dist/factory-assets/connectors/sharepoint.js +15 -15
- package/dist/factory-assets/connectors/sqlite.js +15 -15
- package/dist/factory-assets/connectors/static-server.js +15 -15
- package/dist/factory-assets/connectors/tunnel.js +15 -15
- package/dist/factory-assets/connectors/webdav.js +15 -15
- package/dist/factory-assets/connectors/xstate-store.js +15 -15
- package/dist/factory-assets/connectors/xstate.js +15 -15
- package/dist/{flows-X7JFAVRR.js → flows-6MDMBQUZ.js} +9 -9
- package/dist/{flows-X7JFAVRR.js.map → flows-6MDMBQUZ.js.map} +1 -1
- package/dist/{helpers-KLO5VUVZ.js → helpers-IELIL4YR.js} +13 -13
- package/dist/{helpers-KLO5VUVZ.js.map → helpers-IELIL4YR.js.map} +1 -1
- package/dist/library/index.js +7 -7
- package/dist/{library-publish-X6JGR7K3.js → library-publish-YKBYHZ43.js} +17 -17
- package/dist/{library-publish-X6JGR7K3.js.map → library-publish-YKBYHZ43.js.map} +1 -1
- package/dist/{open-library-S2ZFKJUK.js → open-library-ULRYWTEA.js} +15 -15
- package/dist/{open-library-S2ZFKJUK.js.map → open-library-ULRYWTEA.js.map} +1 -1
- package/dist/{paths-OI5IIS22.js → paths-4MTICP3T.js} +7 -7
- package/dist/{paths-OI5IIS22.js.map → paths-4MTICP3T.js.map} +1 -1
- package/dist/{plugin-store-C67RLSPD.js → plugin-store-GQ4WQZJ2.js} +6 -6
- package/dist/{plugin-store-C67RLSPD.js.map → plugin-store-GQ4WQZJ2.js.map} +1 -1
- package/dist/{project-7VOTYB7O.js → project-VKYNDEB6.js} +14 -14
- package/dist/{project-7VOTYB7O.js.map → project-VKYNDEB6.js.map} +1 -1
- package/dist/resolver/index.js +5 -5
- package/dist/runner/index.js +24 -24
- package/dist/runner/src/capability-registry.d.ts +13 -0
- package/dist/runner/src/capability-registry.d.ts.map +1 -1
- package/dist/runner/src/compaction/orchestrator.d.ts +8 -0
- package/dist/runner/src/compaction/orchestrator.d.ts.map +1 -1
- package/dist/runner/src/compaction-gate.d.ts +64 -1
- package/dist/runner/src/compaction-gate.d.ts.map +1 -1
- package/dist/runner/src/driver-swap-gate.d.ts +17 -0
- package/dist/runner/src/driver-swap-gate.d.ts.map +1 -1
- package/dist/runner/src/external-mcp.d.ts +6 -0
- package/dist/runner/src/external-mcp.d.ts.map +1 -1
- package/dist/runner/src/mcp-pinned-ca.d.ts +8 -0
- package/dist/runner/src/mcp-pinned-ca.d.ts.map +1 -0
- package/dist/runner/src/prompt-turn-queue.d.ts +51 -0
- package/dist/runner/src/prompt-turn-queue.d.ts.map +1 -0
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +10 -10
- package/dist/sdk/bridge.js +11 -11
- package/dist/sdk/core.js +4 -4
- package/dist/sdk/flow.js +5 -5
- package/dist/sdk/index.js +24 -24
- package/dist/sdk/resolver.js +5 -5
- package/dist/sdk/runner.js +24 -24
- package/dist/sdk/session.js +2 -2
- package/dist/sdk/store.js +1 -1
- package/dist/sdk/types.js +1 -1
- package/dist/session/index.js +2 -2
- package/dist/session/src/bounded-subscriber-transport.d.ts +11 -4
- package/dist/session/src/bounded-subscriber-transport.d.ts.map +1 -1
- package/dist/session/src/dispatcher.d.ts +5 -0
- package/dist/session/src/dispatcher.d.ts.map +1 -1
- package/dist/session/src/index.d.ts +1 -1
- package/dist/session/src/index.d.ts.map +1 -1
- package/dist/session/src/types.d.ts +20 -1
- package/dist/session/src/types.d.ts.map +1 -1
- package/dist/{setup-RO3PGJYS.js → setup-INJFK3VJ.js} +20 -20
- package/dist/{setup-RO3PGJYS.js.map → setup-INJFK3VJ.js.map} +1 -1
- package/dist/{skills-4YTVHMOH.js → skills-JHUY4DFE.js} +10 -10
- package/dist/{skills-4YTVHMOH.js.map → skills-JHUY4DFE.js.map} +1 -1
- package/dist/{source-ZZLLOP2U.js → source-IZXICUBU.js} +16 -16
- package/dist/{source-ZZLLOP2U.js.map → source-IZXICUBU.js.map} +1 -1
- package/dist/{source-manifest-publish-7WRQDIXO.js → source-manifest-publish-4JHOT4PA.js} +18 -18
- package/dist/{source-manifest-publish-7WRQDIXO.js.map → source-manifest-publish-4JHOT4PA.js.map} +1 -1
- package/dist/store/index.js +1 -1
- package/dist/store/src/store.d.ts +30 -1
- package/dist/store/src/store.d.ts.map +1 -1
- package/dist/store/src/types.d.ts +17 -0
- package/dist/store/src/types.d.ts.map +1 -1
- package/dist/tui/index.js +24 -24
- package/dist/types/index.js +1 -1
- package/dist/types/manifests.js +1 -1
- package/dist/types/src/events.d.ts +24 -1
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/manifests/mcp-server.d.ts +1 -0
- package/dist/types/src/manifests/mcp-server.d.ts.map +1 -1
- package/dist/types/src/protocol.d.ts +2 -0
- package/dist/types/src/protocol.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +12 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +11 -11
- package/dist/workspace-plugin/adapters/omp.js +7 -7
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-2FBPAR2V.js.map +0 -1
- package/dist/chunk-66A35U4V.js.map +0 -1
- package/dist/chunk-7LZJRVKJ.js.map +0 -1
- package/dist/chunk-AO7TCPOS.js.map +0 -1
- package/dist/chunk-DHLE66FV.js.map +0 -1
- package/dist/chunk-IFUQ6XBQ.js.map +0 -1
- package/dist/chunk-JS7DCCDA.js.map +0 -1
- package/dist/chunk-LRCSWOZO.js.map +0 -1
- package/dist/chunk-MTWZ7KHZ.js.map +0 -1
- package/dist/chunk-TGE33MKN.js.map +0 -1
- package/dist/chunk-Z2QI42YH.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../resolver/src/parser.ts","../resolver/src/preamble.ts","../resolver/src/validator.ts","../resolver/src/version.ts"],"names":["parseYaml"],"mappings":"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","file":"chunk-T3YUSWVK.js","sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport type { ConnectorRequirement, InputField, SkillRequirements } from \"./types.js\";\n\n/**\n * Extract YAML frontmatter from a SKILL.md string.\n *\n * Frontmatter is delimited by leading `---` fences. Returns the parsed object,\n * or an empty object `{}` if no frontmatter block is found or if the YAML is malformed.\n * Errors are silently swallowed — callers should treat an empty result as \"no requirements\".\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Parsed frontmatter object, or `{}` on absence or parse failure\n *\n * @docLink packages/resolver/api-reference#parseskill-frontmatter\n */\nexport function parseSkillFrontmatter(content: string): Record<string, any> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n try {\n return parseYaml(match[1]!) ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Parse skill requirements from raw SKILL.md content into a `SkillRequirements` object.\n *\n * Supports two frontmatter formats:\n * 1. **New format** — `metadata.prerequisites` with explicit\n * `files`, `inputs_required`, `inputs_optional`, `reads`, `produces`, and `resources` arrays.\n * 2. **Legacy format** — `metadata.user_inputs.dialog[]` array, automatically promoted to\n * `inputs_required` / `inputs_optional` based on each entry's `required` flag.\n *\n * Returns empty requirements `{ files: [], inputs_required: [], inputs_optional: [], reads: [], produces: [], resources: [] }`\n * when no recognisable prerequisites section is found.\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Structured `SkillRequirements` (never throws)\n *\n * @docLink packages/resolver/api-reference#parseskill-requirements\n */\nexport function parseSkillRequirements(content: string): SkillRequirements {\n const fm = parseSkillFrontmatter(content);\n const meta = fm.metadata ?? {};\n const prerequisites = meta.prerequisites ?? {};\n\n const empty: SkillRequirements = {\n files: [],\n inputs_required: [],\n inputs_optional: [],\n reads: [],\n produces: [],\n resources: [],\n connectors: [],\n };\n\n // New format: metadata.prerequisites\n if (\n prerequisites.files ||\n prerequisites.inputs_required ||\n prerequisites.inputs_optional ||\n prerequisites.reads ||\n prerequisites.produces ||\n prerequisites.resources ||\n prerequisites.connectors\n ) {\n return {\n files: (prerequisites.files ?? []).map((f: any) => ({\n path: f.path,\n gate: f.gate ?? \"hard\",\n description: f.description ?? \"\",\n ...(f.min_entries != null ? { min_entries: f.min_entries } : {}),\n })),\n inputs_required: (prerequisites.inputs_required ?? []).map(normalizeInputField(true)),\n inputs_optional: (prerequisites.inputs_optional ?? []).map(normalizeInputField(false)),\n reads: (prerequisites.reads ?? []).map((r: any) => ({\n path: r.path,\n description: r.description ?? \"\",\n })),\n produces: (prerequisites.produces ?? []).map((p: any) => ({\n path: p.path,\n description: p.description ?? \"\",\n })),\n resources: (prerequisites.resources ?? []).map((r: any) => ({\n id: r.id,\n ...(r.operations ? { operations: r.operations } : {}),\n optional: r.optional ?? false,\n ...(r.description ? { description: r.description } : {}),\n })),\n connectors: parseConnectorRequirements(prerequisites.connectors),\n };\n }\n\n // Legacy format: metadata.user_inputs.dialog[]\n const dialog = meta.user_inputs?.dialog;\n if (Array.isArray(dialog)) {\n const required: InputField[] = [];\n const optional: InputField[] = [];\n for (const d of dialog) {\n const field = normalizeInputField(d.required ?? false)(d);\n if (d.required) required.push(field);\n else optional.push(field);\n }\n return { ...empty, inputs_required: required, inputs_optional: optional, resources: [] };\n }\n\n return empty;\n}\n\n/**\n * Extract compaction directives from a SKILL.md markdown body.\n *\n * Scans the markdown body (not frontmatter) for a `## Compaction Directives` section\n * and returns each bullet point as a trimmed string. Compaction directives are hints\n * the agent uses to summarise context when the conversation history grows long.\n * Returns an empty array when the section is absent.\n *\n * @param content - Raw SKILL.md file content (full string including frontmatter and body)\n * @returns Array of directive strings extracted from the bullet list, or `[]` if none found\n *\n * @docLink packages/resolver/api-reference#parse-compaction-directives\n */\nexport function parseCompactionDirectives(content: string): string[] {\n const headerIdx = content.search(/^## Compaction Directives/m);\n if (headerIdx === -1) return [];\n\n // Header on the last line (no trailing newline) → no body to scan.\n const newlineIdx = content.indexOf(\"\\n\", headerIdx);\n if (newlineIdx === -1) return [];\n const bodyStart = newlineIdx + 1;\n const rest = content.slice(bodyStart);\n const nextSection = rest.search(/^##\\s/m);\n const sectionBody = nextSection === -1 ? rest : rest.slice(0, nextSection);\n\n const bullets: string[] = [];\n for (const line of sectionBody.split(\"\\n\")) {\n const match = line.match(/^\\s*[-*]\\s+(.+)/);\n if (match) bullets.push(match[1].trim());\n }\n return bullets;\n}\n\nfunction normalizeInputField(defaultRequired: boolean) {\n return (d: any): InputField => ({\n // UserInputSchema permits `key` or `id`; `prompt` is the legacy label alias.\n id: d.id ?? d.key,\n label: d.label ?? d.prompt ?? d.id ?? d.key,\n type: d.type ?? \"text\",\n required: d.required ?? defaultRequired,\n ...(d.options ? { options: d.options } : {}),\n ...(d.default != null ? { default: d.default } : {}),\n ...(d.hint ? { hint: d.hint } : {}),\n ...(d.schema ? { schema: d.schema } : {}),\n });\n}\n\nfunction parseConnectorRequirements(raw: unknown): ConnectorRequirement[] {\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((c): c is Record<string, unknown> => typeof c === \"object\" && c !== null)\n .map((c) => ({\n driver: String(c.driver ?? \"\"),\n ...(c.access === \"read-write\"\n ? { access: \"read-write\" as const }\n : { access: \"read-only\" as const }),\n }))\n .filter((c) => c.driver.length > 0);\n}\n","import type { SkillRequirements } from \"./types.js\";\n\n/**\n * Generate a DSL-format preamble from skill requirements.\n *\n * The preamble is prepended to the skill prompt when the skill runs standalone\n * (without an orchestrator), giving the agent an explicit checklist of what to\n * verify before starting work. Each section maps to a requirement category:\n *\n * - `REQUIRES` — file/directory gates (`hard:` or `soft:` prefix)\n * - `INPUT` — user input fields, with a pointer to `input.json` if `skillId` is provided\n * - `READS` — informational read sources (not gated)\n * - `WRITES` — files the skill will produce\n * - `RESOURCE` — runtime resource dependencies\n *\n * Sections with no entries are omitted. Returns an empty string when all\n * requirement arrays are empty.\n *\n * @param requirements - Parsed requirements (output of `parseSkillRequirements`)\n * @param skillId - Optional skill identifier; when provided, the INPUT section includes\n * the canonical `input.json` path so the agent knows where to read collected values\n * @returns Multi-section DSL string, or `\"\"` if there are no requirements to list\n *\n * @example\n * ```ts\n * const preamble = buildRequiresPreamble(requirements, \"cf_overview\");\n * const fullPrompt = preamble ? `${preamble}\\n\\n${skillBody}` : skillBody;\n * ```\n *\n * @docLink packages/resolver/api-reference#build-requires-preamble\n */\nexport function buildRequiresPreamble(requirements: SkillRequirements, skillId?: string): string {\n const sections: string[] = [];\n\n pushSection(sections, buildRequiresSection(requirements));\n pushSection(sections, buildInputSection(requirements, skillId));\n pushSection(sections, buildReadsSection(requirements));\n pushSection(sections, buildWritesSection(requirements));\n pushSection(sections, buildResourceSection(requirements));\n\n return sections.join(\"\\n\\n\");\n}\n\n/** Append a section to the list when it produced output. */\nfunction pushSection(sections: string[], section: string | null): void {\n if (section !== null) sections.push(section);\n}\n\n/** REQUIRES section (file gates). Returns `null` when there are no file gates. */\nfunction buildRequiresSection(requirements: SkillRequirements): string | null {\n if (requirements.files.length === 0) return null;\n const lines = [\"REQUIRES\"];\n for (const f of requirements.files) {\n const prefix = f.gate === \"hard\" ? \"hard\" : \"soft\";\n lines.push(` ${prefix}: ${f.path} — ${f.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** INPUT section (user inputs). Returns `null` when there are no inputs. */\nfunction buildInputSection(requirements: SkillRequirements, skillId?: string): string | null {\n const allInputs = [...requirements.inputs_required, ...requirements.inputs_optional];\n if (allInputs.length === 0) return null;\n const lines = [\"INPUT\"];\n if (skillId) {\n lines.push(` Read from: _concept/_grounding/${skillId}/input.json`);\n lines.push(\n ` If input.json is missing, ask the user for the following values and write the file:`,\n );\n }\n for (const input of allInputs) {\n const req = input.required ? \"(required)\" : \"(optional)\";\n const opts = input.options ? ` [${input.options.join(\" | \")}]` : \"\";\n const def = input.default != null ? ` default: ${input.default}` : \"\";\n lines.push(` - ${input.id}: ${input.label} ${req}${opts}${def}`);\n if (input.hint) lines.push(` hint: ${input.hint}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** READS section. Returns `null` when there are no read sources. */\nfunction buildReadsSection(requirements: SkillRequirements): string | null {\n if (requirements.reads.length === 0) return null;\n const lines = [\"READS\"];\n for (const r of requirements.reads) {\n lines.push(` ? ${r.path} — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** WRITES section (produces). Returns `null` when there is nothing produced. */\nfunction buildWritesSection(requirements: SkillRequirements): string | null {\n if (requirements.produces.length === 0) return null;\n const lines = [\"WRITES\"];\n for (const p of requirements.produces) {\n lines.push(` ${p.path} — ${p.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** RESOURCE section. Returns `null` when there are no resources. */\nfunction buildResourceSection(requirements: SkillRequirements): string | null {\n if (!requirements.resources || requirements.resources.length === 0) return null;\n const lines = [\"RESOURCE\"];\n for (const r of requirements.resources) {\n const req = r.optional ? \"(optional)\" : \"(required)\";\n const ops = r.operations ? ` ops: [${r.operations.join(\", \")}]` : \"\";\n lines.push(` ${r.id} ${req}${ops}`);\n if (r.description) lines.push(` — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n tryWithFsDeadline,\n walkDir,\n type WalkTruncation,\n withFsDeadline,\n} from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type {\n ConnectorRequirement,\n FileCheck,\n InputCheck,\n NodeOverrides,\n ReadCheck,\n RequirementsReport,\n ResourceCheck,\n SkillInputFile,\n SkillRequirements,\n} from \"./types.js\";\n\nlet validatorLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n validatorLogger ??= createLogger({ kind: \"runner\", subkind: \"skill-requirements\" });\n return validatorLogger;\n}\n\n/** Best-effort existence probe. A missing path, an unreadable one, and an\n * unresponsive mount are all \"not usable here\" for a requirement check. */\nasync function pathExists(target: string): Promise<boolean> {\n return tryWithFsDeadline(\n `stat ${target}`,\n async () => {\n await stat(target);\n return true;\n },\n false,\n );\n}\n\n/**\n * Validate skill requirements against the filesystem and collected inputs.\n *\n * File checks resolve paths relative to `projectDir`. Hard-gate files that are absent\n * set `satisfied: false` on the returned report; soft-gate misses are recorded but do not block.\n * Input checks read `_concept/_grounding/{skillId}/input.json`; missing files are treated as\n * no inputs collected. Resource checks are always recorded as `available: true` — actual\n * availability must be confirmed by the runner's `ResourceManager`.\n *\n * **Async and bounded since #454.** `projectDir` reaches this function straight\n * from the agent — `workspace_check_skill_requirements` takes `target_dir` as a\n * tool argument — so it can be `/skaile/workspace`, the rclone FUSE mount. Every\n * probe is now awaited and deadline-bounded, and the `min_entries` count walks\n * through the bounded {@link walkDir}, so a wedged mount or a symlink cycle\n * costs one failed tool call instead of the whole `skaile serve` event loop.\n *\n * @param skillId - Canonical skill identifier, used to locate `input.json`\n * @param requirements - Parsed requirements from SKILL.md (`parseSkillRequirements` output)\n * @param projectDir - Absolute path to the project root directory\n * @param overrides - Optional flow-level overrides; paths in `skip_checks` are treated as present\n * @param producesIndex - Maps file paths to the skill ID that produces them, enabling \"produced by\" hints in the report\n * @returns `RequirementsReport` with per-check results and an overall `satisfied` flag\n *\n * @docLink packages/resolver/api-reference#validate-requirements\n */\nexport async function validateRequirements(\n skillId: string,\n requirements: SkillRequirements,\n projectDir: string,\n overrides?: NodeOverrides,\n producesIndex?: Map<string, string>,\n): Promise<RequirementsReport> {\n const skipSet = new Set(overrides?.skip_checks ?? []);\n\n // Check files. Serial on purpose: `projectDir` may be one network mount, and\n // fanning every probe out concurrently multiplies the queue depth on exactly\n // the resource that is already the bottleneck.\n const files: FileCheck[] = [];\n for (const req of requirements.files) {\n if (skipSet.has(req.path)) {\n files.push({ path: req.path, gate: req.gate, exists: true, description: req.description });\n continue;\n }\n\n const fullPath = path.join(projectDir, req.path);\n const check: FileCheck = {\n path: req.path,\n gate: req.gate,\n exists: false,\n description: req.description,\n producedBy: producesIndex?.get(req.path),\n };\n\n if (req.min_entries != null) {\n const counted = await checkDirectoryMinEntries(fullPath, req.min_entries);\n check.exists = counted.satisfied;\n if (counted.truncated) check.truncated = true;\n } else {\n check.exists = await pathExists(fullPath);\n }\n\n files.push(check);\n }\n\n // Check inputs — look for _concept/_grounding/{skillId}/input.json\n const inputFile = path.join(projectDir, \"_concept\", \"_grounding\", skillId, \"input.json\");\n let collectedValues: Record<string, any> = {};\n try {\n const raw = await withFsDeadline(`readFile ${inputFile}`, () => readFile(inputFile, \"utf-8\"));\n const parsed = JSON.parse(raw) as SkillInputFile;\n collectedValues = parsed.values ?? {};\n } catch {\n // No input file — all inputs are missing\n }\n\n const allInputs = [\n ...requirements.inputs_required.map((f) => ({ field: f, required: true })),\n ...requirements.inputs_optional.map((f) => ({ field: f, required: false })),\n ];\n\n const inputs: InputCheck[] = allInputs.map(({ field, required }) => ({\n id: field.id,\n required,\n present: field.id in collectedValues,\n field,\n }));\n\n // Check reads (informational only)\n const reads: ReadCheck[] = [];\n for (const r of requirements.reads) {\n reads.push({\n path: r.path,\n exists: await pathExists(path.join(projectDir, r.path)),\n description: r.description,\n });\n }\n\n // Check resources (validated at a higher level if a ResourceManager is available;\n // here we just record them in the report with unknown status)\n const resources: ResourceCheck[] = (requirements.resources ?? []).map((r) => ({\n id: r.id,\n available: true, // Actual availability checked by runner with ResourceManager\n missingOps: [],\n optional: r.optional ?? false,\n }));\n\n // Satisfaction: all hard file gates pass AND all required inputs present\n const hardFilesSatisfied = files.filter((f) => f.gate === \"hard\").every((f) => f.exists);\n\n const requiredInputsSatisfied = inputs.filter((i) => i.required).every((i) => i.present);\n\n const requiredResourcesSatisfied = resources.filter((r) => !r.optional).every((r) => r.available);\n\n return {\n skillId,\n satisfied: hardFilesSatisfied && requiredInputsSatisfied && requiredResourcesSatisfied,\n files,\n inputs,\n reads,\n resources,\n };\n}\n\n/**\n * A warning produced by `validateConnectorRequirements` when a skill's declared\n * connector requirement is not satisfied by the connectors in skaile.yaml.\n * Each warning covers either a missing driver or an insufficient access level.\n *\n * @docLink packages/resolver/api-reference#connector-validation-warning\n */\nexport interface ConnectorValidationWarning {\n /** Driver name that triggered the warning. */\n driver: string;\n /** Human-readable explanation of the gap, including a remediation command where applicable. */\n message: string;\n}\n\n/** Minimal structural type accepted by validateConnectorRequirements. Compatible with both\n * ConnectorDeclaration shapes in @skaile/workspaces/core and @skaile/workspaces/connectors. */\ninterface AvailableConnector {\n driver: string;\n access?: \"read-only\" | \"read-write\";\n}\n\n/**\n * Check that all connector requirements declared in a skill's SKILL.md are\n * satisfied by the connectors declared in skaile.yaml.\n *\n * Returns one warning per gap — either a missing driver or an insufficient\n * access level. This is a pre-flight advisory; no runtime enforcement is done.\n *\n * @param requirements - Connector requirements from `parseSkillRequirements().connectors`\n * @param available - Connector declarations from `skaile.yaml` (via `loadConnectorDeclarations`)\n * @returns Array of warnings — one per gap. Empty array when all requirements are satisfied.\n *\n * @docLink packages/resolver/api-reference#validate-connector-requirements\n */\nexport function validateConnectorRequirements(\n requirements: ConnectorRequirement[],\n available: AvailableConnector[],\n): ConnectorValidationWarning[] {\n const warnings: ConnectorValidationWarning[] = [];\n\n for (const req of requirements) {\n const matches = available.filter((a) => a.driver === req.driver);\n\n if (matches.length === 0) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires connector driver \"${req.driver}\" but none is declared in skaile.yaml. ` +\n `Run: skaile connector add ${req.driver}`,\n });\n continue;\n }\n\n if (req.access === \"read-write\") {\n const hasReadWrite = matches.some((m) => (m.access ?? \"read-only\") === \"read-write\");\n if (!hasReadWrite) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires \"${req.driver}\" with read-write access, but all declared instances ` +\n `are read-only. Update access in skaile.yaml.`,\n });\n }\n }\n }\n\n return warnings;\n}\n\n/**\n * Does `dirPath` hold at least `minEntries` files, counted recursively?\n *\n * `truncated` is set when a walk bound was hit *and* the count still fell\n * short: the number is then a floor, not the truth, so `satisfied: false` is\n * \"we could not prove it\" rather than \"there are not enough files\". Reaching\n * `minEntries` short-circuits the walk, so the common case never pays for the\n * whole tree and a bound hit after that point is irrelevant.\n */\nasync function checkDirectoryMinEntries(\n dirPath: string,\n minEntries: number,\n): Promise<{ satisfied: boolean; truncated: boolean }> {\n const st = await tryWithFsDeadline(`stat ${dirPath}`, () => stat(dirPath), null);\n if (!st?.isDirectory()) return { satisfied: false, truncated: false };\n\n const { count, truncation } = await countFilesRecursive(dirPath, minEntries);\n const satisfied = count >= minEntries;\n if (!satisfied && truncation) {\n log().warn(\"min_entries count truncated — result is a lower bound, not the file count\", {\n dirPath,\n minEntries,\n count,\n ...truncation,\n });\n }\n return { satisfied, truncated: !satisfied && truncation !== undefined };\n}\n\n/**\n * Count files under `dirPath`, stopping at `limit`.\n *\n * Delegates to core's {@link walkDir} rather than recursing here: `dirPath` is\n * agent-supplied and can be a network mount, so the walk needs the deadline per\n * `opendir`, the depth / entry / wall-clock bounds, and the visited-inode cycle\n * guard that walker already owns. The pre-#454 `readdirSync` recursion had none\n * of them and recursed forever on `a/link -> a`.\n *\n * Inheriting `walkDir` also inherits its skip list: `.git` and `node_modules`\n * no longer count toward `min_entries`, which is what a prerequisite like\n * \"at least 3 feature files\" meant in the first place.\n */\nasync function countFilesRecursive(\n dirPath: string,\n limit: number,\n): Promise<{ count: number; truncation?: WalkTruncation }> {\n let count = 0;\n let truncation: WalkTruncation | undefined;\n for await (const _entry of walkDir(dirPath, {\n onTruncate: (info) => {\n truncation ??= info;\n },\n })) {\n count++;\n // Enough is enough — no reason to keep walking a large tree (or a wedged\n // mount) once the requirement is already met.\n if (count >= limit) return { count };\n }\n return { count, truncation };\n}\n","import { satisfies, valid, validRange } from \"semver\";\n\n/**\n * Result of a single flow-node version pin check.\n * Returned in the array produced by `validateFlowVersions()` for every\n * node that declares a `requestedVersion`.\n *\n * @docLink packages/resolver/api-reference#version-check\n */\nexport interface VersionCheck {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier. */\n skillId: string;\n /** Semver range from the flow node (e.g. \"^1.0.0\") */\n requested: string;\n /** Version from the skill's frontmatter */\n actual: string;\n /** Whether `actual` satisfies the `requested` semver range. */\n satisfied: boolean;\n}\n\n/**\n * Minimal descriptor for a flow node that optionally pins a skill version.\n * Passed as input to `validateFlowVersions()`. Nodes without `requestedVersion`\n * are skipped during version checking.\n *\n * @docLink packages/resolver/api-reference#flow-version-node\n */\nexport interface FlowVersionNode {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier referenced by this node. */\n skillId: string;\n /** Optional semver range the node requires (e.g. `\"^1.2.0\"`). Omit to skip version checking. */\n requestedVersion?: string;\n}\n\n/**\n * Validate flow node version pins against discovered skill versions.\n *\n * Only checks nodes that declare a `requestedVersion`. Nodes without a\n * version pin are skipped entirely (no entry is produced for those nodes).\n * A check is marked `satisfied: false` when the range is invalid, the actual\n * version string is not valid semver, or the version does not satisfy the range.\n *\n * @param nodes - Flow nodes to check; only those with `requestedVersion` are evaluated\n * @param skillVersions - Map from skill ID to the semver version string in its frontmatter\n * @returns Array of `VersionCheck` results, one per node that declared a version pin\n *\n * @docLink packages/resolver/api-reference#validate-flow-versions\n */\nexport function validateFlowVersions(\n nodes: FlowVersionNode[],\n skillVersions: Map<string, string>,\n): VersionCheck[] {\n const checks: VersionCheck[] = [];\n\n for (const node of nodes) {\n if (!node.requestedVersion) continue;\n\n const actual = skillVersions.get(node.skillId) ?? \"\";\n const requested = node.requestedVersion;\n\n // Invalid range or missing/invalid actual version → not satisfied\n const rangeValid = validRange(requested) !== null;\n const actualValid = actual !== \"\" && valid(actual) !== null;\n const isSatisfied = rangeValid && actualValid && satisfies(actual, requested);\n\n checks.push({\n nodeId: node.nodeId,\n skillId: node.skillId,\n requested,\n actual,\n satisfied: isSatisfied,\n });\n }\n\n return checks;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../resolver/src/parser.ts","../resolver/src/preamble.ts","../resolver/src/validator.ts","../resolver/src/version.ts"],"names":["parseYaml"],"mappings":"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","file":"chunk-3SUWLY3H.js","sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport type { ConnectorRequirement, InputField, SkillRequirements } from \"./types.js\";\n\n/**\n * Extract YAML frontmatter from a SKILL.md string.\n *\n * Frontmatter is delimited by leading `---` fences. Returns the parsed object,\n * or an empty object `{}` if no frontmatter block is found or if the YAML is malformed.\n * Errors are silently swallowed — callers should treat an empty result as \"no requirements\".\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Parsed frontmatter object, or `{}` on absence or parse failure\n *\n * @docLink packages/resolver/api-reference#parseskill-frontmatter\n */\nexport function parseSkillFrontmatter(content: string): Record<string, any> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n try {\n return parseYaml(match[1]!) ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Parse skill requirements from raw SKILL.md content into a `SkillRequirements` object.\n *\n * Supports two frontmatter formats:\n * 1. **New format** — `metadata.prerequisites` with explicit\n * `files`, `inputs_required`, `inputs_optional`, `reads`, `produces`, and `resources` arrays.\n * 2. **Legacy format** — `metadata.user_inputs.dialog[]` array, automatically promoted to\n * `inputs_required` / `inputs_optional` based on each entry's `required` flag.\n *\n * Returns empty requirements `{ files: [], inputs_required: [], inputs_optional: [], reads: [], produces: [], resources: [] }`\n * when no recognisable prerequisites section is found.\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Structured `SkillRequirements` (never throws)\n *\n * @docLink packages/resolver/api-reference#parseskill-requirements\n */\nexport function parseSkillRequirements(content: string): SkillRequirements {\n const fm = parseSkillFrontmatter(content);\n const meta = fm.metadata ?? {};\n const prerequisites = meta.prerequisites ?? {};\n\n const empty: SkillRequirements = {\n files: [],\n inputs_required: [],\n inputs_optional: [],\n reads: [],\n produces: [],\n resources: [],\n connectors: [],\n };\n\n // New format: metadata.prerequisites\n if (\n prerequisites.files ||\n prerequisites.inputs_required ||\n prerequisites.inputs_optional ||\n prerequisites.reads ||\n prerequisites.produces ||\n prerequisites.resources ||\n prerequisites.connectors\n ) {\n return {\n files: (prerequisites.files ?? []).map((f: any) => ({\n path: f.path,\n gate: f.gate ?? \"hard\",\n description: f.description ?? \"\",\n ...(f.min_entries != null ? { min_entries: f.min_entries } : {}),\n })),\n inputs_required: (prerequisites.inputs_required ?? []).map(normalizeInputField(true)),\n inputs_optional: (prerequisites.inputs_optional ?? []).map(normalizeInputField(false)),\n reads: (prerequisites.reads ?? []).map((r: any) => ({\n path: r.path,\n description: r.description ?? \"\",\n })),\n produces: (prerequisites.produces ?? []).map((p: any) => ({\n path: p.path,\n description: p.description ?? \"\",\n })),\n resources: (prerequisites.resources ?? []).map((r: any) => ({\n id: r.id,\n ...(r.operations ? { operations: r.operations } : {}),\n optional: r.optional ?? false,\n ...(r.description ? { description: r.description } : {}),\n })),\n connectors: parseConnectorRequirements(prerequisites.connectors),\n };\n }\n\n // Legacy format: metadata.user_inputs.dialog[]\n const dialog = meta.user_inputs?.dialog;\n if (Array.isArray(dialog)) {\n const required: InputField[] = [];\n const optional: InputField[] = [];\n for (const d of dialog) {\n const field = normalizeInputField(d.required ?? false)(d);\n if (d.required) required.push(field);\n else optional.push(field);\n }\n return { ...empty, inputs_required: required, inputs_optional: optional, resources: [] };\n }\n\n return empty;\n}\n\n/**\n * Extract compaction directives from a SKILL.md markdown body.\n *\n * Scans the markdown body (not frontmatter) for a `## Compaction Directives` section\n * and returns each bullet point as a trimmed string. Compaction directives are hints\n * the agent uses to summarise context when the conversation history grows long.\n * Returns an empty array when the section is absent.\n *\n * @param content - Raw SKILL.md file content (full string including frontmatter and body)\n * @returns Array of directive strings extracted from the bullet list, or `[]` if none found\n *\n * @docLink packages/resolver/api-reference#parse-compaction-directives\n */\nexport function parseCompactionDirectives(content: string): string[] {\n const headerIdx = content.search(/^## Compaction Directives/m);\n if (headerIdx === -1) return [];\n\n // Header on the last line (no trailing newline) → no body to scan.\n const newlineIdx = content.indexOf(\"\\n\", headerIdx);\n if (newlineIdx === -1) return [];\n const bodyStart = newlineIdx + 1;\n const rest = content.slice(bodyStart);\n const nextSection = rest.search(/^##\\s/m);\n const sectionBody = nextSection === -1 ? rest : rest.slice(0, nextSection);\n\n const bullets: string[] = [];\n for (const line of sectionBody.split(\"\\n\")) {\n const match = line.match(/^\\s*[-*]\\s+(.+)/);\n if (match) bullets.push(match[1].trim());\n }\n return bullets;\n}\n\nfunction normalizeInputField(defaultRequired: boolean) {\n return (d: any): InputField => ({\n // UserInputSchema permits `key` or `id`; `prompt` is the legacy label alias.\n id: d.id ?? d.key,\n label: d.label ?? d.prompt ?? d.id ?? d.key,\n type: d.type ?? \"text\",\n required: d.required ?? defaultRequired,\n ...(d.options ? { options: d.options } : {}),\n ...(d.default != null ? { default: d.default } : {}),\n ...(d.hint ? { hint: d.hint } : {}),\n ...(d.schema ? { schema: d.schema } : {}),\n });\n}\n\nfunction parseConnectorRequirements(raw: unknown): ConnectorRequirement[] {\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((c): c is Record<string, unknown> => typeof c === \"object\" && c !== null)\n .map((c) => ({\n driver: String(c.driver ?? \"\"),\n ...(c.access === \"read-write\"\n ? { access: \"read-write\" as const }\n : { access: \"read-only\" as const }),\n }))\n .filter((c) => c.driver.length > 0);\n}\n","import type { SkillRequirements } from \"./types.js\";\n\n/**\n * Generate a DSL-format preamble from skill requirements.\n *\n * The preamble is prepended to the skill prompt when the skill runs standalone\n * (without an orchestrator), giving the agent an explicit checklist of what to\n * verify before starting work. Each section maps to a requirement category:\n *\n * - `REQUIRES` — file/directory gates (`hard:` or `soft:` prefix)\n * - `INPUT` — user input fields, with a pointer to `input.json` if `skillId` is provided\n * - `READS` — informational read sources (not gated)\n * - `WRITES` — files the skill will produce\n * - `RESOURCE` — runtime resource dependencies\n *\n * Sections with no entries are omitted. Returns an empty string when all\n * requirement arrays are empty.\n *\n * @param requirements - Parsed requirements (output of `parseSkillRequirements`)\n * @param skillId - Optional skill identifier; when provided, the INPUT section includes\n * the canonical `input.json` path so the agent knows where to read collected values\n * @returns Multi-section DSL string, or `\"\"` if there are no requirements to list\n *\n * @example\n * ```ts\n * const preamble = buildRequiresPreamble(requirements, \"cf_overview\");\n * const fullPrompt = preamble ? `${preamble}\\n\\n${skillBody}` : skillBody;\n * ```\n *\n * @docLink packages/resolver/api-reference#build-requires-preamble\n */\nexport function buildRequiresPreamble(requirements: SkillRequirements, skillId?: string): string {\n const sections: string[] = [];\n\n pushSection(sections, buildRequiresSection(requirements));\n pushSection(sections, buildInputSection(requirements, skillId));\n pushSection(sections, buildReadsSection(requirements));\n pushSection(sections, buildWritesSection(requirements));\n pushSection(sections, buildResourceSection(requirements));\n\n return sections.join(\"\\n\\n\");\n}\n\n/** Append a section to the list when it produced output. */\nfunction pushSection(sections: string[], section: string | null): void {\n if (section !== null) sections.push(section);\n}\n\n/** REQUIRES section (file gates). Returns `null` when there are no file gates. */\nfunction buildRequiresSection(requirements: SkillRequirements): string | null {\n if (requirements.files.length === 0) return null;\n const lines = [\"REQUIRES\"];\n for (const f of requirements.files) {\n const prefix = f.gate === \"hard\" ? \"hard\" : \"soft\";\n lines.push(` ${prefix}: ${f.path} — ${f.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** INPUT section (user inputs). Returns `null` when there are no inputs. */\nfunction buildInputSection(requirements: SkillRequirements, skillId?: string): string | null {\n const allInputs = [...requirements.inputs_required, ...requirements.inputs_optional];\n if (allInputs.length === 0) return null;\n const lines = [\"INPUT\"];\n if (skillId) {\n lines.push(` Read from: _concept/_grounding/${skillId}/input.json`);\n lines.push(\n ` If input.json is missing, ask the user for the following values and write the file:`,\n );\n }\n for (const input of allInputs) {\n const req = input.required ? \"(required)\" : \"(optional)\";\n const opts = input.options ? ` [${input.options.join(\" | \")}]` : \"\";\n const def = input.default != null ? ` default: ${input.default}` : \"\";\n lines.push(` - ${input.id}: ${input.label} ${req}${opts}${def}`);\n if (input.hint) lines.push(` hint: ${input.hint}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** READS section. Returns `null` when there are no read sources. */\nfunction buildReadsSection(requirements: SkillRequirements): string | null {\n if (requirements.reads.length === 0) return null;\n const lines = [\"READS\"];\n for (const r of requirements.reads) {\n lines.push(` ? ${r.path} — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** WRITES section (produces). Returns `null` when there is nothing produced. */\nfunction buildWritesSection(requirements: SkillRequirements): string | null {\n if (requirements.produces.length === 0) return null;\n const lines = [\"WRITES\"];\n for (const p of requirements.produces) {\n lines.push(` ${p.path} — ${p.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** RESOURCE section. Returns `null` when there are no resources. */\nfunction buildResourceSection(requirements: SkillRequirements): string | null {\n if (!requirements.resources || requirements.resources.length === 0) return null;\n const lines = [\"RESOURCE\"];\n for (const r of requirements.resources) {\n const req = r.optional ? \"(optional)\" : \"(required)\";\n const ops = r.operations ? ` ops: [${r.operations.join(\", \")}]` : \"\";\n lines.push(` ${r.id} ${req}${ops}`);\n if (r.description) lines.push(` — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n tryWithFsDeadline,\n walkDir,\n type WalkTruncation,\n withFsDeadline,\n} from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type {\n ConnectorRequirement,\n FileCheck,\n InputCheck,\n NodeOverrides,\n ReadCheck,\n RequirementsReport,\n ResourceCheck,\n SkillInputFile,\n SkillRequirements,\n} from \"./types.js\";\n\nlet validatorLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n validatorLogger ??= createLogger({ kind: \"runner\", subkind: \"skill-requirements\" });\n return validatorLogger;\n}\n\n/** Best-effort existence probe. A missing path, an unreadable one, and an\n * unresponsive mount are all \"not usable here\" for a requirement check. */\nasync function pathExists(target: string): Promise<boolean> {\n return tryWithFsDeadline(\n `stat ${target}`,\n async () => {\n await stat(target);\n return true;\n },\n false,\n );\n}\n\n/**\n * Validate skill requirements against the filesystem and collected inputs.\n *\n * File checks resolve paths relative to `projectDir`. Hard-gate files that are absent\n * set `satisfied: false` on the returned report; soft-gate misses are recorded but do not block.\n * Input checks read `_concept/_grounding/{skillId}/input.json`; missing files are treated as\n * no inputs collected. Resource checks are always recorded as `available: true` — actual\n * availability must be confirmed by the runner's `ResourceManager`.\n *\n * **Async and bounded since #454.** `projectDir` reaches this function straight\n * from the agent — `workspace_check_skill_requirements` takes `target_dir` as a\n * tool argument — so it can be `/skaile/workspace`, the rclone FUSE mount. Every\n * probe is now awaited and deadline-bounded, and the `min_entries` count walks\n * through the bounded {@link walkDir}, so a wedged mount or a symlink cycle\n * costs one failed tool call instead of the whole `skaile serve` event loop.\n *\n * @param skillId - Canonical skill identifier, used to locate `input.json`\n * @param requirements - Parsed requirements from SKILL.md (`parseSkillRequirements` output)\n * @param projectDir - Absolute path to the project root directory\n * @param overrides - Optional flow-level overrides; paths in `skip_checks` are treated as present\n * @param producesIndex - Maps file paths to the skill ID that produces them, enabling \"produced by\" hints in the report\n * @returns `RequirementsReport` with per-check results and an overall `satisfied` flag\n *\n * @docLink packages/resolver/api-reference#validate-requirements\n */\nexport async function validateRequirements(\n skillId: string,\n requirements: SkillRequirements,\n projectDir: string,\n overrides?: NodeOverrides,\n producesIndex?: Map<string, string>,\n): Promise<RequirementsReport> {\n const skipSet = new Set(overrides?.skip_checks ?? []);\n\n // Check files. Serial on purpose: `projectDir` may be one network mount, and\n // fanning every probe out concurrently multiplies the queue depth on exactly\n // the resource that is already the bottleneck.\n const files: FileCheck[] = [];\n for (const req of requirements.files) {\n if (skipSet.has(req.path)) {\n files.push({ path: req.path, gate: req.gate, exists: true, description: req.description });\n continue;\n }\n\n const fullPath = path.join(projectDir, req.path);\n const check: FileCheck = {\n path: req.path,\n gate: req.gate,\n exists: false,\n description: req.description,\n producedBy: producesIndex?.get(req.path),\n };\n\n if (req.min_entries != null) {\n const counted = await checkDirectoryMinEntries(fullPath, req.min_entries);\n check.exists = counted.satisfied;\n if (counted.truncated) check.truncated = true;\n } else {\n check.exists = await pathExists(fullPath);\n }\n\n files.push(check);\n }\n\n // Check inputs — look for _concept/_grounding/{skillId}/input.json\n const inputFile = path.join(projectDir, \"_concept\", \"_grounding\", skillId, \"input.json\");\n let collectedValues: Record<string, any> = {};\n try {\n const raw = await withFsDeadline(`readFile ${inputFile}`, () => readFile(inputFile, \"utf-8\"));\n const parsed = JSON.parse(raw) as SkillInputFile;\n collectedValues = parsed.values ?? {};\n } catch {\n // No input file — all inputs are missing\n }\n\n const allInputs = [\n ...requirements.inputs_required.map((f) => ({ field: f, required: true })),\n ...requirements.inputs_optional.map((f) => ({ field: f, required: false })),\n ];\n\n const inputs: InputCheck[] = allInputs.map(({ field, required }) => ({\n id: field.id,\n required,\n present: field.id in collectedValues,\n field,\n }));\n\n // Check reads (informational only)\n const reads: ReadCheck[] = [];\n for (const r of requirements.reads) {\n reads.push({\n path: r.path,\n exists: await pathExists(path.join(projectDir, r.path)),\n description: r.description,\n });\n }\n\n // Check resources (validated at a higher level if a ResourceManager is available;\n // here we just record them in the report with unknown status)\n const resources: ResourceCheck[] = (requirements.resources ?? []).map((r) => ({\n id: r.id,\n available: true, // Actual availability checked by runner with ResourceManager\n missingOps: [],\n optional: r.optional ?? false,\n }));\n\n // Satisfaction: all hard file gates pass AND all required inputs present\n const hardFilesSatisfied = files.filter((f) => f.gate === \"hard\").every((f) => f.exists);\n\n const requiredInputsSatisfied = inputs.filter((i) => i.required).every((i) => i.present);\n\n const requiredResourcesSatisfied = resources.filter((r) => !r.optional).every((r) => r.available);\n\n return {\n skillId,\n satisfied: hardFilesSatisfied && requiredInputsSatisfied && requiredResourcesSatisfied,\n files,\n inputs,\n reads,\n resources,\n };\n}\n\n/**\n * A warning produced by `validateConnectorRequirements` when a skill's declared\n * connector requirement is not satisfied by the connectors in skaile.yaml.\n * Each warning covers either a missing driver or an insufficient access level.\n *\n * @docLink packages/resolver/api-reference#connector-validation-warning\n */\nexport interface ConnectorValidationWarning {\n /** Driver name that triggered the warning. */\n driver: string;\n /** Human-readable explanation of the gap, including a remediation command where applicable. */\n message: string;\n}\n\n/** Minimal structural type accepted by validateConnectorRequirements. Compatible with both\n * ConnectorDeclaration shapes in @skaile/workspaces/core and @skaile/workspaces/connectors. */\ninterface AvailableConnector {\n driver: string;\n access?: \"read-only\" | \"read-write\";\n}\n\n/**\n * Check that all connector requirements declared in a skill's SKILL.md are\n * satisfied by the connectors declared in skaile.yaml.\n *\n * Returns one warning per gap — either a missing driver or an insufficient\n * access level. This is a pre-flight advisory; no runtime enforcement is done.\n *\n * @param requirements - Connector requirements from `parseSkillRequirements().connectors`\n * @param available - Connector declarations from `skaile.yaml` (via `loadConnectorDeclarations`)\n * @returns Array of warnings — one per gap. Empty array when all requirements are satisfied.\n *\n * @docLink packages/resolver/api-reference#validate-connector-requirements\n */\nexport function validateConnectorRequirements(\n requirements: ConnectorRequirement[],\n available: AvailableConnector[],\n): ConnectorValidationWarning[] {\n const warnings: ConnectorValidationWarning[] = [];\n\n for (const req of requirements) {\n const matches = available.filter((a) => a.driver === req.driver);\n\n if (matches.length === 0) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires connector driver \"${req.driver}\" but none is declared in skaile.yaml. ` +\n `Run: skaile connector add ${req.driver}`,\n });\n continue;\n }\n\n if (req.access === \"read-write\") {\n const hasReadWrite = matches.some((m) => (m.access ?? \"read-only\") === \"read-write\");\n if (!hasReadWrite) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires \"${req.driver}\" with read-write access, but all declared instances ` +\n `are read-only. Update access in skaile.yaml.`,\n });\n }\n }\n }\n\n return warnings;\n}\n\n/**\n * Does `dirPath` hold at least `minEntries` files, counted recursively?\n *\n * `truncated` is set when a walk bound was hit *and* the count still fell\n * short: the number is then a floor, not the truth, so `satisfied: false` is\n * \"we could not prove it\" rather than \"there are not enough files\". Reaching\n * `minEntries` short-circuits the walk, so the common case never pays for the\n * whole tree and a bound hit after that point is irrelevant.\n */\nasync function checkDirectoryMinEntries(\n dirPath: string,\n minEntries: number,\n): Promise<{ satisfied: boolean; truncated: boolean }> {\n const st = await tryWithFsDeadline(`stat ${dirPath}`, () => stat(dirPath), null);\n if (!st?.isDirectory()) return { satisfied: false, truncated: false };\n\n const { count, truncation } = await countFilesRecursive(dirPath, minEntries);\n const satisfied = count >= minEntries;\n if (!satisfied && truncation) {\n log().warn(\"min_entries count truncated — result is a lower bound, not the file count\", {\n dirPath,\n minEntries,\n count,\n ...truncation,\n });\n }\n return { satisfied, truncated: !satisfied && truncation !== undefined };\n}\n\n/**\n * Count files under `dirPath`, stopping at `limit`.\n *\n * Delegates to core's {@link walkDir} rather than recursing here: `dirPath` is\n * agent-supplied and can be a network mount, so the walk needs the deadline per\n * `opendir`, the depth / entry / wall-clock bounds, and the visited-inode cycle\n * guard that walker already owns. The pre-#454 `readdirSync` recursion had none\n * of them and recursed forever on `a/link -> a`.\n *\n * Inheriting `walkDir` also inherits its skip list: `.git` and `node_modules`\n * no longer count toward `min_entries`, which is what a prerequisite like\n * \"at least 3 feature files\" meant in the first place.\n */\nasync function countFilesRecursive(\n dirPath: string,\n limit: number,\n): Promise<{ count: number; truncation?: WalkTruncation }> {\n let count = 0;\n let truncation: WalkTruncation | undefined;\n for await (const _entry of walkDir(dirPath, {\n onTruncate: (info) => {\n truncation ??= info;\n },\n })) {\n count++;\n // Enough is enough — no reason to keep walking a large tree (or a wedged\n // mount) once the requirement is already met.\n if (count >= limit) return { count };\n }\n return { count, truncation };\n}\n","import { satisfies, valid, validRange } from \"semver\";\n\n/**\n * Result of a single flow-node version pin check.\n * Returned in the array produced by `validateFlowVersions()` for every\n * node that declares a `requestedVersion`.\n *\n * @docLink packages/resolver/api-reference#version-check\n */\nexport interface VersionCheck {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier. */\n skillId: string;\n /** Semver range from the flow node (e.g. \"^1.0.0\") */\n requested: string;\n /** Version from the skill's frontmatter */\n actual: string;\n /** Whether `actual` satisfies the `requested` semver range. */\n satisfied: boolean;\n}\n\n/**\n * Minimal descriptor for a flow node that optionally pins a skill version.\n * Passed as input to `validateFlowVersions()`. Nodes without `requestedVersion`\n * are skipped during version checking.\n *\n * @docLink packages/resolver/api-reference#flow-version-node\n */\nexport interface FlowVersionNode {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier referenced by this node. */\n skillId: string;\n /** Optional semver range the node requires (e.g. `\"^1.2.0\"`). Omit to skip version checking. */\n requestedVersion?: string;\n}\n\n/**\n * Validate flow node version pins against discovered skill versions.\n *\n * Only checks nodes that declare a `requestedVersion`. Nodes without a\n * version pin are skipped entirely (no entry is produced for those nodes).\n * A check is marked `satisfied: false` when the range is invalid, the actual\n * version string is not valid semver, or the version does not satisfy the range.\n *\n * @param nodes - Flow nodes to check; only those with `requestedVersion` are evaluated\n * @param skillVersions - Map from skill ID to the semver version string in its frontmatter\n * @returns Array of `VersionCheck` results, one per node that declared a version pin\n *\n * @docLink packages/resolver/api-reference#validate-flow-versions\n */\nexport function validateFlowVersions(\n nodes: FlowVersionNode[],\n skillVersions: Map<string, string>,\n): VersionCheck[] {\n const checks: VersionCheck[] = [];\n\n for (const node of nodes) {\n if (!node.requestedVersion) continue;\n\n const actual = skillVersions.get(node.skillId) ?? \"\";\n const requested = node.requestedVersion;\n\n // Invalid range or missing/invalid actual version → not satisfied\n const rangeValid = validRange(requested) !== null;\n const actualValid = actual !== \"\" && valid(actual) !== null;\n const isSatisfied = rangeValid && actualValid && satisfies(actual, requested);\n\n checks.push({\n nodeId: node.nodeId,\n skillId: node.skillId,\n requested,\n actual,\n satisfied: isSatisfied,\n });\n }\n\n return checks;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { tryWithFsDeadline, withFsDeadline, fsDeadlineMs } from './chunk-
|
|
1
|
+
import { tryWithFsDeadline, withFsDeadline, fsDeadlineMs } from './chunk-SQ7IN7KR.js';
|
|
2
2
|
import { createLogger } from './chunk-BOFL7GIF.js';
|
|
3
3
|
import { stat, mkdir, cp, writeFile, rm } from 'fs/promises';
|
|
4
4
|
import { resolve, sep, join } from 'path';
|
|
@@ -155,5 +155,5 @@ function resolveFlowSkills(flow, allEntries) {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
export { WORKSPACE_MOUNT_ENV_VAR, deployAll, deployCatalogEntry, findAiAssetsRoot, isUnderWorkspaceMount, resolveFlowSkills, undeployCatalogEntry, workspaceMountDirs };
|
|
158
|
-
//# sourceMappingURL=chunk-
|
|
159
|
-
//# sourceMappingURL=chunk-
|
|
158
|
+
//# sourceMappingURL=chunk-5JAO4MXA.js.map
|
|
159
|
+
//# sourceMappingURL=chunk-5JAO4MXA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../asset-manager/src/catalog-deployer.ts"],"names":[],"mappings":"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","file":"chunk-Q6NDQ6BH.js","sourcesContent":["/**\n * Platform-triggered asset deployment.\n *\n * Takes catalog entries (with source_path relative to ai-assets/) and deploys\n * them to a session's .claude/skills/ directory. Handles skill context injection\n * and catalog priority-based name resolution.\n */\n\nimport { cp, mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { fsDeadlineMs, tryWithFsDeadline, withFsDeadline } from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\n\n// ---------------------------------------------------------------------------\n// Types (formerly in catalog-compiler.ts, inlined after tear-out in Task 1.5)\n// ---------------------------------------------------------------------------\n\n/**\n * A single user-facing input parameter declared in a SKILL.md.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface InputSpec {\n /** Input parameter key used in skill invocation. */\n key: string;\n /** Whether the input must be provided before running the skill. */\n required?: boolean;\n /** Question string shown to the user when collecting this input. */\n prompt?: string;\n /** Short display label for UI forms. */\n label?: string;\n /** Input data type hint (e.g. `\"string\"`, `\"number\"`, `\"file\"`). */\n type?: string;\n /** Additional guidance text shown alongside the input field. */\n hint?: string;\n}\n\n/**\n * A compiled catalog entry (skill or flow).\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface CatalogEntryCompiled {\n /** Unique ID in `domain/name` form (e.g. `skaileup-conceptualization/cf_overview`). */\n id: string;\n /** Asset kind. */\n kind: \"skill\" | \"flow\";\n /** Human-readable asset name. */\n name: string;\n /** One-line description. */\n description: string;\n /** Semantic version string. */\n version: string;\n /** Maturity stage. */\n stage: \"alpha\" | \"beta\" | \"stable\";\n /** Searchable keywords. */\n keywords: string[];\n /** User-facing input specifications. */\n inputs: InputSpec[];\n /** Domain directory name. */\n source_domain: string;\n /** Asset path relative to assetsRoot. */\n source_path: string;\n /** Optional icon identifier. */\n icon?: string;\n /** Flow-only: required skill names. */\n required_skills?: string[];\n /** Flow-only: optional skill names. */\n optional_skills?: string[];\n}\n\n/**\n * Options controlling how platform-triggered skill deployment is performed.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployFromCatalogOptions {\n /** Root directory of ai-assets (where `source_path` in catalog entries is relative to). */\n assetsRoot: string;\n /** Target directory for deployed skills (e.g. `/workspace/.claude/skills/`). */\n skillsDir: string;\n /** Optional context markdown appended to the deployed skill directory as `CONTEXT.md`. */\n context?: string;\n}\n\n/**\n * Result of a platform-triggered batch skill deployment.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployResult {\n /** IDs of catalog entries successfully deployed. */\n deployed: string[];\n /** IDs of catalog entries skipped (non-skill kinds). */\n skipped: string[];\n /** Error messages for entries that could not be deployed. */\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Workspace-mount awareness\n// ---------------------------------------------------------------------------\n\n/**\n * Multiplier applied to the base filesystem deadline for whole-tree operations\n * (recursive copy / remove), which legitimately outlast a single `stat`.\n */\nconst TREE_OP_DEADLINE_FACTOR = 4;\n\n/** Default number of parent levels {@link findAiAssetsRoot} inspects. */\nconst AI_ASSETS_WALK_LEVELS = 6;\n\nlet deployerLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n deployerLogger ??= createLogger({ kind: \"runner\", subkind: \"catalog-deployer\" });\n return deployerLogger;\n}\n\n/**\n * Where the agent container binds its rclone FUSE mount. Nothing under this\n * path is a safe place to read an asset tree from: the mount is remote\n * (SharePoint / OneDrive / WebDAV) and can wedge indefinitely.\n */\nconst DEFAULT_WORKSPACE_MOUNT_DIR = \"/skaile/workspace\";\n\n/**\n * Env override for the workspace-mount path(s), comma-separated.\n *\n * Set it when the runner binds the mount somewhere other than\n * {@link DEFAULT_WORKSPACE_MOUNT_DIR}; set it to the empty string to disable\n * the guard entirely (single-machine dev, where nothing is a network mount).\n */\nexport const WORKSPACE_MOUNT_ENV_VAR = \"SKAILE_WORKSPACE_MOUNT_DIR\";\n\n/**\n * Resolve the directories treated as network mounts.\n *\n * Read per call rather than cached: the runner mutates `process.env` while\n * wiring a session, so a module-load snapshot would pin a pre-configuration\n * value.\n *\n * @returns Absolute mount paths; empty when the guard is disabled.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function workspaceMountDirs(): string[] {\n const raw = process.env[WORKSPACE_MOUNT_ENV_VAR];\n if (raw === undefined) return [DEFAULT_WORKSPACE_MOUNT_DIR];\n return raw\n .split(\",\")\n .map((segment) => segment.trim())\n .filter((segment) => segment.length > 0)\n .map((segment) => resolve(segment));\n}\n\n/**\n * Is `candidate` at, or inside, one of the known workspace mount paths?\n *\n * Pure path arithmetic — deliberately no filesystem access, because the whole\n * point is to decide *before* touching a path that might be unresponsive.\n *\n * @param candidate - Path to test.\n * @param mountDirs - Mount roots; defaults to {@link workspaceMountDirs}.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function isUnderWorkspaceMount(\n candidate: string,\n mountDirs: string[] = workspaceMountDirs(),\n): boolean {\n const target = resolve(candidate);\n return mountDirs.some((dir) => {\n const root = resolve(dir);\n return target === root || target.startsWith(root + sep);\n });\n}\n\n/**\n * Walk upward from `startDir` looking for an `ai-assets/` directory.\n *\n * Two properties matter beyond \"find the folder\":\n *\n * 1. **Never synchronous.** The walk probes up to six directories; any one of\n * them can be on a FUSE mount, and the former `existsSync` chain blocked the\n * event loop on the first unresponsive probe. Each probe is now awaited and\n * deadline-bounded, so a wedged mount costs one skipped candidate.\n * 2. **Never resolves onto a mount.** A hit under the workspace mount is\n * skipped with a warning rather than returned: accepting it would wire every\n * later skill deploy — a recursive copy — to a remote filesystem. The walk\n * continues upward, so a legitimate `ai-assets/` in a parent still wins.\n *\n * Only a **directory** counts. An `ai-assets` file would otherwise be returned\n * as a root and every later `join(root, source_path)` would fail with ENOTDIR.\n *\n * @param startDir - Directory to start from (typically the project dir).\n * @param opts - `levels` caps the upward walk; `mountDirs` overrides the mount\n * roots (defaults to {@link workspaceMountDirs}).\n * @returns Absolute path to the `ai-assets/` directory, or `null` if none is\n * reachable within `levels`.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function findAiAssetsRoot(\n startDir: string,\n opts?: { levels?: number; mountDirs?: string[] },\n): Promise<string | null> {\n const mountDirs = opts?.mountDirs ?? workspaceMountDirs();\n const levels = opts?.levels ?? AI_ASSETS_WALK_LEVELS;\n let dir = resolve(startDir);\n // Every level of a `/skaile/workspace/...` start dir is under the mount, so\n // an unconditional warn would fire once per level for one lookup. Collect and\n // report once — the operator needs the fact, not six copies of it.\n const refused: string[] = [];\n\n for (let i = 0; i < levels; i++) {\n const candidate = join(dir, \"ai-assets\");\n if (isUnderWorkspaceMount(candidate, mountDirs)) {\n refused.push(candidate);\n } else {\n const isDir = await tryWithFsDeadline(\n `stat ${candidate}`,\n async () => (await stat(candidate)).isDirectory(),\n false,\n );\n if (isDir) {\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return candidate;\n }\n }\n const parent = resolve(dir, \"..\");\n if (parent === dir) break; // filesystem root — nothing further up\n dir = parent;\n }\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return null;\n}\n\n/** Single warning for every `ai-assets` candidate skipped for sitting on a mount. */\nfunction warnRefused(refused: string[], mountDirs: string[]): void {\n log().warn(\n \"findAiAssetsRoot refused candidates under a workspace mount — deploying skills from a network mount can stall the session\",\n { refused, mountDirs },\n );\n}\n\n/**\n * Deploy a single catalog entry to the session skills directory.\n *\n * Copies the entire skill source directory into `skillsDir/<entry.name>/`.\n * If `context` is provided, a separate `CONTEXT.md` is written alongside\n * `SKILL.md` so the source file is never modified.\n *\n * Only `skill` entries are deployable; other kinds return an error.\n *\n * **Async by necessity.** This runs from the `session_init` command handler\n * with the WebSocket live, and both `assetsRoot` and `skillsDir` can sit on a\n * network mount. The former `cpSync`/`rmSync` pair parked the event loop for\n * the whole copy; every call is now awaited and deadline-bounded, so an\n * unresponsive mount fails one deployment instead of the session.\n *\n * @param entry - Compiled catalog entry to deploy.\n * @param options - Deployment target and optional context.\n * @returns `{ success: true }` on success, `{ success: false, error }` on failure.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployCatalogEntry(\n entry: CatalogEntryCompiled,\n options: DeployFromCatalogOptions,\n): Promise<{ success: boolean; error?: string }> {\n const { assetsRoot, skillsDir, context } = options;\n\n if (entry.kind !== \"skill\") {\n return { success: false, error: `Cannot deploy ${entry.kind} directly — only skills` };\n }\n\n const sourcePath = join(assetsRoot, entry.source_path);\n const skillMdPath = join(sourcePath, \"SKILL.md\");\n\n const hasSkillMd = await tryWithFsDeadline(\n `stat ${skillMdPath}`,\n async () => {\n await stat(skillMdPath);\n return true;\n },\n false,\n );\n if (!hasSkillMd) {\n return { success: false, error: `SKILL.md not found at ${skillMdPath}` };\n }\n\n const destDir = join(skillsDir, entry.name);\n\n try {\n await withFsDeadline(`mkdir ${destDir}`, () => mkdir(destDir, { recursive: true }));\n\n // Copy the entire skill directory\n await withFsDeadline(\n `cp ${sourcePath} -> ${destDir}`,\n () => cp(sourcePath, destDir, { recursive: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n\n // Write context to a separate CONTEXT.md — never modify the original SKILL.md.\n // The agent discovers both files in the skill directory.\n const contextPath = join(destDir, \"CONTEXT.md\");\n if (context) {\n await withFsDeadline(`write ${contextPath}`, () =>\n writeFile(contextPath, `# Additional Context\\n\\n${context}\\n`, \"utf8\"),\n );\n } else {\n // `force: true` makes this a single call: a stale CONTEXT.md is removed,\n // an absent one is a no-op. The former existsSync probe only added a\n // second trip to the same possibly-wedged mount.\n await withFsDeadline(`rm ${contextPath}`, () => rm(contextPath, { force: true }));\n }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n\n return { success: true };\n}\n\n/**\n * Remove a deployed skill directory from the session skills directory.\n *\n * @param name - Skill name (directory basename under `skillsDir`).\n * @param skillsDir - Absolute path to the session skills directory.\n * @returns `true` if the skill was found and removed; `false` if it was not\n * deployed, or if the directory could not be reached within the deadline.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function undeployCatalogEntry(name: string, skillsDir: string): Promise<boolean> {\n const destDir = join(skillsDir, name);\n const exists = await tryWithFsDeadline(\n `stat ${destDir}`,\n async () => {\n await stat(destDir);\n return true;\n },\n false,\n );\n if (!exists) return false;\n await withFsDeadline(\n `rm -r ${destDir}`,\n () => rm(destDir, { recursive: true, force: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n return true;\n}\n\n/**\n * Deploy multiple catalog entries in a single batch operation.\n *\n * Non-skill entries (flows, agents, etc.) are automatically skipped and\n * recorded in `result.skipped`. Deployment failures are collected in\n * `result.errors` without aborting the rest of the batch.\n *\n * @param entries - Compiled catalog entries to deploy.\n * @param options - Deployment target and optional context.\n * @returns Aggregated {@link DeployResult} with deployed, skipped, and error lists.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployAll(\n entries: CatalogEntryCompiled[],\n options: DeployFromCatalogOptions,\n): Promise<DeployResult> {\n const result: DeployResult = { deployed: [], skipped: [], errors: [] };\n\n for (const entry of entries) {\n if (entry.kind !== \"skill\") {\n result.skipped.push(entry.id);\n continue;\n }\n\n // Serial on purpose: concurrent recursive copies onto one mount multiply\n // the queue depth on the exact resource that is already the bottleneck.\n const r = await deployCatalogEntry(entry, options);\n if (r.success) {\n result.deployed.push(entry.id);\n } else {\n result.errors.push(`${entry.id}: ${r.error}`);\n }\n }\n\n return result;\n}\n\n/**\n * Resolve a flow's skill dependencies from the full catalog entry list.\n *\n * Partitions `flow.required_skills` and `flow.optional_skills` into resolved\n * entries and a list of names that could not be found. Missing optional skills\n * are silently ignored (they do not appear in `missing`).\n *\n * @param flow - Compiled flow entry whose skill dependencies should be resolved.\n * @param allEntries - Full set of compiled catalog entries to search.\n * @returns Object containing resolved `required` entries, resolved `optional` entries,\n * and `missing` skill names that were listed as required but not found.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function resolveFlowSkills(\n flow: CatalogEntryCompiled,\n allEntries: CatalogEntryCompiled[],\n): { required: CatalogEntryCompiled[]; optional: CatalogEntryCompiled[]; missing: string[] } {\n const skillsByName = new Map<string, CatalogEntryCompiled>();\n for (const e of allEntries) {\n if (e.kind === \"skill\") skillsByName.set(e.name, e);\n }\n\n const required: CatalogEntryCompiled[] = [];\n const optional: CatalogEntryCompiled[] = [];\n const missing: string[] = [];\n\n for (const name of flow.required_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) required.push(entry);\n else missing.push(name);\n }\n\n for (const name of flow.optional_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) optional.push(entry);\n // Optional skills don't count as missing\n }\n\n return { required, optional, missing };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../asset-manager/src/catalog-deployer.ts"],"names":[],"mappings":"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","file":"chunk-5JAO4MXA.js","sourcesContent":["/**\n * Platform-triggered asset deployment.\n *\n * Takes catalog entries (with source_path relative to ai-assets/) and deploys\n * them to a session's .claude/skills/ directory. Handles skill context injection\n * and catalog priority-based name resolution.\n */\n\nimport { cp, mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { fsDeadlineMs, tryWithFsDeadline, withFsDeadline } from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\n\n// ---------------------------------------------------------------------------\n// Types (formerly in catalog-compiler.ts, inlined after tear-out in Task 1.5)\n// ---------------------------------------------------------------------------\n\n/**\n * A single user-facing input parameter declared in a SKILL.md.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface InputSpec {\n /** Input parameter key used in skill invocation. */\n key: string;\n /** Whether the input must be provided before running the skill. */\n required?: boolean;\n /** Question string shown to the user when collecting this input. */\n prompt?: string;\n /** Short display label for UI forms. */\n label?: string;\n /** Input data type hint (e.g. `\"string\"`, `\"number\"`, `\"file\"`). */\n type?: string;\n /** Additional guidance text shown alongside the input field. */\n hint?: string;\n}\n\n/**\n * A compiled catalog entry (skill or flow).\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface CatalogEntryCompiled {\n /** Unique ID in `domain/name` form (e.g. `skaileup-conceptualization/cf_overview`). */\n id: string;\n /** Asset kind. */\n kind: \"skill\" | \"flow\";\n /** Human-readable asset name. */\n name: string;\n /** One-line description. */\n description: string;\n /** Semantic version string. */\n version: string;\n /** Maturity stage. */\n stage: \"alpha\" | \"beta\" | \"stable\";\n /** Searchable keywords. */\n keywords: string[];\n /** User-facing input specifications. */\n inputs: InputSpec[];\n /** Domain directory name. */\n source_domain: string;\n /** Asset path relative to assetsRoot. */\n source_path: string;\n /** Optional icon identifier. */\n icon?: string;\n /** Flow-only: required skill names. */\n required_skills?: string[];\n /** Flow-only: optional skill names. */\n optional_skills?: string[];\n}\n\n/**\n * Options controlling how platform-triggered skill deployment is performed.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployFromCatalogOptions {\n /** Root directory of ai-assets (where `source_path` in catalog entries is relative to). */\n assetsRoot: string;\n /** Target directory for deployed skills (e.g. `/workspace/.claude/skills/`). */\n skillsDir: string;\n /** Optional context markdown appended to the deployed skill directory as `CONTEXT.md`. */\n context?: string;\n}\n\n/**\n * Result of a platform-triggered batch skill deployment.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployResult {\n /** IDs of catalog entries successfully deployed. */\n deployed: string[];\n /** IDs of catalog entries skipped (non-skill kinds). */\n skipped: string[];\n /** Error messages for entries that could not be deployed. */\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Workspace-mount awareness\n// ---------------------------------------------------------------------------\n\n/**\n * Multiplier applied to the base filesystem deadline for whole-tree operations\n * (recursive copy / remove), which legitimately outlast a single `stat`.\n */\nconst TREE_OP_DEADLINE_FACTOR = 4;\n\n/** Default number of parent levels {@link findAiAssetsRoot} inspects. */\nconst AI_ASSETS_WALK_LEVELS = 6;\n\nlet deployerLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n deployerLogger ??= createLogger({ kind: \"runner\", subkind: \"catalog-deployer\" });\n return deployerLogger;\n}\n\n/**\n * Where the agent container binds its rclone FUSE mount. Nothing under this\n * path is a safe place to read an asset tree from: the mount is remote\n * (SharePoint / OneDrive / WebDAV) and can wedge indefinitely.\n */\nconst DEFAULT_WORKSPACE_MOUNT_DIR = \"/skaile/workspace\";\n\n/**\n * Env override for the workspace-mount path(s), comma-separated.\n *\n * Set it when the runner binds the mount somewhere other than\n * {@link DEFAULT_WORKSPACE_MOUNT_DIR}; set it to the empty string to disable\n * the guard entirely (single-machine dev, where nothing is a network mount).\n */\nexport const WORKSPACE_MOUNT_ENV_VAR = \"SKAILE_WORKSPACE_MOUNT_DIR\";\n\n/**\n * Resolve the directories treated as network mounts.\n *\n * Read per call rather than cached: the runner mutates `process.env` while\n * wiring a session, so a module-load snapshot would pin a pre-configuration\n * value.\n *\n * @returns Absolute mount paths; empty when the guard is disabled.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function workspaceMountDirs(): string[] {\n const raw = process.env[WORKSPACE_MOUNT_ENV_VAR];\n if (raw === undefined) return [DEFAULT_WORKSPACE_MOUNT_DIR];\n return raw\n .split(\",\")\n .map((segment) => segment.trim())\n .filter((segment) => segment.length > 0)\n .map((segment) => resolve(segment));\n}\n\n/**\n * Is `candidate` at, or inside, one of the known workspace mount paths?\n *\n * Pure path arithmetic — deliberately no filesystem access, because the whole\n * point is to decide *before* touching a path that might be unresponsive.\n *\n * @param candidate - Path to test.\n * @param mountDirs - Mount roots; defaults to {@link workspaceMountDirs}.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function isUnderWorkspaceMount(\n candidate: string,\n mountDirs: string[] = workspaceMountDirs(),\n): boolean {\n const target = resolve(candidate);\n return mountDirs.some((dir) => {\n const root = resolve(dir);\n return target === root || target.startsWith(root + sep);\n });\n}\n\n/**\n * Walk upward from `startDir` looking for an `ai-assets/` directory.\n *\n * Two properties matter beyond \"find the folder\":\n *\n * 1. **Never synchronous.** The walk probes up to six directories; any one of\n * them can be on a FUSE mount, and the former `existsSync` chain blocked the\n * event loop on the first unresponsive probe. Each probe is now awaited and\n * deadline-bounded, so a wedged mount costs one skipped candidate.\n * 2. **Never resolves onto a mount.** A hit under the workspace mount is\n * skipped with a warning rather than returned: accepting it would wire every\n * later skill deploy — a recursive copy — to a remote filesystem. The walk\n * continues upward, so a legitimate `ai-assets/` in a parent still wins.\n *\n * Only a **directory** counts. An `ai-assets` file would otherwise be returned\n * as a root and every later `join(root, source_path)` would fail with ENOTDIR.\n *\n * @param startDir - Directory to start from (typically the project dir).\n * @param opts - `levels` caps the upward walk; `mountDirs` overrides the mount\n * roots (defaults to {@link workspaceMountDirs}).\n * @returns Absolute path to the `ai-assets/` directory, or `null` if none is\n * reachable within `levels`.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function findAiAssetsRoot(\n startDir: string,\n opts?: { levels?: number; mountDirs?: string[] },\n): Promise<string | null> {\n const mountDirs = opts?.mountDirs ?? workspaceMountDirs();\n const levels = opts?.levels ?? AI_ASSETS_WALK_LEVELS;\n let dir = resolve(startDir);\n // Every level of a `/skaile/workspace/...` start dir is under the mount, so\n // an unconditional warn would fire once per level for one lookup. Collect and\n // report once — the operator needs the fact, not six copies of it.\n const refused: string[] = [];\n\n for (let i = 0; i < levels; i++) {\n const candidate = join(dir, \"ai-assets\");\n if (isUnderWorkspaceMount(candidate, mountDirs)) {\n refused.push(candidate);\n } else {\n const isDir = await tryWithFsDeadline(\n `stat ${candidate}`,\n async () => (await stat(candidate)).isDirectory(),\n false,\n );\n if (isDir) {\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return candidate;\n }\n }\n const parent = resolve(dir, \"..\");\n if (parent === dir) break; // filesystem root — nothing further up\n dir = parent;\n }\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return null;\n}\n\n/** Single warning for every `ai-assets` candidate skipped for sitting on a mount. */\nfunction warnRefused(refused: string[], mountDirs: string[]): void {\n log().warn(\n \"findAiAssetsRoot refused candidates under a workspace mount — deploying skills from a network mount can stall the session\",\n { refused, mountDirs },\n );\n}\n\n/**\n * Deploy a single catalog entry to the session skills directory.\n *\n * Copies the entire skill source directory into `skillsDir/<entry.name>/`.\n * If `context` is provided, a separate `CONTEXT.md` is written alongside\n * `SKILL.md` so the source file is never modified.\n *\n * Only `skill` entries are deployable; other kinds return an error.\n *\n * **Async by necessity.** This runs from the `session_init` command handler\n * with the WebSocket live, and both `assetsRoot` and `skillsDir` can sit on a\n * network mount. The former `cpSync`/`rmSync` pair parked the event loop for\n * the whole copy; every call is now awaited and deadline-bounded, so an\n * unresponsive mount fails one deployment instead of the session.\n *\n * @param entry - Compiled catalog entry to deploy.\n * @param options - Deployment target and optional context.\n * @returns `{ success: true }` on success, `{ success: false, error }` on failure.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployCatalogEntry(\n entry: CatalogEntryCompiled,\n options: DeployFromCatalogOptions,\n): Promise<{ success: boolean; error?: string }> {\n const { assetsRoot, skillsDir, context } = options;\n\n if (entry.kind !== \"skill\") {\n return { success: false, error: `Cannot deploy ${entry.kind} directly — only skills` };\n }\n\n const sourcePath = join(assetsRoot, entry.source_path);\n const skillMdPath = join(sourcePath, \"SKILL.md\");\n\n const hasSkillMd = await tryWithFsDeadline(\n `stat ${skillMdPath}`,\n async () => {\n await stat(skillMdPath);\n return true;\n },\n false,\n );\n if (!hasSkillMd) {\n return { success: false, error: `SKILL.md not found at ${skillMdPath}` };\n }\n\n const destDir = join(skillsDir, entry.name);\n\n try {\n await withFsDeadline(`mkdir ${destDir}`, () => mkdir(destDir, { recursive: true }));\n\n // Copy the entire skill directory\n await withFsDeadline(\n `cp ${sourcePath} -> ${destDir}`,\n () => cp(sourcePath, destDir, { recursive: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n\n // Write context to a separate CONTEXT.md — never modify the original SKILL.md.\n // The agent discovers both files in the skill directory.\n const contextPath = join(destDir, \"CONTEXT.md\");\n if (context) {\n await withFsDeadline(`write ${contextPath}`, () =>\n writeFile(contextPath, `# Additional Context\\n\\n${context}\\n`, \"utf8\"),\n );\n } else {\n // `force: true` makes this a single call: a stale CONTEXT.md is removed,\n // an absent one is a no-op. The former existsSync probe only added a\n // second trip to the same possibly-wedged mount.\n await withFsDeadline(`rm ${contextPath}`, () => rm(contextPath, { force: true }));\n }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n\n return { success: true };\n}\n\n/**\n * Remove a deployed skill directory from the session skills directory.\n *\n * @param name - Skill name (directory basename under `skillsDir`).\n * @param skillsDir - Absolute path to the session skills directory.\n * @returns `true` if the skill was found and removed; `false` if it was not\n * deployed, or if the directory could not be reached within the deadline.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function undeployCatalogEntry(name: string, skillsDir: string): Promise<boolean> {\n const destDir = join(skillsDir, name);\n const exists = await tryWithFsDeadline(\n `stat ${destDir}`,\n async () => {\n await stat(destDir);\n return true;\n },\n false,\n );\n if (!exists) return false;\n await withFsDeadline(\n `rm -r ${destDir}`,\n () => rm(destDir, { recursive: true, force: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n return true;\n}\n\n/**\n * Deploy multiple catalog entries in a single batch operation.\n *\n * Non-skill entries (flows, agents, etc.) are automatically skipped and\n * recorded in `result.skipped`. Deployment failures are collected in\n * `result.errors` without aborting the rest of the batch.\n *\n * @param entries - Compiled catalog entries to deploy.\n * @param options - Deployment target and optional context.\n * @returns Aggregated {@link DeployResult} with deployed, skipped, and error lists.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployAll(\n entries: CatalogEntryCompiled[],\n options: DeployFromCatalogOptions,\n): Promise<DeployResult> {\n const result: DeployResult = { deployed: [], skipped: [], errors: [] };\n\n for (const entry of entries) {\n if (entry.kind !== \"skill\") {\n result.skipped.push(entry.id);\n continue;\n }\n\n // Serial on purpose: concurrent recursive copies onto one mount multiply\n // the queue depth on the exact resource that is already the bottleneck.\n const r = await deployCatalogEntry(entry, options);\n if (r.success) {\n result.deployed.push(entry.id);\n } else {\n result.errors.push(`${entry.id}: ${r.error}`);\n }\n }\n\n return result;\n}\n\n/**\n * Resolve a flow's skill dependencies from the full catalog entry list.\n *\n * Partitions `flow.required_skills` and `flow.optional_skills` into resolved\n * entries and a list of names that could not be found. Missing optional skills\n * are silently ignored (they do not appear in `missing`).\n *\n * @param flow - Compiled flow entry whose skill dependencies should be resolved.\n * @param allEntries - Full set of compiled catalog entries to search.\n * @returns Object containing resolved `required` entries, resolved `optional` entries,\n * and `missing` skill names that were listed as required but not found.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function resolveFlowSkills(\n flow: CatalogEntryCompiled,\n allEntries: CatalogEntryCompiled[],\n): { required: CatalogEntryCompiled[]; optional: CatalogEntryCompiled[]; missing: string[] } {\n const skillsByName = new Map<string, CatalogEntryCompiled>();\n for (const e of allEntries) {\n if (e.kind === \"skill\") skillsByName.set(e.name, e);\n }\n\n const required: CatalogEntryCompiled[] = [];\n const optional: CatalogEntryCompiled[] = [];\n const missing: string[] = [];\n\n for (const name of flow.required_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) required.push(entry);\n else missing.push(name);\n }\n\n for (const name of flow.optional_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) optional.push(entry);\n // Optional skills don't count as missing\n }\n\n return { required, optional, missing };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { classifyClaudeSdkError } from './chunk-XBSQ4KMC.js';
|
|
2
|
-
import { toMergedRegistry, createDriver, getProviderPreset, resolvePresetBaseUrl, expandPreset, resolveProbeUrl, buildCredentialHeaders } from './chunk-
|
|
3
|
-
import { stripActivityLabel, TOOL_ACTIVITY_LABEL_PARAM, TOOL_ACTIVITY_LABEL_MAX_CHARS } from './chunk-
|
|
2
|
+
import { toMergedRegistry, createDriver, getProviderPreset, resolvePresetBaseUrl, expandPreset, resolveProbeUrl, buildCredentialHeaders } from './chunk-WQULDAH2.js';
|
|
3
|
+
import { stripActivityLabel, TOOL_ACTIVITY_LABEL_PARAM, TOOL_ACTIVITY_LABEL_MAX_CHARS } from './chunk-V2OQ3BI6.js';
|
|
4
4
|
|
|
5
5
|
// bridge/src/normalizer.ts
|
|
6
6
|
function resultUsageFields(event) {
|
|
@@ -633,5 +633,5 @@ async function validateApiKey(provider, key, options = {}) {
|
|
|
633
633
|
}
|
|
634
634
|
|
|
635
635
|
export { BridgeRuntime, EventNormalizer, createRuntime, detectFileChange, detectFileChanges, labelToolCall, summarizeToolCall, summarizeToolResult, validateApiKey };
|
|
636
|
-
//# sourceMappingURL=chunk-
|
|
637
|
-
//# sourceMappingURL=chunk-
|
|
636
|
+
//# sourceMappingURL=chunk-5SGS5SN2.js.map
|
|
637
|
+
//# sourceMappingURL=chunk-5SGS5SN2.js.map
|