@skaile/workspaces 0.45.0 → 0.47.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 (136) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/dist/{asset-feeds-AOZLZMDV.js → asset-feeds-DLRQWELS.js} +7 -7
  3. package/dist/{asset-feeds-AOZLZMDV.js.map → asset-feeds-DLRQWELS.js.map} +1 -1
  4. package/dist/asset-manager/index.js +7 -7
  5. package/dist/asset-manager/installer.js +6 -6
  6. package/dist/asset-manager/renderers.js +2 -2
  7. package/dist/asset-manager/src/index.d.ts.map +1 -1
  8. package/dist/{chunk-VPXV2Z5E.js → chunk-3VBQJZYL.js} +6 -6
  9. package/dist/chunk-3VBQJZYL.js.map +1 -0
  10. package/dist/{chunk-FYLIR4AV.js → chunk-4OCZBSBY.js} +5 -2
  11. package/dist/chunk-4OCZBSBY.js.map +1 -0
  12. package/dist/{chunk-CVWA4RIK.js → chunk-4VPRAG35.js} +5 -5
  13. package/dist/{chunk-CVWA4RIK.js.map → chunk-4VPRAG35.js.map} +1 -1
  14. package/dist/{chunk-RGPBEGP2.js → chunk-CU5Z7GH3.js} +6 -2
  15. package/dist/chunk-CU5Z7GH3.js.map +1 -0
  16. package/dist/{chunk-CBZEIFU4.js → chunk-DDR4OSSM.js} +3 -3
  17. package/dist/{chunk-CBZEIFU4.js.map → chunk-DDR4OSSM.js.map} +1 -1
  18. package/dist/{chunk-L6BKSTAX.js → chunk-DHU4LJZV.js} +16 -18
  19. package/dist/chunk-DHU4LJZV.js.map +1 -0
  20. package/dist/{chunk-PCXU2CVW.js → chunk-FAALG3QN.js} +4 -4
  21. package/dist/{chunk-PCXU2CVW.js.map → chunk-FAALG3QN.js.map} +1 -1
  22. package/dist/{chunk-BLGHFVXE.js → chunk-G3GODNHM.js} +66 -4
  23. package/dist/chunk-G3GODNHM.js.map +1 -0
  24. package/dist/{chunk-JUZGLINM.js → chunk-HETXFD2Q.js} +2 -2
  25. package/dist/{chunk-JUZGLINM.js.map → chunk-HETXFD2Q.js.map} +1 -1
  26. package/dist/{chunk-ETDXTGDF.js → chunk-HOEP5CJQ.js} +3 -3
  27. package/dist/{chunk-ETDXTGDF.js.map → chunk-HOEP5CJQ.js.map} +1 -1
  28. package/dist/{chunk-5FVJXQDP.js → chunk-JXHULIOA.js} +3 -3
  29. package/dist/{chunk-5FVJXQDP.js.map → chunk-JXHULIOA.js.map} +1 -1
  30. package/dist/{chunk-ZAEJ33Y6.js → chunk-LLOXWWB6.js} +5 -5
  31. package/dist/{chunk-ZAEJ33Y6.js.map → chunk-LLOXWWB6.js.map} +1 -1
  32. package/dist/{chunk-N2KV5RK3.js → chunk-ON5NSPB6.js} +8 -8
  33. package/dist/{chunk-N2KV5RK3.js.map → chunk-ON5NSPB6.js.map} +1 -1
  34. package/dist/{chunk-GM3BV6JK.js → chunk-P6HRQPXC.js} +2 -2
  35. package/dist/{chunk-GM3BV6JK.js.map → chunk-P6HRQPXC.js.map} +1 -1
  36. package/dist/{chunk-LHUCCPH4.js → chunk-THAJ4MOW.js} +5 -5
  37. package/dist/{chunk-LHUCCPH4.js.map → chunk-THAJ4MOW.js.map} +1 -1
  38. package/dist/{chunk-XUXVH3JK.js → chunk-WRBF34YE.js} +3 -3
  39. package/dist/{chunk-XUXVH3JK.js.map → chunk-WRBF34YE.js.map} +1 -1
  40. package/dist/{chunk-COSTF7QW.js → chunk-WTFJFW7F.js} +50 -12
  41. package/dist/chunk-WTFJFW7F.js.map +1 -0
  42. package/dist/{chunk-LMRO2QNF.js → chunk-XUUMKMMJ.js} +119 -6
  43. package/dist/chunk-XUUMKMMJ.js.map +1 -0
  44. package/dist/{chunk-XF2BBX6P.js → chunk-Z3ZRI2AE.js} +3 -3
  45. package/dist/{chunk-XF2BBX6P.js.map → chunk-Z3ZRI2AE.js.map} +1 -1
  46. package/dist/cli/index.js +128 -81
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  49. package/dist/cli/src/commands/catalog.d.ts +2 -1
  50. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  51. package/dist/cli/src/commands/npx.d.ts.map +1 -1
  52. package/dist/cli/src/commands/project.d.ts.map +1 -1
  53. package/dist/cli/src/commands/source.d.ts +17 -4
  54. package/dist/cli/src/commands/source.d.ts.map +1 -1
  55. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  56. package/dist/cli/src/ensure-sources.d.ts.map +1 -1
  57. package/dist/connectors/config.js +4 -4
  58. package/dist/connectors/index.js +6 -6
  59. package/dist/connectors/rclone.js +1 -1
  60. package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
  61. package/dist/core/index.js +3 -3
  62. package/dist/core/runtime-assets.js +2 -2
  63. package/dist/core/src/conformance.d.ts +33 -0
  64. package/dist/core/src/conformance.d.ts.map +1 -0
  65. package/dist/core/src/index.d.ts +2 -1
  66. package/dist/core/src/index.d.ts.map +1 -1
  67. package/dist/core/src/repo-manager.d.ts +24 -0
  68. package/dist/core/src/repo-manager.d.ts.map +1 -1
  69. package/dist/core/src/runtime-assets.d.ts.map +1 -1
  70. package/dist/core/src/workspace-config.d.ts.map +1 -1
  71. package/dist/core/workspace-config.js +1 -1
  72. package/dist/deploy/index.js +3 -3
  73. package/dist/discovery/index.js +2 -2
  74. package/dist/{ensure-sources-NSDMTAWN.js → ensure-sources-KLCGXVE6.js} +12 -13
  75. package/dist/ensure-sources-KLCGXVE6.js.map +1 -0
  76. package/dist/factory-assets/connectors/deploy.js +6 -6
  77. package/dist/factory-assets/connectors/devserver.js +6 -6
  78. package/dist/factory-assets/connectors/flow/adapter.js +6 -6
  79. package/dist/factory-assets/connectors/flow/engine.js +3 -3
  80. package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
  81. package/dist/factory-assets/connectors/flow.js +6 -6
  82. package/dist/factory-assets/connectors/git/CONNECTOR.md +8 -0
  83. package/dist/factory-assets/connectors/git/driver.d.ts +55 -1
  84. package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
  85. package/dist/factory-assets/connectors/git.js +6 -6
  86. package/dist/factory-assets/connectors/gmail.js +6 -6
  87. package/dist/factory-assets/connectors/googledrive.js +6 -6
  88. package/dist/factory-assets/connectors/local.js +6 -6
  89. package/dist/factory-assets/connectors/mattermost.js +6 -6
  90. package/dist/factory-assets/connectors/memory.js +6 -6
  91. package/dist/factory-assets/connectors/minio.js +6 -6
  92. package/dist/factory-assets/connectors/postgres.js +6 -6
  93. package/dist/factory-assets/connectors/s3.js +6 -6
  94. package/dist/factory-assets/connectors/sharepoint.js +6 -6
  95. package/dist/factory-assets/connectors/sqlite.js +6 -6
  96. package/dist/factory-assets/connectors/static-server.js +6 -6
  97. package/dist/factory-assets/connectors/tunnel.js +6 -6
  98. package/dist/factory-assets/connectors/webdav.js +6 -6
  99. package/dist/factory-assets/connectors/xstate-store.js +6 -6
  100. package/dist/factory-assets/connectors/xstate.js +6 -6
  101. package/dist/{flows-WELXQ7IG.js → flows-PNDUCOJR.js} +3 -3
  102. package/dist/{flows-WELXQ7IG.js.map → flows-PNDUCOJR.js.map} +1 -1
  103. package/dist/library/index.js +6 -6
  104. package/dist/library/install.js +3 -3
  105. package/dist/{open-library-362BZ6OW.js → open-library-COHFCT4N.js} +9 -9
  106. package/dist/{open-library-362BZ6OW.js.map → open-library-COHFCT4N.js.map} +1 -1
  107. package/dist/{paths-4SSFMX5Z.js → paths-2SYXGTZJ.js} +6 -6
  108. package/dist/{paths-4SSFMX5Z.js.map → paths-2SYXGTZJ.js.map} +1 -1
  109. package/dist/{plugin-store-2X2YXJVG.js → plugin-store-UNENLB56.js} +5 -5
  110. package/dist/{plugin-store-2X2YXJVG.js.map → plugin-store-UNENLB56.js.map} +1 -1
  111. package/dist/runner/index.js +8 -8
  112. package/dist/sdk/asset-manager.js +7 -7
  113. package/dist/sdk/core.js +3 -3
  114. package/dist/sdk/flow.js +3 -3
  115. package/dist/sdk/index.js +8 -8
  116. package/dist/sdk/runner.js +8 -8
  117. package/dist/{setup-VGZTFQ32.js → setup-AYH6SR4U.js} +5 -5
  118. package/dist/{setup-VGZTFQ32.js.map → setup-AYH6SR4U.js.map} +1 -1
  119. package/dist/{store-client-XFZFKY3W.js → store-client-U4FMAIWX.js} +6 -6
  120. package/dist/{store-client-XFZFKY3W.js.map → store-client-U4FMAIWX.js.map} +1 -1
  121. package/dist/tui/index.js +8 -8
  122. package/dist/types/manifests.js +1 -1
  123. package/dist/types/src/manifests/skill.d.ts +1 -0
  124. package/dist/types/src/manifests/skill.d.ts.map +1 -1
  125. package/dist/workspace-plugin/adapters/mcp.js +1 -1
  126. package/dist/workspace-plugin/adapters/omp.js +3 -3
  127. package/dist/workspace-plugin/index.js +1 -1
  128. package/package.json +1 -1
  129. package/dist/chunk-BLGHFVXE.js.map +0 -1
  130. package/dist/chunk-COSTF7QW.js.map +0 -1
  131. package/dist/chunk-FYLIR4AV.js.map +0 -1
  132. package/dist/chunk-L6BKSTAX.js.map +0 -1
  133. package/dist/chunk-LMRO2QNF.js.map +0 -1
  134. package/dist/chunk-RGPBEGP2.js.map +0 -1
  135. package/dist/chunk-VPXV2Z5E.js.map +0 -1
  136. package/dist/ensure-sources-NSDMTAWN.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { globalSettingsPath, mapLegacyFields } from './chunk-BLGHFVXE.js';
