@skaile/workspaces 1.0.0 → 1.1.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 (171) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/dist/{asset-feeds-677S5NX7.js → asset-feeds-NIAABO6U.js} +11 -11
  3. package/dist/{asset-feeds-677S5NX7.js.map → asset-feeds-NIAABO6U.js.map} +1 -1
  4. package/dist/asset-manager/index.js +8 -8
  5. package/dist/asset-manager/installer.js +7 -7
  6. package/dist/asset-manager/src/index.d.ts +128 -0
  7. package/dist/asset-manager/src/index.d.ts.map +1 -1
  8. package/dist/bridge/drivers/claude-sdk.js +2 -2
  9. package/dist/bridge/drivers/codex.js +1 -1
  10. package/dist/bridge/drivers/continue.js +2 -2
  11. package/dist/bridge/drivers/echo.js +1 -1
  12. package/dist/bridge/drivers/gemini.js +3 -3
  13. package/dist/bridge/drivers/goose.js +2 -2
  14. package/dist/bridge/drivers/omp.js +1 -1
  15. package/dist/bridge/drivers/opencode.js +2 -2
  16. package/dist/bridge/drivers/qwen.js +3 -3
  17. package/dist/bridge/index.js +3 -3
  18. package/dist/{chunk-FLRHP3UC.js → chunk-35TLBMHX.js} +4 -4
  19. package/dist/{chunk-FLRHP3UC.js.map → chunk-35TLBMHX.js.map} +1 -1
  20. package/dist/{chunk-6VUP6XHK.js → chunk-52XHXSBN.js} +3 -3
  21. package/dist/{chunk-6VUP6XHK.js.map → chunk-52XHXSBN.js.map} +1 -1
  22. package/dist/{chunk-NXC6IEL4.js → chunk-5AGARSQT.js} +267 -261
  23. package/dist/chunk-5AGARSQT.js.map +1 -0
  24. package/dist/{chunk-WSQ5J7CE.js → chunk-B4IOSXRZ.js} +98 -49
  25. package/dist/chunk-B4IOSXRZ.js.map +1 -0
  26. package/dist/{chunk-EXNTTJGP.js → chunk-BCJL2UNH.js} +3 -3
  27. package/dist/{chunk-EXNTTJGP.js.map → chunk-BCJL2UNH.js.map} +1 -1
  28. package/dist/{chunk-W53D5Q52.js → chunk-BM37QD6U.js} +3 -3
  29. package/dist/{chunk-W53D5Q52.js.map → chunk-BM37QD6U.js.map} +1 -1
  30. package/dist/{chunk-PLQVAEM2.js → chunk-DMHVL5MC.js} +5 -5
  31. package/dist/{chunk-PLQVAEM2.js.map → chunk-DMHVL5MC.js.map} +1 -1
  32. package/dist/{chunk-K5JIAHDV.js → chunk-EE4NL25D.js} +29 -20
  33. package/dist/chunk-EE4NL25D.js.map +1 -0
  34. package/dist/{chunk-43JDPQJ4.js → chunk-G2X3THJV.js} +5 -5
  35. package/dist/{chunk-43JDPQJ4.js.map → chunk-G2X3THJV.js.map} +1 -1
  36. package/dist/{chunk-KSISPZV3.js → chunk-INUQVXUE.js} +2 -2
  37. package/dist/{chunk-KSISPZV3.js.map → chunk-INUQVXUE.js.map} +1 -1
  38. package/dist/{chunk-UTHEIPEY.js → chunk-KVZ6XKVN.js} +56 -14
  39. package/dist/chunk-KVZ6XKVN.js.map +1 -0
  40. package/dist/{chunk-SFVEHSCI.js → chunk-L3SLC3S4.js} +253 -14
  41. package/dist/chunk-L3SLC3S4.js.map +1 -0
  42. package/dist/{chunk-3KPNDTMR.js → chunk-MG6UIS7G.js} +3 -3
  43. package/dist/{chunk-3KPNDTMR.js.map → chunk-MG6UIS7G.js.map} +1 -1
  44. package/dist/{chunk-LKOMH3QC.js → chunk-OIGYDVCM.js} +3 -3
  45. package/dist/{chunk-LKOMH3QC.js.map → chunk-OIGYDVCM.js.map} +1 -1
  46. package/dist/{chunk-N5AE5SOC.js → chunk-QVE3ILCY.js} +2 -2
  47. package/dist/{chunk-N5AE5SOC.js.map → chunk-QVE3ILCY.js.map} +1 -1
  48. package/dist/{chunk-GYPA2Q7F.js → chunk-SHOKXRL4.js} +21 -4
  49. package/dist/chunk-SHOKXRL4.js.map +1 -0
  50. package/dist/{chunk-6AD3NS7R.js → chunk-U5J77IIZ.js} +4 -4
  51. package/dist/{chunk-6AD3NS7R.js.map → chunk-U5J77IIZ.js.map} +1 -1
  52. package/dist/{chunk-OYMSCV7T.js → chunk-UY5Q2NZH.js} +3 -3
  53. package/dist/{chunk-OYMSCV7T.js.map → chunk-UY5Q2NZH.js.map} +1 -1
  54. package/dist/{chunk-2D5YE3FL.js → chunk-VYIK5IE5.js} +85 -6
  55. package/dist/chunk-VYIK5IE5.js.map +1 -0
  56. package/dist/{chunk-DW5MIJK3.js → chunk-YI5OZ7QO.js} +2 -2
  57. package/dist/{chunk-DW5MIJK3.js.map → chunk-YI5OZ7QO.js.map} +1 -1
  58. package/dist/{chunk-XD7GYMAU.js → chunk-Z4EJOBEL.js} +7 -7
  59. package/dist/{chunk-XD7GYMAU.js.map → chunk-Z4EJOBEL.js.map} +1 -1
  60. package/dist/{chunk-2ZK7M2SG.js → chunk-ZUE2PIJ5.js} +3 -3
  61. package/dist/{chunk-2ZK7M2SG.js.map → chunk-ZUE2PIJ5.js.map} +1 -1
  62. package/dist/cli/index.js +190 -55
  63. package/dist/cli/index.js.map +1 -1
  64. package/dist/cli/src/commands/catalog.d.ts +18 -0
  65. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  66. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  67. package/dist/cli/src/commands/tree.d.ts.map +1 -1
  68. package/dist/cli/src/commands/why.d.ts.map +1 -1
  69. package/dist/cli/src/helpers.d.ts +25 -0
  70. package/dist/cli/src/helpers.d.ts.map +1 -1
  71. package/dist/connectors/config.js +7 -7
  72. package/dist/connectors/index.js +8 -8
  73. package/dist/connectors/src/connector-registry.d.ts.map +1 -1
  74. package/dist/core/index.js +6 -6
  75. package/dist/core/runtime-assets.js +2 -2
  76. package/dist/core/src/index.d.ts +1 -1
  77. package/dist/core/src/index.d.ts.map +1 -1
  78. package/dist/core/src/repo-manager.d.ts +19 -1
  79. package/dist/core/src/repo-manager.d.ts.map +1 -1
  80. package/dist/core/src/walker.d.ts +7 -0
  81. package/dist/core/src/walker.d.ts.map +1 -1
  82. package/dist/core/workspace-config.js +1 -1
  83. package/dist/deploy/index.js +6 -6
  84. package/dist/discovery/index.js +1 -1
  85. package/dist/discovery/src/discover.d.ts.map +1 -1
  86. package/dist/discovery/src/index.d.ts +1 -1
  87. package/dist/discovery/src/index.d.ts.map +1 -1
  88. package/dist/discovery/src/reference-lint.d.ts +30 -0
  89. package/dist/discovery/src/reference-lint.d.ts.map +1 -1
  90. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  91. package/dist/{ensure-sources-OCMHK7LT.js → ensure-sources-MJYHZ77Y.js} +16 -9
  92. package/dist/ensure-sources-MJYHZ77Y.js.map +1 -0
  93. package/dist/factory-assets/connectors/box/CONNECTOR.md +33 -0
  94. package/dist/factory-assets/connectors/box/driver.d.ts +27 -0
  95. package/dist/factory-assets/connectors/box/driver.d.ts.map +1 -0
  96. package/dist/factory-assets/connectors/box.d.ts +2 -0
  97. package/dist/factory-assets/connectors/box.js +20 -0
  98. package/dist/factory-assets/connectors/box.js.map +1 -0
  99. package/dist/factory-assets/connectors/deploy.js +8 -8
  100. package/dist/factory-assets/connectors/devserver.js +8 -8
  101. package/dist/factory-assets/connectors/flow/adapter.js +8 -8
  102. package/dist/factory-assets/connectors/flow/engine.js +6 -6
  103. package/dist/factory-assets/connectors/flow/run-flow.js +9 -9
  104. package/dist/factory-assets/connectors/flow.js +8 -8
  105. package/dist/factory-assets/connectors/git.js +8 -8
  106. package/dist/factory-assets/connectors/gmail.js +8 -8
  107. package/dist/factory-assets/connectors/googledrive.js +8 -8
  108. package/dist/factory-assets/connectors/local.js +8 -8
  109. package/dist/factory-assets/connectors/mattermost.js +8 -8
  110. package/dist/factory-assets/connectors/memory.js +8 -8
  111. package/dist/factory-assets/connectors/minio.js +8 -8
  112. package/dist/factory-assets/connectors/postgres.js +8 -8
  113. package/dist/factory-assets/connectors/s3.js +8 -8
  114. package/dist/factory-assets/connectors/sharepoint.js +8 -8
  115. package/dist/factory-assets/connectors/sqlite.js +8 -8
  116. package/dist/factory-assets/connectors/static-server.js +8 -8
  117. package/dist/factory-assets/connectors/tunnel.js +8 -8
  118. package/dist/factory-assets/connectors/webdav.js +8 -8
  119. package/dist/factory-assets/connectors/xstate-store.js +8 -8
  120. package/dist/factory-assets/connectors/xstate.js +8 -8
  121. package/dist/factory-assets/skaile.manifest.yaml +4 -1
  122. package/dist/{flows-36PZESON.js → flows-4Z74KY2H.js} +3 -3
  123. package/dist/{flows-36PZESON.js.map → flows-4Z74KY2H.js.map} +1 -1
  124. package/dist/helpers-7KOVCMHW.js +22 -0
  125. package/dist/{helpers-F4NZ66VD.js.map → helpers-7KOVCMHW.js.map} +1 -1
  126. package/dist/library/index.js +8 -8
  127. package/dist/library/install.js +6 -6
  128. package/dist/library/src/library.d.ts +6 -0
  129. package/dist/library/src/library.d.ts.map +1 -1
  130. package/dist/library/src/local/db.d.ts.map +1 -1
  131. package/dist/library/src/local/library.d.ts +9 -0
  132. package/dist/library/src/local/library.d.ts.map +1 -1
  133. package/dist/library/src/local/local-catalog-source.d.ts +9 -0
  134. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  135. package/dist/library/src/local/schema.d.ts +19 -0
  136. package/dist/library/src/local/schema.d.ts.map +1 -1
  137. package/dist/open-library-PGTL332T.js +29 -0
  138. package/dist/{open-library-WRFYABFP.js.map → open-library-PGTL332T.js.map} +1 -1
  139. package/dist/{paths-EUNVMONC.js → paths-S7QNXYMB.js} +9 -9
  140. package/dist/{paths-EUNVMONC.js.map → paths-S7QNXYMB.js.map} +1 -1
  141. package/dist/{plugin-store-35KIMX6W.js → plugin-store-3DAVGKHN.js} +8 -8
  142. package/dist/{plugin-store-35KIMX6W.js.map → plugin-store-3DAVGKHN.js.map} +1 -1
  143. package/dist/runner/index.js +13 -13
  144. package/dist/runner/src/serve.d.ts.map +1 -1
  145. package/dist/sdk/asset-manager.js +8 -8
  146. package/dist/sdk/bridge.js +3 -3
  147. package/dist/sdk/core.js +6 -6
  148. package/dist/sdk/flow.js +6 -6
  149. package/dist/sdk/index.js +13 -13
  150. package/dist/sdk/runner.js +13 -13
  151. package/dist/{setup-HM6HATAC.js → setup-WBGDT2WY.js} +11 -11
  152. package/dist/{setup-HM6HATAC.js.map → setup-WBGDT2WY.js.map} +1 -1
  153. package/dist/{source-EZ5Y3CKP.js → source-FJXRQ2NU.js} +19 -13
  154. package/dist/{source-EZ5Y3CKP.js.map → source-FJXRQ2NU.js.map} +1 -1
  155. package/dist/{store-client-BUUF7BPK.js → store-client-YGDN4L2G.js} +9 -9
  156. package/dist/{store-client-BUUF7BPK.js.map → store-client-YGDN4L2G.js.map} +1 -1
  157. package/dist/tui/index.js +13 -13
  158. package/dist/workspace-plugin/adapters/mcp.js +2 -2
  159. package/dist/workspace-plugin/adapters/omp.js +3 -3
  160. package/dist/workspace-plugin/index.js +1 -1
  161. package/package.json +7 -1
  162. package/dist/chunk-2D5YE3FL.js.map +0 -1
  163. package/dist/chunk-GYPA2Q7F.js.map +0 -1
  164. package/dist/chunk-K5JIAHDV.js.map +0 -1
  165. package/dist/chunk-NXC6IEL4.js.map +0 -1
  166. package/dist/chunk-SFVEHSCI.js.map +0 -1
  167. package/dist/chunk-UTHEIPEY.js.map +0 -1
  168. package/dist/chunk-WSQ5J7CE.js.map +0 -1
  169. package/dist/ensure-sources-OCMHK7LT.js.map +0 -1
  170. package/dist/helpers-F4NZ66VD.js +0 -4
  171. package/dist/open-library-WRFYABFP.js +0 -23
