@skaile/workspaces 2.5.0 → 2.7.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +26 -11
  3. package/dist/{asset-feeds-4AWAT5PW.js → asset-feeds-23CP6YUY.js} +4 -4
  4. package/dist/{asset-feeds-4AWAT5PW.js.map → asset-feeds-23CP6YUY.js.map} +1 -1
  5. package/dist/asset-manager/index.js +1 -1
  6. package/dist/{chunk-WSARNOPP.js → chunk-6AYGXPPF.js} +2 -2
  7. package/dist/{chunk-WSARNOPP.js.map → chunk-6AYGXPPF.js.map} +1 -1
  8. package/dist/{chunk-ENBTXMPL.js → chunk-AZ44F3AT.js} +6 -6
  9. package/dist/{chunk-ENBTXMPL.js.map → chunk-AZ44F3AT.js.map} +1 -1
  10. package/dist/{chunk-4O2RAXKJ.js → chunk-E4AVJMOJ.js} +316 -6
  11. package/dist/chunk-E4AVJMOJ.js.map +1 -0
  12. package/dist/{chunk-JAFEMG7W.js → chunk-FW2C6JJP.js} +3 -3
  13. package/dist/{chunk-JAFEMG7W.js.map → chunk-FW2C6JJP.js.map} +1 -1
  14. package/dist/{chunk-EEHOMCRU.js → chunk-HVQWLYZB.js} +129 -11
  15. package/dist/chunk-HVQWLYZB.js.map +1 -0
  16. package/dist/{chunk-V4ZLZJFN.js → chunk-IWUIXNMF.js} +6 -3
  17. package/dist/chunk-IWUIXNMF.js.map +1 -0
  18. package/dist/{chunk-IHX2SN35.js → chunk-JIA2S3T2.js} +6 -6
  19. package/dist/{chunk-IHX2SN35.js.map → chunk-JIA2S3T2.js.map} +1 -1
  20. package/dist/{chunk-RK3HU3H3.js → chunk-KSHCQ777.js} +8 -6
  21. package/dist/chunk-KSHCQ777.js.map +1 -0
  22. package/dist/{chunk-YWPEDILM.js → chunk-OAUKA7VT.js} +8 -8
  23. package/dist/{chunk-YWPEDILM.js.map → chunk-OAUKA7VT.js.map} +1 -1
  24. package/dist/{chunk-MADO7PH5.js → chunk-ONUDDQGS.js} +2 -2
  25. package/dist/{chunk-MADO7PH5.js.map → chunk-ONUDDQGS.js.map} +1 -1
  26. package/dist/{chunk-EUWN4EK4.js → chunk-P3DUVOAW.js} +6 -6
  27. package/dist/{chunk-EUWN4EK4.js.map → chunk-P3DUVOAW.js.map} +1 -1
  28. package/dist/{chunk-FKBQRV4J.js → chunk-SCR3WGW7.js} +3 -3
  29. package/dist/{chunk-FKBQRV4J.js.map → chunk-SCR3WGW7.js.map} +1 -1
  30. package/dist/{chunk-4QROZZ5Z.js → chunk-TUYN2HDT.js} +7 -4
  31. package/dist/chunk-TUYN2HDT.js.map +1 -0
  32. package/dist/{chunk-OEGHKO5N.js → chunk-XJ74XFIZ.js} +20 -9
  33. package/dist/chunk-XJ74XFIZ.js.map +1 -0
  34. package/dist/{chunk-PJ6INYDD.js → chunk-XTFZOYNY.js} +3 -3
  35. package/dist/{chunk-PJ6INYDD.js.map → chunk-XTFZOYNY.js.map} +1 -1
  36. package/dist/{chunk-UZYTSIX6.js → chunk-ZJ7MRR2R.js} +4 -4
  37. package/dist/{chunk-UZYTSIX6.js.map → chunk-ZJ7MRR2R.js.map} +1 -1
  38. package/dist/{chunk-AKVAZ5CB.js → chunk-ZJOEU5GP.js} +2 -2
  39. package/dist/{chunk-AKVAZ5CB.js.map → chunk-ZJOEU5GP.js.map} +1 -1
  40. package/dist/cli/index.js +31 -31
  41. package/dist/connectors/index.js +5 -5
  42. package/dist/{ensure-sources-QF72HVUM.js → ensure-sources-N7B7657V.js} +4 -4
  43. package/dist/{ensure-sources-QF72HVUM.js.map → ensure-sources-N7B7657V.js.map} +1 -1
  44. package/dist/factory-assets/connectors/box.js +5 -5
  45. package/dist/factory-assets/connectors/deploy.js +5 -5
  46. package/dist/factory-assets/connectors/devserver.js +5 -5
  47. package/dist/factory-assets/connectors/flow/CONNECTOR.md +36 -8
  48. package/dist/factory-assets/connectors/flow/adapter.d.ts +4 -1
  49. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  50. package/dist/factory-assets/connectors/flow/adapter.js +5 -5
  51. package/dist/factory-assets/connectors/flow/contract/expression.d.ts +3 -0
  52. package/dist/factory-assets/connectors/flow/contract/expression.d.ts.map +1 -1
  53. package/dist/factory-assets/connectors/flow/contract/flow.v2.schema.json +5 -1
  54. package/dist/factory-assets/connectors/flow/contract/hash.d.ts.map +1 -1
  55. package/dist/factory-assets/connectors/flow/contract/index.d.ts +1 -1
  56. package/dist/factory-assets/connectors/flow/contract/index.d.ts.map +1 -1
  57. package/dist/factory-assets/connectors/flow/contract/schema.d.ts +21 -2
  58. package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
  59. package/dist/factory-assets/connectors/flow/contract.js +2 -2
  60. package/dist/factory-assets/connectors/flow/engine/engine.d.ts +30 -0
  61. package/dist/factory-assets/connectors/flow/engine/engine.d.ts.map +1 -1
  62. package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts +6 -0
  63. package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts.map +1 -1
  64. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts +48 -0
  65. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts.map +1 -0
  66. package/dist/factory-assets/connectors/flow/engine/types.d.ts +13 -24
  67. package/dist/factory-assets/connectors/flow/engine/types.d.ts.map +1 -1
  68. package/dist/factory-assets/connectors/flow/engine.js +3 -3
  69. package/dist/factory-assets/connectors/flow/prompt-fragments.js +2 -2
  70. package/dist/factory-assets/connectors/flow/run-flow.js +6 -6
  71. package/dist/factory-assets/connectors/flow.js +5 -5
  72. package/dist/factory-assets/connectors/git.js +5 -5
  73. package/dist/factory-assets/connectors/gmail.js +5 -5
  74. package/dist/factory-assets/connectors/googledrive.js +5 -5
  75. package/dist/factory-assets/connectors/local.js +5 -5
  76. package/dist/factory-assets/connectors/mattermost.js +5 -5
  77. package/dist/factory-assets/connectors/memory.js +5 -5
  78. package/dist/factory-assets/connectors/minio.js +5 -5
  79. package/dist/factory-assets/connectors/postgres.js +5 -5
  80. package/dist/factory-assets/connectors/s3.js +5 -5
  81. package/dist/factory-assets/connectors/sharepoint.js +5 -5
  82. package/dist/factory-assets/connectors/sqlite.js +5 -5
  83. package/dist/factory-assets/connectors/static-server.js +5 -5
  84. package/dist/factory-assets/connectors/tunnel.js +5 -5
  85. package/dist/factory-assets/connectors/webdav.js +5 -5
  86. package/dist/factory-assets/connectors/xstate-store.js +5 -5
  87. package/dist/factory-assets/connectors/xstate.js +5 -5
  88. package/dist/{flows-YIW4HL3L.js → flows-K7B253U6.js} +3 -3
  89. package/dist/{flows-YIW4HL3L.js.map → flows-K7B253U6.js.map} +1 -1
  90. package/dist/{helpers-LURCZHA4.js → helpers-PXEHIKF7.js} +4 -4
  91. package/dist/{helpers-LURCZHA4.js.map → helpers-PXEHIKF7.js.map} +1 -1
  92. package/dist/{library-publish-2GMJM3NZ.js → library-publish-3Z33J2ZY.js} +9 -9
  93. package/dist/{library-publish-2GMJM3NZ.js.map → library-publish-3Z33J2ZY.js.map} +1 -1
  94. package/dist/{open-library-POFOXZWH.js → open-library-Y5SKFAMK.js} +8 -8
  95. package/dist/{open-library-POFOXZWH.js.map → open-library-Y5SKFAMK.js.map} +1 -1
  96. package/dist/{project-GVOPZEJZ.js → project-DQRC6J6M.js} +5 -5
  97. package/dist/{project-GVOPZEJZ.js.map → project-DQRC6J6M.js.map} +1 -1
  98. package/dist/runner/index.js +9 -9
  99. package/dist/sdk/asset-manager.js +1 -1
  100. package/dist/sdk/flow.js +3 -3
  101. package/dist/sdk/index.js +9 -9
  102. package/dist/sdk/runner.js +9 -9
  103. package/dist/sdk/store.js +1 -1
  104. package/dist/{source-FB3T4IHP.js → source-XBJ5KTAV.js} +9 -9
  105. package/dist/{source-FB3T4IHP.js.map → source-XBJ5KTAV.js.map} +1 -1
  106. package/dist/{source-manifest-publish-XTRDVPSC.js → source-manifest-publish-Q7TXBMCW.js} +10 -10
  107. package/dist/{source-manifest-publish-XTRDVPSC.js.map → source-manifest-publish-Q7TXBMCW.js.map} +1 -1
  108. package/dist/store/index.js +1 -1
  109. package/dist/store/src/store.d.ts +3 -2
  110. package/dist/store/src/store.d.ts.map +1 -1
  111. package/dist/tui/index.js +9 -9
  112. package/dist/types/src/events.d.ts +5 -1
  113. package/dist/types/src/events.d.ts.map +1 -1
  114. package/dist/workspace-plugin/adapters/mcp.js +1 -1
  115. package/dist/workspace-plugin/adapters/omp.js +3 -3
  116. package/dist/workspace-plugin/index.js +1 -1
  117. package/package.json +1 -1
  118. package/dist/chunk-4O2RAXKJ.js.map +0 -1
  119. package/dist/chunk-4QROZZ5Z.js.map +0 -1
  120. package/dist/chunk-EEHOMCRU.js.map +0 -1
  121. package/dist/chunk-OEGHKO5N.js.map +0 -1
  122. package/dist/chunk-RK3HU3H3.js.map +0 -1
  123. package/dist/chunk-V4ZLZJFN.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { logErr, logOk, colorRef, logInfo, S, logWarn, formatSoftDepHint } from './chunk-PJ6INYDD.js';
