@skaile/workspaces 0.22.0-beta.1 → 0.22.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 (164) hide show
  1. package/CHANGELOG.md +380 -0
  2. package/dist/{asset-feeds-QXCSAJRN.js → asset-feeds-Y2CDCM3W.js} +13 -14
  3. package/dist/asset-feeds-Y2CDCM3W.js.map +1 -0
  4. package/dist/asset-manager/index.js +7 -7
  5. package/dist/asset-manager/installer.js +6 -6
  6. package/dist/asset-manager/src/index.d.ts.map +1 -1
  7. package/dist/base-assets/connectors/deploy.js +7 -7
  8. package/dist/base-assets/connectors/devserver.js +7 -7
  9. package/dist/base-assets/connectors/flow/adapter.js +7 -7
  10. package/dist/base-assets/connectors/flow/run-flow.js +8 -8
  11. package/dist/base-assets/connectors/flow.js +7 -7
  12. package/dist/base-assets/connectors/git/driver.d.ts.map +1 -1
  13. package/dist/base-assets/connectors/git.js +7 -7
  14. package/dist/base-assets/connectors/gmail.js +7 -7
  15. package/dist/base-assets/connectors/googledrive.js +7 -7
  16. package/dist/base-assets/connectors/local.js +7 -7
  17. package/dist/base-assets/connectors/mattermost.js +7 -7
  18. package/dist/base-assets/connectors/memory.js +7 -7
  19. package/dist/base-assets/connectors/minio.js +7 -7
  20. package/dist/base-assets/connectors/postgres.js +7 -7
  21. package/dist/base-assets/connectors/s3.js +7 -7
  22. package/dist/base-assets/connectors/sharepoint.js +7 -7
  23. package/dist/base-assets/connectors/sqlite.js +7 -7
  24. package/dist/base-assets/connectors/static-server.js +7 -7
  25. package/dist/base-assets/connectors/tunnel.js +7 -7
  26. package/dist/base-assets/connectors/webdav.js +7 -7
  27. package/dist/base-assets/connectors/xstate-store.js +7 -7
  28. package/dist/base-assets/connectors/xstate.js +7 -7
  29. package/dist/{chunk-PTIHB2TV.js → chunk-2RYQERIT.js} +4 -4
  30. package/dist/{chunk-PTIHB2TV.js.map → chunk-2RYQERIT.js.map} +1 -1
  31. package/dist/chunk-32NA4TVC.js +30 -0
  32. package/dist/chunk-32NA4TVC.js.map +1 -0
  33. package/dist/{chunk-DKGDOALM.js → chunk-53UNDY6K.js} +5 -5
  34. package/dist/{chunk-DKGDOALM.js.map → chunk-53UNDY6K.js.map} +1 -1
  35. package/dist/{chunk-VCYXVP2S.js → chunk-7HSXUKNB.js} +24 -13
  36. package/dist/chunk-7HSXUKNB.js.map +1 -0
  37. package/dist/chunk-7QBNJTTQ.js +3 -0
  38. package/dist/{chunk-W2O5LWYU.js.map → chunk-7QBNJTTQ.js.map} +1 -1
  39. package/dist/{chunk-UMOENHVH.js → chunk-ETMUGBHF.js} +3 -3
  40. package/dist/{chunk-UMOENHVH.js.map → chunk-ETMUGBHF.js.map} +1 -1
  41. package/dist/{chunk-7PTP3SQJ.js → chunk-GTS2FODO.js} +32 -7
  42. package/dist/chunk-GTS2FODO.js.map +1 -0
  43. package/dist/{chunk-D7K72XEY.js → chunk-JN2CUVSU.js} +3 -3
  44. package/dist/{chunk-D7K72XEY.js.map → chunk-JN2CUVSU.js.map} +1 -1
  45. package/dist/{chunk-3ECS5PFD.js → chunk-K2HDYSAM.js} +4 -4
  46. package/dist/{chunk-3ECS5PFD.js.map → chunk-K2HDYSAM.js.map} +1 -1
  47. package/dist/{chunk-4AZKT2BU.js → chunk-K7WPR77X.js} +33 -50
  48. package/dist/chunk-K7WPR77X.js.map +1 -0
  49. package/dist/{chunk-JHF66MCK.js → chunk-MNAHNDUI.js} +5 -3
  50. package/dist/chunk-MNAHNDUI.js.map +1 -0
  51. package/dist/{chunk-APAOQLPT.js → chunk-NBJ5TOEC.js} +3 -3
  52. package/dist/{chunk-APAOQLPT.js.map → chunk-NBJ5TOEC.js.map} +1 -1
  53. package/dist/{chunk-NJLHHZIW.js → chunk-NDD5VMN5.js} +2 -2
  54. package/dist/{chunk-NJLHHZIW.js.map → chunk-NDD5VMN5.js.map} +1 -1
  55. package/dist/{chunk-LT4DLEYE.js → chunk-OJN25VJO.js} +24 -8
  56. package/dist/chunk-OJN25VJO.js.map +1 -0
  57. package/dist/{chunk-GFNW72LW.js → chunk-PFOXL4SH.js} +4 -4
  58. package/dist/{chunk-GFNW72LW.js.map → chunk-PFOXL4SH.js.map} +1 -1
  59. package/dist/{chunk-V3QMSM5I.js → chunk-SKXCTV55.js} +13 -14
  60. package/dist/chunk-SKXCTV55.js.map +1 -0
  61. package/dist/{chunk-J3VKAEQP.js → chunk-V5TBKO5Q.js} +64 -14
  62. package/dist/chunk-V5TBKO5Q.js.map +1 -0
  63. package/dist/{chunk-I3UEM3FX.js → chunk-VUCPJBAG.js} +9 -4
  64. package/dist/chunk-VUCPJBAG.js.map +1 -0
  65. package/dist/{chunk-XIHFJVOD.js → chunk-WH2EB2SF.js} +3 -3
  66. package/dist/{chunk-XIHFJVOD.js.map → chunk-WH2EB2SF.js.map} +1 -1
  67. package/dist/{chunk-PBWMV5GM.js → chunk-WQ7DE5UC.js} +18 -4
  68. package/dist/chunk-WQ7DE5UC.js.map +1 -0
  69. package/dist/cli/index.js +199 -200
  70. package/dist/cli/index.js.map +1 -1
  71. package/dist/cli/src/commands/manage.d.ts +23 -32
  72. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  73. package/dist/cli/src/commands/npx.d.ts +5 -3
  74. package/dist/cli/src/commands/npx.d.ts.map +1 -1
  75. package/dist/cli/src/commands/source.d.ts +7 -0
  76. package/dist/cli/src/commands/source.d.ts.map +1 -1
  77. package/dist/connectors/config.js +6 -6
  78. package/dist/connectors/index.js +7 -7
  79. package/dist/core/index.js +5 -5
  80. package/dist/core/manifest.js +2 -2
  81. package/dist/core/models.js +1 -1
  82. package/dist/core/runtime-assets.js +4 -4
  83. package/dist/core/src/index.d.ts +2 -2
  84. package/dist/core/src/index.d.ts.map +1 -1
  85. package/dist/core/src/manifest.d.ts +16 -0
  86. package/dist/core/src/manifest.d.ts.map +1 -1
  87. package/dist/core/src/models.d.ts +8 -2
  88. package/dist/core/src/models.d.ts.map +1 -1
  89. package/dist/core/src/repo-manager.d.ts +17 -2
  90. package/dist/core/src/repo-manager.d.ts.map +1 -1
  91. package/dist/core/src/walker.d.ts +4 -0
  92. package/dist/core/src/walker.d.ts.map +1 -1
  93. package/dist/core/src/workspace-config.d.ts +14 -0
  94. package/dist/core/src/workspace-config.d.ts.map +1 -1
  95. package/dist/core/workspace-config.js +3 -3
  96. package/dist/deploy/index.js +138 -42
  97. package/dist/deploy/index.js.map +1 -1
  98. package/dist/deploy/src/index.d.ts +4 -3
  99. package/dist/deploy/src/index.d.ts.map +1 -1
  100. package/dist/deploy/src/targets/container-runtime.d.ts.map +1 -1
  101. package/dist/deploy/src/targets/local.d.ts.map +1 -1
  102. package/dist/deploy/src/targets/nix.d.ts +36 -0
  103. package/dist/deploy/src/targets/nix.d.ts.map +1 -0
  104. package/dist/deploy/src/targets/process-handle.d.ts +34 -0
  105. package/dist/deploy/src/targets/process-handle.d.ts.map +1 -0
  106. package/dist/discovery/index.js +3 -3
  107. package/dist/{ensure-sources-SL2S4UEX.js → ensure-sources-REWWBH2K.js} +9 -9
  108. package/dist/{ensure-sources-SL2S4UEX.js.map → ensure-sources-REWWBH2K.js.map} +1 -1
  109. package/dist/library/index.js +4 -4
  110. package/dist/open-library-CT4VVESU.js +13 -0
  111. package/dist/{open-library-M4DB3D3J.js.map → open-library-CT4VVESU.js.map} +1 -1
  112. package/dist/plugin-registry/src/context.d.ts +30 -1
  113. package/dist/plugin-registry/src/context.d.ts.map +1 -1
  114. package/dist/plugin-registry/src/index.d.ts +1 -1
  115. package/dist/plugin-registry/src/index.d.ts.map +1 -1
  116. package/dist/{plugin-store-AJ3FGXIC.js → plugin-store-QS7TC5HY.js} +7 -7
  117. package/dist/{plugin-store-AJ3FGXIC.js.map → plugin-store-QS7TC5HY.js.map} +1 -1
  118. package/dist/plugins/src/catalog-source.d.ts +5 -0
  119. package/dist/plugins/src/catalog-source.d.ts.map +1 -1
  120. package/dist/runner/index.js +13 -12
  121. package/dist/runner/src/serve.d.ts +7 -0
  122. package/dist/runner/src/serve.d.ts.map +1 -1
  123. package/dist/sdk/asset-manager.js +7 -7
  124. package/dist/sdk/core.js +5 -5
  125. package/dist/sdk/index.js +13 -12
  126. package/dist/sdk/index.js.map +1 -1
  127. package/dist/sdk/runner.js +13 -12
  128. package/dist/sdk/transport/ws/client.js +2 -1
  129. package/dist/sdk/transport/ws/server.js +2 -1
  130. package/dist/sdk/transport/ws.js +4 -3
  131. package/dist/sdk/transport.js +4 -3
  132. package/dist/{setup-GBSQX7JF.js → setup-F6DGKL7J.js} +7 -7
  133. package/dist/{setup-GBSQX7JF.js.map → setup-F6DGKL7J.js.map} +1 -1
  134. package/dist/store-client-JP642EEI.js +14 -0
  135. package/dist/{store-client-5WBRUC5U.js.map → store-client-JP642EEI.js.map} +1 -1
  136. package/dist/transport/index.js +4 -3
  137. package/dist/transport/src/ws/auth.d.ts +34 -0
  138. package/dist/transport/src/ws/auth.d.ts.map +1 -0
  139. package/dist/transport/src/ws/client.d.ts +4 -0
  140. package/dist/transport/src/ws/client.d.ts.map +1 -1
  141. package/dist/transport/src/ws/index.d.ts +3 -2
  142. package/dist/transport/src/ws/index.d.ts.map +1 -1
  143. package/dist/transport/src/ws/server.d.ts +5 -0
  144. package/dist/transport/src/ws/server.d.ts.map +1 -1
  145. package/dist/transport/ws/client.js +2 -1
  146. package/dist/transport/ws/server.js +2 -1
  147. package/dist/transport/ws.js +4 -3
  148. package/dist/tui/index.js +13 -12
  149. package/dist/tui/index.js.map +1 -1
  150. package/dist/workspace-plugin/index.js +1 -1
  151. package/package.json +1 -1
  152. package/dist/asset-feeds-QXCSAJRN.js.map +0 -1
  153. package/dist/chunk-4AZKT2BU.js.map +0 -1
  154. package/dist/chunk-7PTP3SQJ.js.map +0 -1
  155. package/dist/chunk-I3UEM3FX.js.map +0 -1
  156. package/dist/chunk-J3VKAEQP.js.map +0 -1
  157. package/dist/chunk-JHF66MCK.js.map +0 -1
  158. package/dist/chunk-LT4DLEYE.js.map +0 -1
  159. package/dist/chunk-PBWMV5GM.js.map +0 -1
  160. package/dist/chunk-V3QMSM5I.js.map +0 -1
  161. package/dist/chunk-VCYXVP2S.js.map +0 -1
  162. package/dist/chunk-W2O5LWYU.js +0 -3
  163. package/dist/open-library-M4DB3D3J.js +0 -13
  164. package/dist/store-client-5WBRUC5U.js +0 -14