@@ -1,9 +1,10 @@
1
- import { deployAll, removeAsset, createScaffold } from './chunk-FLRHP3UC.js';
2
- import { writeLock, buildLockFile, readLock, verifyLock, extractForPatch, generatePatch, savePatch, applyPatch } from './chunk-3KPNDTMR.js';
3
- import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-W53D5Q52.js';
1
+ import { deployAll, removeAsset, createScaffold } from './chunk-35TLBMHX.js';
2
+ import { writeLock, buildLockFile, readLock, verifyLock, extractForPatch, generatePatch, savePatch, applyPatch } from './chunk-MG6UIS7G.js';
3
+ import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-BM37QD6U.js';
4
+ import { globalSkaileDir, resolveGlobalBackends, globalCacheRoot, migrateLegacyDir, resolveGlobalSkWorkspaceConfig, resolveSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, resolveAll, buildProvenanceIndex, ensureRepo, sourceShortName, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, readLinks } from './chunk-5AGARSQT.js';
5
+ import { parseRequires } from './chunk-BQCGFPHW.js';
6
+ import { parseAssetRef, assetRefToStr } from './chunk-GEEW6SY2.js';
4
7
  import { deployedBase, isDeployed, deployedDir } from './chunk-F3HNW354.js';
5
- import { globalSkaileDir, resolveGlobalBackends, globalCacheRoot, migrateLegacyDir, resolveGlobalSkWorkspaceConfig, resolveSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, resolveAll, buildProvenanceIndex, ensureRepo, sourceShortName, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, readLinks } from './chunk-NXC6IEL4.js';
6
- import { parseAssetRef } from './chunk-GEEW6SY2.js';
7
8
  import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
