@try-works/dsh-model-as-tool 0.1.2 → 0.3.6

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 (267) hide show
  1. package/bin/dsh-tool-mode-credentials.mjs +20 -0
  2. package/bin/dsh-tool-mode.mjs +202 -0
  3. package/catalog/desert-ant-models.json +693 -693
  4. package/client/client.model-tools.js +592 -0
  5. package/client/index.js +1679 -0
  6. package/lib/adapters/index.d.ts.map +1 -1
  7. package/lib/adapters/index.js +4 -4
  8. package/lib/bindings.d.ts.map +1 -1
  9. package/lib/bindings.js +26 -25
  10. package/lib/capability.d.ts.map +1 -1
  11. package/lib/capability.js +17 -0
  12. package/lib/capture-path.d.ts +97 -0
  13. package/lib/capture-path.d.ts.map +1 -0
  14. package/lib/capture-path.js +152 -0
  15. package/lib/diagnostics.d.ts +166 -0
  16. package/lib/diagnostics.d.ts.map +1 -0
  17. package/lib/diagnostics.js +135 -0
  18. package/lib/extension-dependencies.d.ts +197 -0
  19. package/lib/extension-dependencies.d.ts.map +1 -0
  20. package/lib/extension-dependencies.js +369 -0
  21. package/lib/extension-dispatch.d.ts +117 -0
  22. package/lib/extension-dispatch.d.ts.map +1 -0
  23. package/lib/extension-dispatch.js +124 -0
  24. package/lib/extension-registrar.d.ts +100 -0
  25. package/lib/extension-registrar.d.ts.map +1 -0
  26. package/lib/extension-registrar.js +134 -0
  27. package/lib/extensions-api.d.ts +217 -0
  28. package/lib/extensions-api.d.ts.map +1 -0
  29. package/lib/extensions-api.js +17 -0
  30. package/lib/extensions-remote.d.ts +54 -0
  31. package/lib/extensions-remote.d.ts.map +1 -0
  32. package/lib/extensions-remote.js +66 -0
  33. package/lib/extensions-service.d.ts +334 -0
  34. package/lib/extensions-service.d.ts.map +1 -0
  35. package/lib/extensions-service.js +1351 -0
  36. package/lib/harness-llm.d.ts +138 -0
  37. package/lib/harness-llm.d.ts.map +1 -0
  38. package/lib/harness-llm.js +218 -0
  39. package/lib/harness-serving.d.ts +95 -0
  40. package/lib/harness-serving.d.ts.map +1 -0
  41. package/lib/harness-serving.js +157 -0
  42. package/lib/headless.d.ts +97 -0
  43. package/lib/headless.d.ts.map +1 -0
  44. package/lib/headless.js +349 -0
  45. package/lib/http-acquisition.d.ts +27 -0
  46. package/lib/http-acquisition.d.ts.map +1 -0
  47. package/lib/http-acquisition.js +136 -0
  48. package/lib/index.d.ts +250 -7
  49. package/lib/index.d.ts.map +1 -1
  50. package/lib/index.js +2625 -70
  51. package/lib/invocation-accounting.d.ts +169 -0
  52. package/lib/invocation-accounting.d.ts.map +1 -0
  53. package/lib/invocation-accounting.js +148 -0
  54. package/lib/legacy-migration.d.ts +95 -0
  55. package/lib/legacy-migration.d.ts.map +1 -0
  56. package/lib/legacy-migration.js +429 -0
  57. package/lib/managed-workers.d.ts +151 -0
  58. package/lib/managed-workers.d.ts.map +1 -0
  59. package/lib/managed-workers.js +249 -0
  60. package/lib/mcp/client-grant.d.ts +74 -0
  61. package/lib/mcp/client-grant.d.ts.map +1 -0
  62. package/lib/mcp/client-grant.js +60 -0
  63. package/lib/mcp/credential-cli.d.ts +38 -0
  64. package/lib/mcp/credential-cli.d.ts.map +1 -0
  65. package/lib/mcp/credential-cli.js +148 -0
  66. package/lib/mcp/credential-store.d.ts +143 -0
  67. package/lib/mcp/credential-store.d.ts.map +1 -0
  68. package/lib/mcp/credential-store.js +454 -0
  69. package/lib/mcp/host-binding.d.ts +25 -0
  70. package/lib/mcp/host-binding.d.ts.map +1 -1
  71. package/lib/mcp/host-binding.js +107 -14
  72. package/lib/mcp/http.d.ts +68 -18
  73. package/lib/mcp/http.d.ts.map +1 -1
  74. package/lib/mcp/http.js +390 -62
  75. package/lib/mcp/oauth.d.ts +149 -0
  76. package/lib/mcp/oauth.d.ts.map +1 -0
  77. package/lib/mcp/oauth.js +396 -0
  78. package/lib/mcp/protocol.d.ts +46 -7
  79. package/lib/mcp/protocol.d.ts.map +1 -1
  80. package/lib/mcp/protocol.js +63 -16
  81. package/lib/mcp/rate-limit.d.ts +68 -0
  82. package/lib/mcp/rate-limit.d.ts.map +1 -0
  83. package/lib/mcp/rate-limit.js +114 -0
  84. package/lib/mcp/sdk-v2.d.ts +17 -0
  85. package/lib/mcp/sdk-v2.d.ts.map +1 -0
  86. package/lib/mcp/sdk-v2.js +181 -0
  87. package/lib/mcp/server.d.ts +11 -1
  88. package/lib/mcp/server.d.ts.map +1 -1
  89. package/lib/mcp/server.js +80 -13
  90. package/lib/mcp/stdio.d.ts.map +1 -1
  91. package/lib/mcp/stdio.js +9 -1
  92. package/lib/mcp/subscriptions.d.ts +43 -1
  93. package/lib/mcp/subscriptions.d.ts.map +1 -1
  94. package/lib/mcp/subscriptions.js +90 -9
  95. package/lib/model-qualification.d.ts +192 -0
  96. package/lib/model-qualification.d.ts.map +1 -0
  97. package/lib/model-qualification.js +178 -0
  98. package/lib/planning.d.ts +246 -0
  99. package/lib/planning.d.ts.map +1 -0
  100. package/lib/planning.js +457 -0
  101. package/lib/prepared-assets.d.ts +178 -0
  102. package/lib/prepared-assets.d.ts.map +1 -0
  103. package/lib/prepared-assets.js +286 -0
  104. package/lib/provider-bridge.d.ts +37 -0
  105. package/lib/provider-bridge.d.ts.map +1 -1
  106. package/lib/provider-bridge.js +189 -12
  107. package/lib/ptc-authority.d.ts +140 -0
  108. package/lib/ptc-authority.d.ts.map +1 -0
  109. package/lib/ptc-authority.js +216 -0
  110. package/lib/ptc-runtime.d.ts +156 -0
  111. package/lib/ptc-runtime.d.ts.map +1 -0
  112. package/lib/ptc-runtime.js +191 -0
  113. package/lib/publication.d.ts +2 -1
  114. package/lib/publication.d.ts.map +1 -1
  115. package/lib/publication.js +13 -5
  116. package/lib/receipt.d.ts.map +1 -1
  117. package/lib/receipt.js +8 -0
  118. package/lib/title-proposal.d.ts +194 -0
  119. package/lib/title-proposal.d.ts.map +1 -0
  120. package/lib/title-proposal.js +244 -0
  121. package/lib/tool-mode-run.d.ts +235 -0
  122. package/lib/tool-mode-run.d.ts.map +1 -0
  123. package/lib/tool-mode-run.js +283 -0
  124. package/lib/types.d.ts +3 -1
  125. package/lib/types.d.ts.map +1 -1
  126. package/lib/update-surface.d.ts +79 -0
  127. package/lib/update-surface.d.ts.map +1 -0
  128. package/lib/update-surface.js +224 -0
  129. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts +16 -0
  130. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts.map +1 -0
  131. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.js +85 -0
  132. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
  133. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
  134. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
  135. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts +20 -0
  136. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts.map +1 -0
  137. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.js +112 -0
  138. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
  139. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
  140. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
  141. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
  142. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
  143. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
  144. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts +82 -0
  145. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -0
  146. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +274 -0
  147. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +26 -0
  148. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -0
  149. package/node_modules/@try-works/tool-mode-contracts/lib/index.js +48 -0
  150. package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts +104 -0
  151. package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts.map +1 -0
  152. package/node_modules/@try-works/tool-mode-contracts/lib/meta.js +55 -0
  153. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +107 -0
  154. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -0
  155. package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +246 -0
  156. package/node_modules/@try-works/tool-mode-contracts/package.json +34 -0
  157. package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
  158. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
  159. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
  160. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
  161. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +83 -0
  162. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
  163. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +125 -0
  164. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
  165. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
  166. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
  167. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
  168. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
  169. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
  170. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +31 -0
  171. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
  172. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +31 -0
  173. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
  174. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
  175. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +185 -0
  176. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +126 -0
  177. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
  178. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +297 -0
  179. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +216 -0
  180. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
  181. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +800 -0
  182. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
  183. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
  184. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
  185. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
  186. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
  187. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
  188. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
  189. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
  190. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
  191. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
  192. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
  193. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +235 -0
  194. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +367 -0
  195. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
  196. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +807 -0
  197. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
  198. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
  199. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
  200. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
  201. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
  202. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
  203. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
  204. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
  205. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
  206. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
  207. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
  208. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
  209. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
  210. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
  211. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
  212. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +118 -0
  213. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
  214. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
  215. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
  216. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
  217. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
  218. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +150 -0
  219. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
  220. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +670 -0
  221. package/node_modules/@try-works/tool-mode-extension-sdk/package.json +53 -0
  222. package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
  223. package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
  224. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +427 -0
  225. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
  226. package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +592 -0
  227. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +60 -0
  228. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
  229. package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +936 -0
  230. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
  231. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
  232. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +200 -0
  233. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
  234. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
  235. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
  236. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +105 -0
  237. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
  238. package/node_modules/@try-works/tool-mode-recipes/lib/images.js +129 -0
  239. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
  240. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
  241. package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
  242. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +325 -0
  243. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
  244. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1310 -0
  245. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
  246. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
  247. package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
  248. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +227 -0
  249. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
  250. package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +407 -0
  251. package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
  252. package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
  253. package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
  254. package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
  255. package/package.json +50 -17
  256. package/remote/spec.mjs +439 -0
  257. package/remote/typert.host.mjs +14 -0
  258. package/remote/typert.remote-client.mjs +16 -0
  259. package/lib/adapters/tongue.d.ts +0 -31
  260. package/lib/adapters/tongue.d.ts.map +0 -1
  261. package/lib/adapters/tongue.js +0 -93
  262. package/lib/adapters/voz.d.ts +0 -28
  263. package/lib/adapters/voz.d.ts.map +0 -1
  264. package/lib/adapters/voz.js +0 -102
  265. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts +0 -0
  266. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts.map +0 -0
  267. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.js +0 -0
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Legacy enable/disable migration into the extension/tool world (BASE-09, BASE-10).
3
+ *
4
+ * The pre-extraction plugin persisted ONE unversioned document —
5
+ * `<DSH_HOME>/model-as-tool/state.json` — holding two arrays of MODEL IDS:
6
+ * `enabled` and `disabled`, with no version key, no provider selections and no
7
+ * extension/tool identity (the host's legacy shape is
8
+ * `packages/dsh-model-as-tool/src/state.ts`'s `PersistedState`). BASE-09's unmet
9
+ * clause is that no table maps those choices into the new world, so an upgrade
10
+ * either loses the operator's choices or guesses.
11
+ *
12
+ * This module is that table. Its rules follow BASE-10 verbatim:
13
+ *
14
+ * - A legacy DISABLE is a tool-level choice, preserved as an `enabled: false`
15
+ * tool selection — never an extension deactivation and never an install.
16
+ * - A legacy ENABLE is NOT consent: it cannot install executable third-party
17
+ * code, run install scripts, widen exports or accept license obligations, so
18
+ * the choice is STAGED (reported) and the tool stays disabled until the
19
+ * operator enables it in the new world.
20
+ * - Unresolved mappings — ids with no table row, providers with no mapping,
21
+ * asset ids with no model deployment — are REPORTED, never silently enabled.
22
+ * - An id recorded as both enabled and disabled is a conflict; the DISABLE wins
23
+ * (fail closed).
24
+ * - A choice already present in the new world's state is never overwritten: the
25
+ * newer world wins and the migration reports that it stood back.
26
+ *
27
+ * BASE-09's "preserve model IDs, selected providers, prepared-asset mappings and
28
+ * disabled choices" maps onto this module as: the table carries the legacy model
29
+ * id and its new extension/model identity (model IDs), `providers` carries
30
+ * legacy-provider → implementation mappings (selected providers), `assetSet`
31
+ * carries the new asset identity for durably recorded prepared-asset mappings,
32
+ * and disabled choices become persisted tool selections. Prepared assets are
33
+ * BORROWED assets under BASE-09: recording a mapping must not seize ownership,
34
+ * authorize deletion, or claim the new deployment is prepared.
35
+ *
36
+ * The table is EXPLICIT (every row is written out, no glob or prefix rule) and
37
+ * ORDERED (earlier rows are consulted first; today each legacy id appears in at
38
+ * most one row, and the order is the order operators see in the report).
39
+ *
40
+ * @module @try-works/tool-mode-extension-sdk/install/migration
41
+ */
42
+ import type { ExtensionState } from './../state.ts';
43
+ /**
44
+ * The on-disk state era this SDK writes (BASE-09's STATE_VERSION key).
45
+ *
46
+ * Bump it only when the persisted profile-state shape changes and a new
47
+ * migration step is appended to `LEGACY_MODEL_MIGRATIONS`. A document carrying a
48
+ * HIGHER number was written by a newer SDK and must be refused, not rewritten.
49
+ */
50
+ export declare const STATE_VERSION: 1;
51
+ /**
52
+ * The schema identifier stamped beside `stateVersion` (BASE-09's schemaVersion).
53
+ *
54
+ * `stateVersion` says which era the document is; `schemaVersion` says which
55
+ * schema dialect wrote it, so a reader can tell "v1 from the pre-schema era"
56
+ * from "v1 with the schemaVersion key" without a data migration.
57
+ */
58
+ export declare const STATE_SCHEMA_VERSION: "1.0.0";
59
+ /** The legacy model-id era document, exactly as the old host persisted it. */
60
+ export interface LegacyModelState {
61
+ /** Model ids the user turned on in the old world. */
62
+ readonly enabled: readonly string[];
63
+ /** Model ids the user turned off in the old world. */
64
+ readonly disabled: readonly string[];
65
+ /**
66
+ * Provider selections recorded alongside the choices, when the source document
67
+ * carried them: legacy model id → provider/implementation identifier. The old
68
+ * host never wrote this key; the migration accepts it so a deployment whose
69
+ * legacy document DID record picks migrates them instead of dropping them.
70
+ */
71
+ readonly providers?: Readonly<Record<string, string>>;
72
+ /** Assets prepared in the old world, recorded so their mapping survives. */
73
+ readonly preparedAssets?: readonly string[];
74
+ }
75
+ /** One row of the explicit, ordered migration table (BASE-09). */
76
+ export interface LegacyModelMigration {
77
+ /** The model id the old world persisted in `enabled`/`disabled`. */
78
+ readonly legacyModelId: string;
79
+ /** The new-world extension package that owns the model/tool. */
80
+ readonly extensionId: string;
81
+ /** The new-world model identity, when the tool is model-backed. */
82
+ readonly modelId?: string;
83
+ /** The new-world asset set the legacy prepared asset corresponds to. */
84
+ readonly assetSet?: string;
85
+ /** The standard contract the extension implements. */
86
+ readonly contractId: string;
87
+ /** The tool name the choice maps onto in the new world. */
88
+ readonly toolName: string;
89
+ /**
90
+ * Legacy provider identifiers → new-world implementation ids. A recorded
91
+ * provider outside this map is reported unresolved, never substituted.
92
+ */
93
+ readonly providers?: Readonly<Record<string, string>>;
94
+ }
95
+ /**
96
+ * The migration table (BASE-09, BASE-10).
97
+ *
98
+ * Rows are grounded in the repository's real extension manifests:
99
+ * `extension-desert-ant-tongue` (`tool-mode/lang_detect`, implementation
100
+ * `tongue-default`, asset set `tongue-bundled`), `extension-desert-ant-voz`
101
+ * (`tool-mode/stt_transcribe`, implementation `voz-default`, asset set
102
+ * `voz-weights`; BASE-03's opt-in `transcribe_audio` alias keeps its documented
103
+ * legacy contract separately and is not re-introduced here), and
104
+ * `extension-declarative-recipes` (`text.title`, implementation `text-title`,
105
+ * model-less — BASE-13's recipe package).
106
+ *
107
+ * Legacy ids without a row (align, clear, clips, ear, emo, eye, face, gist,
108
+ * moderator, redact, schemer, shapes, toxic, uhm, who — the old catalog's
109
+ * remaining models, which the new release tool set does not ship) are reported
110
+ * unresolved by construction: the table lookup simply misses.
111
+ */
112
+ export declare const LEGACY_MODEL_MIGRATIONS: readonly LegacyModelMigration[];
113
+ /** What one report entry is about. */
114
+ export type MigrationEntryKind = 'disabled-choice' | 'enabled-choice' | 'provider-selection' | 'prepared-asset';
115
+ /** What the migration did with one fact. */
116
+ export type MigrationOutcome =
117
+ /** Mapped into the new state exactly (disabled choices, provider picks). */
118
+ 'preserved'
119
+ /** Recorded but deliberately NOT granted (a legacy enable, per BASE-10). */
120
+ | 'staged'
121
+ /** The id sat in both lists; the DISABLE won (fail closed). */
122
+ | 'conflicting'
123
+ /** No table row / no provider mapping / no model deployment. Nothing enabled. */
124
+ | 'unresolved'
125
+ /** The prepared-asset mapping was recorded durably. */
126
+ | 'mapped'
127
+ /** The new world already carries a choice for this tool; it won untouched. */
128
+ | 'existing-state-preserved';
129
+ /** One reported fact about the migration (BASE-10's "report unresolved mappings"). */
130
+ export interface MigrationEntry {
131
+ readonly kind: MigrationEntryKind;
132
+ readonly outcome: MigrationOutcome;
133
+ readonly legacyModelId: string;
134
+ readonly extensionId?: string;
135
+ readonly modelId?: string;
136
+ readonly toolName?: string;
137
+ /** The implementation a preserved provider pick selected. */
138
+ readonly selectedImplementation?: string;
139
+ readonly assetSet?: string;
140
+ /** Why the outcome is what it is; always present for non-preserved facts. */
141
+ readonly reason?: string;
142
+ }
143
+ /**
144
+ * A durably recorded legacy prepared-asset → new deployment mapping (BASE-09).
145
+ *
146
+ * Recording it is NOT a claim that the new deployment is prepared: the new
147
+ * world's asset pipeline differs from the old world's, and BASE-09 makes the old
148
+ * assets borrowed. The mapping survives so a later preparation step can ask the
149
+ * operator whether the borrowed bytes may be reused, instead of silently
150
+ * re-downloading or silently claiming readiness.
151
+ */
152
+ export interface MigratedAssetRecord {
153
+ readonly legacyAssetId: string;
154
+ readonly extensionId: string;
155
+ readonly modelId?: string;
156
+ readonly assetSet?: string;
157
+ }
158
+ /** The pure result of applying the table to one legacy document. */
159
+ export interface AppliedMigration {
160
+ readonly extensions: readonly ExtensionState[];
161
+ readonly entries: readonly MigrationEntry[];
162
+ readonly migratedAssets: readonly MigratedAssetRecord[];
163
+ }
164
+ /** The report a store-level migration returns to the host. */
165
+ export interface MigrationReport {
166
+ readonly profile: string;
167
+ /** Where the legacy document came from, for operator-facing logs. */
168
+ readonly legacySource: string;
169
+ /** The legacy document carries no version key; null records that fact. */
170
+ readonly fromStateVersion: null;
171
+ readonly toStateVersion: typeof STATE_VERSION;
172
+ readonly toSchemaVersion: string;
173
+ /** True when the profile already held current-version state; nothing changed. */
174
+ readonly alreadyCurrent: boolean;
175
+ /** True when a versioned profile state file was written. */
176
+ readonly wroteState: boolean;
177
+ /** Why nothing was written, when the migration was skipped. */
178
+ readonly skippedReason?: string;
179
+ readonly entries: readonly MigrationEntry[];
180
+ }
181
+ /** The result of inspecting one legacy document. */
182
+ export interface LegacyParseResult {
183
+ readonly state?: LegacyModelState;
184
+ readonly diagnostic?: string;
185
+ }
186
+ /**
187
+ * Recognize and normalize the legacy model-id era document.
188
+ *
189
+ * Detection is by SHAPE, not by which file it came from: an object holding
190
+ * `enabled`/`disabled` string arrays (or neither) and no version key is the old
191
+ * world's document. A document that already carries `stateVersion` or
192
+ * `schemaVersion` is NOT legacy — it belongs to this world's versioned store.
193
+ * @param raw - the decoded JSON value.
194
+ * @param source - description of the origin, for messages.
195
+ * @returns the legacy state, or a diagnostic explaining why it is not one.
196
+ */
197
+ export declare function parseLegacyModelState(raw: unknown, source: string): LegacyParseResult;
198
+ /**
199
+ * Apply the migration table to one legacy document (BASE-09, BASE-10).
200
+ *
201
+ * Pure: it maps facts to facts and never touches the filesystem, so the store
202
+ * wraps it with locking and atomic writes, and tests can exercise every
203
+ * disposition without a store.
204
+ * @param legacy - the parsed legacy document.
205
+ * @param existing - the new world's current profile state to merge into.
206
+ * @param table - the migration table; defaults to `LEGACY_MODEL_MIGRATIONS`.
207
+ * @returns the merged state, the report entries, and the durable asset mappings.
208
+ */
209
+ export declare function applyLegacyChoices(legacy: LegacyModelState, existing?: readonly ExtensionState[], table?: readonly LegacyModelMigration[]): AppliedMigration;
210
+ //# sourceMappingURL=migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/install/migration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Legacy enable/disable migration into the extension/tool world (BASE-09, BASE-10).
3
+ *
4
+ * The pre-extraction plugin persisted ONE unversioned document —
5
+ * `<DSH_HOME>/model-as-tool/state.json` — holding two arrays of MODEL IDS:
6
+ * `enabled` and `disabled`, with no version key, no provider selections and no
7
+ * extension/tool identity (the host's legacy shape is
8
+ * `packages/dsh-model-as-tool/src/state.ts`'s `PersistedState`). BASE-09's unmet
9
+ * clause is that no table maps those choices into the new world, so an upgrade
10
+ * either loses the operator's choices or guesses.
11
+ *
12
+ * This module is that table. Its rules follow BASE-10 verbatim:
13
+ *
14
+ * - A legacy DISABLE is a tool-level choice, preserved as an `enabled: false`
15
+ * tool selection — never an extension deactivation and never an install.
16
+ * - A legacy ENABLE is NOT consent: it cannot install executable third-party
17
+ * code, run install scripts, widen exports or accept license obligations, so
18
+ * the choice is STAGED (reported) and the tool stays disabled until the
19
+ * operator enables it in the new world.
20
+ * - Unresolved mappings — ids with no table row, providers with no mapping,
21
+ * asset ids with no model deployment — are REPORTED, never silently enabled.
22
+ * - An id recorded as both enabled and disabled is a conflict; the DISABLE wins
23
+ * (fail closed).
24
+ * - A choice already present in the new world's state is never overwritten: the
25
+ * newer world wins and the migration reports that it stood back.
26
+ *
27
+ * BASE-09's "preserve model IDs, selected providers, prepared-asset mappings and
28
+ * disabled choices" maps onto this module as: the table carries the legacy model
29
+ * id and its new extension/model identity (model IDs), `providers` carries
30
+ * legacy-provider → implementation mappings (selected providers), `assetSet`
31
+ * carries the new asset identity for durably recorded prepared-asset mappings,
32
+ * and disabled choices become persisted tool selections. Prepared assets are
33
+ * BORROWED assets under BASE-09: recording a mapping must not seize ownership,
34
+ * authorize deletion, or claim the new deployment is prepared.
35
+ *
36
+ * The table is EXPLICIT (every row is written out, no glob or prefix rule) and
37
+ * ORDERED (earlier rows are consulted first; today each legacy id appears in at
38
+ * most one row, and the order is the order operators see in the report).
39
+ *
40
+ * @module @try-works/tool-mode-extension-sdk/install/migration
41
+ */
42
+ /**
43
+ * The on-disk state era this SDK writes (BASE-09's STATE_VERSION key).
44
+ *
45
+ * Bump it only when the persisted profile-state shape changes and a new
46
+ * migration step is appended to `LEGACY_MODEL_MIGRATIONS`. A document carrying a
47
+ * HIGHER number was written by a newer SDK and must be refused, not rewritten.
48
+ */
49
+ export const STATE_VERSION = 1;
50
+ /**
51
+ * The schema identifier stamped beside `stateVersion` (BASE-09's schemaVersion).
52
+ *
53
+ * `stateVersion` says which era the document is; `schemaVersion` says which
54
+ * schema dialect wrote it, so a reader can tell "v1 from the pre-schema era"
55
+ * from "v1 with the schemaVersion key" without a data migration.
56
+ */
57
+ export const STATE_SCHEMA_VERSION = '1.0.0';
58
+ /**
59
+ * The migration table (BASE-09, BASE-10).
60
+ *
61
+ * Rows are grounded in the repository's real extension manifests:
62
+ * `extension-desert-ant-tongue` (`tool-mode/lang_detect`, implementation
63
+ * `tongue-default`, asset set `tongue-bundled`), `extension-desert-ant-voz`
64
+ * (`tool-mode/stt_transcribe`, implementation `voz-default`, asset set
65
+ * `voz-weights`; BASE-03's opt-in `transcribe_audio` alias keeps its documented
66
+ * legacy contract separately and is not re-introduced here), and
67
+ * `extension-declarative-recipes` (`text.title`, implementation `text-title`,
68
+ * model-less — BASE-13's recipe package).
69
+ *
70
+ * Legacy ids without a row (align, clear, clips, ear, emo, eye, face, gist,
71
+ * moderator, redact, schemer, shapes, toxic, uhm, who — the old catalog's
72
+ * remaining models, which the new release tool set does not ship) are reported
73
+ * unresolved by construction: the table lookup simply misses.
74
+ */
75
+ export const LEGACY_MODEL_MIGRATIONS = [
76
+ {
77
+ legacyModelId: 'tongue',
78
+ extensionId: '@try-works/extension-desert-ant-tongue',
79
+ modelId: 'tongue',
80
+ assetSet: 'tongue-bundled',
81
+ contractId: 'tool-mode/lang_detect',
82
+ toolName: 'lang_detect',
83
+ providers: {
84
+ tongue: 'tongue-default',
85
+ '@desert-ant-labs/tongue': 'tongue-default',
86
+ },
87
+ },
88
+ {
89
+ legacyModelId: 'voz',
90
+ extensionId: '@try-works/extension-desert-ant-voz',
91
+ modelId: 'voz',
92
+ assetSet: 'voz-weights',
93
+ contractId: 'tool-mode/stt_transcribe',
94
+ toolName: 'stt_transcribe',
95
+ providers: {
96
+ voz: 'voz-default',
97
+ '@desert-ant-labs/voz': 'voz-default',
98
+ },
99
+ },
100
+ {
101
+ legacyModelId: 'title',
102
+ extensionId: '@try-works/extension-declarative-recipes',
103
+ contractId: 'text.title',
104
+ toolName: 'text_title',
105
+ providers: {
106
+ title: 'text-title',
107
+ },
108
+ },
109
+ ];
110
+ /**
111
+ * Recognize and normalize the legacy model-id era document.
112
+ *
113
+ * Detection is by SHAPE, not by which file it came from: an object holding
114
+ * `enabled`/`disabled` string arrays (or neither) and no version key is the old
115
+ * world's document. A document that already carries `stateVersion` or
116
+ * `schemaVersion` is NOT legacy — it belongs to this world's versioned store.
117
+ * @param raw - the decoded JSON value.
118
+ * @param source - description of the origin, for messages.
119
+ * @returns the legacy state, or a diagnostic explaining why it is not one.
120
+ */
121
+ export function parseLegacyModelState(raw, source) {
122
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
123
+ return { diagnostic: `${source} must be a JSON object` };
124
+ }
125
+ const record = raw;
126
+ if (record.stateVersion !== undefined || record.schemaVersion !== undefined) {
127
+ return { diagnostic: `${source} already carries a version key; it is not a legacy model-id era document` };
128
+ }
129
+ const list = (key) => {
130
+ const value = record[key];
131
+ if (value === undefined)
132
+ return undefined;
133
+ if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
134
+ return undefined;
135
+ }
136
+ return value;
137
+ };
138
+ const enabled = list('enabled');
139
+ const disabled = list('disabled');
140
+ if (record.enabled !== undefined && enabled === undefined) {
141
+ return { diagnostic: `${source} field "enabled" must be an array of model ids` };
142
+ }
143
+ if (record.disabled !== undefined && disabled === undefined) {
144
+ return { diagnostic: `${source} field "disabled" must be an array of model ids` };
145
+ }
146
+ let providers;
147
+ if (record.providers !== undefined) {
148
+ const value = record.providers;
149
+ if (typeof value !== 'object' || value === null || Array.isArray(value)
150
+ || Object.values(value).some(item => typeof item !== 'string')) {
151
+ return { diagnostic: `${source} field "providers" must be an object mapping model ids to provider identifiers` };
152
+ }
153
+ providers = value;
154
+ }
155
+ let preparedAssets;
156
+ if (record.preparedAssets !== undefined) {
157
+ const value = record.preparedAssets;
158
+ if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
159
+ return { diagnostic: `${source} field "preparedAssets" must be an array of asset ids` };
160
+ }
161
+ preparedAssets = value;
162
+ }
163
+ return {
164
+ state: {
165
+ enabled: enabled ?? [],
166
+ disabled: disabled ?? [],
167
+ ...providers === undefined ? {} : { providers },
168
+ ...preparedAssets === undefined ? {} : { preparedAssets },
169
+ },
170
+ };
171
+ }
172
+ /**
173
+ * Apply the migration table to one legacy document (BASE-09, BASE-10).
174
+ *
175
+ * Pure: it maps facts to facts and never touches the filesystem, so the store
176
+ * wraps it with locking and atomic writes, and tests can exercise every
177
+ * disposition without a store.
178
+ * @param legacy - the parsed legacy document.
179
+ * @param existing - the new world's current profile state to merge into.
180
+ * @param table - the migration table; defaults to `LEGACY_MODEL_MIGRATIONS`.
181
+ * @returns the merged state, the report entries, and the durable asset mappings.
182
+ */
183
+ export function applyLegacyChoices(legacy, existing = [], table = LEGACY_MODEL_MIGRATIONS) {
184
+ const enabled = new Set(legacy.enabled);
185
+ const disabled = new Set(legacy.disabled);
186
+ const providers = legacy.providers ?? {};
187
+ const preparedAssets = legacy.preparedAssets ?? [];
188
+ const extensions = [...existing];
189
+ const entries = [];
190
+ const migratedAssets = [];
191
+ const indexOf = new Map(extensions.map((state, index) => [state.extensionId, index]));
192
+ /** The new-world identity of a table row, with exact-optional discipline. */
193
+ const rowIdentity = (row) => ({
194
+ extensionId: row.extensionId,
195
+ ...row.modelId === undefined ? {} : { modelId: row.modelId },
196
+ toolName: row.toolName,
197
+ });
198
+ // Iteration order is the report order: enabled first, then disabled, then
199
+ // providers, then prepared assets. One id yields one report entry per fact.
200
+ const legacyIds = [];
201
+ for (const id of [...enabled, ...disabled, ...Object.keys(providers), ...preparedAssets]) {
202
+ if (!legacyIds.includes(id))
203
+ legacyIds.push(id);
204
+ }
205
+ for (const legacyModelId of legacyIds) {
206
+ const row = table.find(candidate => candidate.legacyModelId === legacyModelId);
207
+ const isEnabled = enabled.has(legacyModelId);
208
+ const isDisabled = disabled.has(legacyModelId);
209
+ const conflict = isEnabled && isDisabled;
210
+ const providerId = providers[legacyModelId];
211
+ const assetPrepared = preparedAssets.includes(legacyModelId);
212
+ if (row === undefined) {
213
+ // No table row: REPORT, never enable (BASE-10's "report unresolved
214
+ // mappings without enabling everything").
215
+ if (isEnabled && !conflict) {
216
+ entries.push({ kind: 'enabled-choice', outcome: 'unresolved', legacyModelId, reason: 'no migration table row for this legacy model id' });
217
+ }
218
+ if (isDisabled || conflict) {
219
+ entries.push({
220
+ kind: 'disabled-choice', outcome: 'unresolved', legacyModelId,
221
+ reason: conflict
222
+ ? 'the id appears in both lists and has no migration table row; nothing was enabled'
223
+ : 'no migration table row for this legacy model id; the disabled choice cannot be attached to a tool',
224
+ });
225
+ }
226
+ if (providerId !== undefined) {
227
+ entries.push({ kind: 'provider-selection', outcome: 'unresolved', legacyModelId, reason: 'no migration table row for this legacy model id' });
228
+ }
229
+ if (assetPrepared) {
230
+ entries.push({ kind: 'prepared-asset', outcome: 'unresolved', legacyModelId, reason: 'no migration table row for this legacy asset id' });
231
+ }
232
+ continue;
233
+ }
234
+ const existingIndex = indexOf.get(row.extensionId);
235
+ const existingState = existingIndex === undefined ? undefined : extensions[existingIndex];
236
+ const existingTool = existingState?.tools.find(candidate => candidate.toolName === row.toolName);
237
+ // Provider pick: a resolved pick rides on whichever tool selection the
238
+ // choice yields, so it survives the operator re-enabling the tool later.
239
+ // When the profile already carries a choice for this tool, the newer world
240
+ // wins wholesale and the pick is reported as NOT applied.
241
+ let selectedImplementation;
242
+ if (providerId !== undefined) {
243
+ const mapped = row.providers?.[providerId];
244
+ if (mapped !== undefined) {
245
+ if (existingTool === undefined)
246
+ selectedImplementation = mapped;
247
+ entries.push({
248
+ kind: 'provider-selection',
249
+ outcome: existingTool === undefined ? 'preserved' : 'existing-state-preserved',
250
+ legacyModelId,
251
+ ...rowIdentity(row),
252
+ selectedImplementation: mapped,
253
+ ...existingTool === undefined ? {} : {
254
+ reason: 'the profile state already records a choice for this tool; the legacy provider pick was mapped but not applied',
255
+ },
256
+ });
257
+ }
258
+ else {
259
+ entries.push({
260
+ kind: 'provider-selection', outcome: 'unresolved', legacyModelId,
261
+ extensionId: row.extensionId, toolName: row.toolName,
262
+ reason: `the recorded provider ${JSON.stringify(providerId)} has no mapping for ${row.extensionId}; no implementation was substituted`,
263
+ });
264
+ }
265
+ }
266
+ if (existingTool !== undefined) {
267
+ // The new world already carries a choice for this tool. The newer world
268
+ // wins; the legacy fact is reported, not applied (BASE-11's spirit: never
269
+ // silently overwrite an operator-pinned choice).
270
+ if (isEnabled || isDisabled) {
271
+ entries.push({
272
+ kind: isEnabled ? 'enabled-choice' : 'disabled-choice',
273
+ outcome: 'existing-state-preserved',
274
+ legacyModelId,
275
+ ...rowIdentity(row),
276
+ reason: 'the profile state already records a choice for this tool; the legacy choice was not applied',
277
+ });
278
+ if (conflict) {
279
+ entries.push({
280
+ kind: 'enabled-choice', outcome: 'existing-state-preserved', legacyModelId,
281
+ ...rowIdentity(row),
282
+ reason: 'the legacy conflict was not resolved against an existing choice; the existing choice stands',
283
+ });
284
+ }
285
+ }
286
+ }
287
+ else if (conflict || isDisabled || isEnabled || selectedImplementation !== undefined) {
288
+ // BASE-10: a disable is preserved; an enable is staged; a conflict keeps
289
+ // the disable. Every path produces a DISABLED tool — migration never
290
+ // enables anything on its own. A RESOLVED PROVIDER PICK alone (an id
291
+ // recorded only in `providers`) also creates the disabled selection:
292
+ // BASE-09's "selected providers" preservation is only true if the pick is
293
+ // durably attached to the tool it selects, so it survives the operator
294
+ // enabling the tool later instead of living in the report alone.
295
+ let tool = { toolName: row.toolName, enabled: false };
296
+ if (selectedImplementation !== undefined)
297
+ tool = { ...tool, selectedImplementation };
298
+ if (conflict) {
299
+ entries.push({
300
+ kind: 'enabled-choice', outcome: 'conflicting', legacyModelId,
301
+ ...rowIdentity(row),
302
+ reason: 'the id appears in both enabled and disabled; the disable won (fail closed)',
303
+ });
304
+ entries.push({
305
+ kind: 'disabled-choice', outcome: 'preserved', legacyModelId,
306
+ ...rowIdentity(row),
307
+ });
308
+ }
309
+ else if (isDisabled) {
310
+ entries.push({
311
+ kind: 'disabled-choice', outcome: 'preserved', legacyModelId,
312
+ ...rowIdentity(row),
313
+ });
314
+ }
315
+ else if (isEnabled) {
316
+ entries.push({
317
+ kind: 'enabled-choice', outcome: 'staged', legacyModelId,
318
+ ...rowIdentity(row),
319
+ reason: 'a legacy enable is not consent to install, activate or prepare code (BASE-10); the choice is staged for the operator, not granted',
320
+ });
321
+ }
322
+ if (existingState !== undefined) {
323
+ extensions[existingIndex] = { ...existingState, tools: [...existingState.tools, tool] };
324
+ }
325
+ else {
326
+ // BASE-10: migrating a choice must NOT install or activate anything. The
327
+ // entry exists only to carry the tool choice (and its provider pick)
328
+ // until the operator acts in the new world.
329
+ const state = {
330
+ extensionId: row.extensionId,
331
+ installation: 'absent',
332
+ desiredActivation: 'inactive',
333
+ observedActivation: 'inactive',
334
+ readiness: {},
335
+ tools: [tool],
336
+ export: 'not-exported',
337
+ };
338
+ indexOf.set(row.extensionId, extensions.length);
339
+ extensions.push(state);
340
+ }
341
+ }
342
+ if (assetPrepared) {
343
+ if (row.modelId !== undefined) {
344
+ migratedAssets.push({
345
+ legacyAssetId: legacyModelId,
346
+ extensionId: row.extensionId,
347
+ modelId: row.modelId,
348
+ ...row.assetSet === undefined ? {} : { assetSet: row.assetSet },
349
+ });
350
+ entries.push({
351
+ kind: 'prepared-asset', outcome: 'mapped', legacyModelId,
352
+ extensionId: row.extensionId, modelId: row.modelId,
353
+ ...row.assetSet === undefined ? {} : { assetSet: row.assetSet },
354
+ reason: 'the mapping is recorded; the borrowed asset is not seized and the new deployment is NOT claimed prepared (BASE-09)',
355
+ });
356
+ }
357
+ else {
358
+ entries.push({
359
+ kind: 'prepared-asset', outcome: 'unresolved', legacyModelId,
360
+ extensionId: row.extensionId, toolName: row.toolName,
361
+ reason: 'the new world has no model deployment for this id; the prepared-asset mapping has nothing to attach to',
362
+ });
363
+ }
364
+ }
365
+ }
366
+ return { extensions, entries, migratedAssets };
367
+ }
368
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Make the runtime SDK resolvable from inside an installed extension (EXT-02, EXT-19).
3
+ *
4
+ * THE GAP THIS CLOSES. Installing a package puts it at
5
+ * `<store>/extensions/<id>/<version>/`, which has no `node_modules`. An extension that
6
+ * declares `@try-works/tool-mode-extension-sdk` — which is what the extension protocol
7
+ * requires it to depend on — therefore cannot import it, and its entry fails with
8
+ * `ERR_MODULE_NOT_FOUND`. The package is discoverable and activatable and cannot RUN.
9
+ *
10
+ * This is the same class of problem the host hit when its own dependency was unpublished:
11
+ * a package is only loadable where its dependencies resolve. The store has no install step,
12
+ * so the link has to be made deliberately.
13
+ *
14
+ * WHY A DIRECTORY LINK RATHER THAN A COPY. The SDK is HOST-PROVIDED and versioned with the
15
+ * host, so copying it into every install would ship N copies that drift independently — and
16
+ * an extension running against a stale copy of the runtime is worse than one that refuses
17
+ * to start. The link keeps a single implementation.
18
+ *
19
+ * A JUNCTION ON WINDOWS: `symlinkSync` with a `'dir'` type needs elevation, while a
20
+ * junction does not, and junctions are the realistic Windows case in this repository's
21
+ * other escape tests for the same reason.
22
+ *
23
+ * @module @try-works/tool-mode-extension-sdk/install/runtime-link
24
+ */
25
+ /** The one runtime dependency an extension is allowed to have (EXT-02). */
26
+ export declare const RUNTIME_SDK_NAME = "@try-works/tool-mode-extension-sdk";
27
+ /**
28
+ * Locate this package's own root.
29
+ *
30
+ * Resolved from the SDK itself rather than from the caller, so the link points at the
31
+ * runtime the INSTALLER is running from — the one that will actually execute the extension.
32
+ * @returns the absolute package root, or undefined when it cannot be found.
33
+ */
34
+ export declare function runtimeSdkRoot(): string | undefined;
35
+ /** What linking did. */
36
+ export interface RuntimeLinkOutcome {
37
+ readonly linked: boolean;
38
+ /** Why it did not link, when it did not. */
39
+ readonly reason?: 'already-present' | 'sdk-not-locatable' | 'link-failed' | 'sdk-shadowed';
40
+ /** The path the link was made at. */
41
+ readonly path?: string;
42
+ /** A failure detail worth reporting rather than swallowing. */
43
+ readonly detail?: string;
44
+ }
45
+ /**
46
+ * Make the runtime SDK resolvable from an installed extension.
47
+ *
48
+ * @param installPath - the installed package directory.
49
+ * @param sdkRoot - where the runtime lives; resolved automatically when omitted.
50
+ * @returns what happened, which is reported rather than assumed.
51
+ */
52
+ export declare function linkRuntimeSdk(installPath: string, sdkRoot?: string | undefined): RuntimeLinkOutcome;
53
+ /**
54
+ * Remove a runtime link, for an uninstall (EXT-24).
55
+ *
56
+ * Removed separately from the package directory so a caller that removes the link but keeps
57
+ * the package — or the reverse — does not end up with an extension whose imports resolve
58
+ * against a runtime it was not installed for.
59
+ * @param installPath - the installed package directory.
60
+ * @returns whether a link was removed.
61
+ */
62
+ export declare function unlinkRuntimeSdk(installPath: string): boolean;
63
+ //# sourceMappingURL=runtime-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-link.d.ts","sourceRoot":"","sources":["../../src/install/runtime-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,uCAAuC,CAAA;AAEpE;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CASnD;AAED,wBAAwB;AACxB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,mBAAmB,GAAG,aAAa,GAAG,cAAc,CAAA;IAC1F,qCAAqC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,qBAAmB,GAAG,kBAAkB,CAiElG;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAK7D"}