1
+ import { globalSettingsPath, mapLegacyFields } from './chunk-G3GODNHM.js';
2
2
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
3
3
  import { homedir } from 'os';
4
4
  import { join } from 'path';
@@ -89,5 +89,5 @@ function isStoreAuthenticated(config) {
89
89
  }
90
90
 
91
91
  export { clearStoreTokens, getStoreConfig, isStoreAuthenticated, saveStoreTokens, storeFetch };
92
- //# sourceMappingURL=chunk-XF2BBX6P.js.map
93
- //# sourceMappingURL=chunk-XF2BBX6P.js.map
92
+ //# sourceMappingURL=chunk-Z3ZRI2AE.js.map
93
+ //# sourceMappingURL=chunk-Z3ZRI2AE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../cli/src/store-client.ts"],"names":[],"mappings":"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","file":"chunk-XF2BBX6P.js","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { globalSettingsPath, mapLegacyFields } from \"@skaile/workspaces/core\";\n\n/**\n * Connection configuration for the AI Asset Store API.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport interface StoreConfig {\n url: string;\n jwt: string | null;\n refreshToken: string | null;\n}\n\n/**\n * Read store connection config from global user settings, falling back to\n * `SKAILE_STORE_URL` env var and the default store URL.\n *\n * @returns Populated {@link StoreConfig} with `url`, `jwt`, and `refreshToken`.\n * @docLink cli/dev-guide#store-client\n */\nexport function getStoreConfig(): StoreConfig {\n const settingsPath = globalSettingsPath();\n let settings: Record<string, any> = {};\n if (existsSync(settingsPath)) {\n try {\n settings = mapLegacyFields(JSON.parse(readFileSync(settingsPath, \"utf-8\")));\n } catch {\n settings = {};\n }\n }\n return {\n url: settings.storeUrl ?? process.env.SKAILE_STORE_URL ?? \"https://store.skaile.ai\",\n jwt: settings.storeJwt ?? null,\n refreshToken: settings.storeRefreshToken ?? null,\n };\n}\n\n/** Path to user-level settings */\nfunction userSettingsPath(): string {\n return join(homedir(), \".skaile\", \"settings.json\");\n}\n\n/**\n * Persist store authentication tokens to `~/.skaile/settings.json`.\n *\n * @param jwt - The JWT access token returned by the store login endpoint.\n * @param refreshToken - The refresh token for obtaining new JWTs.\n * @docLink cli/dev-guide#store-client\n */\nexport function saveStoreTokens(jwt: string, refreshToken: string): void {\n const settingsPath = userSettingsPath();\n const dir = join(settingsPath, \"..\");\n mkdirSync(dir, { recursive: true });\n\n let current: Record<string, any> = {};\n if (existsSync(settingsPath)) {\n try {\n current = JSON.parse(readFileSync(settingsPath, \"utf-8\"));\n } catch {\n current = {};\n }\n }\n\n current.storeJwt = jwt;\n current.storeRefreshToken = refreshToken;\n writeFileSync(settingsPath, JSON.stringify(current, null, 2), \"utf-8\");\n}\n\n/**\n * Remove store authentication tokens from `~/.skaile/settings.json`.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport function clearStoreTokens(): void {\n const settingsPath = userSettingsPath();\n if (!existsSync(settingsPath)) return;\n\n try {\n const current = JSON.parse(readFileSync(settingsPath, \"utf-8\"));\n delete current.storeJwt;\n delete current.storeRefreshToken;\n writeFileSync(settingsPath, JSON.stringify(current, null, 2), \"utf-8\");\n } catch {\n // ignore\n }\n}\n\n/**\n * Make an authenticated HTTP request to the store REST API with a 1.5s timeout.\n *\n * @param config - Store connection config (URL + auth token).\n * @param path - API path (e.g. `/api/assets`).\n * @param opts - Optional method, body, query params, and extra headers.\n * @returns Parsed JSON response body.\n * @docLink cli/dev-guide#store-client\n */\nexport async function storeFetch<T = any>(\n config: StoreConfig,\n path: string,\n opts?: {\n method?: string;\n body?: unknown;\n params?: Record<string, string>;\n headers?: Record<string, string>;\n },\n): Promise<T> {\n let url = `${config.url}${path}`;\n if (opts?.params) {\n const sp = new URLSearchParams(opts.params);\n url += `?${sp}`;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...(opts?.headers ?? {}),\n };\n if (config.jwt) {\n headers.Authorization = `Bearer ${config.jwt}`;\n }\n\n const fetchOpts: RequestInit = {\n method: opts?.method ?? \"GET\",\n headers,\n };\n if (opts?.body) {\n fetchOpts.body = JSON.stringify(opts.body);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 1_500);\n try {\n const res = await fetch(url, { ...fetchOpts, signal: controller.signal });\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error((body as any).error ?? `Store API error: ${res.status}`);\n }\n return res.json() as Promise<T>;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Return `true` if a JWT token is present in the provided (or default) store config.\n *\n * @param config - Optional pre-loaded config; if omitted, calls {@link getStoreConfig}.\n * @docLink cli/dev-guide#store-client\n */\nexport function isStoreAuthenticated(config?: StoreConfig): boolean {\n const c = config ?? getStoreConfig();\n return !!c.jwt;\n}\n"]}
1
+ {"version":3,"sources":["../cli/src/store-client.ts"],"names":[],"mappings":"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","file":"chunk-Z3ZRI2AE.js","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { globalSettingsPath, mapLegacyFields } from \"@skaile/workspaces/core\";\n\n/**\n * Connection configuration for the AI Asset Store API.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport interface StoreConfig {\n url: string;\n jwt: string | null;\n refreshToken: string | null;\n}\n\n/**\n * Read store connection config from global user settings, falling back to\n * `SKAILE_STORE_URL` env var and the default store URL.\n *\n * @returns Populated {@link StoreConfig} with `url`, `jwt`, and `refreshToken`.\n * @docLink cli/dev-guide#store-client\n */\nexport function getStoreConfig(): StoreConfig {\n const settingsPath = globalSettingsPath();\n let settings: Record<string, any> = {};\n if (existsSync(settingsPath)) {\n try {\n settings = mapLegacyFields(JSON.parse(readFileSync(settingsPath, \"utf-8\")));\n } catch {\n settings = {};\n }\n }\n return {\n url: settings.storeUrl ?? process.env.SKAILE_STORE_URL ?? \"https://store.skaile.ai\",\n jwt: settings.storeJwt ?? null,\n refreshToken: settings.storeRefreshToken ?? null,\n };\n}\n\n/** Path to user-level settings */\nfunction userSettingsPath(): string {\n return join(homedir(), \".skaile\", \"settings.json\");\n}\n\n/**\n * Persist store authentication tokens to `~/.skaile/settings.json`.\n *\n * @param jwt - The JWT access token returned by the store login endpoint.\n * @param refreshToken - The refresh token for obtaining new JWTs.\n * @docLink cli/dev-guide#store-client\n */\nexport function saveStoreTokens(jwt: string, refreshToken: string): void {\n const settingsPath = userSettingsPath();\n const dir = join(settingsPath, \"..\");\n mkdirSync(dir, { recursive: true });\n\n let current: Record<string, any> = {};\n if (existsSync(settingsPath)) {\n try {\n current = JSON.parse(readFileSync(settingsPath, \"utf-8\"));\n } catch {\n current = {};\n }\n }\n\n current.storeJwt = jwt;\n current.storeRefreshToken = refreshToken;\n writeFileSync(settingsPath, JSON.stringify(current, null, 2), \"utf-8\");\n}\n\n/**\n * Remove store authentication tokens from `~/.skaile/settings.json`.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport function clearStoreTokens(): void {\n const settingsPath = userSettingsPath();\n if (!existsSync(settingsPath)) return;\n\n try {\n const current = JSON.parse(readFileSync(settingsPath, \"utf-8\"));\n delete current.storeJwt;\n delete current.storeRefreshToken;\n writeFileSync(settingsPath, JSON.stringify(current, null, 2), \"utf-8\");\n } catch {\n // ignore\n }\n}\n\n/**\n * Make an authenticated HTTP request to the store REST API with a 1.5s timeout.\n *\n * @param config - Store connection config (URL + auth token).\n * @param path - API path (e.g. `/api/assets`).\n * @param opts - Optional method, body, query params, and extra headers.\n * @returns Parsed JSON response body.\n * @docLink cli/dev-guide#store-client\n */\nexport async function storeFetch<T = any>(\n config: StoreConfig,\n path: string,\n opts?: {\n method?: string;\n body?: unknown;\n params?: Record<string, string>;\n headers?: Record<string, string>;\n },\n): Promise<T> {\n let url = `${config.url}${path}`;\n if (opts?.params) {\n const sp = new URLSearchParams(opts.params);\n url += `?${sp}`;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...(opts?.headers ?? {}),\n };\n if (config.jwt) {\n headers.Authorization = `Bearer ${config.jwt}`;\n }\n\n const fetchOpts: RequestInit = {\n method: opts?.method ?? \"GET\",\n headers,\n };\n if (opts?.body) {\n fetchOpts.body = JSON.stringify(opts.body);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 1_500);\n try {\n const res = await fetch(url, { ...fetchOpts, signal: controller.signal });\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error((body as any).error ?? `Store API error: ${res.status}`);\n }\n return res.json() as Promise<T>;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Return `true` if a JWT token is present in the provided (or default) store config.\n *\n * @param config - Optional pre-loaded config; if omitted, calls {@link getStoreConfig}.\n * @docLink cli/dev-guide#store-client\n */\nexport function isStoreAuthenticated(config?: StoreConfig): boolean {\n const c = config ?? getStoreConfig();\n return !!c.jwt;\n}\n"]}
package/dist/cli/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-PCXU2CVW.js';
2
+ import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-FAALG3QN.js';
3
3
  import { logErr, S, logOk, logInfo, colorRef, logWarn, kindColorPad, kindColor, formatRelativeTime, fitWidth } from '../chunk-GYPA2Q7F.js';