package/dist/cli/index.js CHANGED
@@ -1,23 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import { openCatalogSource, openLibrary, createFullRegistry, openLibraryManager } from '../chunk-3ECS5PFD.js';
2
+ import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-K2HDYSAM.js';
3
3
  import { logErr, S, logOk, colorRef, logInfo, logWarn, kindColorPad, kindColor, formatRelativeTime } from '../chunk-4NDWKA64.js';
4
- import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-XIHFJVOD.js';
4
+ import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-WH2EB2SF.js';
5
5
  import { AI_RESOURCES } from '../chunk-2M3XTMOL.js';
6
6
  import { LocalSecretsProvider } from '../chunk-JDX54X4Y.js';
7
- import { resolveLibraryDir, LocalCatalogSource, skaileHomeDir } from '../chunk-JHF66MCK.js';
7
+ import { resolveLibraryDir, LocalCatalogSource, skaileHomeDir } from '../chunk-MNAHNDUI.js';
8
8
  import '../chunk-R7FOF242.js';
9
- import '../chunk-D7K72XEY.js';
9
+ import '../chunk-JN2CUVSU.js';
10
10
  import '../chunk-OKRUTSG7.js';
11
- import { runFlow, resumeFlow } from '../chunk-DKGDOALM.js';
11
+ import { runFlow, resumeFlow } from '../chunk-53UNDY6K.js';
12
12
  import '../chunk-GCJXPUHG.js';