2
- import { AssetManager } from './chunk-WSARNOPP.js';
1
+ import { logErr, logOk, colorRef, logInfo, S, logWarn, formatSoftDepHint } from './chunk-XTFZOYNY.js';
2
+ import { AssetManager } from './chunk-6AYGXPPF.js';
3
3
  import { readLock } from './chunk-P43HBWKK.js';
4
4
  import { SUPPORTED_DRIVER_TARGETS } from './chunk-MENCWIHW.js';
5
5
  import { parseAssetRef } from './chunk-GEEW6SY2.js';
@@ -82,7 +82,7 @@ async function runRefInstall(ref, opts) {
82
82
  const spinner2 = p.spinner();
83
83
  spinner2.start(`Installing ${ref}`);
84
84
  try {
85
- const { openCatalogSource, openLibrary } = await import('./open-library-POFOXZWH.js');
85
+ const { openCatalogSource, openLibrary } = await import('./open-library-Y5SKFAMK.js');
86
86
  const catalog = await openCatalogSource({ projectDir: path.resolve(opts.projectDir) });
87
87
  if (!supportsInstallManifest(catalog)) {
88
88
  throw new Error(
@@ -122,7 +122,7 @@ async function runYamlInstall(opts) {
122
122
  return;
123
123
  }
124
124
  try {
125
- const { ensureSourcesCloned } = await import('./ensure-sources-QF72HVUM.js');
125
+ const { ensureSourcesCloned } = await import('./ensure-sources-N7B7657V.js');
126
126
  const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
127
127
  if (hydrate.cloned.length > 0) {
128
128
  logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
@@ -288,5 +288,5 @@ function makeCleanCommand() {
288
288
  }
289
289
 
290
290
  export { makeCheckCommand, makeCleanCommand, makeInstallCommand, reportInstalledSoftDeps, runPointerOnlyInstall, supportsInstallManifest };
291
- //# sourceMappingURL=chunk-ENBTXMPL.js.map
292
- //# sourceMappingURL=chunk-ENBTXMPL.js.map
291
+ //# sourceMappingURL=chunk-AZ44F3AT.js.map
292
+ //# sourceMappingURL=chunk-AZ44F3AT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../cli/src/commands/project.ts"],"names":["spinner","confirm"],"mappings":"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","file":"chunk-ENBTXMPL.js","sourcesContent":["import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { AssetManager } from \"@skaile/workspaces/asset-manager\";\nimport {\n type DriverTarget,\n parseAssetRef,\n readLock,\n SUPPORTED_DRIVER_TARGETS,\n} from \"@skaile/workspaces/core\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\nimport { Command } from \"commander\";\nimport { colorRef, formatSoftDepHint, logErr, logInfo, logOk, logWarn, S } from \"../helpers.ts\";\n\n/**\n * Canonical asset-ref shape accepted by `skaile install <ref>`:\n * `kind:@<publisher>/<name>#<version>` (the `#` version sigil). Validated via\n * `parseAssetRef` so the CLI shares the single canonical grammar; the legacy\n * trailing-`@version` shape is rejected.\n */\nconst REF_HINT = \"kind:@<publisher>/<name>#<version> (e.g. skill:@skaile/use-exa#1.0.0)\";\n\n/** True when `ref` parses as a canonical asset ref. */\nfunction isValidAssetRef(ref: string): boolean {\n try {\n parseAssetRef(ref);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Minimal catalog-source surface the pointer-only install path needs.\n * `RemoteCatalogSource` satisfies this — narrowing keeps {@link runPointerOnlyInstall}\n * testable with a hand-rolled stub.\n */\nexport interface InstallManifestSource {\n getInstallManifest(ref: string): Promise<InstallManifest>;\n}\n\n/**\n * Capability check: is this catalog source able to serve install manifests?\n *\n * `openCatalogSource` returns a `RemoteCatalogSource | RestCatalogSource`.\n * Only the tRPC-framed `RemoteCatalogSource` implements `getInstallManifest`;\n * the REST-framed `RestCatalogSource` (the default for any catalog URL other\n * than `https://skaile.store`) does not. Calling it unconditionally would be a\n * runtime `TypeError`, so the pointer-only install path must capability-detect\n * first and fail with a clear, actionable message.\n */\nexport function supportsInstallManifest(source: unknown): source is InstallManifestSource {\n return (\n typeof (source as { getInstallManifest?: unknown } | null | undefined)?.getInstallManifest ===\n \"function\"\n );\n}\n\n/**\n * Minimal library surface the pointer-only install path needs.\n * `LocalIndex` satisfies this.\n */\nexport interface InstallLibrary {\n install(manifest: InstallManifest): Promise<{ installPath: string }>;\n}\n\n/**\n * Result of a pointer-only catalog install.\n */\nexport interface PointerOnlyInstallResult {\n /** Absolute path the verified asset bytes were written to. */\n installPath: string;\n /** The pinned upstream commit SHA the asset was fetched at. */\n commitSha: string;\n /** Number of files in the install manifest. */\n fileCount: number;\n}\n\n/**\n * Pointer-only catalog install — the `skaile install <ref>` code path.\n *\n * 1. Resolves the pointer-only {@link InstallManifest} from the Catalog.\n * 2. Hands it to the library, which fetches each file's bytes directly from\n * the upstream repo at the pinned commit, verifies every per-file SHA256\n * plus the composite SHA256, and only then writes the verified files.\n *\n * Both dependencies are injected so the function is unit-testable without a\n * network round-trip. In production the CLI passes a `RemoteCatalogSource`\n * and a `LocalIndex`.\n *\n * @param ref - Asset ref (`<publisher>/<name>@<version>`, optional leading `@`).\n * @param deps - Injected catalog source + library.\n * @returns The install path, pinned commit SHA, and file count.\n * @throws When the ref is malformed, the manifest cannot be resolved, or any\n * hash verification fails. The underlying error message is surfaced as-is.\n */\nexport async function runPointerOnlyInstall(\n ref: string,\n deps: { catalog: InstallManifestSource; library: InstallLibrary },\n): Promise<PointerOnlyInstallResult> {\n let requested: ReturnType<typeof parseAssetRef>;\n try {\n requested = parseAssetRef(ref);\n } catch (e) {\n throw new Error(\n `malformed asset ref '${ref}' — expected ${REF_HINT}: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n const manifest = await deps.catalog.getInstallManifest(ref);\n // [M1] Identity check: the catalog must not install a different asset than\n // requested. Compare the PARSED refs (kind/publisher/name/pin) so equivalent\n // spellings (optional `kind:`, default `skill`) are treated as the same ref.\n const got = parseAssetRef(manifest.ref);\n if (\n got.kind !== requested.kind ||\n got.publisher !== requested.publisher ||\n got.name !== requested.name ||\n got.pin !== requested.pin\n ) {\n throw new Error(\n `catalog identity mismatch: requested '${ref}' but the catalog returned a manifest for '${manifest.ref}'`,\n );\n }\n const { installPath } = await deps.library.install(manifest);\n return {\n installPath,\n commitSha: manifest.source.commitSha,\n fileCount: manifest.files.length,\n };\n}\n\n/**\n * Creates the `skaile install` command.\n *\n * Two modes, selected by argument shape:\n *\n * - `skaile install` (no positional arg) — reads `skaile.yaml` and deploys all\n * declared assets (and their transitive dependencies) to the configured\n * driver target directory. Supports `--locked` for CI-mode install from a\n * lock file.\n * - `skaile install <publisher>/<name>@<version>` — pointer-only catalog\n * install: resolves the pointer-only install manifest from the configured\n * Catalog, fetches each file's bytes directly from the upstream repo at the\n * pinned commit, verifies every per-file + the composite SHA256, then writes\n * the verified files into the local Library.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-install-command\n */\nexport function makeInstallCommand(): Command {\n return new Command(\"install\")\n .description(`Install dependencies from skaile.yaml, or a single asset by ref (${REF_HINT})`)\n .argument(\"[ref]\", `Asset ref to install from the Catalog (${REF_HINT})`)\n .option(\"--locked\", \"Install from lock file (CI mode — fails on drift)\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .option(\"--target <agent>\", \"Agent framework\", \"claude-code\")\n .option(\n \"--global\",\n \"Install the global SSOT (~/.skaile/skaile.yaml), fanning out to every global backend\",\n )\n .option(\n \"--backend <ids>\",\n \"Comma-separated global backends to install into (default: all resolved); implies --global\",\n )\n .option(\n \"--link\",\n \"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)\",\n )\n .action(runInstallCommand);\n}\n\n/** Options shape accepted by the `skaile install` command action. */\ninterface InstallCommandOptions {\n locked?: boolean;\n projectDir: string;\n target: string;\n global?: boolean;\n backend?: string;\n link?: boolean;\n}\n\n/**\n * Parse a `--backend a,b` value into validated {@link DriverTarget}s, exiting on\n * an unknown id. Returns `undefined` when the flag is absent (resolve the full\n * global set instead).\n */\nfunction parseBackendFilter(raw: string | undefined): DriverTarget[] | undefined {\n if (!raw) return undefined;\n const ids = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const out: DriverTarget[] = [];\n for (const id of ids) {\n if (!(SUPPORTED_DRIVER_TARGETS as string[]).includes(id)) {\n logErr(`unknown backend '${id}' — expected one of: ${SUPPORTED_DRIVER_TARGETS.join(\", \")}`);\n process.exit(1);\n }\n out.push(id as DriverTarget);\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * `skaile install` action body. Dispatches by argument shape:\n * a positional `ref` selects pointer-only catalog install, otherwise the\n * legacy `skaile.yaml` install path runs.\n */\nasync function runInstallCommand(\n ref: string | undefined,\n opts: InstallCommandOptions,\n): Promise<void> {\n // ── Pointer-only catalog install: `skaile install <ref>` ──────────────\n if (ref !== undefined) {\n await runRefInstall(ref, opts);\n return;\n }\n\n // ── Legacy install: `skaile install` reads skaile.yaml ────────────────\n await runYamlInstall(opts);\n}\n\n/** Pointer-only catalog install path for `skaile install <ref>`. */\nasync function runRefInstall(ref: string, opts: InstallCommandOptions): Promise<void> {\n if (!isValidAssetRef(ref)) {\n logErr(`malformed asset ref '${ref}' — expected ${REF_HINT}`);\n process.exit(1);\n }\n const spinner = p.spinner();\n spinner.start(`Installing ${ref}`);\n try {\n const { openCatalogSource, openLibrary } = await import(\"../open-library.ts\");\n const catalog = await openCatalogSource({ projectDir: path.resolve(opts.projectDir) });\n // [H2] REST-framed catalogs (the default for any catalog URL other\n // than https://skaile.store) cannot serve install manifests. Detect\n // and fail clearly rather than throwing a runtime TypeError.\n if (!supportsInstallManifest(catalog)) {\n throw new Error(\n \"pointer-only install (skaile install <ref>) requires a tRPC-framed Catalog. \" +\n \"The configured catalog uses REST framing, which does not serve install \" +\n \"manifests. Set catalog.url to https://skaile.store, or catalog.framing: trpc, \" +\n \"in ~/.skaile/config.yaml.\",\n );\n }\n const library = await openLibrary();\n try {\n const result = await runPointerOnlyInstall(ref, { catalog, library });\n spinner.stop(\"Done\");\n logOk(`Installed ${colorRef(ref)}`);\n logInfo(`Path: ${S.dim(result.installPath)}`);\n logInfo(`Commit: ${S.dim(result.commitSha)}`);\n logInfo(`Files: ${S.dim(String(result.fileCount))}`);\n logInfo(\n S.dim(`Installed globally (see Path above) — use \\`skaile add ${ref}\\` to deploy into this project.`),\n );\n } finally {\n library.close();\n }\n } catch (err) {\n spinner.stop(\"Failed\");\n const msg = err instanceof Error ? err.message : String(err);\n if (/unreachable/i.test(msg)) {\n logErr(`asset uninstallable — source commit no longer available (${msg})`);\n } else {\n logErr(msg);\n }\n process.exit(1);\n }\n}\n\n/** Legacy install path for bare `skaile install` (reads skaile.yaml). */\nasync function runYamlInstall(opts: InstallCommandOptions): Promise<void> {\n const projectDir = path.resolve(opts.projectDir);\n\n const backends = parseBackendFilter(opts.backend);\n // `--backend` implies `--global`.\n if (opts.global || backends) {\n await runGlobalInstall(opts, backends);\n return;\n }\n\n // Hydrate sources declared in skaile.yaml before resolving assets, so\n // freshly checked-out projects pull their source clones automatically.\n try {\n const { ensureSourcesCloned } = await import(\"../ensure-sources.ts\");\n const hydrate = ensureSourcesCloned(projectDir, { quiet: true });\n if (hydrate.cloned.length > 0) {\n logOk(`Cloned source(s): ${hydrate.cloned.join(\", \")}`);\n }\n if (hydrate.failed.length > 0) {\n logErr(`Failed to clone source(s): ${hydrate.failed.join(\", \")}`);\n }\n } catch (err) {\n logWarn(`source hydration skipped: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const am = new AssetManager({\n projectDir,\n driverTarget: opts.target as DriverTarget,\n });\n const spinner = p.spinner();\n spinner.start(opts.locked ? \"Installing from lock file\" : \"Installing dependencies\");\n try {\n const result = await am.install({ locked: opts.locked, link: opts.link });\n spinner.stop(\"Done\");\n if (result.deployed.length > 0) {\n for (const d of result.deployed) logOk(d);\n }\n if (result.removed.length > 0) {\n for (const r of result.removed) logWarn(`Removed: ${r}`);\n }\n if (result.deployed.length === 0 && result.removed.length === 0) {\n logInfo(\"Nothing to install (already up to date).\");\n }\n if (result.missing.length > 0) {\n for (const m of result.missing) logErr(`Missing: ${m}`);\n // Partial-miss must fail the process — CI can't otherwise distinguish a\n // clean install from \"half the assets never resolved\".\n process.exitCode = 1;\n }\n if (result.lockWritten) {\n logInfo(`Lock file written: ${S.dim(\"skaile.lock.yaml\")}`);\n }\n // Report-only: surface soft deps the declared assets reference but aren't\n // present. Never a prompt — install is a batch/CI path. Skipped under\n // --locked: that mode is \"restore exactly\", so an `add` nudge would jar.\n if (!opts.locked) await reportInstalledSoftDeps(am);\n } catch (err) {\n spinner.stop(\"Failed\");\n logErr(String(err));\n process.exit(1);\n }\n}\n\n/**\n * Report (never prompt) the body-link soft deps that the declared assets\n * reference but that aren't in the project — the `install` counterpart to the\n * `add`-time soft-dep surface. `install` is a batch/CI path (often non-TTY), so\n * it only ever prints a hint: pulling stays an explicit `skaile add`. Best-effort\n * — `reportSoftDeps` swallows any index failure and returns `[]`.\n */\nexport async function reportInstalledSoftDeps(\n am: Pick<AssetManager, \"listDeclared\" | \"reportSoftDeps\">,\n onHint: (line: string) => void = (l) => logInfo(S.dim(l)),\n): Promise<void> {\n try {\n const declared = (await am.listDeclared()).map((d) => d.ref);\n if (declared.length === 0) return;\n const edges = await am.reportSoftDeps(declared);\n for (const edge of edges) onHint(formatSoftDepHint(edge));\n } catch {\n // Best-effort: a soft-dep report must never fail an install that succeeded.\n }\n}\n\n/**\n * Global cross-backend install: deploy every dep declared in the global SSOT\n * (`~/.skaile/skaile.yaml`) into each resolved global backend's dir under `~`,\n * write the global lock (`~/.skaile/skaile.lock.yaml`), then print per-backend\n * state. `backends` is the `--backend` filter (omit for the full resolved set).\n */\nasync function runGlobalInstall(\n opts: InstallCommandOptions,\n backends: DriverTarget[] | undefined,\n): Promise<void> {\n const am = new AssetManager({\n projectDir: path.resolve(opts.projectDir),\n global: true,\n backends,\n });\n const spinner = p.spinner();\n spinner.start(\"Installing global dependencies\");\n try {\n const result = await am.install({ locked: opts.locked, link: opts.link });\n spinner.stop(\"Done\");\n if (result.deployed.length > 0) for (const d of result.deployed) logOk(d);\n if (result.removed.length > 0) for (const r of result.removed) logWarn(`Removed: ${r}`);\n if (result.deployed.length === 0 && result.removed.length === 0)\n logInfo(\"Nothing to install (already up to date).\");\n if (result.missing.length > 0) {\n for (const m of result.missing) logErr(`Missing: ${m}`);\n process.exitCode = 1;\n }\n if (result.lockWritten) logInfo(`Global lock written: ${S.dim(\"~/.skaile/skaile.lock.yaml\")}`);\n\n // Per-backend reconciliation summary so a partial fan-out is visible.\n const state = am.globalState({});\n const byBackend = new Map<string, number>();\n for (const s of state)\n if (s.state === \"installed\") byBackend.set(s.backend, (byBackend.get(s.backend) ?? 0) + 1);\n for (const [backend, n] of byBackend) logInfo(`${backend}: ${n} installed`);\n } catch (err) {\n spinner.stop(\"Failed\");\n logErr(String(err));\n process.exit(1);\n }\n}\n\n/**\n * Creates the `skaile check` command.\n *\n * Scans all deployed assets for unmet dependency requirements **and** the\n * declared set for deps that resolved into the lock but never materialized, and\n * exits with code 1 if either is found. `doctor()` alone only walks *deployed*\n * assets' `requires`, so a declared dep whose bytes never landed (e.g. a\n * store-sourced `mcp-server`) used to report \"satisfied\" (#462).\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-check-command\n */\nexport function makeCheckCommand(): Command {\n return new Command(\"check\")\n .description(\"Check for unmet requirements\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .action(async (opts) => {\n const am = new AssetManager({ projectDir: path.resolve(opts.projectDir) });\n const issues = await am.doctor();\n // A project with no (or an unreadable) skaile.yaml has no declared set to\n // reconcile — treat it as drift-free so `check` behaves as it always has.\n let drifted: Awaited<ReturnType<typeof am.listDeclared>> = [];\n try {\n drifted = (await am.listDeclared()).filter((d) => d.state === \"drift\");\n } catch {\n // ignored — doctor() below is still authoritative for deployed assets.\n }\n if (issues.length === 0 && drifted.length === 0) {\n logOk(\"All dependencies satisfied.\");\n } else {\n for (const i of issues) {\n logErr(\n `${i.assetKind}:${i.assetName} requires ${i.depKind}:${i.depName} (${i.inRepos ? \"fixable\" : \"not found\"})`,\n );\n }\n for (const d of drifted) {\n logErr(`${d.ref} is declared and locked but not materialized — run \\`skaile install\\``);\n }\n process.exit(1);\n }\n });\n}\n\n/**\n * Creates the `skaile clean` command.\n *\n * Removes all skaile-managed assets tracked in `skaile.lock.yaml` from the\n * workspace. With `--all` also removes history, patches, repos, and the lock\n * file itself. Preserves unmanaged (manually placed) assets.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-clean-command\n */\nexport function makeCleanCommand(): Command {\n return new Command(\"clean\")\n .description(\"Remove all skaile-managed assets from the workspace\")\n .option(\"--all\", \"Full reset: also remove history, patches, repos, and lock file\")\n .option(\"--dry-run\", \"Show what would be removed without doing it\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .option(\"--target <agent>\", \"Agent framework\", \"claude-code\")\n .action(async (opts) => {\n const am = new AssetManager({\n projectDir: path.resolve(opts.projectDir),\n driverTarget: opts.target as DriverTarget,\n });\n\n // Preview: load lock file to show what will be cleaned\n const lock = readLock(path.resolve(opts.projectDir, \"skaile.lock.yaml\"));\n\n if (!lock || Object.keys(lock.assets).length === 0) {\n logInfo(\"Nothing to clean (no skaile-managed assets found).\");\n return;\n }\n\n const assetRefs = Object.keys(lock.assets);\n console.log();\n console.log(` ${S.heading(\"Assets to remove:\")} ${S.dim(`(${assetRefs.length})`)}`);\n for (const ref of assetRefs) {\n console.log(` ${colorRef(ref)}`);\n }\n\n if (opts.all) {\n console.log();\n console.log(` ${S.heading(\"Also removing:\")}`);\n console.log(` ${S.dim(\".skaile/history.yaml\")}`);\n console.log(` ${S.dim(\".skaile/patches/\")}`);\n console.log(` ${S.dim(\"skaile.lock.yaml\")}`);\n }\n\n if (opts.dryRun) {\n console.log();\n logInfo(\"Dry run — no changes made.\");\n return;\n }\n\n if (!opts.yes) {\n const confirm = await p.confirm({ message: \"Proceed?\" });\n if (p.isCancel(confirm) || !confirm) {\n logInfo(\"Cancelled.\");\n return;\n }\n }\n\n const result = am.clean({ all: opts.all });\n\n console.log();\n for (const r of result.removed) {\n logOk(`Removed ${r}`);\n }\n for (const s of result.skipped) {\n logWarn(`Skipped ${s.ref}: ${s.reason}`);\n }\n if (result.unmanaged.length > 0) {\n console.log();\n logInfo(`Kept ${result.unmanaged.length} unmanaged asset(s):`);\n for (const u of result.unmanaged) {\n console.log(` ${S.dim(u)}`);\n }\n }\n if (opts.all) {\n console.log();\n logOk(\"Full reset complete.\");\n }\n });\n}\n"]}
1
+ {"version":3,"sources":["../cli/src/commands/project.ts"],"names":["spinner","confirm"],"mappings":"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","file":"chunk-AZ44F3AT.js","sourcesContent":["import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { AssetManager } from \"@skaile/workspaces/asset-manager\";\nimport {\n type DriverTarget,\n parseAssetRef,\n readLock,\n SUPPORTED_DRIVER_TARGETS,\n} from \"@skaile/workspaces/core\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\nimport { Command } from \"commander\";\nimport { colorRef, formatSoftDepHint, logErr, logInfo, logOk, logWarn, S } from \"../helpers.ts\";\n\n/**\n * Canonical asset-ref shape accepted by `skaile install <ref>`:\n * `kind:@<publisher>/<name>#<version>` (the `#` version sigil). Validated via\n * `parseAssetRef` so the CLI shares the single canonical grammar; the legacy\n * trailing-`@version` shape is rejected.\n */\nconst REF_HINT = \"kind:@<publisher>/<name>#<version> (e.g. skill:@skaile/use-exa#1.0.0)\";\n\n/** True when `ref` parses as a canonical asset ref. */\nfunction isValidAssetRef(ref: string): boolean {\n try {\n parseAssetRef(ref);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Minimal catalog-source surface the pointer-only install path needs.\n * `RemoteCatalogSource` satisfies this — narrowing keeps {@link runPointerOnlyInstall}\n * testable with a hand-rolled stub.\n */\nexport interface InstallManifestSource {\n getInstallManifest(ref: string): Promise<InstallManifest>;\n}\n\n/**\n * Capability check: is this catalog source able to serve install manifests?\n *\n * `openCatalogSource` returns a `RemoteCatalogSource | RestCatalogSource`.\n * Only the tRPC-framed `RemoteCatalogSource` implements `getInstallManifest`;\n * the REST-framed `RestCatalogSource` (the default for any catalog URL other\n * than `https://skaile.store`) does not. Calling it unconditionally would be a\n * runtime `TypeError`, so the pointer-only install path must capability-detect\n * first and fail with a clear, actionable message.\n */\nexport function supportsInstallManifest(source: unknown): source is InstallManifestSource {\n return (\n typeof (source as { getInstallManifest?: unknown } | null | undefined)?.getInstallManifest ===\n \"function\"\n );\n}\n\n/**\n * Minimal library surface the pointer-only install path needs.\n * `LocalIndex` satisfies this.\n */\nexport interface InstallLibrary {\n install(manifest: InstallManifest): Promise<{ installPath: string }>;\n}\n\n/**\n * Result of a pointer-only catalog install.\n */\nexport interface PointerOnlyInstallResult {\n /** Absolute path the verified asset bytes were written to. */\n installPath: string;\n /** The pinned upstream commit SHA the asset was fetched at. */\n commitSha: string;\n /** Number of files in the install manifest. */\n fileCount: number;\n}\n\n/**\n * Pointer-only catalog install — the `skaile install <ref>` code path.\n *\n * 1. Resolves the pointer-only {@link InstallManifest} from the Catalog.\n * 2. Hands it to the library, which fetches each file's bytes directly from\n * the upstream repo at the pinned commit, verifies every per-file SHA256\n * plus the composite SHA256, and only then writes the verified files.\n *\n * Both dependencies are injected so the function is unit-testable without a\n * network round-trip. In production the CLI passes a `RemoteCatalogSource`\n * and a `LocalIndex`.\n *\n * @param ref - Asset ref (`<publisher>/<name>@<version>`, optional leading `@`).\n * @param deps - Injected catalog source + library.\n * @returns The install path, pinned commit SHA, and file count.\n * @throws When the ref is malformed, the manifest cannot be resolved, or any\n * hash verification fails. The underlying error message is surfaced as-is.\n */\nexport async function runPointerOnlyInstall(\n ref: string,\n deps: { catalog: InstallManifestSource; library: InstallLibrary },\n): Promise<PointerOnlyInstallResult> {\n let requested: ReturnType<typeof parseAssetRef>;\n try {\n requested = parseAssetRef(ref);\n } catch (e) {\n throw new Error(\n `malformed asset ref '${ref}' — expected ${REF_HINT}: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n const manifest = await deps.catalog.getInstallManifest(ref);\n // [M1] Identity check: the catalog must not install a different asset than\n // requested. Compare the PARSED refs (kind/publisher/name/pin) so equivalent\n // spellings (optional `kind:`, default `skill`) are treated as the same ref.\n const got = parseAssetRef(manifest.ref);\n if (\n got.kind !== requested.kind ||\n got.publisher !== requested.publisher ||\n got.name !== requested.name ||\n got.pin !== requested.pin\n ) {\n throw new Error(\n `catalog identity mismatch: requested '${ref}' but the catalog returned a manifest for '${manifest.ref}'`,\n );\n }\n const { installPath } = await deps.library.install(manifest);\n return {\n installPath,\n commitSha: manifest.source.commitSha,\n fileCount: manifest.files.length,\n };\n}\n\n/**\n * Creates the `skaile install` command.\n *\n * Two modes, selected by argument shape:\n *\n * - `skaile install` (no positional arg) — reads `skaile.yaml` and deploys all\n * declared assets (and their transitive dependencies) to the configured\n * driver target directory. Supports `--locked` for CI-mode install from a\n * lock file.\n * - `skaile install <publisher>/<name>@<version>` — pointer-only catalog\n * install: resolves the pointer-only install manifest from the configured\n * Catalog, fetches each file's bytes directly from the upstream repo at the\n * pinned commit, verifies every per-file + the composite SHA256, then writes\n * the verified files into the local Library.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-install-command\n */\nexport function makeInstallCommand(): Command {\n return new Command(\"install\")\n .description(`Install dependencies from skaile.yaml, or a single asset by ref (${REF_HINT})`)\n .argument(\"[ref]\", `Asset ref to install from the Catalog (${REF_HINT})`)\n .option(\"--locked\", \"Install from lock file (CI mode — fails on drift)\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .option(\"--target <agent>\", \"Agent framework\", \"claude-code\")\n .option(\n \"--global\",\n \"Install the global SSOT (~/.skaile/skaile.yaml), fanning out to every global backend\",\n )\n .option(\n \"--backend <ids>\",\n \"Comma-separated global backends to install into (default: all resolved); implies --global\",\n )\n .option(\n \"--link\",\n \"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)\",\n )\n .action(runInstallCommand);\n}\n\n/** Options shape accepted by the `skaile install` command action. */\ninterface InstallCommandOptions {\n locked?: boolean;\n projectDir: string;\n target: string;\n global?: boolean;\n backend?: string;\n link?: boolean;\n}\n\n/**\n * Parse a `--backend a,b` value into validated {@link DriverTarget}s, exiting on\n * an unknown id. Returns `undefined` when the flag is absent (resolve the full\n * global set instead).\n */\nfunction parseBackendFilter(raw: string | undefined): DriverTarget[] | undefined {\n if (!raw) return undefined;\n const ids = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const out: DriverTarget[] = [];\n for (const id of ids) {\n if (!(SUPPORTED_DRIVER_TARGETS as string[]).includes(id)) {\n logErr(`unknown backend '${id}' — expected one of: ${SUPPORTED_DRIVER_TARGETS.join(\", \")}`);\n process.exit(1);\n }\n out.push(id as DriverTarget);\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * `skaile install` action body. Dispatches by argument shape:\n * a positional `ref` selects pointer-only catalog install, otherwise the\n * legacy `skaile.yaml` install path runs.\n */\nasync function runInstallCommand(\n ref: string | undefined,\n opts: InstallCommandOptions,\n): Promise<void> {\n // ── Pointer-only catalog install: `skaile install <ref>` ──────────────\n if (ref !== undefined) {\n await runRefInstall(ref, opts);\n return;\n }\n\n // ── Legacy install: `skaile install` reads skaile.yaml ────────────────\n await runYamlInstall(opts);\n}\n\n/** Pointer-only catalog install path for `skaile install <ref>`. */\nasync function runRefInstall(ref: string, opts: InstallCommandOptions): Promise<void> {\n if (!isValidAssetRef(ref)) {\n logErr(`malformed asset ref '${ref}' — expected ${REF_HINT}`);\n process.exit(1);\n }\n const spinner = p.spinner();\n spinner.start(`Installing ${ref}`);\n try {\n const { openCatalogSource, openLibrary } = await import(\"../open-library.ts\");\n const catalog = await openCatalogSource({ projectDir: path.resolve(opts.projectDir) });\n // [H2] REST-framed catalogs (the default for any catalog URL other\n // than https://skaile.store) cannot serve install manifests. Detect\n // and fail clearly rather than throwing a runtime TypeError.\n if (!supportsInstallManifest(catalog)) {\n throw new Error(\n \"pointer-only install (skaile install <ref>) requires a tRPC-framed Catalog. \" +\n \"The configured catalog uses REST framing, which does not serve install \" +\n \"manifests. Set catalog.url to https://skaile.store, or catalog.framing: trpc, \" +\n \"in ~/.skaile/config.yaml.\",\n );\n }\n const library = await openLibrary();\n try {\n const result = await runPointerOnlyInstall(ref, { catalog, library });\n spinner.stop(\"Done\");\n logOk(`Installed ${colorRef(ref)}`);\n logInfo(`Path: ${S.dim(result.installPath)}`);\n logInfo(`Commit: ${S.dim(result.commitSha)}`);\n logInfo(`Files: ${S.dim(String(result.fileCount))}`);\n logInfo(\n S.dim(`Installed globally (see Path above) — use \\`skaile add ${ref}\\` to deploy into this project.`),\n );\n } finally {\n library.close();\n }\n } catch (err) {\n spinner.stop(\"Failed\");\n const msg = err instanceof Error ? err.message : String(err);\n if (/unreachable/i.test(msg)) {\n logErr(`asset uninstallable — source commit no longer available (${msg})`);\n } else {\n logErr(msg);\n }\n process.exit(1);\n }\n}\n\n/** Legacy install path for bare `skaile install` (reads skaile.yaml). */\nasync function runYamlInstall(opts: InstallCommandOptions): Promise<void> {\n const projectDir = path.resolve(opts.projectDir);\n\n const backends = parseBackendFilter(opts.backend);\n // `--backend` implies `--global`.\n if (opts.global || backends) {\n await runGlobalInstall(opts, backends);\n return;\n }\n\n // Hydrate sources declared in skaile.yaml before resolving assets, so\n // freshly checked-out projects pull their source clones automatically.\n try {\n const { ensureSourcesCloned } = await import(\"../ensure-sources.ts\");\n const hydrate = ensureSourcesCloned(projectDir, { quiet: true });\n if (hydrate.cloned.length > 0) {\n logOk(`Cloned source(s): ${hydrate.cloned.join(\", \")}`);\n }\n if (hydrate.failed.length > 0) {\n logErr(`Failed to clone source(s): ${hydrate.failed.join(\", \")}`);\n }\n } catch (err) {\n logWarn(`source hydration skipped: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const am = new AssetManager({\n projectDir,\n driverTarget: opts.target as DriverTarget,\n });\n const spinner = p.spinner();\n spinner.start(opts.locked ? \"Installing from lock file\" : \"Installing dependencies\");\n try {\n const result = await am.install({ locked: opts.locked, link: opts.link });\n spinner.stop(\"Done\");\n if (result.deployed.length > 0) {\n for (const d of result.deployed) logOk(d);\n }\n if (result.removed.length > 0) {\n for (const r of result.removed) logWarn(`Removed: ${r}`);\n }\n if (result.deployed.length === 0 && result.removed.length === 0) {\n logInfo(\"Nothing to install (already up to date).\");\n }\n if (result.missing.length > 0) {\n for (const m of result.missing) logErr(`Missing: ${m}`);\n // Partial-miss must fail the process — CI can't otherwise distinguish a\n // clean install from \"half the assets never resolved\".\n process.exitCode = 1;\n }\n if (result.lockWritten) {\n logInfo(`Lock file written: ${S.dim(\"skaile.lock.yaml\")}`);\n }\n // Report-only: surface soft deps the declared assets reference but aren't\n // present. Never a prompt — install is a batch/CI path. Skipped under\n // --locked: that mode is \"restore exactly\", so an `add` nudge would jar.\n if (!opts.locked) await reportInstalledSoftDeps(am);\n } catch (err) {\n spinner.stop(\"Failed\");\n logErr(String(err));\n process.exit(1);\n }\n}\n\n/**\n * Report (never prompt) the body-link soft deps that the declared assets\n * reference but that aren't in the project — the `install` counterpart to the\n * `add`-time soft-dep surface. `install` is a batch/CI path (often non-TTY), so\n * it only ever prints a hint: pulling stays an explicit `skaile add`. Best-effort\n * — `reportSoftDeps` swallows any index failure and returns `[]`.\n */\nexport async function reportInstalledSoftDeps(\n am: Pick<AssetManager, \"listDeclared\" | \"reportSoftDeps\">,\n onHint: (line: string) => void = (l) => logInfo(S.dim(l)),\n): Promise<void> {\n try {\n const declared = (await am.listDeclared()).map((d) => d.ref);\n if (declared.length === 0) return;\n const edges = await am.reportSoftDeps(declared);\n for (const edge of edges) onHint(formatSoftDepHint(edge));\n } catch {\n // Best-effort: a soft-dep report must never fail an install that succeeded.\n }\n}\n\n/**\n * Global cross-backend install: deploy every dep declared in the global SSOT\n * (`~/.skaile/skaile.yaml`) into each resolved global backend's dir under `~`,\n * write the global lock (`~/.skaile/skaile.lock.yaml`), then print per-backend\n * state. `backends` is the `--backend` filter (omit for the full resolved set).\n */\nasync function runGlobalInstall(\n opts: InstallCommandOptions,\n backends: DriverTarget[] | undefined,\n): Promise<void> {\n const am = new AssetManager({\n projectDir: path.resolve(opts.projectDir),\n global: true,\n backends,\n });\n const spinner = p.spinner();\n spinner.start(\"Installing global dependencies\");\n try {\n const result = await am.install({ locked: opts.locked, link: opts.link });\n spinner.stop(\"Done\");\n if (result.deployed.length > 0) for (const d of result.deployed) logOk(d);\n if (result.removed.length > 0) for (const r of result.removed) logWarn(`Removed: ${r}`);\n if (result.deployed.length === 0 && result.removed.length === 0)\n logInfo(\"Nothing to install (already up to date).\");\n if (result.missing.length > 0) {\n for (const m of result.missing) logErr(`Missing: ${m}`);\n process.exitCode = 1;\n }\n if (result.lockWritten) logInfo(`Global lock written: ${S.dim(\"~/.skaile/skaile.lock.yaml\")}`);\n\n // Per-backend reconciliation summary so a partial fan-out is visible.\n const state = am.globalState({});\n const byBackend = new Map<string, number>();\n for (const s of state)\n if (s.state === \"installed\") byBackend.set(s.backend, (byBackend.get(s.backend) ?? 0) + 1);\n for (const [backend, n] of byBackend) logInfo(`${backend}: ${n} installed`);\n } catch (err) {\n spinner.stop(\"Failed\");\n logErr(String(err));\n process.exit(1);\n }\n}\n\n/**\n * Creates the `skaile check` command.\n *\n * Scans all deployed assets for unmet dependency requirements **and** the\n * declared set for deps that resolved into the lock but never materialized, and\n * exits with code 1 if either is found. `doctor()` alone only walks *deployed*\n * assets' `requires`, so a declared dep whose bytes never landed (e.g. a\n * store-sourced `mcp-server`) used to report \"satisfied\" (#462).\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-check-command\n */\nexport function makeCheckCommand(): Command {\n return new Command(\"check\")\n .description(\"Check for unmet requirements\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .action(async (opts) => {\n const am = new AssetManager({ projectDir: path.resolve(opts.projectDir) });\n const issues = await am.doctor();\n // A project with no (or an unreadable) skaile.yaml has no declared set to\n // reconcile — treat it as drift-free so `check` behaves as it always has.\n let drifted: Awaited<ReturnType<typeof am.listDeclared>> = [];\n try {\n drifted = (await am.listDeclared()).filter((d) => d.state === \"drift\");\n } catch {\n // ignored — doctor() below is still authoritative for deployed assets.\n }\n if (issues.length === 0 && drifted.length === 0) {\n logOk(\"All dependencies satisfied.\");\n } else {\n for (const i of issues) {\n logErr(\n `${i.assetKind}:${i.assetName} requires ${i.depKind}:${i.depName} (${i.inRepos ? \"fixable\" : \"not found\"})`,\n );\n }\n for (const d of drifted) {\n logErr(`${d.ref} is declared and locked but not materialized — run \\`skaile install\\``);\n }\n process.exit(1);\n }\n });\n}\n\n/**\n * Creates the `skaile clean` command.\n *\n * Removes all skaile-managed assets tracked in `skaile.lock.yaml` from the\n * workspace. With `--all` also removes history, patches, repos, and the lock\n * file itself. Preserves unmanaged (manually placed) assets.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-clean-command\n */\nexport function makeCleanCommand(): Command {\n return new Command(\"clean\")\n .description(\"Remove all skaile-managed assets from the workspace\")\n .option(\"--all\", \"Full reset: also remove history, patches, repos, and lock file\")\n .option(\"--dry-run\", \"Show what would be removed without doing it\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .option(\"--target <agent>\", \"Agent framework\", \"claude-code\")\n .action(async (opts) => {\n const am = new AssetManager({\n projectDir: path.resolve(opts.projectDir),\n driverTarget: opts.target as DriverTarget,\n });\n\n // Preview: load lock file to show what will be cleaned\n const lock = readLock(path.resolve(opts.projectDir, \"skaile.lock.yaml\"));\n\n if (!lock || Object.keys(lock.assets).length === 0) {\n logInfo(\"Nothing to clean (no skaile-managed assets found).\");\n return;\n }\n\n const assetRefs = Object.keys(lock.assets);\n console.log();\n console.log(` ${S.heading(\"Assets to remove:\")} ${S.dim(`(${assetRefs.length})`)}`);\n for (const ref of assetRefs) {\n console.log(` ${colorRef(ref)}`);\n }\n\n if (opts.all) {\n console.log();\n console.log(` ${S.heading(\"Also removing:\")}`);\n console.log(` ${S.dim(\".skaile/history.yaml\")}`);\n console.log(` ${S.dim(\".skaile/patches/\")}`);\n console.log(` ${S.dim(\"skaile.lock.yaml\")}`);\n }\n\n if (opts.dryRun) {\n console.log();\n logInfo(\"Dry run — no changes made.\");\n return;\n }\n\n if (!opts.yes) {\n const confirm = await p.confirm({ message: \"Proceed?\" });\n if (p.isCancel(confirm) || !confirm) {\n logInfo(\"Cancelled.\");\n return;\n }\n }\n\n const result = am.clean({ all: opts.all });\n\n console.log();\n for (const r of result.removed) {\n logOk(`Removed ${r}`);\n }\n for (const s of result.skipped) {\n logWarn(`Skipped ${s.ref}: ${s.reason}`);\n }\n if (result.unmanaged.length > 0) {\n console.log();\n logInfo(`Kept ${result.unmanaged.length} unmanaged asset(s):`);\n for (const u of result.unmanaged) {\n console.log(` ${S.dim(u)}`);\n }\n }\n if (opts.all) {\n console.log();\n logOk(\"Full reset complete.\");\n }\n });\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { resolveFlowBindings, stableFlowJson, parseFlowDefinition, evaluateFlowExpression, inspectFlowExpression, collectFlowBindingExpressions } from './chunk-OEGHKO5N.js';
2
- import { isAgentNode, nodeBindings, nodeIsOptional, nodeSkillId, nodeLabel, isActiveRuntimeNode } from './chunk-4QROZZ5Z.js';
1
+ import { resolveFlowBindings, stableFlowJson, evaluateFlowExpression, FlowExpressionError, parseFlowDefinition, inspectFlowExpression, collectFlowBindingExpressions } from './chunk-XJ74XFIZ.js';
2
+ import { isAgentNode, nodeBindings, isRouterNode, nodeIsOptional, nodeSkillId, nodeLabel, isActiveRuntimeNode } from './chunk-TUYN2HDT.js';
3
3
  import { assetSearchDirs } from './chunk-ZAP2BDHG.js';
4
4
  import * as z2 from 'zod';
5
5
  import * as path from 'path';
@@ -42,6 +42,286 @@ function interpolateNodeInstruction(instruction, values) {
42
42
  });
43
43
  }
44
44
 
45
+ // factory-assets/connectors/flow/engine/router-settlement.ts
46
+ var ROUTER_SELECTION_MARKER = "\n\n[skaile:flow-router-selection:";
47
+ function pendingProducerOutput(flow, snapshots, missingPath) {
48
+ if (!missingPath) return false;
49
+ const segments = missingPath.split(".");
50
+ if (segments.length < 5 || segments[0] !== "nodes" || segments[2] !== "output" || segments[3] !== "fields") {
51
+ return false;
52
+ }
53
+ const producer = flow.nodes.find(({ id }) => id === segments[1]);
54
+ if (!producer?.contract?.output?.fields) return false;
55
+ return snapshots.get(producer.id)?.status !== "complete";
56
+ }
57
+ function evaluateRouterSelection(flow, router, snapshots) {
58
+ if (!isRouterNode(router)) return { unresolved: "no-match" };
59
+ const context = buildFlowExpressionContext(flow, snapshots);
60
+ for (const route of router.run.routes) {
61
+ try {
62
+ if (evaluateFlowExpression(route.when, context)) {
63
+ return { selectedTarget: route.target };
64
+ }
65
+ } catch (error) {
66
+ if (error instanceof FlowExpressionError && pendingProducerOutput(flow, snapshots, error.missingPath)) {
67
+ return { unresolved: "not-ready" };
68
+ }
69
+ throw error;
70
+ }
71
+ }
72
+ return { unresolved: "no-match" };
73
+ }
74
+ function routerSelectionOutput(selectedTarget) {
75
+ const summary = selectedTarget === null ? "Router completed without selecting a target." : `Router selected ${selectedTarget}.`;
76
+ return {
77
+ summary: `${summary}${ROUTER_SELECTION_MARKER}${JSON.stringify(selectedTarget)}]`,
78
+ artifacts: []
79
+ };
80
+ }
81
+ function routeTargets(router) {
82
+ if (!isRouterNode(router)) return [];
83
+ return [...new Set(router.run.routes.flatMap(({ target }) => target === null ? [] : [target]))];
84
+ }
85
+ function routerOwnershipIndex(flow, snapshots) {
86
+ const routers = flow.nodes.filter(
87
+ (node) => isRouterNode(node) && !["complete", "failed", "skipped"].includes(snapshots.get(node.id)?.status ?? "not_started")
88
+ );
89
+ const routerIds = new Set(routers.map(({ id }) => id));
90
+ const hardOutgoing = /* @__PURE__ */ new Map();
91
+ for (const edge of flow.edges) {
92
+ if (edge.type !== "flow") continue;
93
+ const targets = hardOutgoing.get(edge.source) ?? [];
94
+ targets.push(edge.target);
95
+ hardOutgoing.set(edge.source, targets);
96
+ }
97
+ const outgoing = /* @__PURE__ */ new Map();
98
+ for (const router of routers) {
99
+ const owned = /* @__PURE__ */ new Set();
100
+ const visited = /* @__PURE__ */ new Set();
101
+ const queue = routeTargets(router);
102
+ for (let index = 0; index < queue.length; index++) {
103
+ const nodeId = queue[index];
104
+ if (visited.has(nodeId)) continue;
105
+ visited.add(nodeId);
106
+ if (routerIds.has(nodeId)) owned.add(nodeId);
107
+ queue.push(...hardOutgoing.get(nodeId) ?? []);
108
+ }
109
+ outgoing.set(router.id, [...owned]);
110
+ }
111
+ return { routers, outgoing };
112
+ }
113
+ function routerOwnershipSourceComponents(flow, snapshots) {
114
+ const { routers, outgoing } = routerOwnershipIndex(flow, snapshots);
115
+ const reverse = /* @__PURE__ */ new Map();
116
+ for (const router of routers) reverse.set(router.id, []);
117
+ for (const [source, targets] of outgoing) {
118
+ for (const target of targets) reverse.get(target)?.push(source);
119
+ }
120
+ const visited = /* @__PURE__ */ new Set();
121
+ const finished = [];
122
+ for (const router of routers) {
123
+ if (visited.has(router.id)) continue;
124
+ const stack = [
125
+ { nodeId: router.id, exiting: false }
126
+ ];
127
+ while (stack.length > 0) {
128
+ const frame = stack.pop();
129
+ if (!frame) break;
130
+ if (frame.exiting) {
131
+ finished.push(frame.nodeId);
132
+ continue;
133
+ }
134
+ if (visited.has(frame.nodeId)) continue;
135
+ visited.add(frame.nodeId);
136
+ stack.push({ nodeId: frame.nodeId, exiting: true });
137
+ const targets = outgoing.get(frame.nodeId) ?? [];
138
+ for (let index = targets.length - 1; index >= 0; index--) {
139
+ if (!visited.has(targets[index])) {
140
+ stack.push({ nodeId: targets[index], exiting: false });
141
+ }
142
+ }
143
+ }
144
+ }
145
+ const componentByRouter = /* @__PURE__ */ new Map();
146
+ const components = [];
147
+ for (let index = finished.length - 1; index >= 0; index--) {
148
+ const start = finished[index];
149
+ if (componentByRouter.has(start)) continue;
150
+ const componentId = components.length;
151
+ const component = [];
152
+ const stack = [start];
153
+ componentByRouter.set(start, componentId);
154
+ while (stack.length > 0) {
155
+ const nodeId = stack.pop();
156
+ if (!nodeId) break;
157
+ component.push(nodeId);
158
+ for (const source of reverse.get(nodeId) ?? []) {
159
+ if (componentByRouter.has(source)) continue;
160
+ componentByRouter.set(source, componentId);
161
+ stack.push(source);
162
+ }
163
+ }
164
+ components.push(component);
165
+ }
166
+ const incomingComponents = /* @__PURE__ */ new Set();
167
+ for (const [source, targets] of outgoing) {
168
+ const sourceComponent = componentByRouter.get(source);
169
+ for (const target of targets) {
170
+ const targetComponent = componentByRouter.get(target);
171
+ if (sourceComponent !== void 0 && targetComponent !== void 0 && sourceComponent !== targetComponent) {
172
+ incomingComponents.add(targetComponent);
173
+ }
174
+ }
175
+ }
176
+ const definitionOrder = new Map(flow.nodes.map((node, index) => [node.id, index]));
177
+ const sourceComponents = components.filter(
178
+ (_, componentId) => !incomingComponents.has(componentId)
179
+ );
180
+ for (const component of sourceComponents) {
181
+ component.sort(
182
+ (left, right) => (definitionOrder.get(left) ?? Number.MAX_SAFE_INTEGER) - (definitionOrder.get(right) ?? Number.MAX_SAFE_INTEGER)
183
+ );
184
+ }
185
+ return sourceComponents.sort(
186
+ (left, right) => (definitionOrder.get(left[0]) ?? Number.MAX_SAFE_INTEGER) - (definitionOrder.get(right[0]) ?? Number.MAX_SAFE_INTEGER)
187
+ );
188
+ }
189
+ function persistedRouterSelection(router, snapshot) {
190
+ if (!isRouterNode(router) || snapshot?.status !== "complete") return void 0;
191
+ const summary = snapshot.output?.summary;
192
+ const markerIndex = summary?.lastIndexOf(ROUTER_SELECTION_MARKER) ?? -1;
193
+ if (!summary || markerIndex < 0 || !summary.endsWith("]")) return void 0;
194
+ let selectedTarget;
195
+ try {
196
+ selectedTarget = JSON.parse(summary.slice(markerIndex + ROUTER_SELECTION_MARKER.length, -1));
197
+ } catch {
198
+ return void 0;
199
+ }
200
+ if (selectedTarget !== null && (typeof selectedTarget !== "string" || !routeTargets(router).includes(selectedTarget))) {
201
+ return void 0;
202
+ }
203
+ if (selectedTarget === null && !router.run.routes.some(({ target }) => target === null)) {
204
+ return void 0;
205
+ }
206
+ return summary === routerSelectionOutput(selectedTarget).summary ? { selectedTarget } : void 0;
207
+ }
208
+ function edgeKey(source, target) {
209
+ return `${source}\0${target}`;
210
+ }
211
+ function planRouterSkips(flow, snapshots, settlements) {
212
+ const routers = flow.nodes.filter(isRouterNode);
213
+ const currentSelections = new Map(
214
+ settlements.map(({ routerNodeId, selectedTarget }) => [routerNodeId, selectedTarget])
215
+ );
216
+ const knownSelections = /* @__PURE__ */ new Map();
217
+ for (const router of routers) {
218
+ if (currentSelections.has(router.id)) {
219
+ knownSelections.set(router.id, currentSelections.get(router.id) ?? null);
220
+ continue;
221
+ }
222
+ const persisted = persistedRouterSelection(router, snapshots.get(router.id));
223
+ if (persisted) knownSelections.set(router.id, persisted.selectedTarget);
224
+ }
225
+ const outgoing = /* @__PURE__ */ new Map();
226
+ const incoming = /* @__PURE__ */ new Map();
227
+ for (const edge of flow.edges) {
228
+ if (edge.type !== "flow") continue;
229
+ const targets = outgoing.get(edge.source) ?? [];
230
+ targets.push(edge.target);
231
+ outgoing.set(edge.source, targets);
232
+ const sources = incoming.get(edge.target) ?? [];
233
+ sources.push(edge.source);
234
+ incoming.set(edge.target, sources);
235
+ }
236
+ const losingRoots = /* @__PURE__ */ new Set();
237
+ const selectedRoots = /* @__PURE__ */ new Set();
238
+ const losingRouteEdges = /* @__PURE__ */ new Set();
239
+ for (const router of routers) {
240
+ if (!knownSelections.has(router.id)) continue;
241
+ const selectedTarget = knownSelections.get(router.id) ?? null;
242
+ if (selectedTarget !== null) selectedRoots.add(selectedTarget);
243
+ for (const target of routeTargets(router)) {
244
+ if (target === selectedTarget) continue;
245
+ losingRoots.add(target);
246
+ losingRouteEdges.add(edgeKey(router.id, target));
247
+ }
248
+ }
249
+ const candidateOrigins = /* @__PURE__ */ new Map();
250
+ for (const root of losingRoots) {
251
+ const visited = /* @__PURE__ */ new Set();
252
+ const queue = [root];
253
+ for (let index = 0; index < queue.length; index++) {
254
+ const nodeId = queue[index];
255
+ if (visited.has(nodeId)) continue;
256
+ visited.add(nodeId);
257
+ const origins = candidateOrigins.get(nodeId) ?? /* @__PURE__ */ new Set();
258
+ origins.add(root);
259
+ candidateOrigins.set(nodeId, origins);
260
+ for (const target of outgoing.get(nodeId) ?? []) queue.push(target);
261
+ }
262
+ }
263
+ const candidates = new Set(candidateOrigins.keys());
264
+ const protectionQueue = [...selectedRoots];
265
+ for (const [nodeId, origins] of candidateOrigins) {
266
+ if (origins.size >= 2) protectionQueue.push(nodeId);
267
+ for (const source of incoming.get(nodeId) ?? []) {
268
+ if (candidates.has(source)) continue;
269
+ if (losingRouteEdges.has(edgeKey(source, nodeId))) continue;
270
+ if (["failed", "skipped"].includes(snapshots.get(source)?.status ?? "not_started")) continue;
271
+ protectionQueue.push(nodeId);
272
+ break;
273
+ }
274
+ }
275
+ const unknownSelections = /* @__PURE__ */ new Map();
276
+ for (const router of routers) {
277
+ if (knownSelections.has(router.id)) continue;
278
+ const status = snapshots.get(router.id)?.status ?? "not_started";
279
+ if (status === "failed" || status === "skipped") continue;
280
+ const targets = routeTargets(router);
281
+ unknownSelections.set(router.id, targets);
282
+ if (!candidates.has(router.id)) protectionQueue.push(...targets);
283
+ }
284
+ const protectedNodes = /* @__PURE__ */ new Set();
285
+ for (let index = 0; index < protectionQueue.length; index++) {
286
+ const nodeId = protectionQueue[index];
287
+ if (protectedNodes.has(nodeId)) continue;
288
+ protectedNodes.add(nodeId);
289
+ protectionQueue.push(...outgoing.get(nodeId) ?? []);
290
+ protectionQueue.push(...unknownSelections.get(nodeId) ?? []);
291
+ }
292
+ return flow.nodes.flatMap(
293
+ (node) => candidates.has(node.id) && !protectedNodes.has(node.id) ? [node.id] : []
294
+ );
295
+ }
296
+ function unsettledRouterBranchIds(flow, snapshots) {
297
+ const unsettled = flow.nodes.filter(
298
+ (node) => isRouterNode(node) && !["complete", "failed", "skipped"].includes(snapshots.get(node.id)?.status ?? "not_started")
299
+ );
300
+ const branches = new Set(
301
+ planRouterSkips(
302
+ flow,
303
+ snapshots,
304
+ unsettled.map(({ id }) => ({ routerNodeId: id, selectedTarget: null }))
305
+ )
306
+ );
307
+ for (const component of routerOwnershipSourceComponents(flow, snapshots)) {
308
+ for (const routerId of component) branches.delete(routerId);
309
+ }
310
+ return branches;
311
+ }
312
+ function availableRouterFrontier(flow, snapshots) {
313
+ const nodesById = new Map(flow.nodes.map((node) => [node.id, node]));
314
+ return routerOwnershipSourceComponents(flow, snapshots).flatMap((component) => {
315
+ for (const routerId of component) {
316
+ const node = nodesById.get(routerId);
317
+ if (!node || snapshots.get(routerId)?.status !== "available") continue;
318
+ if ("unresolved" in evaluateRouterSelection(flow, node, snapshots)) continue;
319
+ return [node];
320
+ }
321
+ return [];
322
+ });
323
+ }
324
+
45
325
  // factory-assets/connectors/flow/engine/engine.ts
46
326
  function activeRuntimeNodes(flow) {
47
327
  return flow.nodes.filter(isActiveRuntimeNode);
@@ -81,6 +361,20 @@ function buildOutgoing(edges) {
81
361
  }
82
362
  return map;
83
363
  }
364
+ function resolveAvailableRouter(flow, routerNodeId, snapshots) {
365
+ const router = flow.nodes.find((node) => node.id === routerNodeId);
366
+ if (!router || !isRouterNode(router)) return void 0;
367
+ const state = computeFlowStateFromSnapshots(flow, snapshots);
368
+ if (!state.available.includes(routerNodeId)) return void 0;
369
+ const selected = evaluateRouterSelection(flow, router, snapshots);
370
+ if ("unresolved" in selected) return selected;
371
+ return {
372
+ selectedTarget: selected.selectedTarget,
373
+ skippedNodeIds: planRouterSkips(flow, snapshots, [
374
+ { routerNodeId, selectedTarget: selected.selectedTarget }
375
+ ])
376
+ };
377
+ }
84
378
  function computeFlowState(flow, completedIds, runningIds = /* @__PURE__ */ new Set(), skippedIds = /* @__PURE__ */ new Set()) {
85
379
  const nodes = activeRuntimeNodes(flow);
86
380
  const incoming = buildIncoming(flow.edges);
@@ -89,6 +383,7 @@ function computeFlowState(flow, completedIds, runningIds = /* @__PURE__ */ new S
89
383
  const status = completedIds.has(node.id) ? "complete" : runningIds.has(node.id) ? "running" : skippedIds.has(node.id) ? "skipped" : "not_started";
90
384
  snapshots.set(node.id, { status });
91
385
  }
386
+ const gatedBranches = unsettledRouterBranchIds(flow, snapshots);
92
387
  const context = buildFlowExpressionContext(flow, snapshots);
93
388
  const nodeStates = nodes.map((node) => {
94
389
  const optional = nodeIsOptional(node);
@@ -130,6 +425,18 @@ function computeFlowState(flow, completedIds, runningIds = /* @__PURE__ */ new S
130
425
  failedPreconditions: []
131
426
  };
132
427
  }
428
+ if (gatedBranches.has(node.id)) {
429
+ return {
430
+ nodeId: node.id,
431
+ skillId,
432
+ label,
433
+ status: "not_started",
434
+ optional,
435
+ canRun: false,
436
+ blockers: [],
437
+ failedPreconditions: []
438
+ };
439
+ }
133
440
  const edges = incoming.get(node.id) ?? [];
134
441
  const hardBlockers = edges.filter((e) => e.type === "flow").filter((e) => !completedIds.has(e.source) && !skippedIds.has(e.source)).map((e) => e.source);
135
442
  const preconditionFailures = failedPreconditions(node, context);
@@ -164,6 +471,7 @@ function computeFlowState(flow, completedIds, runningIds = /* @__PURE__ */ new S
164
471
  function computeFlowStateFromSnapshots(flow, snapshots) {
165
472
  const nodes = activeRuntimeNodes(flow);
166
473
  const incoming = buildIncoming(flow.edges);
474
+ const gatedBranches = unsettledRouterBranchIds(flow, snapshots);
167
475
  const context = buildFlowExpressionContext(flow, snapshots);
168
476
  const statusFor = (nodeId) => snapshots.get(nodeId)?.status ?? "not_started";
169
477
  const passed = (nodeId) => {
@@ -182,7 +490,9 @@ function computeFlowStateFromSnapshots(flow, snapshots) {
182
490
  const isAdmissionState = status === "not_started" || status === "available";
183
491
  const preconditionFailures = isAdmissionState ? failedPreconditions(node, context) : [];
184
492
  let effectiveStatus = status;
185
- if (isAdmissionState) {
493
+ if (isAdmissionState && gatedBranches.has(node.id)) {
494
+ effectiveStatus = "not_started";
495
+ } else if (isAdmissionState) {
186
496
  effectiveStatus = hardBlockers.length === 0 && preconditionFailures.length === 0 ? "available" : "not_started";
187
497
  }
188
498
  return {
@@ -441,6 +751,6 @@ function loadAllFlows(aiResourcesRoot) {
441
751
  return [...byId.values()];
442
752
  }
443
753
 
444
- export { FlowManifestSchema, buildFlowExpressionContext, computeFlowState, computeFlowStateFromSnapshots, computeSkippable, flowKindProvider, getConsumedOutputSchema, interpolateNodeInstruction, isBlocking, loadAllFlows, loadFlow, loadFlowsFromDir, resolveNextNodes, resolveNodeBindings, validateConsumedNodeOutput, validateFlow };
445
- //# sourceMappingURL=chunk-4O2RAXKJ.js.map
446
- //# sourceMappingURL=chunk-4O2RAXKJ.js.map
754
+ export { FlowManifestSchema, availableRouterFrontier, buildFlowExpressionContext, computeFlowState, computeFlowStateFromSnapshots, computeSkippable, evaluateRouterSelection, flowKindProvider, getConsumedOutputSchema, interpolateNodeInstruction, isBlocking, loadAllFlows, loadFlow, loadFlowsFromDir, persistedRouterSelection, planRouterSkips, resolveAvailableRouter, resolveNextNodes, resolveNodeBindings, routerSelectionOutput, unsettledRouterBranchIds, validateConsumedNodeOutput, validateFlow };
755
+ //# sourceMappingURL=chunk-E4AVJMOJ.js.map
756
+ //# sourceMappingURL=chunk-E4AVJMOJ.js.map