@skaile/workspaces 0.22.0-beta.1 → 0.22.0-beta.2

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 (157) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/dist/{asset-feeds-QXCSAJRN.js → asset-feeds-2M6UKEJ7.js} +13 -14
  3. package/dist/asset-feeds-2M6UKEJ7.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-32NA4TVC.js +30 -0
  30. package/dist/chunk-32NA4TVC.js.map +1 -0
  31. package/dist/{chunk-DKGDOALM.js → chunk-3KLWGHDE.js} +5 -5
  32. package/dist/{chunk-DKGDOALM.js.map → chunk-3KLWGHDE.js.map} +1 -1
  33. package/dist/{chunk-LT4DLEYE.js → chunk-6SA2SIOU.js} +24 -8
  34. package/dist/chunk-6SA2SIOU.js.map +1 -0
  35. package/dist/{chunk-GFNW72LW.js → chunk-74GTZ4TJ.js} +4 -4
  36. package/dist/{chunk-GFNW72LW.js.map → chunk-74GTZ4TJ.js.map} +1 -1
  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-D7K72XEY.js → chunk-CEUHU3C4.js} +3 -3
  40. package/dist/{chunk-D7K72XEY.js.map → chunk-CEUHU3C4.js.map} +1 -1
  41. package/dist/{chunk-NJLHHZIW.js → chunk-FIHVQFXB.js} +2 -2
  42. package/dist/{chunk-NJLHHZIW.js.map → chunk-FIHVQFXB.js.map} +1 -1
  43. package/dist/{chunk-XIHFJVOD.js → chunk-FVZLCBSX.js} +3 -3
  44. package/dist/{chunk-XIHFJVOD.js.map → chunk-FVZLCBSX.js.map} +1 -1
  45. package/dist/{chunk-7PTP3SQJ.js → chunk-GTS2FODO.js} +32 -7
  46. package/dist/chunk-GTS2FODO.js.map +1 -0
  47. package/dist/{chunk-JHF66MCK.js → chunk-I5SGBFMM.js} +5 -3
  48. package/dist/chunk-I5SGBFMM.js.map +1 -0
  49. package/dist/{chunk-PTIHB2TV.js → chunk-LDLZFYLR.js} +4 -4
  50. package/dist/{chunk-PTIHB2TV.js.map → chunk-LDLZFYLR.js.map} +1 -1
  51. package/dist/{chunk-J3VKAEQP.js → chunk-LDYPQVRU.js} +23 -6
  52. package/dist/chunk-LDYPQVRU.js.map +1 -0
  53. package/dist/{chunk-APAOQLPT.js → chunk-M5JDVO6D.js} +3 -3
  54. package/dist/{chunk-APAOQLPT.js.map → chunk-M5JDVO6D.js.map} +1 -1
  55. package/dist/{chunk-V3QMSM5I.js → chunk-NICAMYPV.js} +13 -14
  56. package/dist/chunk-NICAMYPV.js.map +1 -0
  57. package/dist/{chunk-4AZKT2BU.js → chunk-NQL3T75I.js} +14 -49
  58. package/dist/chunk-NQL3T75I.js.map +1 -0
  59. package/dist/{chunk-UMOENHVH.js → chunk-P4FYHEHW.js} +3 -3
  60. package/dist/{chunk-UMOENHVH.js.map → chunk-P4FYHEHW.js.map} +1 -1
  61. package/dist/{chunk-VCYXVP2S.js → chunk-TWQPDBHB.js} +24 -13
  62. package/dist/chunk-TWQPDBHB.js.map +1 -0
  63. package/dist/{chunk-3ECS5PFD.js → chunk-UBLTUFFI.js} +4 -4
  64. package/dist/{chunk-3ECS5PFD.js.map → chunk-UBLTUFFI.js.map} +1 -1
  65. package/dist/{chunk-I3UEM3FX.js → chunk-VUCPJBAG.js} +9 -4
  66. package/dist/chunk-VUCPJBAG.js.map +1 -0
  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 +189 -195
  70. package/dist/cli/index.js.map +1 -1
  71. package/dist/cli/src/commands/manage.d.ts +22 -31
  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/manifest.d.ts.map +1 -1
  84. package/dist/core/src/models.d.ts +8 -2
  85. package/dist/core/src/models.d.ts.map +1 -1
  86. package/dist/core/src/repo-manager.d.ts +17 -2
  87. package/dist/core/src/repo-manager.d.ts.map +1 -1
  88. package/dist/core/workspace-config.js +3 -3
  89. package/dist/deploy/index.js +138 -42
  90. package/dist/deploy/index.js.map +1 -1
  91. package/dist/deploy/src/index.d.ts +4 -3
  92. package/dist/deploy/src/index.d.ts.map +1 -1
  93. package/dist/deploy/src/targets/container-runtime.d.ts.map +1 -1
  94. package/dist/deploy/src/targets/local.d.ts.map +1 -1
  95. package/dist/deploy/src/targets/nix.d.ts +36 -0
  96. package/dist/deploy/src/targets/nix.d.ts.map +1 -0
  97. package/dist/deploy/src/targets/process-handle.d.ts +34 -0
  98. package/dist/deploy/src/targets/process-handle.d.ts.map +1 -0
  99. package/dist/discovery/index.js +3 -3
  100. package/dist/{ensure-sources-SL2S4UEX.js → ensure-sources-ALTI5PXR.js} +9 -9
  101. package/dist/{ensure-sources-SL2S4UEX.js.map → ensure-sources-ALTI5PXR.js.map} +1 -1
  102. package/dist/library/index.js +4 -4
  103. package/dist/open-library-EEGG6RDN.js +13 -0
  104. package/dist/{open-library-M4DB3D3J.js.map → open-library-EEGG6RDN.js.map} +1 -1
  105. package/dist/plugin-registry/src/context.d.ts +30 -1
  106. package/dist/plugin-registry/src/context.d.ts.map +1 -1
  107. package/dist/plugin-registry/src/index.d.ts +1 -1
  108. package/dist/plugin-registry/src/index.d.ts.map +1 -1
  109. package/dist/{plugin-store-AJ3FGXIC.js → plugin-store-G277ZX3B.js} +7 -7
  110. package/dist/{plugin-store-AJ3FGXIC.js.map → plugin-store-G277ZX3B.js.map} +1 -1
  111. package/dist/plugins/src/catalog-source.d.ts +5 -0
  112. package/dist/plugins/src/catalog-source.d.ts.map +1 -1
  113. package/dist/runner/index.js +13 -12
  114. package/dist/runner/src/serve.d.ts +7 -0
  115. package/dist/runner/src/serve.d.ts.map +1 -1
  116. package/dist/sdk/asset-manager.js +7 -7
  117. package/dist/sdk/core.js +5 -5
  118. package/dist/sdk/index.js +13 -12
  119. package/dist/sdk/index.js.map +1 -1
  120. package/dist/sdk/runner.js +13 -12
  121. package/dist/sdk/transport/ws/client.js +2 -1
  122. package/dist/sdk/transport/ws/server.js +2 -1
  123. package/dist/sdk/transport/ws.js +4 -3
  124. package/dist/sdk/transport.js +4 -3
  125. package/dist/{setup-GBSQX7JF.js → setup-REX4I5NE.js} +7 -7
  126. package/dist/{setup-GBSQX7JF.js.map → setup-REX4I5NE.js.map} +1 -1
  127. package/dist/store-client-IX3Y67NK.js +14 -0
  128. package/dist/{store-client-5WBRUC5U.js.map → store-client-IX3Y67NK.js.map} +1 -1
  129. package/dist/transport/index.js +4 -3
  130. package/dist/transport/src/ws/auth.d.ts +34 -0
  131. package/dist/transport/src/ws/auth.d.ts.map +1 -0
  132. package/dist/transport/src/ws/client.d.ts +4 -0
  133. package/dist/transport/src/ws/client.d.ts.map +1 -1
  134. package/dist/transport/src/ws/index.d.ts +3 -2
  135. package/dist/transport/src/ws/index.d.ts.map +1 -1
  136. package/dist/transport/src/ws/server.d.ts +5 -0
  137. package/dist/transport/src/ws/server.d.ts.map +1 -1
  138. package/dist/transport/ws/client.js +2 -1
  139. package/dist/transport/ws/server.js +2 -1
  140. package/dist/transport/ws.js +4 -3
  141. package/dist/tui/index.js +13 -12
  142. package/dist/tui/index.js.map +1 -1
  143. package/dist/workspace-plugin/index.js +1 -1
  144. package/package.json +1 -1
  145. package/dist/asset-feeds-QXCSAJRN.js.map +0 -1
  146. package/dist/chunk-4AZKT2BU.js.map +0 -1
  147. package/dist/chunk-7PTP3SQJ.js.map +0 -1
  148. package/dist/chunk-I3UEM3FX.js.map +0 -1
  149. package/dist/chunk-J3VKAEQP.js.map +0 -1
  150. package/dist/chunk-JHF66MCK.js.map +0 -1
  151. package/dist/chunk-LT4DLEYE.js.map +0 -1
  152. package/dist/chunk-PBWMV5GM.js.map +0 -1
  153. package/dist/chunk-V3QMSM5I.js.map +0 -1
  154. package/dist/chunk-VCYXVP2S.js.map +0 -1
  155. package/dist/chunk-W2O5LWYU.js +0 -3
  156. package/dist/open-library-M4DB3D3J.js +0 -13
  157. 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-UBLTUFFI.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-FVZLCBSX.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-I5SGBFMM.js';