4
- import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-XF2BBX6P.js';
5
- import { AI_RESOURCES, aiResourceRoots } from '../chunk-ETDXTGDF.js';
4
+ import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-Z3ZRI2AE.js';
5
+ import { AI_RESOURCES, aiResourceRoots } from '../chunk-HOEP5CJQ.js';
6
6
  import { LocalSecretsProvider } from '../chunk-6BEGKO2Q.js';
7
- import { resolveLibraryDir, LocalCatalogSource } from '../chunk-ZAEJ33Y6.js';
8
- import '../chunk-5FVJXQDP.js';
7
+ import { resolveLibraryDir, LocalCatalogSource } from '../chunk-LLOXWWB6.js';
8
+ import '../chunk-JXHULIOA.js';
9
9
  import '../chunk-JXT46QFC.js';
10
10
  import '../chunk-UKJMQZV6.js';
11
11
  import '../chunk-R7FOF242.js';
12
- import { runFlow, resumeFlow } from '../chunk-LHUCCPH4.js';
12
+ import { runFlow, resumeFlow } from '../chunk-THAJ4MOW.js';
13
13
  import '../chunk-4R6DROGN.js';
14
14
  import { validateFlowVersions, parseSkillFrontmatter } from '../chunk-GXC3TYMQ.js';