8
9
  import { commitChanges } from './chunk-UQ6LFBPZ.js';
9
10
  import { spawnSync } from 'child_process';
@@ -105,6 +106,40 @@ function parseCanonicalLockKey(key) {
105
106
  return {};
106
107
  }
107
108
  }
109
+ function softDepName(ref) {
110
+ const at = ref.lastIndexOf("@");
111
+ const base = at > 0 ? ref.slice(0, at) : ref;
112
+ const slash = base.lastIndexOf("/");
113
+ return slash >= 0 ? base.slice(slash + 1) : base;
114
+ }
115
+ function depRefFromDef(def) {
116
+ const publisher = def.publisher.replace(/^@/, "");
117
+ if (!publisher) return void 0;
118
+ return assetRefToStr({ kind: def.kind, name: def.name, publisher });
119
+ }
120
+ function parseRefLoose(ref) {
121
+ try {
122
+ return parseAssetRef(ref);
123
+ } catch {
124
+ const hash = ref.indexOf("#");
125
+ if (hash < 0) return null;
126
+ try {
127
+ return parseAssetRef(ref.slice(0, hash));
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ }
133
+ function matchDefsForRef(defs, ref) {
134
+ const exact = defs.filter((d) => d.id === ref);
135
+ if (exact.length > 0) return exact;
136
+ const parsed = parseRefLoose(ref);
137
+ if (!parsed) return [];
138
+ const wantPub = parsed.publisher?.replace(/^@/, "");
139
+ return defs.filter(
140
+ (d) => d.name === parsed.name && d.kind === parsed.kind && (wantPub === void 0 || d.publisher.replace(/^@/, "") === wantPub)
141
+ );
142
+ }
108
143
  var MissingManifestError = class extends Error {
109
144
  constructor(projectDir) {
110
145
  super(`No skaile.yaml in ${projectDir}.`);
@@ -151,6 +186,8 @@ var AssetManager = class {
151
186
  injectedAssetFetcher;
152
187
  /** Injected global catalog URL override for the no-project-store fallback. */
153
188
  catalogUrlOverride;
189
+ /** Injected index SQLite path override (tests); else the default index.db. */
190
+ indexPathOverride;
154
191
  constructor(opts) {
155
192
  this.projectDir = resolve(opts.projectDir);
156
193
  this.driverTarget = opts.driverTarget ?? "claude-code";
@@ -159,6 +196,7 @@ var AssetManager = class {
159
196
  this.injectedStoreFetcher = opts.storeFetcher;
160
197
  this.injectedAssetFetcher = opts.assetFetcher;
161
198
  this.catalogUrlOverride = opts.catalogUrl;
199
+ this.indexPathOverride = opts.indexPath;
162
200
  }
163
201
  /**
164
202
  * Root for this manager's **state** — config SSOT, lock, cache, history.
@@ -766,6 +804,198 @@ var AssetManager = class {
766
804
  }
767
805
  return deployed;
768
806
  }
807
+ /**
808
+ * Report the body-link **soft dependencies** of the given assets that are not
809
+ * already present in the project.
810
+ *
811
+ * Looks up each ref's persisted `softDeps` in the local index
812
+ * (`~/.skaile/index.db`, populated by `skaile source sync`) and returns the
813
+ * edges whose target is neither a declared dependency nor deployed on disk. It
814
+ * does **not** install anything and never touches the resolver / lock /
815
+ * reconcile path: callers surface the result as a hint, the user opts in with
816
+ * a follow-up `skaile add`. Inspects exactly the passed `refs` — soft deps of
817
+ * their transitively-deployed dependencies are not surfaced here.
818
+ *
819
+ * Opening the index runs its idempotent migrations, so this is not a pure
820
+ * read — but it is **best-effort**: any failure (legacy/corrupt index, a
821
+ * removed-backend guard) yields `[]`, so it can never fail a primary `add`
822
+ * that already succeeded.
823
+ *
824
+ * @param refs - Asset refs to inspect (canonical, `kind:@pub/name`, or `kind:name`).
825
+ * @returns One edge per absent soft-dep target (deduped by target). `toRef` is
826
+ * the parseable `skaile add` ref, omitted when the target isn't in the index.
827
+ */
828
+ async reportSoftDeps(refs) {
829
+ if (refs.length === 0) return [];
830
+ return this.withIndexDefs(
831
+ (allDefs) => this.collectSoftDeps(allDefs, refs, true),
832
+ []
833
+ );
834
+ }
835
+ /**
836
+ * All body-link soft dependencies of the given assets — present or not.
837
+ *
838
+ * Unlike {@link reportSoftDeps} (which filters to *absent* targets so it can
839
+ * nudge a follow-up `skaile add`), this returns the asset's full inferred
840
+ * soft-dep set for display surfaces (`skaile info` / `tree` / `why`). Read-only
841
+ * and best-effort: any index failure yields `[]`. Targets are deduped.
842
+ *
843
+ * @param refs - Asset refs to inspect (canonical, `kind:@pub/name`, or `kind:name`).
844
+ * @returns One {@link SoftDepEdge} per soft-dep target. `toRef` is the parseable
845
+ * ref, omitted when the target isn't in the index.
846
+ */
847
+ async softDepsOf(refs) {
848
+ if (refs.length === 0) return [];
849
+ return this.withIndexDefs((allDefs) => this.collectSoftDeps(allDefs, refs, false), []);
850
+ }
851
+ /**
852
+ * Reverse lookup: refs (canonical ids) of cached assets whose persisted
853
+ * `softDeps` include `targetRef`. Scans the whole index, not just present
854
+ * assets. Read-only and best-effort (`[]` on any index failure).
855
+ *
856
+ * @param targetRef - Canonical soft-dep target ref (`<publisher>/<name>@<version>`).
857
+ * @returns Def ids that declare `targetRef` as a soft dependency.
858
+ */
859
+ async softDepDependents(targetRef) {
860
+ return this.withIndexDefs(
861
+ (allDefs) => allDefs.filter((d) => d.softDeps?.includes(targetRef)).map((d) => d.id),
862
+ []
863
+ );
864
+ }
865
+ /**
866
+ * Compute which soft-dependency targets would be left **orphaned** by removing
867
+ * `refs`: targets still present in the project that came in as one of `refs`'
868
+ * soft dependencies and that **nothing else still needs** — neither another
869
+ * present asset's soft-dep ({@link softDepDependents}) nor a typed `requires`.
870
+ *
871
+ * Pure read — never removes anything. The CLI / manage surfaces each result as
872
+ * a prompt (default No) so the user opts in to an extra `skaile remove`. Safe to
873
+ * call before or after the primary remove: assets being removed are excluded
874
+ * from the "needed by others" scan, so a soft target referenced only by the
875
+ * removed asset is still reported as an orphan.
876
+ *
877
+ * @param refs - Asset refs being removed (canonical, `kind:@pub/name`, or `kind:name`).
878
+ * @returns One {@link OrphanedSoftDep} per orphaned target (deduped).
879
+ */
880
+ async orphanedSoftDepsAfterRemoving(refs) {
881
+ if (refs.length === 0) return [];
882
+ return this.withIndexDefs((allDefs) => {
883
+ const byId = new Map(allDefs.map((d) => [d.id, d]));
884
+ const present = this.presentRefNames();
885
+ const removedNames = /* @__PURE__ */ new Set();
886
+ for (const ref of refs) {
887
+ for (const def of matchDefsForRef(allDefs, ref)) removedNames.add(def.name);
888
+ try {
889
+ removedNames.add(parseAssetRef(ref).name);
890
+ } catch {
891
+ }
892
+ }
893
+ const neededByOthers = /* @__PURE__ */ new Set();
894
+ for (const presentRef of this.presentRefs()) {
895
+ for (const def of matchDefsForRef(allDefs, presentRef)) {
896
+ if (removedNames.has(def.name)) continue;
897
+ for (const to of def.softDeps ?? []) neededByOthers.add(softDepName(to));
898
+ for (const req of parseRequires(def.manifest)) neededByOthers.add(softDepName(req.name));
899
+ }
900
+ }
901
+ const out = [];
902
+ const seen = /* @__PURE__ */ new Set();
903
+ for (const ref of refs) {
904
+ for (const def of matchDefsForRef(allDefs, ref)) {
905
+ for (const to of def.softDeps ?? []) {
906
+ const targetName = softDepName(to);
907
+ if (!present.has(targetName)) continue;
908
+ if (removedNames.has(targetName)) continue;
909
+ if (neededByOthers.has(targetName)) continue;
910
+ if (seen.has(to)) continue;
911
+ seen.add(to);
912
+ const targetDef = byId.get(to);
913
+ out.push({
914
+ from: def.id,
915
+ target: to,
916
+ targetRef: targetDef ? depRefFromDef(targetDef) : void 0
917
+ });
918
+ }
919
+ }
920
+ }
921
+ return out;
922
+ }, []);
923
+ }
924
+ /**
925
+ * Open the local index, run `fn` against its cached asset defs, and close it.
926
+ * Best-effort: no index (user never ran `source sync`), a missing file, or any
927
+ * open/guard failure yields `fallback` — so a read surface can never throw or
928
+ * create an empty `index.db` as a side effect.
929
+ */
930
+ async withIndexDefs(fn, fallback) {
931
+ try {
932
+ const { LocalIndex, resolveIndexPath } = await import('./library/index.js');
933
+ const indexPath = this.indexPathOverride ?? resolveIndexPath();
934
+ if (!existsSync(indexPath)) return fallback;
935
+ const index = new LocalIndex({ indexPath });
936
+ try {
937
+ return fn(await index.listAssetDefs());
938
+ } finally {
939
+ index.close();
940
+ }
941
+ } catch {
942
+ return fallback;
943
+ }
944
+ }
945
+ /**
946
+ * Build soft-dep edges for `refs` from cached defs. With `onlyAbsent`, targets
947
+ * already present in the project are skipped (the `reportSoftDeps` nudge); else
948
+ * the full inferred set is returned (the `softDepsOf` display). Deduped by target.
949
+ */
950
+ collectSoftDeps(allDefs, refs, onlyAbsent) {
951
+ const present = onlyAbsent ? this.presentRefNames() : null;
952
+ const byId = new Map(allDefs.map((d) => [d.id, d]));
953
+ const out = [];
954
+ const seen = /* @__PURE__ */ new Set();
955
+ for (const ref of refs) {
956
+ for (const def of matchDefsForRef(allDefs, ref)) {
957
+ for (const to of def.softDeps ?? []) {
958
+ if (present?.has(softDepName(to))) continue;
959
+ if (seen.has(to)) continue;
960
+ seen.add(to);
961
+ const targetDef = byId.get(to);
962
+ out.push({ from: def.id, to, toRef: targetDef ? depRefFromDef(targetDef) : void 0 });
963
+ }
964
+ }
965
+ }
966
+ return out;
967
+ }
968
+ /**
969
+ * Names of assets already in the project — declared deps + deployed on disk.
970
+ * Bare name only (see {@link softDepName}): a same-named asset of a different
971
+ * publisher/kind counts as present, so the report under-reports rather than
972
+ * nags about something already installed.
973
+ */
974
+ presentRefNames() {
975
+ const names = /* @__PURE__ */ new Set();
976
+ for (const ref of this.presentRefs()) {
977
+ try {
978
+ names.add(parseAssetRef(ref).name);
979
+ } catch {
980
+ }
981
+ }
982
+ return names;
983
+ }
984
+ /**
985
+ * Present asset refs — declared `skaile.yaml` deps (canonical refs as written)
986
+ * plus deployed assets as `kind:name`. Used by the soft-dep present-check and
987
+ * the orphan "needed by others" scan.
988
+ */
989
+ presentRefs() {
990
+ const refs = [];
991
+ try {
992
+ for (const ref of resolveSkWorkspaceConfig(this.projectDir).dependencies ?? [])
993
+ refs.push(ref);
994
+ } catch {
995
+ }
996
+ for (const e of this.listDeployed()) refs.push(`${e.kind}:${e.name}`);
997
+ return refs;
998
+ }
769
999
  /**
770
1000
  * Remove a deployed asset and unregister it from `skaile.yaml`.
771
1001
  *
@@ -780,7 +1010,7 @@ var AssetManager = class {
780
1010
  }
781
1011
  if (ok) {
782
1012
  const depRef = `${parsed.kind}:${parsed.name}`;
783
- this.removeDependencyFromConfig(depRef);
1013
+ this.removeDependencyFromConfig(parsed);
784
1014
  appendHistory(this.projectDir, {
785
1015
  ref: depRef,
786
1016
  action: "remove",
@@ -1080,8 +1310,10 @@ var AssetManager = class {
1080
1310
  why(ref) {
1081
1311
  const lock = this.tryReadLock();
1082
1312
  if (!lock) return [];
1083
- if (!lock.assets[ref]) return [];
1084
- return [ref, "direct (skaile.yaml)"];
1313
+ const bare = (s) => s.includes("#") ? s.slice(0, s.indexOf("#")) : s;
1314
+ const key = lock.assets[ref] ? ref : Object.keys(lock.assets).find((k) => bare(k) === bare(ref));
1315
+ if (!key) return [];
1316
+ return [key, "direct (skaile.yaml)"];
1085
1317
  }
1086
1318
  /**
1087
1319
  * List installed assets whose source repository is behind the remote.
@@ -1440,12 +1672,19 @@ var AssetManager = class {
1440
1672
  * Remove a dependency ref from the manifest `dependencies:`. Targets the same
1441
1673
  * file as {@link addDependencyToConfig} (`~/.skaile/skaile.yaml` in global mode).
1442
1674
  */
1443
- removeDependencyFromConfig(ref) {
1675
+ removeDependencyFromConfig(target) {
1444
1676
  const configPath = join(this.stateRoot, "skaile.yaml");
1445
1677
  if (!existsSync(configPath)) return;
1446
1678
  const raw = parse(readFileSync(configPath, "utf8")) ?? {};
1447
- if (!raw.dependencies) return;
1448
- const idx = raw.dependencies.indexOf(ref);
1679
+ if (!Array.isArray(raw.dependencies)) return;
1680
+ const wantPub = target.publisher?.replace(/^@/, "");
1681
+ const idx = raw.dependencies.findIndex((dep) => {
1682
+ if (typeof dep !== "string") return false;
1683
+ const p = parseRefLoose(dep);
1684
+ if (!p || p.kind !== target.kind || p.name !== target.name) return false;
1685
+ const havePub = p.publisher?.replace(/^@/, "");
1686
+ return wantPub === void 0 || havePub === void 0 || havePub === wantPub;
1687
+ });
1449
1688
  if (idx !== -1) {
1450
1689
  raw.dependencies.splice(idx, 1);
1451
1690
  writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
@@ -1468,6 +1707,6 @@ var AssetManager = class {
1468
1707
  }
1469
1708
  };
1470
1709
 
1471
- export { AssetManager, MissingManifestError, NON_DEPLOYABLE_KINDS, parseCanonicalLockKey };
1472
- //# sourceMappingURL=chunk-SFVEHSCI.js.map
1473
- //# sourceMappingURL=chunk-SFVEHSCI.js.map
1710
+ export { AssetManager, MissingManifestError, NON_DEPLOYABLE_KINDS, parseCanonicalLockKey, softDepName };
1711
+ //# sourceMappingURL=chunk-L3SLC3S4.js.map
1712
+ //# sourceMappingURL=chunk-L3SLC3S4.js.map