8
8
  import '../chunk-R7FOF242.js';
9
- import '../chunk-D7K72XEY.js';
9
+ import '../chunk-CEUHU3C4.js';
10
10
  import '../chunk-OKRUTSG7.js';
11
- import { runFlow, resumeFlow } from '../chunk-DKGDOALM.js';
11
+ import { runFlow, resumeFlow } from '../chunk-3KLWGHDE.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-NICAMYPV.js';
15
+ import { buildClaudePluginFiles } from '../chunk-FIHVQFXB.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-6SA2SIOU.js';
31
+ import '../chunk-M5JDVO6D.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-TWQPDBHB.js';
39
+ import '../chunk-LDLZFYLR.js';
40
+ import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-P4FYHEHW.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-74GTZ4TJ.js';
44
+ import { resolveSkWorkspaceConfig, resolveAgentDir, decodeSkaileYaml, findWorkspaceRoot, workspaceConfigFilename } from '../chunk-LDYPQVRU.js';
45
+ import { parseFrontmatter } from '../chunk-NQL3T75I.js';
46
+ import { ASSET_KINDS } 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-IX3Y67NK.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-EEGG6RDN.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-G277ZX3B.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,45 +2204,25 @@ 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));
2245
2226
  }
2246
2227
  function sourceAssetRefs(rows, source) {
2247
2228
  return rows.filter((r) => isAsset(r) && inSource(r, source)).map((r) => assetRefOf(r));
@@ -2252,10 +2233,9 @@ 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
2241
  if (!isAsset(r) || !r.entry) return null;
@@ -2297,48 +2277,38 @@ function bulkSelection(refs, action3) {
2297
2277
  for (const ref of refs) setSelection(ref, action3);
2298
2278
  }
2299
2279
  function actOnHeader(row, action3) {
2300
- if (row.type === "source-header") {
2280
+ if (row.type === "publisher-header") {
2301
2281
  bulkSelection(sourceAssetRefs(state.assetRows, row.source), action3);
2302
2282
  return true;
2303
2283
  }
2304
- if (row.type === "header") {
2305
- bulkSelection(domainAssetRefs(state.assetRows, row.source, row.domain), action3);
2284
+ if (row.type === "repo-header") {
2285
+ bulkSelection(repoAssetRefs(state.assetRows, row.source, row.repo), action3);
2306
2286
  return true;
2307
2287
  }
2308
2288
  return false;
2309
2289
  }
2310
2290
  async function loadAssets() {
2311
- const { gatherAssetFeeds } = await import('../asset-feeds-QXCSAJRN.js');
2291
+ const { gatherAssetFeeds } = await import('../asset-feeds-2M6UKEJ7.js');
2312
2292
  const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
2313
2293
  if (notes.length > 0) {
2314
2294
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
2315
2295
  }
2316
2296
  const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
2317
- const bySource = /* @__PURE__ */ new Map();
2297
+ const byPublisher = /* @__PURE__ */ new Map();
2318
2298
  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);
2299
+ const publisher = e.publisher || "other";
2300
+ const repo = e.repo || "";
2301
+ if (!byPublisher.has(publisher)) byPublisher.set(publisher, /* @__PURE__ */ new Map());
2302
+ const byRepo = byPublisher.get(publisher);
2303
+ if (!byRepo.has(repo)) byRepo.set(repo, []);
2304
+ byRepo.get(repo).push(e);
2325
2305
  }
2326
2306
  const rows = [];
2327
- for (const [source, domainMap] of [...bySource.entries()].sort(
2307
+ for (const [publisher, byRepo] of [...byPublisher.entries()].sort(
2328
2308
  (a, b) => a[0].localeCompare(b[0])
2329
2309
  )) {
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
- }
2310
+ rows.push({ type: "publisher-header", source: publisher });
2311
+ const pushAssets = (items) => {
2342
2312
  items.sort(
2343
2313
  (a, b) => a.kind !== b.kind ? a.kind.localeCompare(b.kind) : a.name.localeCompare(b.name)
2344
2314
  );
@@ -2346,26 +2316,34 @@ async function loadAssets() {
2346
2316
  const ref = `${entry.kind}:${entry.name}`;
2347
2317
  rows.push({ type: "asset", entry, installed: installed.has(ref) });
2348
2318
  }
2319
+ };
2320
+ const noRepo = byRepo.get("");
2321
+ if (noRepo) pushAssets(noRepo);
2322
+ for (const [repo, items] of [...byRepo.entries()].filter(([r]) => r !== "").sort((a, b) => a[0].localeCompare(b[0]))) {
2323
+ rows.push({ type: "repo-header", source: publisher, repo });
2324
+ pushAssets(items);
2349
2325
  }
2350
2326
  }
2351
2327
  state.assetRows = rows;
2352
- const newSources = new Set(rows.filter((r) => r.type === "source-header").map((r) => r.source));
2328
+ const newSources = new Set(
2329
+ rows.filter((r) => r.type === "publisher-header").map((r) => r.source)
2330
+ );
2353
2331
  for (const s of state.collapsedSources) {
2354
2332
  if (!newSources.has(s)) state.collapsedSources.delete(s);
2355
2333
  }
2356
- const newDomainKeys = new Set(
2357
- rows.filter((r) => r.type === "header").map((r) => `${r.source}:${r.domain}`)
2334
+ const newRepoKeys = new Set(
2335
+ rows.filter((r) => r.type === "repo-header").map((r) => `${r.source}:${r.repo}`)
2358
2336
  );
2359
- for (const d of state.collapsedDomains) {
2360
- if (!newDomainKeys.has(d)) state.collapsedDomains.delete(d);
2337
+ for (const d of state.collapsedRepos) {
2338
+ if (!newRepoKeys.has(d)) state.collapsedRepos.delete(d);
2361
2339
  }
2362
- for (const d of newDomainKeys) state.collapsedDomains.add(d);
2340
+ for (const d of newRepoKeys) state.collapsedRepos.add(d);
2363
2341
  rebuildVisible();
2364
2342
  }
2365
2343
  async function loadSourcesAndLibraries() {
2366
2344
  try {
2367
2345
  const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir: skaileHomeDir2 }] = await Promise.all([
2368
- import('../open-library-M4DB3D3J.js'),
2346
+ import('../open-library-EEGG6RDN.js'),
2369
2347
  import('../library/index.js')
2370
2348
  ]);
2371
2349
  const { manager, library, close } = await openLibraryManager2();
@@ -2404,7 +2382,7 @@ function rebuildVisible() {
2404
2382
  state.visibleRows = buildVisibleRows(
2405
2383
  state.assetRows,
2406
2384
  state.collapsedSources,
2407
- state.collapsedDomains
2385
+ state.collapsedRepos
2408
2386
  );
2409
2387
  clampCursor();
2410
2388
  }
@@ -2512,7 +2490,7 @@ function renderHeaderLine(opts) {
2512
2490
  return opts.selected ? pc5.bgWhite(pc5.black(`${line} `.padEnd(state.cols))) : line;
2513
2491
  }
2514
2492
  function renderAssetRow(row, selected) {
2515
- if (row.type === "source-header") {
2493
+ if (row.type === "publisher-header") {
2516
2494
  return renderHeaderLine({
2517
2495
  indent: " ",
2518
2496
  collapsed: state.collapsedSources.has(row.source),
@@ -2522,16 +2500,15 @@ function renderAssetRow(row, selected) {
2522
2500
  selected
2523
2501
  });
2524
2502
  }
2525
- if (row.type === "header") {
2526
- const depth2 = row.depth ?? 1;
2527
- const segs = row.domain.split("/");
2528
- const segment = segs[segs.length - 1];
2503
+ if (row.type === "repo-header") {
2504
+ const slug = row.repo;
2505
+ const bare = slug.includes("/") ? slug.slice(slug.indexOf("/") + 1) : slug;
2529
2506
  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),
2507
+ indent: " ".repeat(3),
2508
+ collapsed: state.collapsedRepos.has(`${row.source}:${slug}`),
2509
+ match: (r) => isAsset(r) && inRepo(r, row.source, slug),
2510
+ refs: repoAssetRefs(state.assetRows, row.source, slug),
2511
+ label: pc5.bold(bare),
2535
2512
  selected
2536
2513
  });
2537
2514
  }
@@ -2544,10 +2521,10 @@ function renderAssetRow(row, selected) {
2544
2521
  else status4 = pc5.dim("\xB7 ");
2545
2522
  const kind = kindColorPad(e.kind, 8);
2546
2523
  const name = e.name.padEnd(30);
2524
+ const badge = e.category ? `${pc5.dim("[")}${pc5.cyan(e.category)}${pc5.dim("]")} ` : "";
2547
2525
  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)}`;
2526
+ const indent = " ".repeat(e.repo ? 5 : 3);
2527
+ const line = `${indent}${status4} ${kind} ${name} ${badge}${pc5.dim(desc)}`;
2551
2528
  return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
2552
2529
  }
2553
2530
  function renderSourceRow(row, selected) {
@@ -2686,13 +2663,13 @@ async function showInfo() {
2686
2663
  function expandUnderCursor() {
2687
2664
  const row = state.visibleRows[state.cursor];
2688
2665
  if (!row) return;
2689
- if (row.type === "source-header" && state.collapsedSources.has(row.source)) {
2666
+ if (row.type === "publisher-header" && state.collapsedSources.has(row.source)) {
2690
2667
  state.collapsedSources.delete(row.source);
2691
2668
  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);
2669
+ } else if (row.type === "repo-header") {
2670
+ const dk = `${row.source}:${row.repo}`;
2671
+ if (state.collapsedRepos.has(dk)) {
2672
+ state.collapsedRepos.delete(dk);
2696
2673
  rebuildVisible();
2697
2674
  }
2698
2675
  }
@@ -2700,23 +2677,23 @@ function expandUnderCursor() {
2700
2677
  function collapseOrJumpUnderCursor() {
2701
2678
  const row = state.visibleRows[state.cursor];
2702
2679
  if (!row) return;
2703
- if (row.type === "source-header") {
2680
+ if (row.type === "publisher-header") {
2704
2681
  if (!state.collapsedSources.has(row.source)) {
2705
2682
  state.collapsedSources.add(row.source);
2706
2683
  rebuildVisible();
2707
2684
  }
2708
2685
  return;
2709
2686
  }
2710
- if (row.type === "header") {
2711
- const dk = `${row.source}:${row.domain}`;
2712
- if (!state.collapsedDomains.has(dk)) {
2713
- state.collapsedDomains.add(dk);
2687
+ if (row.type === "repo-header") {
2688
+ const dk = `${row.source}:${row.repo}`;
2689
+ if (!state.collapsedRepos.has(dk)) {
2690
+ state.collapsedRepos.add(dk);
2714
2691
  rebuildVisible();
2715
2692
  } else {
2716
2693
  const idx2 = findLastIndex(
2717
2694
  state.visibleRows,
2718
2695
  state.cursor,
2719
- (r) => r.type === "source-header"
2696
+ (r) => r.type === "publisher-header"
2720
2697
  );
2721
2698
  if (idx2 >= 0) state.cursor = idx2;
2722
2699
  }
@@ -2725,7 +2702,7 @@ function collapseOrJumpUnderCursor() {
2725
2702
  const idx = findLastIndex(
2726
2703
  state.visibleRows,
2727
2704
  state.cursor,
2728
- (r) => r.type === "header" || r.type === "source-header"
2705
+ (r) => r.type === "repo-header" || r.type === "publisher-header"
2729
2706
  );
2730
2707
  if (idx >= 0) state.cursor = idx;
2731
2708
  }
@@ -2912,54 +2889,50 @@ function makeMcpServerCommand() {
2912
2889
  function makeNpxCommand() {
2913
2890
  const npx = new Command("npx").description("Compatibility shim for npx skills syntax");
2914
2891
  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) => {
2892
+ skills.command("add <url>").description(
2893
+ "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
2894
+ ).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
2895
  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
- }
2896
+ const projYaml = path14__default.join(projectDir, "skaile.yaml");
2897
+ if (!existsSync(projYaml)) {
2898
+ logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
2899
+ process.exit(1);
2900
+ }
2901
+ if (!/^(?:https?:|git@|git:)/.test(url)) {
2902
+ logErr(
2903
+ "npx skills add requires a git URL \u2014 resolution runs through the project's sources[]."
2904
+ );
2905
+ process.exit(1);
2939
2906
  }
2940
- const library = await openLibrary();
2907
+ const spinner5 = p5.spinner();
2908
+ const slug = sourceSlug(url);
2909
+ const clonePath = path14__default.join(homedir(), ".skaile", "sources", slug);
2910
+ spinner5.start(`Cloning ${url}`);
2941
2911
  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
- });
2912
+ if (!existsSync(clonePath)) {
2913
+ execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
2951
2914
  }
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();
2915
+ spinner5.stop(`Cloned to ${slug}`);
2916
+ } catch (err) {
2917
+ spinner5.stop("Clone failed");
2918
+ logErr(err instanceof Error ? err.message : String(err));
2919
+ process.exit(1);
2961
2920
  }
2962
- const skillRef = `skill:${opts.skill}`;
2921
+ const editor = WorkspaceYamlEditor.load(projYaml);
2922
+ editor.setSource({ url });
2923
+ editor.save();
2924
+ const publisher = resolvePublisher(clonePath, url);
2925
+ if (!publisher) {
2926
+ logErr(
2927
+ `Could not determine the publisher for "${opts.skill}". Declare \`publisher:\` in the source's skaile.yaml, or use a github URL.`
2928
+ );
2929
+ process.exit(1);
2930
+ }
2931
+ const skillName = resolveSkillName(clonePath, opts.skill);
2932
+ if (skillName !== opts.skill) {
2933
+ logInfo(`Resolved "${opts.skill}" \u2192 directory "${skillName}".`);
2934
+ }
2935
+ const skillRef = `skill:${skillName}@${publisher}`;
2963
2936
  const am2 = new AssetManager({ projectDir, global: opts.global, driverTarget: opts.target });
2964
2937
  spinner5.start(`Installing ${skillRef}`);
2965
2938
  try {
@@ -2970,9 +2943,7 @@ function makeNpxCommand() {
2970
2943
  } else {
2971
2944
  for (const a of added) logOk(a);
2972
2945
  }
2973
- logInfo(
2974
- `Source registered at ${S.dim(sourcePath)} \u2014 manage via ${S.cmd("skaile source")}.`
2975
- );
2946
+ logInfo(`Source registered in skaile.yaml \u2014 manage via ${S.cmd("skaile source")}.`);
2976
2947
  } catch (err) {
2977
2948
  spinner5.stop("Failed");
2978
2949
  logErr(err.message);
@@ -2983,25 +2954,37 @@ function makeNpxCommand() {
2983
2954
  skills.action(() => skills.help());
2984
2955
  return npx;
2985
2956
  }
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);
2957
+ function resolvePublisher(clonePath, url) {
2958
+ const yamlPath = path14__default.join(clonePath, "skaile.yaml");
2959
+ if (existsSync(yamlPath)) {
2960
+ try {
2961
+ const { config } = decodeSkaileYaml(readFileSync(yamlPath, "utf8"));
2962
+ if (typeof config.publisher === "string" && config.publisher.length > 0) {
2963
+ return config.publisher;
2964
+ }
2965
+ } catch {
2966
+ }
2967
+ }
2968
+ return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
2969
+ }
2970
+ function resolveSkillName(clonePath, requested) {
2971
+ const skillsDir = path14__default.join(clonePath, "skills");
2972
+ if (existsSync(path14__default.join(skillsDir, requested, "SKILL.md"))) return requested;
2973
+ if (!existsSync(skillsDir)) return requested;
2974
+ for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
2975
+ if (!entry.isDirectory()) continue;
2976
+ const md = path14__default.join(skillsDir, entry.name, "SKILL.md");
2977
+ if (!existsSync(md)) continue;
2978
+ try {
2979
+ const { data } = parseFrontmatter(readFileSync(md, "utf8"));
2980
+ if (typeof data.name === "string" && data.name === requested) return entry.name;
2981
+ } catch {
2982
+ }
2983
+ }
2984
+ return requested;
2985
+ }
2986
+ function sourceSlug(url) {
2987
+ return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
3005
2988
  }
3006
2989
  var SKAILE_MCP_NAME = "skaile-workspace";
3007
2990
  var MCP_SERVER_ENTRY = {
@@ -3691,7 +3674,7 @@ function action2(fn) {
3691
3674
  };
3692
3675
  }
3693
3676
  async function reconcileAndReport(projectDir, plugins) {
3694
- const { reconcilePlugins } = await import('../plugin-store-AJ3FGXIC.js');
3677
+ const { reconcilePlugins } = await import('../plugin-store-G277ZX3B.js');
3695
3678
  if (plugins.length === 0) {
3696
3679
  logInfo("No plugins declared \u2014 nothing to reconcile.");
3697
3680
  return;
@@ -3707,7 +3690,7 @@ async function reconcileAndReport(projectDir, plugins) {
3707
3690
  async function runInstall2(spec, opts) {
3708
3691
  const projectDir = path14__default.resolve(opts.projectDir);
3709
3692
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
3710
- const { specName } = await import('../plugin-store-AJ3FGXIC.js');
3693
+ const { specName } = await import('../plugin-store-G277ZX3B.js');
3711
3694
  const yamlPath = path14__default.join(projectDir, "skaile.yaml");
3712
3695
  const editor = WorkspaceYamlEditor2.load(yamlPath);
3713
3696
  const replaced = editor.addPlugin(spec, specName);
@@ -3719,7 +3702,7 @@ async function runInstall2(spec, opts) {
3719
3702
  async function runRemove(name, opts) {
3720
3703
  const projectDir = path14__default.resolve(opts.projectDir);
3721
3704
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
3722
- const { specName } = await import('../plugin-store-AJ3FGXIC.js');
3705
+ const { specName } = await import('../plugin-store-G277ZX3B.js');
3723
3706
  const yamlPath = path14__default.join(projectDir, "skaile.yaml");
3724
3707
  const editor = WorkspaceYamlEditor2.load(yamlPath);
3725
3708
  const removed = editor.removePlugin(name, specName);
@@ -3747,7 +3730,7 @@ async function runList(opts) {
3747
3730
  const registry = createPluginRegistry();
3748
3731
  if (declared.length > 0) {
3749
3732
  try {
3750
- const { loadPlugins } = await import('../plugin-store-AJ3FGXIC.js');
3733
+ const { loadPlugins } = await import('../plugin-store-G277ZX3B.js');
3751
3734
  const result = await loadPlugins(projectDir, declared, registry);
3752
3735
  for (const f of result.failed) logWarn(f.error);
3753
3736
  } catch (err) {
@@ -3950,7 +3933,7 @@ function makeInstallCommand() {
3950
3933
  const spinner6 = p5.spinner();
3951
3934
  spinner6.start(`Installing ${ref}`);
3952
3935
  try {
3953
- const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-M4DB3D3J.js');
3936
+ const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-EEGG6RDN.js');
3954
3937
  const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
3955
3938
  if (!supportsInstallManifest(catalog)) {
3956
3939
  throw new Error(
@@ -3982,7 +3965,7 @@ function makeInstallCommand() {
3982
3965
  }
3983
3966
  const projectDir = path14__default.resolve(opts.projectDir);
3984
3967
  try {
3985
- const { ensureSourcesCloned } = await import('../ensure-sources-SL2S4UEX.js');
3968
+ const { ensureSourcesCloned } = await import('../ensure-sources-ALTI5PXR.js');
3986
3969
  const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
3987
3970
  if (hydrate.cloned.length > 0) {
3988
3971
  logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
@@ -4440,7 +4423,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
4440
4423
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
4441
4424
  const config = resolveSkWorkspaceConfig2(projectDir);
4442
4425
  if (!config.plugins || config.plugins.length === 0) return;
4443
- const { ensurePluginsLoaded } = await import('../plugin-store-AJ3FGXIC.js');
4426
+ const { ensurePluginsLoaded } = await import('../plugin-store-G277ZX3B.js');
4444
4427
  const { pluginRegistry } = await import('../plugin-registry/index.js');
4445
4428
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
4446
4429
  if (result.loaded.length > 0) {
@@ -5296,6 +5279,14 @@ function sourceClonePath(name) {
5296
5279
  function deriveSlug(url) {
5297
5280
  return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
5298
5281
  }
5282
+ function normalizeSourceUrl(input) {
5283
+ const s = input.trim();
5284
+ if (/^(?:https?|git|ssh|file):\/\//.test(s) || /^git@/.test(s)) return s;
5285
+ const repo = s.replace(/\.git$/, "");
5286
+ if (/^[\w.-]+\/[\w.-]+$/.test(repo)) return `git@github.com:${repo}.git`;
5287
+ if (/^[\w.-]+$/.test(repo)) return `git@github.com:skaile-ai/${repo}.git`;
5288
+ return s;
5289
+ }
5299
5290
  function requireProjectYamlPath() {
5300
5291
  const root = findWorkspaceRoot(process.cwd());
5301
5292
  if (!root) {
@@ -5371,8 +5362,11 @@ function makeSourceCommand() {
5371
5362
  const cmd = new Command("source").description(
5372
5363
  "Manage github sources for the current project (recorded in skaile.yaml)"
5373
5364
  );
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) => {
5365
+ cmd.command("add <source>").description(
5366
+ "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)."
5367
+ ).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(
5368
+ async (source, opts) => {
5369
+ const url = normalizeSourceUrl(source);
5376
5370
  const yamlPath = requireProjectYamlPath();
5377
5371
  if (opts.name) {
5378
5372
  logWarn(
@@ -6244,7 +6238,7 @@ Advanced:
6244
6238
  });
6245
6239
  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
6240
  const { execSync: execSync3 } = await import('child_process');
6247
- const { existsSync: existsSync12, mkdirSync: mkdirSync3, readFileSync: readFileSync5, writeFileSync: writeFileSync2 } = await import('fs');
6241
+ const { existsSync: existsSync12, mkdirSync: mkdirSync3, readFileSync: readFileSync6, writeFileSync: writeFileSync2 } = await import('fs');
6248
6242
  const { stringify } = await import('yaml');
6249
6243
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
6250
6244
  const backend = opts.backend;
@@ -6302,7 +6296,7 @@ program.command("init [project-dir]").description("Initialize a project director
6302
6296
  if (opts.git) {
6303
6297
  const gitignorePath = path14__default.join(resolved, ".gitignore");
6304
6298
  const entries = ["node_modules/", ".skaile/sessions/", "*.log", ".env", ".env.local"];
6305
- const existing = existsSync12(gitignorePath) ? readFileSync5(gitignorePath, "utf-8") : "";
6299
+ const existing = existsSync12(gitignorePath) ? readFileSync6(gitignorePath, "utf-8") : "";
6306
6300
  const have = new Set(existing.split("\n").map((l) => l.trim()));
6307
6301
  const append = entries.filter((e) => !have.has(e));
6308
6302
  if (append.length > 0) {
@@ -6338,7 +6332,7 @@ program.command("init [project-dir]").description("Initialize a project director
6338
6332
  );
6339
6333
  }
6340
6334
  try {
6341
- const { ensureSourcesCloned } = await import('../ensure-sources-SL2S4UEX.js');
6335
+ const { ensureSourcesCloned } = await import('../ensure-sources-ALTI5PXR.js');
6342
6336
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
6343
6337
  for (const n of hydrate.cloned) created.push(`~/.skaile/sources/${n}/`);
6344
6338
  if (hydrate.failed.length > 0) {
@@ -6364,7 +6358,7 @@ program.command("init [project-dir]").description("Initialize a project director
6364
6358
  console.log();
6365
6359
  });
6366
6360
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
6367
- const { cmdSetup } = await import('../setup-GBSQX7JF.js');
6361
+ const { cmdSetup } = await import('../setup-REX4I5NE.js');
6368
6362
  await cmdSetup([], { projectDir: process.cwd() });
6369
6363
  });
6370
6364
  program.addCommand(makeInstallCommand());