15
- import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-N2KV5RK3.js';
16
- import { buildClaudePluginFiles } from '../chunk-JUZGLINM.js';
15
+ import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-ON5NSPB6.js';
16
+ import { buildClaudePluginFiles } from '../chunk-HETXFD2Q.js';
17
17
  import '../chunk-X5YPJV4N.js';
18
18
  import '../chunk-O7SG5PC2.js';
19
19
  import '../chunk-7QBNJTTQ.js';
@@ -28,20 +28,20 @@ import '../chunk-BMQKMOQY.js';
28
28
  import '../chunk-GAH4YRCI.js';
29
29
  import '../chunk-OCAQH66V.js';
30
30
  import '../chunk-LV2HPH3C.js';
31
- import '../chunk-LMRO2QNF.js';
31
+ import '../chunk-XUUMKMMJ.js';
32
32
  import '../chunk-OVRSNIKJ.js';
33
- import '../chunk-CBZEIFU4.js';
34
- import '../chunk-FYLIR4AV.js';
33
+ import '../chunk-DDR4OSSM.js';
34
+ import '../chunk-4OCZBSBY.js';
35
35
  import '../chunk-6E6PKKAD.js';
36
36
  import { loadFlow, loadAllFlows } from '../chunk-X46FY45B.js';
37
37
  import '../chunk-DEYYRFQU.js';
38
38
  import '../chunk-IFGTRL2I.js';
39
- import { AssetManager, NON_DEPLOYABLE_KINDS, MissingManifestError } from '../chunk-L6BKSTAX.js';
40
- import '../chunk-CVWA4RIK.js';
41
- import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-BLGHFVXE.js';
39
+ import { AssetManager, NON_DEPLOYABLE_KINDS, MissingManifestError } from '../chunk-DHU4LJZV.js';
40
+ import '../chunk-4VPRAG35.js';
41
+ import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor, checkAgentSkillConformance } from '../chunk-G3GODNHM.js';
42
42
  import { assetSearchDirs, detectDomains } from '../chunk-ZAP2BDHG.js';
