@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,235 @@
1
+ /**
2
+ * Staged installation (EXT-07, EXT-08).
3
+ *
4
+ * The ordering is the security property. A package is fetched into quarantine,
5
+ * verified, inspected as DATA, validated, and only then promoted into the store —
6
+ * and promotion is not activation. Nothing in this module imports extension code,
7
+ * runs inference, warms a model, or publishes a tool (EXT-07).
8
+ *
9
+ * The fetch and extract steps are INJECTED rather than implemented here, for two
10
+ * reasons: the SDK must stay free of a network stack and an archive library, and
11
+ * a test must be able to drive every rejection path without a real download or a
12
+ * real filesystem. The host supplies the real implementations.
13
+ *
14
+ * @module @try-works/tool-mode-extension-sdk/install/staged
15
+ */
16
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
17
+ import { linkRuntimeSdk, RUNTIME_SDK_NAME } from "./runtime-link.js";
18
+ import { join, resolve, sep } from 'node:path';
19
+ import { ManagementError } from "./../errors.js";
20
+ import { discoverExtension } from "./../discovery.js";
21
+ import { digestInstalledContent, ExtensionStore } from "./store.js";
22
+ import { installDependencyGraph } from "./dependencies.js";
23
+ import { DEFAULT_ARCHIVE_LIMITS, validateArchiveEntries, verifyIntegrity, } from "./archive.js";
24
+ /** Conservative install limits. */
25
+ export const DEFAULT_INSTALL_LIMITS = {
26
+ maxArchiveBytes: 256 * 1024 * 1024,
27
+ fetchTimeoutMs: 120_000,
28
+ archive: DEFAULT_ARCHIVE_LIMITS,
29
+ };
30
+ /**
31
+ * Install an extension into an operator-owned store, staged (EXT-08).
32
+ *
33
+ * Steps, in order: fetch into quarantine → verify integrity → list entries →
34
+ * validate the entry list → extract → discover → validate compatibility →
35
+ * promote atomically → record the installation. A failure at any step removes the
36
+ * quarantine, so a partial install never becomes visible.
37
+ *
38
+ * The store is RECORDED rather than merely written to: an installation that is not
39
+ * in the lock document cannot be activated later, because nothing would know what
40
+ * bytes were approved.
41
+ *
42
+ * @param options - the source, the store, the injected archive source, and limits.
43
+ * @returns the installed (but inactive) extension.
44
+ * @throws ManagementError for every rejection path.
45
+ */
46
+ export async function stagedInstall(options) {
47
+ const limits = options.limits ?? DEFAULT_INSTALL_LIMITS;
48
+ const storeDir = resolve(options.storeDir);
49
+ const staging = join(storeDir, '.staging');
50
+ // A unique per-attempt directory, so two concurrent installs cannot collide and
51
+ // a crashed attempt leaves evidence rather than a half-written package.
52
+ const attempt = join(staging, `attempt-${process.pid}-${Date.now().toString(36)}`);
53
+ mkdirSync(attempt, { recursive: true });
54
+ /** Set when the runtime link could not be made, reported rather than thrown. */
55
+ let runtimeLinkDiagnostic;
56
+ try {
57
+ const bytes = await options.archive.fetch(options.source, {
58
+ maxBytes: limits.maxArchiveBytes,
59
+ timeoutMs: limits.fetchTimeoutMs,
60
+ });
61
+ if (bytes.byteLength > limits.maxArchiveBytes) {
62
+ throw new ManagementError('INVALID_EXTENSION', 'install', `the fetched archive is ${bytes.byteLength} bytes, over the ${limits.maxArchiveBytes} limit`, 'Ask the publisher to reduce the package, or raise the operator limit deliberately.');
63
+ }
64
+ // Integrity first: if the bytes are not the approved ones, nothing downstream
65
+ // is worth doing.
66
+ const archiveDigest = verifyIntegrity(bytes, options.expectedSha512);
67
+ // Entry validation runs on the LIST, before extraction. A traversal entry
68
+ // rejected here never reaches a path join.
69
+ const entries = options.archive.list(bytes);
70
+ validateArchiveEntries(entries, limits.archive);
71
+ const extracted = join(attempt, 'package');
72
+ mkdirSync(extracted, { recursive: true });
73
+ options.archive.extract(bytes, extracted, '');
74
+ // Discovery reads data and imports nothing; a manifest referencing a file the
75
+ // package does not ship is refused before anything is promoted.
76
+ const discovery = discoverExtension(extracted);
77
+ // EXT-09: the extension's runtime dependencies are resolved, verified and
78
+ // materialized into the extension's OWN directory before promotion. A
79
+ // package that declares dependencies without a provided graph installer is
80
+ // REFUSED rather than installed as a guaranteed-broken extension.
81
+ let lockedDependencies = [];
82
+ let declaredDependenciesCount = 0;
83
+ try {
84
+ const packageJson = JSON.parse(readFileSync(join(extracted, 'package.json'), 'utf8'));
85
+ declaredDependenciesCount = Object.keys(packageJson.dependencies ?? {}).length;
86
+ }
87
+ catch {
88
+ // The package.json was already read by discovery; this cannot fail.
89
+ }
90
+ if (declaredDependenciesCount > 0) {
91
+ if (options.dependencies === undefined) {
92
+ throw new ManagementError('DEPENDENCY_UNSATISFIED', 'install', `${discovery.packageName} declares ${declaredDependenciesCount} runtime dependenc${declaredDependenciesCount === 1 ? 'y' : 'ies'} but no dependency-graph installer was provided; the extension would be installed broken`, 'Provide the operator-configured registry resolver, or publish the extension with every runtime dependency bundled.');
93
+ }
94
+ lockedDependencies = await installDependencyGraph(extracted, options.dependencies);
95
+ }
96
+ // EXT-08: the operator approval PREVIEW runs BEFORE materialization — the
97
+ // caller sees the permissions/licenses/platform/download implications and
98
+ // may refuse (throw) to abort the install while nothing is promoted.
99
+ if (options.preview !== undefined) {
100
+ const manifest = discovery.manifest;
101
+ await options.preview({
102
+ extensionId: discovery.packageName,
103
+ version: discovery.packageVersion,
104
+ permissions: manifest.permissions,
105
+ models: manifest.models.map(model => ({
106
+ id: model.id,
107
+ assetSet: model.assetSet,
108
+ platforms: model.platforms.map(platform => `${platform.os}-${platform.arch}${platform.accelerator === undefined ? '' : `-${platform.accelerator}`}`),
109
+ })),
110
+ licenses: (manifest.licenses ?? []).map(layer => `${layer.layer}: ${layer.name}`),
111
+ downloadImplications: manifest.models.length === 0
112
+ ? 'no model assets declared; nothing is downloaded at install'
113
+ : `${manifest.models.length} model asset set(s) declared; downloads require the separate preparation consent, never the install`,
114
+ requiresApproval: manifest.permissions.nativeCode
115
+ || manifest.permissions.networkOrigins.length > 0
116
+ || manifest.permissions.storage !== 'none'
117
+ || manifest.models.length > 0,
118
+ });
119
+ }
120
+ // Promote by rename, which is atomic within a store. The destination is keyed
121
+ // by identity AND version, so an update installs side by side rather than
122
+ // mutating a live directory (EXT-30).
123
+ const destination = installPathFor(storeDir, discovery.packageName, discovery.packageVersion);
124
+ if (existsSync(destination)) {
125
+ throw new ManagementError('UPGRADE_FAILED', 'install', `${discovery.packageName}@${discovery.packageVersion} is already installed`, 'Install a different version, or uninstall the existing one first.');
126
+ }
127
+ mkdirSync(join(destination, '..'), { recursive: true });
128
+ renameSync(extracted, destination);
129
+ /**
130
+ * Make the RUNTIME SDK resolvable from inside the installed package.
131
+ *
132
+ * Without this the package lands in a directory with no `node_modules`, so an extension
133
+ * that declares the SDK — which the protocol requires it to depend on — dies on its
134
+ * first import with ERR_MODULE_NOT_FOUND. It is discoverable and activatable and cannot
135
+ * RUN, which is the worst of the three states because nothing reports it as broken.
136
+ *
137
+ * A failure here is RECORDED rather than thrown: a package that imports nothing (a
138
+ * declarative or tool-only extension) runs fine without the link, and failing the
139
+ * install would break working packages to fix a problem they do not have.
140
+ */
141
+ runtimeLinkDiagnostic = linkRuntimeSdk(destination);
142
+ /**
143
+ * A SHADOWED RUNTIME FAILS THE INSTALL.
144
+ *
145
+ * If the package shipped its own copy of the host SDK, the extension would execute
146
+ * against THAT copy while the operator was told the link was merely already present.
147
+ * Installing it is worse than refusing, because the receipt would then describe a
148
+ * containment the installation does not have. This is the one link outcome that is
149
+ * fatal rather than reported.
150
+ */
151
+ if (runtimeLinkDiagnostic.reason === 'sdk-shadowed') {
152
+ rmSync(destination, { recursive: true, force: true });
153
+ throw new ManagementError('INVALID_EXTENSION', 'install', runtimeLinkDiagnostic.detail ?? 'the package ships its own copy of the host runtime SDK', 'Remove node_modules/' + RUNTIME_SDK_NAME
154
+ + ' from the package; an extension must run against the host runtime.');
155
+ }
156
+ writeFileSync(join(destination, '.tool-mode-install.json'), `${JSON.stringify({
157
+ extensionId: discovery.packageName,
158
+ version: discovery.packageVersion,
159
+ archiveDigest,
160
+ ...runtimeLinkDiagnostic === undefined ? {} : { runtimeLink: runtimeLinkDiagnostic },
161
+ source: { kind: options.source.kind, requested: options.source.requested },
162
+ ...lockedDependencies.length === 0 ? {} : { dependencies: lockedDependencies },
163
+ ...options.provenance === undefined ? {} : { provenance: options.provenance },
164
+ installedAt: new Date().toISOString(),
165
+ }, null, 2)}\n`);
166
+ // Recorded AFTER the bytes are in place: a lock entry naming a directory that
167
+ // does not exist would be worse than no entry, because verification would then
168
+ // report a missing installation as a changed one.
169
+ if (options.record !== false) {
170
+ const store = new ExtensionStore(storeDir);
171
+ store.recordInstall({
172
+ extensionId: discovery.packageName,
173
+ version: discovery.packageVersion,
174
+ installPath: destination,
175
+ archiveDigest,
176
+ ...runtimeLinkDiagnostic === undefined ? {} : { runtimeLink: runtimeLinkDiagnostic },
177
+ // Digest the content as installed, so a later edit is detectable.
178
+ contentDigest: digestInstalledContent(destination),
179
+ source: { kind: options.source.kind, requested: options.source.requested },
180
+ ...lockedDependencies.length === 0 ? {} : { dependencies: lockedDependencies },
181
+ ...options.provenance === undefined ? {} : { provenance: options.provenance },
182
+ installedAt: new Date().toISOString(),
183
+ });
184
+ }
185
+ return {
186
+ extensionId: discovery.packageName,
187
+ version: discovery.packageVersion,
188
+ installPath: destination,
189
+ activation: 'inactive',
190
+ discovery,
191
+ archiveDigest,
192
+ ...runtimeLinkDiagnostic === undefined ? {} : { runtimeLink: runtimeLinkDiagnostic },
193
+ };
194
+ }
195
+ finally {
196
+ // Quarantine is removed on EVERY path, success included: the promoted copy is
197
+ // the installation, and leaving a second copy behind would let the two drift.
198
+ rmSync(attempt, { recursive: true, force: true });
199
+ }
200
+ }
201
+ /**
202
+ * The immutable installation directory for one extension version (EXT-33).
203
+ *
204
+ * The identity is VALIDATED rather than merely escaped. Escaping would turn
205
+ * `../../etc` into a harmless-looking directory name and silently install
206
+ * something under a package name that no registry would accept; refusing says
207
+ * what is actually wrong.
208
+ * @param storeDir - the operator's store root.
209
+ * @param extensionId - the validated extension identity.
210
+ * @param version - the validated version.
211
+ * @returns the absolute installation path.
212
+ * @throws ManagementError when the identity or version is not a legal one.
213
+ */
214
+ export function installPathFor(storeDir, extensionId, version) {
215
+ // A package name is lower-case, may be scoped, and uses a restricted character
216
+ // set. EXT-14 already requires the manifest id to equal the package name, so an
217
+ // identity outside this grammar did not come from a real package.
218
+ const SEGMENT = '[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?';
219
+ const NAME = new RegExp(`^(?:@${SEGMENT}/)?${SEGMENT}$`);
220
+ if (!NAME.test(extensionId)) {
221
+ throw new ManagementError('INVALID_EXTENSION', 'install', `the extension identity ${JSON.stringify(extensionId)} is not a legal package name`, 'Use a normal npm package name; the manifest id must equal it exactly.');
222
+ }
223
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
224
+ throw new ManagementError('INVALID_EXTENSION', 'install', `the version ${JSON.stringify(version)} is not a semantic version`, 'Publish a semantic version.');
225
+ }
226
+ // The separator is the one character a legal name cannot contain, so a
227
+ // validated name needs no further escaping to stay inside the store.
228
+ const path = join(resolve(storeDir), 'extensions', extensionId, version);
229
+ const root = resolve(storeDir);
230
+ if (!path.startsWith(root + sep)) {
231
+ throw new ManagementError('INVALID_EXTENSION', 'install', 'the extension identity would escape the extension store', 'Use a normal package name.');
232
+ }
233
+ return path;
234
+ }
235
+ //# sourceMappingURL=staged.js.map
@@ -0,0 +1,367 @@
1
+ /**
2
+ * The operator-owned extension store (EXT-33).
3
+ *
4
+ * Three properties this module exists to guarantee:
5
+ *
6
+ * 1. **Identity survives restart.** Every installation is recorded in
7
+ * `extensions.lock.json` with its resolved source and a CONTENT digest, so the
8
+ * host can tell on a later boot whether the bytes it is about to activate are
9
+ * still the bytes it installed.
10
+ * 2. **Corruption fails closed.** A state file that cannot be read yields NO
11
+ * active extensions and a diagnostic. The tempting alternative — falling back
12
+ * to "everything installed is active" — is precisely the failure EXT-33 names,
13
+ * because a corrupted file would silently enable every package on the machine.
14
+ * 3. **A write that did not land is never reported as landed.** Every write goes
15
+ * through a temporary file and a rename, and a failure throws rather than
16
+ * leaving the caller believing a preference was stored.
17
+ *
18
+ * @module @try-works/tool-mode-extension-sdk/install/store
19
+ */
20
+ import type { ExtensionState } from './../state.ts';
21
+ import { STATE_VERSION, type MigratedAssetRecord, type MigrationReport } from './migration.ts';
22
+ import type { LockedDependency } from './dependencies.ts';
23
+ /** The lock document name, as EXT-33 specifies. */
24
+ export declare const LOCK_FILE = "extensions.lock.json";
25
+ /** One installed extension, as recorded at install time. */
26
+ export interface InstalledRecord {
27
+ /** Extension identity, which equals the package name. */
28
+ readonly extensionId: string;
29
+ /** Installed version. */
30
+ readonly version: string;
31
+ /** Absolute installation directory. */
32
+ readonly installPath: string;
33
+ /** SHA-512 of the archive the package was installed from (EXT-12). */
34
+ readonly archiveDigest: string;
35
+ /**
36
+ * Digest over the installed files. Re-checked before activation so a package
37
+ * edited on disk after installation is detected rather than trusted.
38
+ */
39
+ readonly contentDigest: string;
40
+ /** Where the archive came from, recorded verbatim. */
41
+ readonly source: {
42
+ readonly kind: string;
43
+ readonly requested: string;
44
+ };
45
+ /** When it was installed, ISO 8601. */
46
+ readonly installedAt: string;
47
+ /**
48
+ * The installer-owned dependency graph (EXT-09, EXT-12): every runtime
49
+ * dependency at its EXACT resolved version with its verified integrity.
50
+ * Absent when the package declares no runtime dependencies.
51
+ */
52
+ readonly dependencies?: readonly LockedDependency[];
53
+ /**
54
+ * Provenance fields recorded AS DATA, NEVER AS TRUST (EXT-12): registry
55
+ * integrity/provenance flags travel with the record for audit; verification
56
+ * is always against the operator-supplied digest.
57
+ */
58
+ readonly provenance?: {
59
+ readonly registryIntegrity?: string;
60
+ readonly provenance?: boolean;
61
+ readonly attestations?: readonly string[];
62
+ readonly signatures?: readonly string[];
63
+ };
64
+ }
65
+ /** The lock document. */
66
+ export interface StoreLock {
67
+ readonly lockVersion: 1;
68
+ readonly extensions: readonly InstalledRecord[];
69
+ }
70
+ /**
71
+ * A profile's persisted activation state (EXT-25, dimensions 2-6).
72
+ *
73
+ * The two version keys are BASE-09's: `stateVersion` is the migration-table era
74
+ * (a document with a higher number was written by a newer SDK and is refused,
75
+ * never rewritten), and `schemaVersion` identifies the schema dialect. Documents
76
+ * written before `schemaVersion` existed (stateVersion 1, no schemaVersion key)
77
+ * still read: the key was added without a data change, so there is no migration
78
+ * step between them.
79
+ */
80
+ export interface ProfileStateFile {
81
+ readonly stateVersion: typeof STATE_VERSION;
82
+ readonly schemaVersion: string;
83
+ readonly profile: string;
84
+ readonly extensions: readonly ExtensionState[];
85
+ /** Legacy prepared-asset mappings recorded by the BASE-09 migration. */
86
+ readonly migratedAssets?: readonly MigratedAssetRecord[];
87
+ /** EXT-30: the active version per extension, the update flow's pointer. */
88
+ readonly activeVersions?: Readonly<Record<string, string>>;
89
+ /** EXT-30: the previous active version per extension, the rollback target. */
90
+ readonly previousVersions?: Readonly<Record<string, string>>;
91
+ }
92
+ /**
93
+ * One EXT-30 approval decision for a staged update.
94
+ *
95
+ * Retained for the store's lifetime (audit trail, no expiry) and write-once per
96
+ * staged version: a decision is a human act, and a later one never silently
97
+ * overwrites it.
98
+ */
99
+ export interface UpdateApprovalRecord {
100
+ readonly extensionId: string;
101
+ readonly version: string;
102
+ readonly approved: boolean;
103
+ readonly deniedReason?: string;
104
+ readonly decidedAt: string;
105
+ }
106
+ /** The outcome of reading state, which never throws on corruption. */
107
+ export interface StateReadResult<T> {
108
+ readonly value: T;
109
+ /** Set when the file existed but could not be trusted. */
110
+ readonly diagnostic?: string;
111
+ /** True when the file existed but could not be read or parsed. */
112
+ readonly corrupt: boolean;
113
+ }
114
+ /**
115
+ * Digest the files inside an installed package.
116
+ *
117
+ * Identity is `relative path` plus size plus a per-file digest, over a sorted
118
+ * walk, so a renamed file, an edited file, an added file and a removed file all
119
+ * change the result. The install receipt is excluded: it is store metadata, not
120
+ * package content, and including it would make the digest depend on itself.
121
+ * @param directory - the installed package directory.
122
+ * @returns the content digest, lowercase hex.
123
+ */
124
+ export declare function digestInstalledContent(directory: string): string;
125
+ /**
126
+ * Whether a process with this pid exists. `process.kill(pid, 0)` is the probe.
127
+ *
128
+ * Exported because surface ownership is recorded as a PID: telling a GONE owner (a
129
+ * crashed or restarted host, whose in-memory handles died with it) from a LIVE one
130
+ * (another host still serving) is the same question the store lock asks.
131
+ * @param pid - the process id to probe.
132
+ * @returns whether the process exists.
133
+ */
134
+ export declare function isProcessAlive(pid: number): boolean;
135
+ /** The operator-owned extension store. */
136
+ export declare class ExtensionStore {
137
+ /** Absolute path of the store root. */
138
+ readonly rootDir: string;
139
+ constructor(rootDir: string);
140
+ /** Path of the lock document. */
141
+ get lockPath(): string;
142
+ /** Path of one profile's state file. */
143
+ profileStatePath(profile: string): string;
144
+ /**
145
+ * Take exclusive ownership of the store for offline edits (EXT-31).
146
+ *
147
+ * EXT-31 requires offline edits to hold exclusive store ownership, because an
148
+ * offline writer and a running host editing the same store would each be working
149
+ * from a state the other cannot see. The lock records the owning process so a
150
+ * stale lock from a crashed run can be reported as stale rather than blocking
151
+ * forever.
152
+ * @returns a release function.
153
+ * @throws ManagementError with `EXTENSION_IN_USE` when another process holds it.
154
+ */
155
+ acquireExclusive(): () => void;
156
+ /**
157
+ * Run a state-mutating operation under the store lock (EXT-31).
158
+ *
159
+ * The HOST LIFECYCLE takes this around every state write, and the offline CLI
160
+ * takes it around its edits; each side refuses while the other's process is
161
+ * alive. Reentrancy is keyed by the RESOLVED STORE ROOT, not the instance:
162
+ * the CLI creates fresh ExtensionStore objects around one directory, so
163
+ * per-instance counting would let an inner acquisition overwrite the outer's
164
+ * lock record (the round-49 review's hole 3). The depth is recorded only
165
+ * AFTER the file lock is taken, so a refusal throws WITHOUT poisoning the
166
+ * count (hole 1), and the lock file is removed only when the depth returns to
167
+ * zero (hole 2: a concurrent section still holds it).
168
+ * @param work - the mutating work.
169
+ * @returns the work's result.
170
+ */
171
+ exclusive<T>(work: () => Promise<T>): Promise<T>;
172
+ /**
173
+ * Read the lock document.
174
+ *
175
+ * A corrupt lock fails closed with a diagnostic and NO records, rather than
176
+ * reporting the store as empty-without-explanation or trusting a partial read.
177
+ * @returns the lock and a diagnostic when it could not be trusted.
178
+ */
179
+ readLock(): StateReadResult<StoreLock>;
180
+ /** List installed extensions. */
181
+ listInstalled(): StateReadResult<readonly InstalledRecord[]>;
182
+ /**
183
+ * Record an installation.
184
+ *
185
+ * Throws when the write fails, so a caller never treats a lost record as a
186
+ * completed install.
187
+ * @param record - the installation to record.
188
+ * @throws ManagementError when the same identity and version is already recorded.
189
+ */
190
+ recordInstall(record: InstalledRecord): void;
191
+ /**
192
+ * Remove an installation record.
193
+ *
194
+ * Removing a record does NOT delete the installed bytes: deletion is a separate,
195
+ * operator-driven step with its own failure modes (EXT-29), and conflating the
196
+ * two would make a failed deletion look like a failed uninstall.
197
+ * @param extensionId - the extension to forget.
198
+ */
199
+ removeRecord(extensionId: string): void;
200
+ /**
201
+ * Check whether an installation still matches what was recorded (EXT-33).
202
+ *
203
+ * Run before activation: a package edited on disk after installation is a
204
+ * different package, and activating it would execute bytes nobody approved.
205
+ * @param record - the recorded installation.
206
+ * @returns whether the content is unchanged, plus the current digest.
207
+ */
208
+ verifyUnchanged(record: InstalledRecord): {
209
+ unchanged: boolean;
210
+ contentDigest?: string;
211
+ diagnostic?: string;
212
+ };
213
+ /**
214
+ * Read one profile's activation state.
215
+ *
216
+ * A corrupt file yields NO states and a diagnostic. Returning the installed set
217
+ * instead would be the failure EXT-33 names: corruption would enable everything.
218
+ *
219
+ * Versioning (BASE-09): a document with a HIGHER `stateVersion` was written by
220
+ * a newer SDK and is refused, not read half-understood. A document with NO
221
+ * `stateVersion` is either a legacy model-id era document (enabled/disabled
222
+ * arrays, migrated via {@link ExtensionStore.migrateLegacyProfileState}) or
223
+ * something this store never wrote — both fail closed with a diagnostic.
224
+ * @param profile - the profile name.
225
+ * @returns the states and any diagnostic.
226
+ */
227
+ readProfileState(profile: string): StateReadResult<readonly ExtensionState[]>;
228
+ /**
229
+ * Persist one profile's activation state.
230
+ *
231
+ * The document carries both BASE-09 version keys: `stateVersion` (the
232
+ * migration era) and `schemaVersion` (the schema dialect), so a later reader
233
+ * can tell an up-to-date document from a legacy one without guessing.
234
+ *
235
+ * MIGRATED-ASSET DURABILITY (BASE-09): when the caller does not pass
236
+ * `migratedAssets`, the mappings already recorded in the file are PRESERVED
237
+ * verbatim instead of dropped. Every lifecycle write and CLI edit calls this
238
+ * method without the parameter, so requiring every caller to carry the
239
+ * mappings through would mean the first forgetful writer silently loses the
240
+ * migration's prepared-asset record; preserving by default makes the store
241
+ * itself the keeper of them. Pass an empty array to clear them deliberately.
242
+ * @param profile - the profile name.
243
+ * @param extensions - the complete state set for that profile.
244
+ * @param migratedAssets - durable legacy prepared-asset mappings. Omitted:
245
+ * preserve the existing ones. `[]`: clear them.
246
+ * @throws ManagementError when the write fails.
247
+ */
248
+ writeProfileState(profile: string, extensions: readonly ExtensionState[], migratedAssets?: readonly MigratedAssetRecord[], activeVersions?: Readonly<Record<string, string>>, previousVersions?: Readonly<Record<string, string>>): void;
249
+ /**
250
+ * Read the EXT-30 active-version pointers from one profile's state document.
251
+ *
252
+ * The maps are OPTIONAL document keys written only by the update flow: an
253
+ * older document simply has no pointers, and a corrupt map fails closed
254
+ * rather than being half-read. The read is separate from
255
+ * {@link ExtensionStore.readProfileState} so the existing per-extension state
256
+ * contract is untouched.
257
+ * @param profile - the profile name.
258
+ * @returns the pointer maps and any diagnostic.
259
+ */
260
+ readProfilePointers(profile: string): StateReadResult<{
261
+ readonly activeVersions: Readonly<Record<string, string>>;
262
+ readonly previousVersions: Readonly<Record<string, string>>;
263
+ }>;
264
+ /** The approval-record path for one staged version (EXT-30, lifetime audit). */
265
+ approvalPath(extensionId: string, version: string): string;
266
+ /**
267
+ * Read the approval record for one staged version.
268
+ *
269
+ * A corrupt record fails closed with the diagnostic: an update whose approval
270
+ * cannot be read must NOT proceed as if it were approved.
271
+ * @param extensionId - the extension.
272
+ * @param version - the staged version.
273
+ * @returns the record (or undefined when none was written) and any diagnostic.
274
+ */
275
+ readApproval(extensionId: string, version: string): StateReadResult<UpdateApprovalRecord | undefined>;
276
+ /**
277
+ * Record ONE approval decision for one staged version (EXT-30).
278
+ *
279
+ * The record is retained for the store's LIFETIME (audit trail, no expiry)
280
+ * and is WRITE-ONCE per staged version: a later decision never silently
281
+ * overwrites an earlier one. A denied record stays as the audit entry.
282
+ * @param extensionId - the extension.
283
+ * @param version - the staged version.
284
+ * @param decision - the operator's decision.
285
+ * @throws ManagementError when an earlier decision exists.
286
+ */
287
+ recordApproval(extensionId: string, version: string, decision: {
288
+ approved: true;
289
+ } | {
290
+ approved: false;
291
+ reason: string;
292
+ }): void;
293
+ /**
294
+ * Remove ONE version's installation record (EXT-30 admission rollback).
295
+ *
296
+ * The per-version removal exists for the update flow's failure cleanup: when
297
+ * a commit fails after the new version was admitted, the new version's record
298
+ * is removed while every OTHER version's record survives.
299
+ * @param extensionId - the extension.
300
+ * @param version - the version to forget.
301
+ */
302
+ removeVersionRecord(extensionId: string, version: string): void;
303
+ /** The cleanup-pending tombstone directory. */
304
+ cleanupPendingDir(): string;
305
+ /**
306
+ * Record an owned deletion that could not complete (EXT-29).
307
+ *
308
+ * A tombstone keeps the CLEANUP_PENDING truth durable: the retry loop
309
+ * ({@link ExtensionStore.retryCleanupPending}) re-attempts the deletion on
310
+ * later runs, bounded, and the directory is never silently forgotten.
311
+ * @param targetPath - the path the deletion could not remove.
312
+ * @param reason - why the deletion failed.
313
+ */
314
+ writeCleanupTombstone(targetPath: string, reason: string): void;
315
+ /**
316
+ * Retry owned deletions recorded by tombstones (EXT-29), bounded.
317
+ *
318
+ * Every tombstone under the attempts cap gets ONE retry attempt per call;
319
+ * a still-failing deletion increments the counter and keeps the truthful
320
+ * CLEANUP_PENDING record. A path that no longer exists counts as deleted.
321
+ * @param maxAttempts - the attempts cap (default 5).
322
+ * @returns the per-run counts.
323
+ */
324
+ retryCleanupPending(maxAttempts?: number): {
325
+ retried: number;
326
+ deleted: number;
327
+ kept: number;
328
+ };
329
+ /**
330
+ * Read the durable legacy prepared-asset mappings a migration recorded.
331
+ *
332
+ * Kept on the store rather than folded into `readProfileState` because the
333
+ * state array is the lifecycle's working surface: changing its shape for the
334
+ * asset record would make every writer a silent dropper of the record, which
335
+ * is exactly the failure BASE-09's preservation clause names. The version
336
+ * gate matches {@link ExtensionStore.readProfileState}.
337
+ * @param profile - the profile name.
338
+ * @returns the recorded mappings and any diagnostic.
339
+ */
340
+ readMigratedAssets(profile: string): StateReadResult<readonly MigratedAssetRecord[]>;
341
+ /**
342
+ * Migrate a legacy model-id era document into this profile (BASE-09, BASE-10).
343
+ *
344
+ * The old world's `<DSH_HOME>/model-as-tool/state.json` held unversioned
345
+ * `enabled`/`disabled` MODEL-ID arrays. The host reads that document and hands
346
+ * its content here; this method runs it through the explicit migration table
347
+ * and writes the versioned profile state atomically under the store lock.
348
+ *
349
+ * Guarantees, per BASE-10:
350
+ * - Disabled choices are preserved as tool-level disables; nothing is
351
+ * installed, activated or prepared by the migration.
352
+ * - Legacy enables are STAGED in the report, never granted.
353
+ * - Unresolved mappings are reported, never silently enabled.
354
+ * - A profile that already holds current-version state is left untouched
355
+ * (double migration is idempotent); a document this SDK cannot interpret is
356
+ * refused rather than overwritten.
357
+ * @param profile - the profile to migrate into.
358
+ * @param legacyJson - the legacy document's text. Omit it to migrate a
359
+ * legacy-shaped document found at the profile state path itself.
360
+ * @param legacySource - description of the origin, for the report.
361
+ * @returns the migration report.
362
+ * @throws ManagementError when the input is not a usable legacy document or
363
+ * the profile already holds a document this SDK refuses to overwrite.
364
+ */
365
+ migrateLegacyProfileState(profile: string, legacyJson?: string, legacySource?: string): Promise<MigrationReport>;
366
+ }
367
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/install/store.ts"],"names":[],"mappings":"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"}