13
13
  import { validateFlowVersions, parseSkillFrontmatter } from '../chunk-IPUYL6TD.js';
14
- import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-V3QMSM5I.js';
15
- import { buildClaudePluginFiles } from '../chunk-NJLHHZIW.js';
14
+ import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-SKXCTV55.js';
15
+ import { buildClaudePluginFiles } from '../chunk-NDD5VMN5.js';
16
16
  import '../chunk-X5YPJV4N.js';
17
17
  import '../chunk-O7SG5PC2.js';
18
- import '../chunk-W2O5LWYU.js';
19
- import '../chunk-7PTP3SQJ.js';
20
- import '../chunk-PBWMV5GM.js';
18
+ import '../chunk-7QBNJTTQ.js';
19
+ import '../chunk-GTS2FODO.js';
20
+ import '../chunk-WQ7DE5UC.js';
21
+ import '../chunk-32NA4TVC.js';
21
22
  import '../chunk-W3UDISS2.js';
22
23
  import '../chunk-TDSRLMDB.js';
23
24
  import '../chunk-M5TE6YI5.js';
@@ -26,23 +27,23 @@ import '../chunk-KOVLSBXK.js';
26
27
  import '../chunk-RRVQAE5D.js';
27
28
  import '../chunk-6VTG73UY.js';
28
29
  import '../chunk-LV2HPH3C.js';
29
- import '../chunk-LT4DLEYE.js';
30
- import '../chunk-APAOQLPT.js';
30
+ import '../chunk-OJN25VJO.js';
31
+ import '../chunk-NBJ5TOEC.js';
31
32
  import '../chunk-6MB7CRME.js';
32
33
  import '../chunk-QAVZOJCV.js';
33
34
  import '../chunk-6E6PKKAD.js';
34
35
  import { loadAllFlows } from '../chunk-ICS76R4T.js';
35
36
  import '../chunk-GZWJGNNN.js';
36
37
  import '../chunk-FVTV7M76.js';
37
- import { AssetManager } from '../chunk-VCYXVP2S.js';
38
- import '../chunk-PTIHB2TV.js';
39
- import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-UMOENHVH.js';
38
+ import { AssetManager } from '../chunk-7HSXUKNB.js';
39
+ import '../chunk-2RYQERIT.js';
40
+ import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-ETMUGBHF.js';
40
41
  import { DRIVER_DEFAULTS } from '../chunk-K5GBV4SA.js';
41
42
  import '../chunk-KLNL7QHN.js';
42
- import '../chunk-GFNW72LW.js';
43
- import { resolveSkWorkspaceConfig, resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename } from '../chunk-J3VKAEQP.js';
44
- import '../chunk-4AZKT2BU.js';
45
- import { ASSET_KINDS } from '../chunk-I3UEM3FX.js';
43
+ import '../chunk-PFOXL4SH.js';
44
+ import { resolveSkWorkspaceConfig, resolveAgentDir, decodeSkaileYaml, findWorkspaceRoot, workspaceConfigFilename } from '../chunk-V5TBKO5Q.js';
45
+ import { parseFrontmatter } from '../chunk-K7WPR77X.js';
46
+ import { ASSET_KINDS, assetRefToStr } from '../chunk-VUCPJBAG.js';
46
47
  import '../chunk-JKNWJ64A.js';
47
48
  import { SUPPORTED_DRIVER_TARGETS } from '../chunk-O4JH3KUE.js';
48
49
  import { openSqlite } from '../chunk-24UIWON4.js';
@@ -53,7 +54,7 @@ import '../chunk-NELZIQ2E.js';
53
54
  import '../chunk-CGYEHQOX.js';
54
55
  import '../chunk-NSBPE2FW.js';
55
56
  import * as fs10 from 'fs';
56
- import fs10__default, { readFileSync, existsSync, writeFileSync, rmSync, statSync } from 'fs';
57
+ import fs10__default, { readFileSync, existsSync, writeFileSync, readdirSync, rmSync, statSync } from 'fs';
57
58
  import * as path14 from 'path';
58
59
  import path14__default, { resolve, join } from 'path';
59
60
  import { fileURLToPath } from 'url';
@@ -309,7 +310,7 @@ function makeSearchCommand() {
309
310
  }