43
- import '../chunk-VPXV2Z5E.js';
44
- import { globalCacheRoot, getGlobalCacheDir, resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-COSTF7QW.js';
43
+ import '../chunk-3VBQJZYL.js';
44
+ import { globalCacheRoot, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, sourceShortName, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-WTFJFW7F.js';
45
45
  import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, saveSkPublishManifest } from '../chunk-DZCK7GRW.js';
46
46
  import { parseFrontmatter } from '../chunk-6IDBWPK2.js';
47
47
  import { parseAssetRef, ASSET_KINDS, isValidAssetName, slugifyAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-GEEW6SY2.js';
@@ -51,12 +51,12 @@ import { DRIVER_DEFAULTS } from '../chunk-K5GBV4SA.js';
51
51
  import { openSqlite } from '../chunk-JB35MVBN.js';
52
52
  import '../chunk-KTBKW2FI.js';
53
53
  import '../chunk-UQ6LFBPZ.js';
54
- import '../chunk-XUXVH3JK.js';
55
- import '../chunk-RGPBEGP2.js';
54
+ import '../chunk-WRBF34YE.js';
55
+ import '../chunk-CU5Z7GH3.js';
56
56
  import '../chunk-CGYEHQOX.js';
57
57
  import '../chunk-NSBPE2FW.js';
58
58
  import * as fs12 from 'fs';
59
- import fs12__default, { readFileSync, existsSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
59
+ import fs12__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
60
60
  import * as path14 from 'path';
61
61
  import path14__default, { resolve, join } from 'path';
62
62
  import { fileURLToPath } from 'url';
@@ -128,7 +128,7 @@ function printLocalEntries(entries) {
128
128
  }
129
129
  async function searchStore(query, kind, opts) {
130
130
  try {
131
- const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-XFZFKY3W.js');
131
+ const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-U4FMAIWX.js');
132
132
  const config = getStoreConfig2();
133
133
  const params = {};
134
134
  if (query) params.q = query;
@@ -158,7 +158,7 @@ function makeSearchCommand() {
158
158
  });
159
159
  }
160
160
  function makeAddCommand() {
161
- return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:name[@repo])").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Deploy to global dir (~/.claude)").option("--target <agent>", "Driver target", "claude-code").action(async (ref, opts) => {
161
+ return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:@<publisher>/name#<version>)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Deploy to global dir (~/.claude)").option("--target <agent>", "Driver target", "claude-code").action(async (ref, opts) => {
162
162
  const am2 = new AssetManager({
163
163
  projectDir: path14__default.resolve(opts.projectDir),
164
164
  global: opts.global,
@@ -495,8 +495,12 @@ function makeAssetCommand() {
495
495
  fs12.cpSync(src.dir, destDir, { recursive: true });
496
496
  fs12.writeFileSync(path14.join(destDir, "SKILL.md"), norm.content, "utf8");
497
497
  for (const note of norm.notes) logInfo(` \u2022 ${note}`);
498
- const descRaw = parseFrontmatter(norm.content).data.description;
498
+ const fm = parseFrontmatter(norm.content).data;
499
+ const descRaw = fm.description;
499
500
  const description = typeof descRaw === "string" ? descRaw.trim() : void 0;
501
+ for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
502
+ logWarn(`conformance: ${f.field} \u2014 ${f.message}`);
503
+ }
500
504
  const root = path14.relative(target.path, destDir);
501
505
  const up = upsertManifestAsset(target.path, {
502
506
  kind: "skill",
@@ -825,7 +829,7 @@ function makeCatalogCommand() {
825
829
  return catalog;
826
830
  }
827
831
  async function runLocalCatalogTest(projectDir) {
828
- const { resolveCatalogSource } = await import('../open-library-362BZ6OW.js');
832
+ const { resolveCatalogSource } = await import('../open-library-COHFCT4N.js');
829
833
  let resolved;
830
834
  try {
831
835
  resolved = await resolveCatalogSource({ projectDir });
@@ -1815,7 +1819,7 @@ async function ensureTargetsRegistered(projectDir) {
1815
1819
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
1816
1820
  const config = resolveSkWorkspaceConfig2(projectDir);
1817
1821
  if (config.plugins && config.plugins.length > 0) {
1818
- const { ensurePluginsLoaded } = await import('../plugin-store-2X2YXJVG.js');
1822
+ const { ensurePluginsLoaded } = await import('../plugin-store-UNENLB56.js');
1819
1823
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
1820
1824
  for (const f of result.failed) logWarn(f.error);
1821
1825
  }
@@ -3401,7 +3405,7 @@ function actOnHeader(row, action3) {
3401
3405
  return row.type === "domain-header" || row.type === "domain-info";
3402
3406
  }
3403
3407
  async function loadAssets() {
3404
- const { gatherAssetFeeds } = await import('../asset-feeds-AOZLZMDV.js');
3408
+ const { gatherAssetFeeds } = await import('../asset-feeds-DLRQWELS.js');
3405
3409
  const { entries, domains, notes } = await gatherAssetFeeds(am, am.projectDir);
3406
3410
  if (notes.length > 0) {
3407
3411
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
@@ -3499,7 +3503,7 @@ function reconcileCollapsedSets(rows) {
3499
3503
  async function loadSourcesAndLibraries() {
3500
3504
  try {
3501
3505
  const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir }, { getGlobalCacheDir: getGlobalCacheDir2 }] = await Promise.all([
3502
- import('../open-library-362BZ6OW.js'),
3506
+ import('../open-library-COHFCT4N.js'),
3503
3507
  import('../library/index.js'),
3504
3508
  import('../core/index.js')
3505
3509
  ]);
@@ -4198,14 +4202,15 @@ function makeNpxCommand() {
4198
4202
  process.exit(1);
4199
4203
  }
4200
4204
  const spinner5 = p6.spinner();
4201
- const slug = sourceSlug(url);
4202
- const clonePath = path14__default.join(getGlobalCacheDir(), slug);
4205
+ const key = sourceCacheKey(url);
4206
+ const clonePath = path14__default.join(getGlobalCacheDir(), key);
4203
4207
  spinner5.start(`Cloning ${url}`);
4204
4208
  try {
4205
4209
  if (!existsSync(clonePath)) {
4210
+ mkdirSync(path14__default.dirname(clonePath), { recursive: true });
4206
4211
  execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
4207
4212
  }
4208
- spinner5.stop(`Cloned to ${slug}`);
4213
+ spinner5.stop(`Cloned to ${key}`);
4209
4214
  } catch (err) {
4210
4215
  spinner5.stop("Clone failed");
4211
4216
  logErr(err instanceof Error ? err.message : String(err));
@@ -4276,9 +4281,6 @@ function resolveSkillName(clonePath, requested) {
4276
4281
  }
4277
4282
  return requested;
4278
4283
  }
4279
- function sourceSlug(url) {
4280
- return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
4281
- }
4282
4284
  function makeOutdatedCommand() {
4283
4285
  return new Command("outdated").description("Check for assets behind their repo").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).addOption(
4284
4286
  new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
@@ -4366,7 +4368,7 @@ function action2(fn) {
4366
4368
  };
4367
4369
  }
4368
4370
  async function reconcileAndReport(projectDir, plugins) {
4369
- const { reconcilePlugins } = await import('../plugin-store-2X2YXJVG.js');
4371
+ const { reconcilePlugins } = await import('../plugin-store-UNENLB56.js');
4370
4372
  if (plugins.length === 0) {
4371
4373
  logInfo("No plugins declared \u2014 nothing to reconcile.");
4372
4374
  return;
@@ -4382,7 +4384,7 @@ async function reconcileAndReport(projectDir, plugins) {
4382
4384
  async function runInstall2(spec, opts) {
4383
4385
  const projectDir = path14__default.resolve(opts.projectDir);
4384
4386
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
4385
- const { specName } = await import('../plugin-store-2X2YXJVG.js');
4387
+ const { specName } = await import('../plugin-store-UNENLB56.js');
4386
4388
  const yamlPath = path14__default.join(projectDir, "skaile.yaml");
4387
4389
  const editor = WorkspaceYamlEditor2.load(yamlPath);
4388
4390
  const replaced = editor.addPlugin(spec, specName);
@@ -4394,7 +4396,7 @@ async function runInstall2(spec, opts) {
4394
4396
  async function runRemove(name, opts) {
4395
4397
  const projectDir = path14__default.resolve(opts.projectDir);
4396
4398
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
4397
- const { specName } = await import('../plugin-store-2X2YXJVG.js');
4399
+ const { specName } = await import('../plugin-store-UNENLB56.js');
4398
4400
  const yamlPath = path14__default.join(projectDir, "skaile.yaml");
4399
4401
  const editor = WorkspaceYamlEditor2.load(yamlPath);
4400
4402
  const removed = editor.removePlugin(name, specName);
@@ -4422,7 +4424,7 @@ async function runList(opts) {
4422
4424
  const registry = createPluginRegistry();
4423
4425
  if (declared.length > 0) {
4424
4426
  try {
4425
- const { loadPlugins } = await import('../plugin-store-2X2YXJVG.js');
4427
+ const { loadPlugins } = await import('../plugin-store-UNENLB56.js');
4426
4428
  const result = await loadPlugins(projectDir, declared, registry);
4427
4429
  for (const f of result.failed) logWarn(f.error);
4428
4430
  } catch (err) {
@@ -4654,7 +4656,7 @@ async function runRefInstall(ref, opts) {
4654
4656
  const spinner5 = p6.spinner();
4655
4657
  spinner5.start(`Installing ${ref}`);
4656
4658
  try {
4657
- const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-362BZ6OW.js');
4659
+ const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-COHFCT4N.js');
4658
4660
  const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
4659
4661
  if (!supportsInstallManifest(catalog)) {
4660
4662
  throw new Error(
@@ -4686,7 +4688,7 @@ async function runRefInstall(ref, opts) {
4686
4688
  async function runYamlInstall(opts) {
4687
4689
  const projectDir = path14__default.resolve(opts.projectDir);
4688
4690
  try {
4689
- const { ensureSourcesCloned } = await import('../ensure-sources-NSDMTAWN.js');
4691
+ const { ensureSourcesCloned } = await import('../ensure-sources-KLCGXVE6.js');
4690
4692
  const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
4691
4693
  if (hydrate.cloned.length > 0) {
4692
4694
  logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
@@ -4717,6 +4719,7 @@ async function runYamlInstall(opts) {
4717
4719
  }
4718
4720
  if (result.missing.length > 0) {
4719
4721
  for (const m of result.missing) logErr(`Missing: ${m}`);
4722
+ process.exitCode = 1;
4720
4723
  }
4721
4724
  if (result.lockWritten) {
4722
4725
  logInfo(`Lock file written: ${S.dim("skaile.lock.yaml")}`);
@@ -5123,7 +5126,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
5123
5126
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
5124
5127
  const config = resolveSkWorkspaceConfig2(projectDir);
5125
5128
  if (!config.plugins || config.plugins.length === 0) return;
5126
- const { ensurePluginsLoaded } = await import('../plugin-store-2X2YXJVG.js');
5129
+ const { ensurePluginsLoaded } = await import('../plugin-store-UNENLB56.js');
5127
5130
  const { pluginRegistry } = await import('../plugin-registry/index.js');
5128
5131
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
5129
5132
  if (result.loaded.length > 0) {
@@ -5139,12 +5142,12 @@ async function ensurePluginsLoadedForServe(projectDir) {
5139
5142
  async function runCompileTest(opts) {
5140
5143
  const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-F4NZ66VD.js');
5141
5144
  const { tmpdir } = await import('os');
5142
- const { dirname: dirname4, join: join6, resolve: resolve5 } = await import('path');
5145
+ const { dirname: dirname5, join: join6, resolve: resolve5 } = await import('path');
5143
5146
  const { fileURLToPath: fileURLToPath2 } = await import('url');
5144
5147
  const { unlinkSync, existsSync: existsSync14 } = await import('fs');
5145
5148
  const { spawn } = await import('child_process');
5146
5149
  const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
5147
- const { MONOREPO_ROOT } = await import('../paths-4SSFMX5Z.js');
5150
+ const { MONOREPO_ROOT } = await import('../paths-2SYXGTZJ.js');
5148
5151
  if (MONOREPO_ROOT === null) {
5149
5152
  logErr2("--compile-test is only available inside the skaile-dev workspace.");
5150
5153
  logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
@@ -5153,7 +5156,7 @@ async function runCompileTest(opts) {
5153
5156
  }
5154
5157
  const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
5155
5158
  const __thisFile = fileURLToPath2(import.meta.url);
5156
- const entryPoint = resolve5(dirname4(__thisFile), "..", "index.ts");
5159
+ const entryPoint = resolve5(dirname5(__thisFile), "..", "index.ts");
5157
5160
  logInfo2(`Building compiled binary...`);
5158
5161
  logInfo2(`Entry: ${S2.dim(entryPoint)}`);
5159
5162
  logInfo2(`Output: ${S2.dim(outfile)}`);
@@ -5976,11 +5979,8 @@ function addSourceManifestCommands(src) {
5976
5979
  }
5977
5980
 
5978
5981
  // cli/src/commands/source.ts
5979
- function sourceClonePath(name) {
5980
- return path14.join(getGlobalCacheDir(), name);
5981
- }
5982
- function deriveSlug(url) {
5983
- return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
5982
+ function sourceClonePath(key) {
5983
+ return path14.join(getGlobalCacheDir(), key);
5984
5984
  }
5985
5985
  function normalizeSourceUrl(input) {
5986
5986
  const s = input.trim();
@@ -5991,9 +5991,14 @@ function normalizeSourceUrl(input) {
5991
5991
  return s;
5992
5992
  }
5993
5993
  function sourceMatchesKey(entry, key) {
5994
- if (entry.url === key || deriveSlug(entry.url) === key) return true;
5994
+ if (entry.url === key) return true;
5995
+ if (sourceCacheKey(entry.url) === key || sourceShortName(entry.url) === key) return true;
5995
5996
  return entry.url === normalizeSourceUrl(key);
5996
5997
  }
5998
+ function findCacheKeyCollision(sources, url) {
5999
+ const key = sourceCacheKey(url);
6000
+ return sources.find((s) => s.url !== url && sourceCacheKey(s.url) === key);
6001
+ }
5997
6002
  function requireProjectYamlPath() {
5998
6003
  const root = findWorkspaceRoot(process.cwd());
5999
6004
  if (!root) {
@@ -6014,12 +6019,12 @@ function readProjectSources(yamlPath) {
6014
6019
  }
6015
6020
  }
6016
6021
  function ensureClone(entry, opts = {}) {
6017
- const slug = deriveSlug(entry.url);
6018
- const dest = sourceClonePath(slug);
6022
+ const dest = sourceClonePath(sourceCacheKey(entry.url));
6019
6023
  if (existsSync(dest)) {
6020
6024
  if (!opts.force) return false;
6021
6025
  rmSync(dest, { recursive: true, force: true });
6022
6026
  }
6027
+ mkdirSync(path14.dirname(dest), { recursive: true });
6023
6028
  const args = ["clone", entry.url, dest];
6024
6029
  if (entry.pin) args.splice(1, 0, "--branch", entry.pin);
6025
6030
  const clone = spawnSync("git", args, { stdio: "inherit" });
@@ -6032,11 +6037,11 @@ function ensureClone(entry, opts = {}) {
6032
6037
  async function refreshManifestCache(entry, includeDev = false) {
6033
6038
  const { manager, library, close } = await openLibraryManager();
6034
6039
  try {
6035
- const slug = deriveSlug(entry.url);
6036
- const dest = sourceClonePath(slug);
6037
- const existing = (await manager.listLibraries()).find((l) => l.name === slug);
6040
+ const name = sourceShortName(entry.url);
6041
+ const dest = sourceClonePath(sourceCacheKey(entry.url));
6042
+ const existing = (await manager.listLibraries()).find((l) => l.name === name);
6038
6043
  const lib = existing ?? await manager.addLibrary({
6039
- name: slug,
6044
+ name,
6040
6045
  path: dest,
6041
6046
  backend: "git",
6042
6047
  backendConfig: { url: entry.url, branch: entry.pin ?? "main", authHint: "ssh" },
@@ -6050,7 +6055,8 @@ async function refreshManifestCache(entry, includeDev = false) {
6050
6055
  close();
6051
6056
  }
6052
6057
  }
6053
- async function dropManifestCache(name, purgeClone) {
6058
+ async function dropManifestCache(url, purgeClone) {
6059
+ const name = sourceShortName(url);
6054
6060
  const { manager, close } = await openLibraryManager();
6055
6061
  try {
6056
6062
  const existing = (await manager.listLibraries()).find((l) => l.name === name);
@@ -6061,7 +6067,7 @@ async function dropManifestCache(name, purgeClone) {
6061
6067
  close();
6062
6068
  }
6063
6069
  if (purgeClone) {
6064
- const dest = sourceClonePath(name);
6070
+ const dest = sourceClonePath(sourceCacheKey(url));
6065
6071
  if (existsSync(dest)) rmSync(dest, { recursive: true, force: true });
6066
6072
  }
6067
6073
  }
@@ -6075,19 +6081,27 @@ function makeSourceCommand() {
6075
6081
  async (source, opts) => {
6076
6082
  const url = normalizeSourceUrl(source);
6077
6083
  const yamlPath = requireProjectYamlPath();
6084
+ const collision = findCacheKeyCollision(readProjectSources(yamlPath), url);
6085
+ if (collision) {
6086
+ logErr(
6087
+ `"${url}" maps to the same cache key (${sourceCacheKey(url)}) as already-registered "${collision.url}". Remove that source first (skaile source remove) or re-use its exact URL to update it.`
6088
+ );
6089
+ process.exitCode = 1;
6090
+ return;
6091
+ }
6078
6092
  if (opts.name) {
6079
6093
  logWarn(
6080
6094
  "the --name flag is deprecated; the source entry now stores only the URL (the cache slug is derived from it)."
6081
6095
  );
6082
6096
  }
6083
6097
  const pin = opts.pin ?? opts.branch;
6084
- const slug = deriveSlug(url);
6098
+ const slug = sourceShortName(url);
6085
6099
  const entry = { url };
6086
6100
  if (pin) entry.pin = pin;
6087
6101
  const editor = WorkspaceYamlEditor.load(yamlPath);
6088
6102
  editor.setSource(entry);
6089
6103
  editor.save();
6090
- const dest = sourceClonePath(slug);
6104
+ const dest = sourceClonePath(sourceCacheKey(url));
6091
6105
  const preexisting = existsSync(dest);
6092
6106
  const cloned = ensureClone(entry, { force: opts.force });
6093
6107
  if (!cloned) {
@@ -6114,8 +6128,8 @@ function makeSourceCommand() {
6114
6128
  console.log();
6115
6129
  console.log(S.heading(" Sources"));
6116
6130
  for (const s of sources) {
6117
- const slug = deriveSlug(s.url);
6118
- const cached = existsSync(sourceClonePath(slug)) ? "" : S.warn(" (not cached)");
6131
+ const slug = sourceShortName(s.url);
6132
+ const cached = existsSync(sourceClonePath(sourceCacheKey(s.url))) ? "" : S.warn(" (not cached)");
6119
6133
  console.log(` ${S.cmd(slug.padEnd(24))} ${S.dim(s.url)}${cached}`);
6120
6134
  }
6121
6135
  console.log(`
@@ -6129,14 +6143,15 @@ function makeSourceCommand() {
6129
6143
  logErr(`No source matching "${key}" in ${yamlPath}.`);
6130
6144
  process.exit(1);
6131
6145
  }
6132
- const slug = deriveSlug(entry.url);
6146
+ const slug = sourceShortName(entry.url);
6147
+ const clonePath = sourceClonePath(sourceCacheKey(entry.url));
6133
6148
  console.log(
6134
6149
  JSON.stringify(
6135
6150
  {
6136
6151
  ...entry,
6137
6152
  slug,
6138
- clonePath: sourceClonePath(slug),
6139
- cached: existsSync(sourceClonePath(slug))
6153
+ clonePath,
6154
+ cached: existsSync(clonePath)
6140
6155
  },
6141
6156
  null,
6142
6157
  2
@@ -6151,10 +6166,10 @@ function makeSourceCommand() {
6151
6166
  logErr(`No source matching "${key}" in ${yamlPath}.`);
6152
6167
  process.exit(1);
6153
6168
  }
6154
- const slug = deriveSlug(match.url);
6169
+ const slug = sourceShortName(match.url);
6155
6170
  editor.removeSource(match.url);
6156
6171
  editor.save();
6157
- await dropManifestCache(slug, opts.purge);
6172
+ await dropManifestCache(match.url, opts.purge);
6158
6173
  logOk(
6159
6174
  opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/cache/sources/).`
6160
6175
  );
@@ -6178,7 +6193,11 @@ function makeSourceCommand() {
6178
6193
  } else {
6179
6194
  const selected = await p6.multiselect({
6180
6195
  message: "Select sources to sync",
6181
- options: sources.map((s) => ({ value: s.url, label: deriveSlug(s.url), hint: s.url })),
6196
+ options: sources.map((s) => ({
6197
+ value: s.url,
6198
+ label: sourceShortName(s.url),
6199
+ hint: s.url
6200
+ })),
6182
6201
  required: true
6183
6202
  });
6184
6203
  if (p6.isCancel(selected)) {
@@ -6189,8 +6208,8 @@ function makeSourceCommand() {
6189
6208
  targets = sources.filter((s) => picked.has(s.url));
6190
6209
  }
6191
6210
  for (const entry of targets) {
6192
- const slug = deriveSlug(entry.url);
6193
- const dest = sourceClonePath(slug);
6211
+ const slug = sourceShortName(entry.url);
6212
+ const dest = sourceClonePath(sourceCacheKey(entry.url));
6194
6213
  if (!existsSync(dest)) {
6195
6214
  ensureClone(entry);
6196
6215
  logOk(`${slug}: cloned to ${dest}.`);
@@ -6513,18 +6532,33 @@ function parseManifestCandidate(c, absRoot) {
6513
6532
  return { kind: "error" };
6514
6533
  }
6515
6534
  }
6516
- function validateManifestCandidate(c, parsed, absRoot, registry) {
6535
+ function validateManifestCandidate(c, parsed, absRoot, registry, strictConformance) {
6517
6536
  const relPath = path14__default.relative(absRoot, c.filePath);
6518
6537
  let errors = 0;
6538
+ let warnings = 0;
6519
6539
  const identityError = checkManifestIdentity(c.kind, parsed);
6520
6540
  if (identityError) {
6521
6541
  logErr(`${relPath} [${c.kind}] \u2014 ${identityError}`);
6522
6542
  errors++;
6523
6543
  }
6544
+ if (c.kind === "skill" && parsed && typeof parsed === "object") {
6545
+ const dirName = path14__default.basename(path14__default.dirname(c.filePath));
6546
+ const findings = checkAgentSkillConformance(parsed, { dirName });
6547
+ for (const f of findings) {
6548
+ const line = `${relPath} [skill conformance] \u2014 ${f.field}: ${f.message}`;
6549
+ if (strictConformance) {
6550
+ logErr(line);
6551
+ errors++;
6552
+ } else {
6553
+ logWarn(line);
6554
+ warnings++;
6555
+ }
6556
+ }
6557
+ }
6524
6558
  const provider = registry.getProvider(c.kind);
6525
6559
  if (!provider) {
6526
6560
  logWarn(`${relPath} [${c.kind}] \u2014 kind "${c.kind}" is not registered, skipping validation`);
6527
- return { errors, warnings: 1 };
6561
+ return { errors, warnings: warnings + 1 };
6528
6562
  }
6529
6563
  const result = provider.validateManifest(parsed);
6530
6564
  if (!result.ok) {
@@ -6533,9 +6567,9 @@ function validateManifestCandidate(c, parsed, absRoot, registry) {
6533
6567
  }
6534
6568
  errors += result.errors.length;
6535
6569
  }
6536
- return { errors, warnings: 0 };
6570
+ return { errors, warnings };
6537
6571
  }
6538
- function validateManifests(rootPath) {
6572
+ function validateManifests(rootPath, strictConformance) {
6539
6573
  const absRoot = path14__default.resolve(rootPath);
6540
6574
  if (!fs12__default.existsSync(absRoot)) {
6541
6575
  logErr(`Path does not exist: ${absRoot}`);
@@ -6552,7 +6586,13 @@ function validateManifests(rootPath) {
6552
6586
  errors++;
6553
6587
  continue;
6554
6588
  }
6555
- const delta = validateManifestCandidate(c, parseResult.parsed, absRoot, registry);
6589
+ const delta = validateManifestCandidate(
6590
+ c,
6591
+ parseResult.parsed,
6592
+ absRoot,
6593
+ registry,
6594
+ strictConformance
6595
+ );
6556
6596
  errors += delta.errors;
6557
6597
  warnings += delta.warnings;
6558
6598
  }
@@ -6859,14 +6899,21 @@ function makeValidateCommand() {
6859
6899
  const cmd = new Command("validate").description(
6860
6900
  "Validate asset manifests, versions, and changelogs"
6861
6901
  );
6862
- cmd.argument("[path]", "Path to asset repo or directory to validate", ".").action((targetPath) => {
6902
+ cmd.argument("[path]", "Path to asset repo or directory to validate", ".").option(
6903
+ "--strict-conformance",
6904
+ "Treat Agent Skills (agentskills.io) standard findings as errors"
6905
+ ).action((targetPath, opts) => {
6863
6906
  const absPath = path14__default.resolve(targetPath);
6864
6907
  logInfo(`Validating manifests in ${absPath}`);
6865
- const { total, errors } = validateManifests(absPath);
6908
+ const { total, errors, warnings } = validateManifests(
6909
+ absPath,
6910
+ opts.strictConformance ?? false
6911
+ );
6866
6912
  const ws = validateWorkspaceManifests(absPath);
6867
6913
  const totalErrors = errors + ws.errors;
6868
6914
  console.log();
6869
6915
  logInfo(`Scanned ${total} asset manifest(s) and ${ws.total} skaile.yaml file(s)`);
6916
+ if (warnings > 0) logWarn(`${warnings} conformance warning(s)`);
6870
6917
  if (totalErrors === 0) {
6871
6918
  logOk("All manifests valid");
6872
6919
  } else {
@@ -7130,7 +7177,7 @@ program.command("init [project-dir]").description("Initialize a project director
7130
7177
  (projectDir, opts) => runInit(projectDir, opts)
7131
7178
  );
7132
7179
  async function runInit(projectDir, opts) {
7133
- const { mkdirSync: mkdirSync4, writeFileSync: writeFileSync4 } = await import('fs');
7180
+ const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync4 } = await import('fs');
7134
7181
  const { stringify } = await import('yaml');
7135
7182
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
7136
7183
  const backend = opts.backend;
@@ -7144,12 +7191,12 @@ async function runInit(projectDir, opts) {
7144
7191
  const created = [];
7145
7192
  const { existsSync: existsSync14 } = await import('fs');
7146
7193
  if (!existsSync14(resolved)) {
7147
- mkdirSync4(resolved, { recursive: true });
7194
+ mkdirSync6(resolved, { recursive: true });
7148
7195
  created.push(".");
7149
7196
  }
7150
7197
  const skaileDir = path14__default.join(resolved, ".skaile");
7151
7198
  if (!existsSync14(skaileDir)) {
7152
- mkdirSync4(path14__default.join(skaileDir, "sessions"), { recursive: true });
7199
+ mkdirSync6(path14__default.join(skaileDir, "sessions"), { recursive: true });
7153
7200
  created.push(".skaile/");
7154
7201
  }
7155
7202
  const settingsPath = path14__default.join(skaileDir, "settings.json");
@@ -7165,7 +7212,7 @@ async function runInit(projectDir, opts) {
7165
7212
  for (const dir of new Set(Object.values(DRIVER_TARGETS[backend].local))) {
7166
7213
  const full = path14__default.join(resolved, dir);
7167
7214
  if (!existsSync14(full)) {
7168
- mkdirSync4(full, { recursive: true });
7215
+ mkdirSync6(full, { recursive: true });
7169
7216
  created.push(`${dir}/`);
7170
7217
  }
7171
7218
  }
@@ -7244,7 +7291,7 @@ async function bootstrapUserConfig() {
7244
7291
  }
7245
7292
  async function hydrateInitSources(resolved, created) {
7246
7293
  try {
7247
- const { ensureSourcesCloned } = await import('../ensure-sources-NSDMTAWN.js');
7294
+ const { ensureSourcesCloned } = await import('../ensure-sources-KLCGXVE6.js');
7248
7295
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
7249
7296
  for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
7250
7297
  if (hydrate.failed.length > 0) {
@@ -7272,7 +7319,7 @@ function printInitSummary(resolved, projectDir, created) {
7272
7319
  console.log();
7273
7320
  }
7274
7321
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
7275
- const { cmdSetup } = await import('../setup-VGZTFQ32.js');
7322
+ const { cmdSetup } = await import('../setup-AYH6SR4U.js');
7276
7323
  await cmdSetup([], { projectDir: process.cwd() });
7277
7324
  });
7278
7325
  program.addCommand(makeInstallCommand());