310
311
  if (showStore) {
311
312
  try {
312
- const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-5WBRUC5U.js');
313
+ const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-JP642EEI.js');
313
314
  const config = getStoreConfig2();
314
315
  const params = {};
315
316
  if (query) params.q = query;
@@ -471,7 +472,7 @@ function makeCatalogCommand() {
471
472
  const cfg = resolveConfig({ projectDir });
472
473
  const baseUrl = opts.url ?? cfg.catalog.url;
473
474
  if (isLocalCatalogUrl(baseUrl)) {
474
- const { resolveCatalogSource } = await import('../open-library-M4DB3D3J.js');
475
+ const { resolveCatalogSource } = await import('../open-library-CT4VVESU.js');
475
476
  let resolved;
476
477
  try {
477
478
  resolved = await resolveCatalogSource({ projectDir: opts.projectDir });
@@ -1432,7 +1433,7 @@ async function ensureTargetsRegistered(projectDir) {
1432
1433
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
1433
1434
  const config = resolveSkWorkspaceConfig2(projectDir);
1434
1435
  if (config.plugins && config.plugins.length > 0) {
1435
- const { ensurePluginsLoaded } = await import('../plugin-store-AJ3FGXIC.js');
1436
+ const { ensurePluginsLoaded } = await import('../plugin-store-QS7TC5HY.js');
1436
1437
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
1437
1438
  for (const f of result.failed) logWarn(f.error);
1438
1439
  }
@@ -2203,48 +2204,28 @@ var state = {
2203
2204
  pendingAdds: /* @__PURE__ */ new Set(),
2204
2205
  pendingRemoves: /* @__PURE__ */ new Set(),
2205
2206
  collapsedSources: /* @__PURE__ */ new Set(),
2206
- collapsedDomains: /* @__PURE__ */ new Set(),
2207
+ collapsedRepos: /* @__PURE__ */ new Set(),
2207
2208
  message: "",
2208
2209
  cols: 80,
2209
2210
  awaitingExitConfirm: false
2210
2211
  };
2211
- function buildVisibleRows(rows, collapsedSources, collapsedDomains) {
2212
+ function buildVisibleRows(rows, collapsedSources, collapsedRepos) {
2212
2213
  return rows.filter((row) => {
2213
- if (row.type === "source-header") return true;
2214
- if (row.type === "header") {
2215
- if (collapsedSources.has(row.source)) return false;
2216
- return !hasCollapsedAncestor(row.source, row.domain, collapsedDomains, true);
2217
- }
2218
- const source = row.entry?.publisher || "other";
2219
- const domain = row.entry?.domain || "other";
2220
- if (collapsedSources.has(source)) return false;
2221
- return !hasCollapsedAncestor(source, domain, collapsedDomains, false);
2222
- });
2223
- }
2224
- function compareDomainPaths(a, b) {
2225
- const A = a.split("/");
2226
- const B = b.split("/");
2227
- const len = Math.min(A.length, B.length);
2228
- for (let i = 0; i < len; i++) {
2229
- const c = A[i].localeCompare(B[i]);
2230
- if (c !== 0) return c;
2231
- }
2232
- return A.length - B.length;
2233
- }
2234
- function hasCollapsedAncestor(source, domain, collapsedDomains, strict) {
2235
- const segs = domain.split("/");
2236
- const upper = strict ? segs.length : segs.length + 1;
2237
- for (let i = 1; i < upper; i++) {
2238
- const prefix = segs.slice(0, i).join("/");
2239
- if (collapsedDomains.has(`${source}:${prefix}`)) return true;
2240
- }
2241
- return false;
2214
+ if (row.type === "publisher-header") return true;
2215
+ if (row.type === "repo-header") {
2216
+ return !collapsedSources.has(row.source);
2217
+ }
2218
+ const publisher = row.entry?.publisher || "other";
2219
+ if (collapsedSources.has(publisher)) return false;
2220
+ const repo = row.entry?.repo || "";
2221
+ return repo === "" || !collapsedRepos.has(`${publisher}:${repo}`);
2222
+ });
2242
2223
  }
2243
- function domainAssetRefs(rows, source, domain) {
2244
- return rows.filter((r) => isAsset(r) && inDomain(r, source, domain)).map((r) => assetRefOf(r));
2224
+ function repoAssetRefs(rows, publisher, repo) {
2225
+ return rows.filter((r) => isAsset(r) && inRepo(r, publisher, repo)).map((r) => assetRefOf(r)).filter((ref) => ref !== null);
2245
2226
  }
2246
2227
  function sourceAssetRefs(rows, source) {
2247
- return rows.filter((r) => isAsset(r) && inSource(r, source)).map((r) => assetRefOf(r));
2228
+ return rows.filter((r) => isAsset(r) && inSource(r, source)).map((r) => assetRefOf(r)).filter((ref) => ref !== null);
2248
2229
  }
2249
2230
  function isAsset(r) {
2250
2231
  return r.type === "asset";
@@ -2252,14 +2233,17 @@ function isAsset(r) {
2252
2233
  function inSource(r, source) {
2253
2234
  return (r.entry?.publisher || "other") === source;
2254
2235
  }
2255
- function inDomain(r, source, domain) {
2256
- if (!inSource(r, source)) return false;
2257
- const d = r.entry?.domain || "other";
2258
- return d === domain || d.startsWith(`${domain}/`);
2236
+ function inRepo(r, publisher, repo) {
2237
+ if (!inSource(r, publisher)) return false;
2238
+ return (r.entry?.repo || "") === repo;
2259
2239
  }
2260
2240
  function assetRefOf(r) {
2261
- if (!isAsset(r) || !r.entry) return null;
2262
- return `${r.entry.kind}:${r.entry.name}`;
2241
+ if (!isAsset(r) || !r.entry?.publisher) return null;
2242
+ return assetRefToStr({
2243
+ kind: r.entry.kind,
2244
+ name: r.entry.name,
2245
+ publisher: r.entry.publisher
2246
+ });
2263
2247
  }
2264
2248
  function findAssetRow(ref) {
2265
2249
  return state.assetRows.find((r) => isAsset(r) && assetRefOf(r) === ref);
@@ -2297,48 +2281,38 @@ function bulkSelection(refs, action3) {
2297
2281
  for (const ref of refs) setSelection(ref, action3);
2298
2282
  }
2299
2283
  function actOnHeader(row, action3) {
2300
- if (row.type === "source-header") {
2284
+ if (row.type === "publisher-header") {
2301
2285
  bulkSelection(sourceAssetRefs(state.assetRows, row.source), action3);
2302
2286
  return true;
2303
2287
  }
2304
- if (row.type === "header") {
2305
- bulkSelection(domainAssetRefs(state.assetRows, row.source, row.domain), action3);
2288
+ if (row.type === "repo-header") {
2289
+ bulkSelection(repoAssetRefs(state.assetRows, row.source, row.repo), action3);
2306
2290
  return true;
2307
2291
  }
2308
2292
  return false;
2309
2293
  }
2310
2294
  async function loadAssets() {
2311
- const { gatherAssetFeeds } = await import('../asset-feeds-QXCSAJRN.js');
2295
+ const { gatherAssetFeeds } = await import('../asset-feeds-Y2CDCM3W.js');
2312
2296
  const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
2313
2297
  if (notes.length > 0) {
2314
2298
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
2315
2299
  }
2316
2300
  const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
2317
- const bySource = /* @__PURE__ */ new Map();
2301
+ const byPublisher = /* @__PURE__ */ new Map();
2318
2302
  for (const e of entries) {
2319
- const source = e.publisher || "other";
2320
- const domain = e.domain || "other";
2321
- if (!bySource.has(source)) bySource.set(source, /* @__PURE__ */ new Map());
2322
- const domainMap = bySource.get(source);
2323
- if (!domainMap.has(domain)) domainMap.set(domain, []);
2324
- domainMap.get(domain).push(e);
2303
+ const publisher = e.publisher || "other";
2304
+ const repo = e.repo || "";
2305
+ if (!byPublisher.has(publisher)) byPublisher.set(publisher, /* @__PURE__ */ new Map());
2306
+ const byRepo = byPublisher.get(publisher);
2307
+ if (!byRepo.has(repo)) byRepo.set(repo, []);
2308
+ byRepo.get(repo).push(e);
2325
2309
  }
2326
2310
  const rows = [];
2327
- for (const [source, domainMap] of [...bySource.entries()].sort(
2311
+ for (const [publisher, byRepo] of [...byPublisher.entries()].sort(
2328
2312
  (a, b) => a[0].localeCompare(b[0])
2329
2313
  )) {
2330
- rows.push({ type: "source-header", source });
2331
- const emittedHeaders = /* @__PURE__ */ new Set();
2332
- for (const [domain, items] of [...domainMap.entries()].sort(
2333
- (a, b) => compareDomainPaths(a[0], b[0])
2334
- )) {
2335
- const segs = domain.split("/");
2336
- for (let i = 1; i <= segs.length; i++) {
2337
- const prefix = segs.slice(0, i).join("/");
2338
- if (emittedHeaders.has(prefix)) continue;
2339
- rows.push({ type: "header", source, domain: prefix, depth: i });
2340
- emittedHeaders.add(prefix);
2341
- }
2314
+ rows.push({ type: "publisher-header", source: publisher });
2315
+ const pushAssets = (items) => {
2342
2316
  items.sort(
2343
2317
  (a, b) => a.kind !== b.kind ? a.kind.localeCompare(b.kind) : a.name.localeCompare(b.name)
2344
2318
  );
@@ -2346,26 +2320,34 @@ async function loadAssets() {
2346
2320
  const ref = `${entry.kind}:${entry.name}`;
2347
2321
  rows.push({ type: "asset", entry, installed: installed.has(ref) });
2348
2322
  }
2323
+ };
2324
+ const noRepo = byRepo.get("");
2325
+ if (noRepo) pushAssets(noRepo);
2326
+ for (const [repo, items] of [...byRepo.entries()].filter(([r]) => r !== "").sort((a, b) => a[0].localeCompare(b[0]))) {
2327
+ rows.push({ type: "repo-header", source: publisher, repo });
2328
+ pushAssets(items);
2349
2329
  }
2350
2330
  }
2351
2331
  state.assetRows = rows;
2352
- const newSources = new Set(rows.filter((r) => r.type === "source-header").map((r) => r.source));
2332
+ const newSources = new Set(
2333
+ rows.filter((r) => r.type === "publisher-header").map((r) => r.source)
2334
+ );
2353
2335
  for (const s of state.collapsedSources) {
2354
2336
  if (!newSources.has(s)) state.collapsedSources.delete(s);
2355
2337
  }
2356
- const newDomainKeys = new Set(
2357
- rows.filter((r) => r.type === "header").map((r) => `${r.source}:${r.domain}`)
2338
+ const newRepoKeys = new Set(
2339
+ rows.filter((r) => r.type === "repo-header").map((r) => `${r.source}:${r.repo}`)
2358
2340
  );
2359
- for (const d of state.collapsedDomains) {
2360
- if (!newDomainKeys.has(d)) state.collapsedDomains.delete(d);
2341
+ for (const d of state.collapsedRepos) {
2342
+ if (!newRepoKeys.has(d)) state.collapsedRepos.delete(d);
2361
2343
  }
2362
- for (const d of newDomainKeys) state.collapsedDomains.add(d);
2344
+ for (const d of newRepoKeys) state.collapsedRepos.add(d);
2363
2345
  rebuildVisible();
2364
2346
  }
2365
2347
  async function loadSourcesAndLibraries() {
2366
2348
  try {
2367
2349
  const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir: skaileHomeDir2 }] = await Promise.all([
2368
- import('../open-library-M4DB3D3J.js'),
2350
+ import('../open-library-CT4VVESU.js'),
2369
2351
  import('../library/index.js')
2370
2352
  ]);
2371
2353
  const { manager, library, close } = await openLibraryManager2();
@@ -2404,7 +2386,7 @@ function rebuildVisible() {
2404
2386
  state.visibleRows = buildVisibleRows(
2405
2387
  state.assetRows,
2406
2388
  state.collapsedSources,
2407
- state.collapsedDomains
2389
+ state.collapsedRepos
2408
2390
  );
2409
2391
  clampCursor();
2410
2392
  }
@@ -2512,7 +2494,7 @@ function renderHeaderLine(opts) {
2512
2494
  return opts.selected ? pc5.bgWhite(pc5.black(`${line} `.padEnd(state.cols))) : line;
2513
2495
  }
2514
2496
  function renderAssetRow(row, selected) {
2515
- if (row.type === "source-header") {
2497
+ if (row.type === "publisher-header") {
2516
2498
  return renderHeaderLine({
2517
2499
  indent: " ",
2518
2500
  collapsed: state.collapsedSources.has(row.source),
@@ -2522,21 +2504,20 @@ function renderAssetRow(row, selected) {
2522
2504
  selected
2523
2505
  });
2524
2506
  }
2525
- if (row.type === "header") {
2526
- const depth2 = row.depth ?? 1;
2527
- const segs = row.domain.split("/");
2528
- const segment = segs[segs.length - 1];
2507
+ if (row.type === "repo-header") {
2508
+ const slug = row.repo;
2509
+ const bare = slug.includes("/") ? slug.slice(slug.indexOf("/") + 1) : slug;
2529
2510
  return renderHeaderLine({
2530
- indent: " ".repeat(1 + depth2 * 2),
2531
- collapsed: state.collapsedDomains.has(`${row.source}:${row.domain}`),
2532
- match: (r) => isAsset(r) && inDomain(r, row.source, row.domain),
2533
- refs: domainAssetRefs(state.assetRows, row.source, row.domain),
2534
- label: pc5.bold(segment),
2511
+ indent: " ".repeat(3),
2512
+ collapsed: state.collapsedRepos.has(`${row.source}:${slug}`),
2513
+ match: (r) => isAsset(r) && inRepo(r, row.source, slug),
2514
+ refs: repoAssetRefs(state.assetRows, row.source, slug),
2515
+ label: pc5.bold(bare),
2535
2516
  selected
2536
2517
  });
2537
2518
  }
2538
2519
  const e = row.entry;
2539
- const ref = assetRefOf(row);
2520
+ const ref = assetRefOf(row) ?? "";
2540
2521
  let status4;
2541
2522
  if (state.pendingAdds.has(ref)) status4 = pc5.blue("+ ");
2542
2523
  else if (state.pendingRemoves.has(ref)) status4 = pc5.red("- ");
@@ -2544,10 +2525,11 @@ function renderAssetRow(row, selected) {
2544
2525
  else status4 = pc5.dim("\xB7 ");
2545
2526
  const kind = kindColorPad(e.kind, 8);
2546
2527
  const name = e.name.padEnd(30);
2547
- const desc = e.description?.slice(0, state.cols - 52) ?? "";
2548
- const depth = (e.domain || "other").split("/").length;
2549
- const indent = " ".repeat(1 + (depth + 1) * 2);
2550
- const line = `${indent}${status4} ${kind} ${name} ${pc5.dim(desc)}`;
2528
+ const badge = e.category ? `${pc5.dim("[")}${pc5.cyan(e.category)}${pc5.dim("]")} ` : "";
2529
+ const badgeWidth = e.category ? e.category.length + 3 : 0;
2530
+ const desc = e.description?.slice(0, Math.max(0, state.cols - 52 - badgeWidth)) ?? "";
2531
+ const indent = " ".repeat(e.repo ? 5 : 3);
2532
+ const line = `${indent}${status4} ${kind} ${name} ${badge}${pc5.dim(desc)}`;
2551
2533
  return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
2552
2534
  }
2553
2535
  function renderSourceRow(row, selected) {
@@ -2686,13 +2668,13 @@ async function showInfo() {
2686
2668
  function expandUnderCursor() {
2687
2669
  const row = state.visibleRows[state.cursor];
2688
2670
  if (!row) return;
2689
- if (row.type === "source-header" && state.collapsedSources.has(row.source)) {
2671
+ if (row.type === "publisher-header" && state.collapsedSources.has(row.source)) {
2690
2672
  state.collapsedSources.delete(row.source);
2691
2673
  rebuildVisible();
2692
- } else if (row.type === "header") {
2693
- const dk = `${row.source}:${row.domain}`;
2694
- if (state.collapsedDomains.has(dk)) {
2695
- state.collapsedDomains.delete(dk);
2674
+ } else if (row.type === "repo-header") {
2675
+ const dk = `${row.source}:${row.repo}`;
2676
+ if (state.collapsedRepos.has(dk)) {
2677
+ state.collapsedRepos.delete(dk);
2696
2678
  rebuildVisible();
2697
2679
  }
2698
2680
  }
@@ -2700,23 +2682,23 @@ function expandUnderCursor() {
2700
2682
  function collapseOrJumpUnderCursor() {
2701
2683
  const row = state.visibleRows[state.cursor];
2702
2684
  if (!row) return;
2703
- if (row.type === "source-header") {
2685
+ if (row.type === "publisher-header") {
2704
2686
  if (!state.collapsedSources.has(row.source)) {
2705
2687
  state.collapsedSources.add(row.source);
2706
2688
  rebuildVisible();
2707
2689
  }
2708
2690
  return;
2709
2691
  }
2710
- if (row.type === "header") {
2711
- const dk = `${row.source}:${row.domain}`;
2712
- if (!state.collapsedDomains.has(dk)) {
2713
- state.collapsedDomains.add(dk);
2692
+ if (row.type === "repo-header") {
2693
+ const dk = `${row.source}:${row.repo}`;
2694
+ if (!state.collapsedRepos.has(dk)) {
2695
+ state.collapsedRepos.add(dk);
2714
2696
  rebuildVisible();
2715
2697
  } else {
2716
2698
  const idx2 = findLastIndex(
2717
2699
  state.visibleRows,
2718
2700
  state.cursor,
2719
- (r) => r.type === "source-header"
2701
+ (r) => r.type === "publisher-header"
2720
2702
  );
2721
2703
  if (idx2 >= 0) state.cursor = idx2;
2722
2704
  }
@@ -2725,7 +2707,7 @@ function collapseOrJumpUnderCursor() {
2725
2707
  const idx = findLastIndex(
2726
2708
  state.visibleRows,
2727
2709
  state.cursor,
2728
- (r) => r.type === "header" || r.type === "source-header"
2710
+ (r) => r.type === "repo-header" || r.type === "publisher-header"
2729
2711
  );
2730
2712
  if (idx >= 0) state.cursor = idx;
2731
2713
  }
@@ -2912,54 +2894,50 @@ function makeMcpServerCommand() {
2912
2894
  function makeNpxCommand() {
2913
2895
  const npx = new Command("npx").description("Compatibility shim for npx skills syntax");
2914
2896
  const skills = npx.command("skills").description("Skill installation from external repos");
2915
- skills.command("add <url>").description("Register a repo as a Library Source and install a skill from it").requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").option("--global", "Deploy globally").action(async (url, opts) => {
2897
+ skills.command("add <url>").description(
2898
+ "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
2899
+ ).requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").option("--global", "Deploy globally").action(async (url, opts) => {
2916
2900
  const projectDir = path14__default.resolve(opts.projectDir);
2917
- const spinner5 = p5.spinner();
2918
- let sourcePath;
2919
- const isUrl = /^(https?:|git@|git:)/.test(url);
2920
- if (isUrl) {
2921
- sourcePath = cloneDestination(url);
2922
- spinner5.start(`Cloning ${url}`);
2923
- try {
2924
- if (!existsSync(sourcePath)) {
2925
- execSync(`git clone ${url} ${sourcePath}`, { stdio: "ignore" });
2926
- }
2927
- spinner5.stop(`Cloned to ${path14__default.basename(sourcePath)}`);
2928
- } catch (err) {
2929
- spinner5.stop("Clone failed");
2930
- logErr(err instanceof Error ? err.message : String(err));
2931
- process.exit(1);
2932
- }
2933
- } else {
2934
- sourcePath = path14__default.resolve(url);
2935
- if (!existsSync(sourcePath)) {
2936
- logErr(`Path does not exist: ${sourcePath}`);
2937
- process.exit(1);
2938
- }
2901
+ const projYaml = path14__default.join(projectDir, "skaile.yaml");
2902
+ if (!existsSync(projYaml)) {
2903
+ logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
2904
+ process.exit(1);
2939
2905
  }
2940
- const library = await openLibrary();
2906
+ if (!/^(?:https?:|git@|git:)/.test(url)) {
2907
+ logErr(
2908
+ "npx skills add requires a git URL \u2014 resolution runs through the project's sources[]."
2909
+ );
2910
+ process.exit(1);
2911
+ }
2912
+ const spinner5 = p5.spinner();
2913
+ const slug = sourceSlug(url);
2914
+ const clonePath = path14__default.join(homedir(), ".skaile", "sources", slug);
2915
+ spinner5.start(`Cloning ${url}`);
2941
2916
  try {
2942
- const existing = await library.listSources();
2943
- let source = existing.find((s) => s.path === sourcePath);
2944
- if (!source) {
2945
- source = await library.addSource({
2946
- backend: "local",
2947
- name: path14__default.basename(sourcePath),
2948
- path: sourcePath,
2949
- ownership: "owner"
2950
- });
2917
+ if (!existsSync(clonePath)) {
2918
+ execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
2951
2919
  }
2952
- spinner5.start("Syncing source");
2953
- const { LocalCatalogSource: LocalCatalogSource2 } = await import('../library/index.js');
2954
- const registry = createFullRegistry();
2955
- const catalogSource = new LocalCatalogSource2(library, source.id, sourcePath, registry);
2956
- const result = await catalogSource.sync();
2957
- await library.syncSource(source.id);
2958
- spinner5.stop(`Indexed ${result.assetsUpdated} assets`);
2959
- } finally {
2960
- library.close();
2920
+ spinner5.stop(`Cloned to ${slug}`);
2921
+ } catch (err) {
2922
+ spinner5.stop("Clone failed");
2923
+ logErr(err instanceof Error ? err.message : String(err));
2924
+ process.exit(1);
2961
2925
  }
2962
- const skillRef = `skill:${opts.skill}`;
2926
+ const editor = WorkspaceYamlEditor.load(projYaml);
2927
+ editor.setSource({ url });
2928
+ editor.save();
2929
+ const publisher = resolvePublisher(clonePath, url);
2930
+ if (!publisher) {
2931
+ logErr(
2932
+ `Could not determine the publisher for "${opts.skill}". Declare \`publisher:\` in the source's skaile.yaml, or use a github URL.`
2933
+ );
2934
+ process.exit(1);
2935
+ }
2936
+ const skillName = resolveSkillName(clonePath, opts.skill);
2937
+ if (skillName !== opts.skill) {
2938
+ logInfo(`Resolved "${opts.skill}" \u2192 directory "${skillName}".`);
2939
+ }
2940
+ const skillRef = `skill:${skillName}@${publisher}`;
2963
2941
  const am2 = new AssetManager({ projectDir, global: opts.global, driverTarget: opts.target });
2964
2942
  spinner5.start(`Installing ${skillRef}`);
2965
2943
  try {
@@ -2970,9 +2948,7 @@ function makeNpxCommand() {
2970
2948
  } else {
2971
2949
  for (const a of added) logOk(a);
2972
2950
  }
2973
- logInfo(
2974
- `Source registered at ${S.dim(sourcePath)} \u2014 manage via ${S.cmd("skaile source")}.`
2975
- );
2951
+ logInfo(`Source registered in skaile.yaml \u2014 manage via ${S.cmd("skaile source")}.`);
2976
2952
  } catch (err) {
2977
2953
  spinner5.stop("Failed");
2978
2954
  logErr(err.message);
@@ -2983,25 +2959,37 @@ function makeNpxCommand() {
2983
2959
  skills.action(() => skills.help());
2984
2960
  return npx;
2985
2961
  }
2986
- function cloneDestination(url) {
2987
- const cleaned = url.replace(/\.git$/, "");
2988
- const root = path14__default.join(homedir(), ".skaile", "clones");
2989
- let host = "unknown";
2990
- let pathPart = cleaned;
2991
- const httpMatch = cleaned.match(/^https?:\/\/([^/]+)\/(.+)$/);
2992
- const gitMatch = cleaned.match(/^git@([^:]+):(.+)$/);
2993
- const gitProtoMatch = cleaned.match(/^git:\/\/([^/]+)\/(.+)$/);
2994
- if (httpMatch) {
2995
- host = httpMatch[1];
2996
- pathPart = httpMatch[2];
2997
- } else if (gitMatch) {
2998
- host = gitMatch[1];
2999
- pathPart = gitMatch[2];
3000
- } else if (gitProtoMatch) {
3001
- host = gitProtoMatch[1];
3002
- pathPart = gitProtoMatch[2];
3003
- }
3004
- return path14__default.join(root, host, pathPart);
2962
+ function resolvePublisher(clonePath, url) {
2963
+ const yamlPath = path14__default.join(clonePath, "skaile.yaml");
2964
+ if (existsSync(yamlPath)) {
2965
+ try {
2966
+ const { config } = decodeSkaileYaml(readFileSync(yamlPath, "utf8"));
2967
+ if (typeof config.publisher === "string" && config.publisher.length > 0) {
2968
+ return config.publisher;
2969
+ }
2970
+ } catch {
2971
+ }
2972
+ }
2973
+ return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
2974
+ }
2975
+ function resolveSkillName(clonePath, requested) {
2976
+ const skillsDir = path14__default.join(clonePath, "skills");
2977
+ if (existsSync(path14__default.join(skillsDir, requested, "SKILL.md"))) return requested;
2978
+ if (!existsSync(skillsDir)) return requested;
2979
+ for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
2980
+ if (!entry.isDirectory()) continue;
2981
+ const md = path14__default.join(skillsDir, entry.name, "SKILL.md");
2982
+ if (!existsSync(md)) continue;
2983
+ try {
2984
+ const { data } = parseFrontmatter(readFileSync(md, "utf8"));
2985
+ if (typeof data.name === "string" && data.name === requested) return entry.name;
2986
+ } catch {
2987
+ }
2988
+ }
2989
+ return requested;
2990
+ }
2991
+ function sourceSlug(url) {
2992
+ return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
3005
2993
  }
3006
2994
  var SKAILE_MCP_NAME = "skaile-workspace";
3007
2995
  var MCP_SERVER_ENTRY = {
@@ -3691,7 +3679,7 @@ function action2(fn) {
3691
3679
  };
3692
3680
  }
3693
3681
  async function reconcileAndReport(projectDir, plugins) {
3694
- const { reconcilePlugins } = await import('../plugin-store-AJ3FGXIC.js');
3682
+ const { reconcilePlugins } = await import('../plugin-store-QS7TC5HY.js');
3695
3683
  if (plugins.length === 0) {
3696
3684
  logInfo("No plugins declared \u2014 nothing to reconcile.");
3697
3685
  return;
@@ -3707,7 +3695,7 @@ async function reconcileAndReport(projectDir, plugins) {
3707
3695
  async function runInstall2(spec, opts) {
3708
3696
  const projectDir = path14__default.resolve(opts.projectDir);
3709
3697
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
3710
- const { specName } = await import('../plugin-store-AJ3FGXIC.js');
3698
+ const { specName } = await import('../plugin-store-QS7TC5HY.js');
3711
3699
  const yamlPath = path14__default.join(projectDir, "skaile.yaml");
3712
3700
  const editor = WorkspaceYamlEditor2.load(yamlPath);
3713
3701
  const replaced = editor.addPlugin(spec, specName);
@@ -3719,7 +3707,7 @@ async function runInstall2(spec, opts) {
3719
3707
  async function runRemove(name, opts) {
3720
3708
  const projectDir = path14__default.resolve(opts.projectDir);
3721
3709
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
3722
- const { specName } = await import('../plugin-store-AJ3FGXIC.js');
3710
+ const { specName } = await import('../plugin-store-QS7TC5HY.js');
3723
3711
  const yamlPath = path14__default.join(projectDir, "skaile.yaml");
3724
3712
  const editor = WorkspaceYamlEditor2.load(yamlPath);
3725
3713
  const removed = editor.removePlugin(name, specName);
@@ -3747,7 +3735,7 @@ async function runList(opts) {
3747
3735
  const registry = createPluginRegistry();
3748
3736
  if (declared.length > 0) {
3749
3737
  try {
3750
- const { loadPlugins } = await import('../plugin-store-AJ3FGXIC.js');
3738
+ const { loadPlugins } = await import('../plugin-store-QS7TC5HY.js');
3751
3739
  const result = await loadPlugins(projectDir, declared, registry);
3752
3740
  for (const f of result.failed) logWarn(f.error);
3753
3741
  } catch (err) {
@@ -3950,7 +3938,7 @@ function makeInstallCommand() {
3950
3938
  const spinner6 = p5.spinner();
3951
3939
  spinner6.start(`Installing ${ref}`);
3952
3940
  try {
3953
- const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-M4DB3D3J.js');
3941
+ const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-CT4VVESU.js');
3954
3942
  const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
3955
3943
  if (!supportsInstallManifest(catalog)) {
3956
3944
  throw new Error(
@@ -3982,7 +3970,7 @@ function makeInstallCommand() {
3982
3970
  }
3983
3971
  const projectDir = path14__default.resolve(opts.projectDir);
3984
3972
  try {
3985
- const { ensureSourcesCloned } = await import('../ensure-sources-SL2S4UEX.js');
3973
+ const { ensureSourcesCloned } = await import('../ensure-sources-REWWBH2K.js');
3986
3974
  const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
3987
3975
  if (hydrate.cloned.length > 0) {
3988
3976
  logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
@@ -4440,7 +4428,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
4440
4428
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
4441
4429
  const config = resolveSkWorkspaceConfig2(projectDir);
4442
4430
  if (!config.plugins || config.plugins.length === 0) return;
4443
- const { ensurePluginsLoaded } = await import('../plugin-store-AJ3FGXIC.js');
4431
+ const { ensurePluginsLoaded } = await import('../plugin-store-QS7TC5HY.js');
4444
4432
  const { pluginRegistry } = await import('../plugin-registry/index.js');
4445
4433
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
4446
4434
  if (result.loaded.length > 0) {
@@ -5296,6 +5284,14 @@ function sourceClonePath(name) {
5296
5284
  function deriveSlug(url) {
5297
5285
  return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
5298
5286
  }
5287
+ function normalizeSourceUrl(input) {
5288
+ const s = input.trim();
5289
+ if (/^(?:https?|git|ssh|file):\/\//.test(s) || /^git@/.test(s)) return s;
5290
+ const repo = s.replace(/\.git$/, "");
5291
+ if (/^[\w.-]+\/[\w.-]+$/.test(repo)) return `git@github.com:${repo}.git`;
5292
+ if (/^[\w.-]+$/.test(repo)) return `git@github.com:skaile-ai/${repo}.git`;
5293
+ return s;
5294
+ }
5299
5295
  function requireProjectYamlPath() {
5300
5296
  const root = findWorkspaceRoot(process.cwd());
5301
5297
  if (!root) {
@@ -5371,8 +5367,11 @@ function makeSourceCommand() {
5371
5367
  const cmd = new Command("source").description(
5372
5368
  "Manage github sources for the current project (recorded in skaile.yaml)"
5373
5369
  );
5374
- cmd.command("add <git-url>").description("Clone a github repo and register it in this project's skaile.yaml").option("--name <slug>", "[deprecated] no-op \u2014 the source entry stores only the URL").option("--pin <ref>", "Pin a branch, tag, or 40-char SHA").option("--branch <branch>", "[deprecated] alias for --pin").option("--force", "Remove an existing clone and re-clone", false).option("--dev", "Also index dev-only assets under the source's dev_paths", false).action(
5375
- async (url, opts) => {
5370
+ cmd.command("add <source>").description(
5371
+ "Clone a github repo and register it in this project's skaile.yaml. <source> may be a full git URL, an owner/repo shorthand, or a bare name (\u2192 git@github.com:skaile-ai/<name>.git)."
5372
+ ).option("--name <slug>", "[deprecated] no-op \u2014 the source entry stores only the URL").option("--pin <ref>", "Pin a branch, tag, or 40-char SHA").option("--branch <branch>", "[deprecated] alias for --pin").option("--force", "Remove an existing clone and re-clone", false).option("--dev", "Also index dev-only assets under the source's dev_paths", false).action(
5373
+ async (source, opts) => {
5374
+ const url = normalizeSourceUrl(source);
5376
5375
  const yamlPath = requireProjectYamlPath();
5377
5376
  if (opts.name) {
5378
5377
  logWarn(
@@ -6244,7 +6243,7 @@ Advanced:
6244
6243
  });
6245
6244
  program.command("init [project-dir]").description("Initialize a project directory (defaults to current directory)").option("--backend <name>", "Coding-agent backend (claude-code | omp | codex)", "claude-code").option("--no-git", "Skip git init and .gitignore").action(async (projectDir, opts) => {
6246
6245
  const { execSync: execSync3 } = await import('child_process');
6247
- const { existsSync: existsSync12, mkdirSync: mkdirSync3, readFileSync: readFileSync5, writeFileSync: writeFileSync2 } = await import('fs');
6246
+ const { existsSync: existsSync12, mkdirSync: mkdirSync3, readFileSync: readFileSync6, writeFileSync: writeFileSync2 } = await import('fs');
6248
6247
  const { stringify } = await import('yaml');
6249
6248
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
6250
6249
  const backend = opts.backend;
@@ -6302,7 +6301,7 @@ program.command("init [project-dir]").description("Initialize a project director
6302
6301
  if (opts.git) {
6303
6302
  const gitignorePath = path14__default.join(resolved, ".gitignore");
6304
6303
  const entries = ["node_modules/", ".skaile/sessions/", "*.log", ".env", ".env.local"];
6305
- const existing = existsSync12(gitignorePath) ? readFileSync5(gitignorePath, "utf-8") : "";
6304
+ const existing = existsSync12(gitignorePath) ? readFileSync6(gitignorePath, "utf-8") : "";
6306
6305
  const have = new Set(existing.split("\n").map((l) => l.trim()));
6307
6306
  const append = entries.filter((e) => !have.has(e));
6308
6307
  if (append.length > 0) {
@@ -6338,7 +6337,7 @@ program.command("init [project-dir]").description("Initialize a project director
6338
6337
  );
6339
6338
  }
6340
6339
  try {
6341
- const { ensureSourcesCloned } = await import('../ensure-sources-SL2S4UEX.js');
6340
+ const { ensureSourcesCloned } = await import('../ensure-sources-REWWBH2K.js');
6342
6341
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
6343
6342
  for (const n of hydrate.cloned) created.push(`~/.skaile/sources/${n}/`);
6344
6343
  if (hydrate.failed.length > 0) {
@@ -6364,7 +6363,7 @@ program.command("init [project-dir]").description("Initialize a project director
6364
6363
  console.log();
6365
6364
  });
6366
6365
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
6367
- const { cmdSetup } = await import('../setup-GBSQX7JF.js');
6366
+ const { cmdSetup } = await import('../setup-F6DGKL7J.js');
6368
6367
  await cmdSetup([], { projectDir: process.cwd() });
6369
6368
  });
6370
6369
  program.addCommand(makeInstallCommand());