@try-works/dsh-tool-mode 0.0.0-stage → 0.5.44

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 (425) hide show
  1. package/README.md +299 -2
  2. package/bin/dsh-tool-mode-credentials.mjs +20 -0
  3. package/bin/dsh-tool-mode-mcp-stdio.mjs +80 -0
  4. package/bin/dsh-tool-mode.mjs +211 -0
  5. package/builtins.lock.json +26 -0
  6. package/catalog/desert-ant-models.json +693 -0
  7. package/catalog/playbooks.json +531 -0
  8. package/client/client.model-tools.js +1910 -0
  9. package/client/index.js +4039 -0
  10. package/cordis.patch.yml +39 -0
  11. package/lib/adapters/index.d.ts +61 -0
  12. package/lib/adapters/index.d.ts.map +1 -0
  13. package/lib/adapters/index.js +82 -0
  14. package/lib/adapters/types.d.ts +106 -0
  15. package/lib/adapters/types.d.ts.map +1 -0
  16. package/lib/adapters/types.js +85 -0
  17. package/lib/approval.d.ts +189 -0
  18. package/lib/approval.d.ts.map +1 -0
  19. package/lib/approval.js +510 -0
  20. package/lib/asset-acquisition.d.ts +149 -0
  21. package/lib/asset-acquisition.d.ts.map +1 -0
  22. package/lib/asset-acquisition.js +175 -0
  23. package/lib/authority.d.ts +185 -0
  24. package/lib/authority.d.ts.map +1 -0
  25. package/lib/authority.js +223 -0
  26. package/lib/bindings.d.ts +144 -0
  27. package/lib/bindings.d.ts.map +1 -0
  28. package/lib/bindings.js +314 -0
  29. package/lib/builtins.d.ts +27 -0
  30. package/lib/builtins.d.ts.map +1 -0
  31. package/lib/builtins.js +37 -0
  32. package/lib/capability.d.ts +58 -0
  33. package/lib/capability.d.ts.map +1 -0
  34. package/lib/capability.js +192 -0
  35. package/lib/capture-path.d.ts +97 -0
  36. package/lib/capture-path.d.ts.map +1 -0
  37. package/lib/capture-path.js +152 -0
  38. package/lib/catalog.d.ts +37 -0
  39. package/lib/catalog.d.ts.map +1 -0
  40. package/lib/catalog.js +274 -0
  41. package/lib/contract-payload.d.ts +39 -0
  42. package/lib/contract-payload.d.ts.map +1 -0
  43. package/lib/contract-payload.js +56 -0
  44. package/lib/custom-tools/compile.d.ts +25 -0
  45. package/lib/custom-tools/compile.d.ts.map +1 -0
  46. package/lib/custom-tools/compile.js +61 -0
  47. package/lib/custom-tools/composite-executor.d.ts +42 -0
  48. package/lib/custom-tools/composite-executor.d.ts.map +1 -0
  49. package/lib/custom-tools/composite-executor.js +113 -0
  50. package/lib/custom-tools/dispatch.d.ts +28 -0
  51. package/lib/custom-tools/dispatch.d.ts.map +1 -0
  52. package/lib/custom-tools/dispatch.js +34 -0
  53. package/lib/custom-tools/http-executor.d.ts +48 -0
  54. package/lib/custom-tools/http-executor.d.ts.map +1 -0
  55. package/lib/custom-tools/http-executor.js +241 -0
  56. package/lib/custom-tools/index.d.ts +12 -0
  57. package/lib/custom-tools/index.d.ts.map +1 -0
  58. package/lib/custom-tools/index.js +12 -0
  59. package/lib/custom-tools/mcp-surface.d.ts +14 -0
  60. package/lib/custom-tools/mcp-surface.d.ts.map +1 -0
  61. package/lib/custom-tools/mcp-surface.js +41 -0
  62. package/lib/custom-tools/prompt-executor.d.ts +39 -0
  63. package/lib/custom-tools/prompt-executor.d.ts.map +1 -0
  64. package/lib/custom-tools/prompt-executor.js +59 -0
  65. package/lib/custom-tools/registry.d.ts +69 -0
  66. package/lib/custom-tools/registry.d.ts.map +1 -0
  67. package/lib/custom-tools/registry.js +130 -0
  68. package/lib/custom-tools/schema.d.ts +26 -0
  69. package/lib/custom-tools/schema.d.ts.map +1 -0
  70. package/lib/custom-tools/schema.js +375 -0
  71. package/lib/custom-tools/service.d.ts +90 -0
  72. package/lib/custom-tools/service.d.ts.map +1 -0
  73. package/lib/custom-tools/service.js +203 -0
  74. package/lib/custom-tools/store.d.ts +61 -0
  75. package/lib/custom-tools/store.d.ts.map +1 -0
  76. package/lib/custom-tools/store.js +240 -0
  77. package/lib/custom-tools/types.d.ts +131 -0
  78. package/lib/custom-tools/types.d.ts.map +1 -0
  79. package/lib/custom-tools/types.js +11 -0
  80. package/lib/decision-combine.d.ts +113 -0
  81. package/lib/decision-combine.d.ts.map +1 -0
  82. package/lib/decision-combine.js +156 -0
  83. package/lib/decision-evaluate.d.ts +185 -0
  84. package/lib/decision-evaluate.d.ts.map +1 -0
  85. package/lib/decision-evaluate.js +227 -0
  86. package/lib/deployment-coordinator.d.ts +213 -0
  87. package/lib/deployment-coordinator.d.ts.map +1 -0
  88. package/lib/deployment-coordinator.js +274 -0
  89. package/lib/diagnostics.d.ts +169 -0
  90. package/lib/diagnostics.d.ts.map +1 -0
  91. package/lib/diagnostics.js +136 -0
  92. package/lib/discovery-contracts.d.ts +14 -0
  93. package/lib/discovery-contracts.d.ts.map +1 -0
  94. package/lib/discovery-contracts.js +90 -0
  95. package/lib/discovery-describe.d.ts +35 -0
  96. package/lib/discovery-describe.d.ts.map +1 -0
  97. package/lib/discovery-describe.js +99 -0
  98. package/lib/embedding-index.d.ts +55 -0
  99. package/lib/embedding-index.d.ts.map +1 -0
  100. package/lib/embedding-index.js +126 -0
  101. package/lib/extension-dependencies.d.ts +355 -0
  102. package/lib/extension-dependencies.d.ts.map +1 -0
  103. package/lib/extension-dependencies.js +987 -0
  104. package/lib/extension-dispatch.d.ts +150 -0
  105. package/lib/extension-dispatch.d.ts.map +1 -0
  106. package/lib/extension-dispatch.js +178 -0
  107. package/lib/extension-page-state.d.ts +69 -0
  108. package/lib/extension-page-state.d.ts.map +1 -0
  109. package/lib/extension-page-state.js +82 -0
  110. package/lib/extension-registrar.d.ts +116 -0
  111. package/lib/extension-registrar.d.ts.map +1 -0
  112. package/lib/extension-registrar.js +144 -0
  113. package/lib/extensions-api.d.ts +346 -0
  114. package/lib/extensions-api.d.ts.map +1 -0
  115. package/lib/extensions-api.js +17 -0
  116. package/lib/extensions-remote.d.ts +57 -0
  117. package/lib/extensions-remote.d.ts.map +1 -0
  118. package/lib/extensions-remote.js +69 -0
  119. package/lib/extensions-service.d.ts +568 -0
  120. package/lib/extensions-service.d.ts.map +1 -0
  121. package/lib/extensions-service.js +2507 -0
  122. package/lib/harness-budgets.d.ts +158 -0
  123. package/lib/harness-budgets.d.ts.map +1 -0
  124. package/lib/harness-budgets.js +152 -0
  125. package/lib/harness-llm.d.ts +138 -0
  126. package/lib/harness-llm.d.ts.map +1 -0
  127. package/lib/harness-llm.js +218 -0
  128. package/lib/harness-serving.d.ts +115 -0
  129. package/lib/harness-serving.d.ts.map +1 -0
  130. package/lib/harness-serving.js +176 -0
  131. package/lib/headless.d.ts +97 -0
  132. package/lib/headless.d.ts.map +1 -0
  133. package/lib/headless.js +407 -0
  134. package/lib/http-acquisition.d.ts +27 -0
  135. package/lib/http-acquisition.d.ts.map +1 -0
  136. package/lib/http-acquisition.js +140 -0
  137. package/lib/index.d.ts +546 -0
  138. package/lib/index.d.ts.map +1 -0
  139. package/lib/index.js +5197 -0
  140. package/lib/invocation-accounting.d.ts +169 -0
  141. package/lib/invocation-accounting.d.ts.map +1 -0
  142. package/lib/invocation-accounting.js +148 -0
  143. package/lib/jev.d.ts +218 -0
  144. package/lib/jev.d.ts.map +1 -0
  145. package/lib/jev.js +366 -0
  146. package/lib/legacy-migration.d.ts +95 -0
  147. package/lib/legacy-migration.d.ts.map +1 -0
  148. package/lib/legacy-migration.js +429 -0
  149. package/lib/license-basis.d.ts +29 -0
  150. package/lib/license-basis.d.ts.map +1 -0
  151. package/lib/license-basis.js +58 -0
  152. package/lib/managed-workers.d.ts +158 -0
  153. package/lib/managed-workers.d.ts.map +1 -0
  154. package/lib/managed-workers.js +269 -0
  155. package/lib/mcp/auth-selection.d.ts +35 -0
  156. package/lib/mcp/auth-selection.d.ts.map +1 -0
  157. package/lib/mcp/auth-selection.js +64 -0
  158. package/lib/mcp/client-grant.d.ts +89 -0
  159. package/lib/mcp/client-grant.d.ts.map +1 -0
  160. package/lib/mcp/client-grant.js +63 -0
  161. package/lib/mcp/credential-cli.d.ts +38 -0
  162. package/lib/mcp/credential-cli.d.ts.map +1 -0
  163. package/lib/mcp/credential-cli.js +148 -0
  164. package/lib/mcp/credential-store.d.ts +143 -0
  165. package/lib/mcp/credential-store.d.ts.map +1 -0
  166. package/lib/mcp/credential-store.js +461 -0
  167. package/lib/mcp/export-policy.d.ts +25 -0
  168. package/lib/mcp/export-policy.d.ts.map +1 -0
  169. package/lib/mcp/export-policy.js +31 -0
  170. package/lib/mcp/host-binding.d.ts +144 -0
  171. package/lib/mcp/host-binding.d.ts.map +1 -0
  172. package/lib/mcp/host-binding.js +280 -0
  173. package/lib/mcp/http.d.ts +180 -0
  174. package/lib/mcp/http.d.ts.map +1 -0
  175. package/lib/mcp/http.js +602 -0
  176. package/lib/mcp/oauth.d.ts +149 -0
  177. package/lib/mcp/oauth.d.ts.map +1 -0
  178. package/lib/mcp/oauth.js +396 -0
  179. package/lib/mcp/protocol.d.ts +329 -0
  180. package/lib/mcp/protocol.d.ts.map +1 -0
  181. package/lib/mcp/protocol.js +459 -0
  182. package/lib/mcp/rate-limit.d.ts +68 -0
  183. package/lib/mcp/rate-limit.d.ts.map +1 -0
  184. package/lib/mcp/rate-limit.js +114 -0
  185. package/lib/mcp/sdk-v2.d.ts +17 -0
  186. package/lib/mcp/sdk-v2.d.ts.map +1 -0
  187. package/lib/mcp/sdk-v2.js +204 -0
  188. package/lib/mcp/server.d.ts +149 -0
  189. package/lib/mcp/server.d.ts.map +1 -0
  190. package/lib/mcp/server.js +302 -0
  191. package/lib/mcp/stdio.d.ts +80 -0
  192. package/lib/mcp/stdio.d.ts.map +1 -0
  193. package/lib/mcp/stdio.js +184 -0
  194. package/lib/mcp/subscriptions.d.ts +177 -0
  195. package/lib/mcp/subscriptions.d.ts.map +1 -0
  196. package/lib/mcp/subscriptions.js +288 -0
  197. package/lib/mcp-status.d.ts +96 -0
  198. package/lib/mcp-status.d.ts.map +1 -0
  199. package/lib/mcp-status.js +70 -0
  200. package/lib/mcp-usage.d.ts +110 -0
  201. package/lib/mcp-usage.d.ts.map +1 -0
  202. package/lib/mcp-usage.js +189 -0
  203. package/lib/model-qualification.d.ts +192 -0
  204. package/lib/model-qualification.d.ts.map +1 -0
  205. package/lib/model-qualification.js +178 -0
  206. package/lib/planning.d.ts +256 -0
  207. package/lib/planning.d.ts.map +1 -0
  208. package/lib/planning.js +471 -0
  209. package/lib/playbook.d.ts +42 -0
  210. package/lib/playbook.d.ts.map +1 -0
  211. package/lib/playbook.js +65 -0
  212. package/lib/prepared-assets.d.ts +269 -0
  213. package/lib/prepared-assets.d.ts.map +1 -0
  214. package/lib/prepared-assets.js +471 -0
  215. package/lib/provider-bridge.d.ts +107 -0
  216. package/lib/provider-bridge.d.ts.map +1 -0
  217. package/lib/provider-bridge.js +423 -0
  218. package/lib/ptc-authority.d.ts +154 -0
  219. package/lib/ptc-authority.d.ts.map +1 -0
  220. package/lib/ptc-authority.js +242 -0
  221. package/lib/ptc-confinement.d.ts +60 -0
  222. package/lib/ptc-confinement.d.ts.map +1 -0
  223. package/lib/ptc-confinement.js +212 -0
  224. package/lib/ptc-runtime.d.ts +166 -0
  225. package/lib/ptc-runtime.d.ts.map +1 -0
  226. package/lib/ptc-runtime.js +231 -0
  227. package/lib/publication.d.ts +161 -0
  228. package/lib/publication.d.ts.map +1 -0
  229. package/lib/publication.js +181 -0
  230. package/lib/receipt-store.d.ts +57 -0
  231. package/lib/receipt-store.d.ts.map +1 -0
  232. package/lib/receipt-store.js +143 -0
  233. package/lib/receipt.d.ts +231 -0
  234. package/lib/receipt.d.ts.map +1 -0
  235. package/lib/receipt.js +165 -0
  236. package/lib/registrar.d.ts +75 -0
  237. package/lib/registrar.d.ts.map +1 -0
  238. package/lib/registrar.js +152 -0
  239. package/lib/resource-governance.d.ts +204 -0
  240. package/lib/resource-governance.d.ts.map +1 -0
  241. package/lib/resource-governance.js +213 -0
  242. package/lib/server-lifecycle.d.ts +175 -0
  243. package/lib/server-lifecycle.d.ts.map +1 -0
  244. package/lib/server-lifecycle.js +269 -0
  245. package/lib/skills.d.ts +31 -0
  246. package/lib/skills.d.ts.map +1 -0
  247. package/lib/skills.js +170 -0
  248. package/lib/speech-bridge.d.ts +74 -0
  249. package/lib/speech-bridge.d.ts.map +1 -0
  250. package/lib/speech-bridge.js +115 -0
  251. package/lib/state.d.ts +100 -0
  252. package/lib/state.d.ts.map +1 -0
  253. package/lib/state.js +160 -0
  254. package/lib/title-proposal.d.ts +194 -0
  255. package/lib/title-proposal.d.ts.map +1 -0
  256. package/lib/title-proposal.js +244 -0
  257. package/lib/tool-inventory.d.ts +90 -0
  258. package/lib/tool-inventory.d.ts.map +1 -0
  259. package/lib/tool-inventory.js +102 -0
  260. package/lib/tool-mode-run.d.ts +310 -0
  261. package/lib/tool-mode-run.d.ts.map +1 -0
  262. package/lib/tool-mode-run.js +411 -0
  263. package/lib/tool-sources.d.ts +80 -0
  264. package/lib/tool-sources.d.ts.map +1 -0
  265. package/lib/tool-sources.js +123 -0
  266. package/lib/tool-usage-projection.d.ts +390 -0
  267. package/lib/tool-usage-projection.d.ts.map +1 -0
  268. package/lib/tool-usage-projection.js +1038 -0
  269. package/lib/tool-usage-report.d.ts +153 -0
  270. package/lib/tool-usage-report.d.ts.map +1 -0
  271. package/lib/tool-usage-report.js +274 -0
  272. package/lib/transport.d.ts +158 -0
  273. package/lib/transport.d.ts.map +1 -0
  274. package/lib/transport.js +332 -0
  275. package/lib/types.d.ts +134 -0
  276. package/lib/types.d.ts.map +1 -0
  277. package/lib/types.js +8 -0
  278. package/lib/update-surface.d.ts +79 -0
  279. package/lib/update-surface.d.ts.map +1 -0
  280. package/lib/update-surface.js +224 -0
  281. package/lib/version.d.ts +3 -0
  282. package/lib/version.d.ts.map +1 -0
  283. package/lib/version.js +27 -0
  284. package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.d.ts +13 -0
  285. package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.d.ts.map +1 -0
  286. package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.js +85 -0
  287. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts +16 -0
  288. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts.map +1 -0
  289. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.js +87 -0
  290. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
  291. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
  292. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
  293. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts +20 -0
  294. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts.map +1 -0
  295. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.js +112 -0
  296. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
  297. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
  298. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
  299. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
  300. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
  301. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
  302. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts +82 -0
  303. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -0
  304. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +274 -0
  305. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +26 -0
  306. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -0
  307. package/node_modules/@try-works/tool-mode-contracts/lib/index.js +53 -0
  308. package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts +133 -0
  309. package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts.map +1 -0
  310. package/node_modules/@try-works/tool-mode-contracts/lib/meta.js +64 -0
  311. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +121 -0
  312. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -0
  313. package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +246 -0
  314. package/node_modules/@try-works/tool-mode-contracts/package.json +35 -0
  315. package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
  316. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
  317. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
  318. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
  319. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +86 -0
  320. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
  321. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +145 -0
  322. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
  323. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
  324. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
  325. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
  326. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
  327. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
  328. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +33 -0
  329. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
  330. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +33 -0
  331. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
  332. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
  333. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +191 -0
  334. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +137 -0
  335. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
  336. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +349 -0
  337. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +274 -0
  338. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
  339. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +932 -0
  340. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
  341. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
  342. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
  343. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
  344. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
  345. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
  346. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
  347. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
  348. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
  349. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
  350. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
  351. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +299 -0
  352. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +395 -0
  353. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
  354. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +839 -0
  355. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts +44 -0
  356. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts.map +1 -0
  357. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.js +255 -0
  358. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
  359. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
  360. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
  361. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
  362. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
  363. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
  364. package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.d.ts +221 -0
  365. package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.d.ts.map +1 -0
  366. package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.js +188 -0
  367. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
  368. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
  369. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
  370. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
  371. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
  372. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
  373. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
  374. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
  375. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
  376. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +128 -0
  377. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
  378. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
  379. package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.d.ts +41 -0
  380. package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.d.ts.map +1 -0
  381. package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.js +52 -0
  382. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
  383. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
  384. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
  385. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +157 -0
  386. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
  387. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +688 -0
  388. package/node_modules/@try-works/tool-mode-extension-sdk/package.json +54 -0
  389. package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
  390. package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
  391. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +460 -0
  392. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
  393. package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +647 -0
  394. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +61 -0
  395. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
  396. package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +1106 -0
  397. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
  398. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
  399. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +205 -0
  400. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
  401. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
  402. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
  403. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +119 -0
  404. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
  405. package/node_modules/@try-works/tool-mode-recipes/lib/images.js +201 -0
  406. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
  407. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
  408. package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
  409. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +345 -0
  410. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
  411. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1465 -0
  412. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
  413. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
  414. package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
  415. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +231 -0
  416. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
  417. package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +435 -0
  418. package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
  419. package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
  420. package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
  421. package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
  422. package/package.json +127 -4
  423. package/remote/spec.mjs +993 -0
  424. package/remote/typert.host.mjs +14 -0
  425. package/remote/typert.remote-client.mjs +16 -0
@@ -0,0 +1,510 @@
1
+ /**
2
+ * SEC-09 — the approval state machine for management-sensitive changes.
3
+ *
4
+ * A management-sensitive mutation (enabling a model, installing/replacing an
5
+ * extension, revoking a credential, changing a model URL or provider, …) must pass an
6
+ * EXPLICIT operator decision before it happens. This module is the standalone state
7
+ * machine for that flow; it deliberately owns no host wiring and no I/O:
8
+ *
9
+ * pending ──approve──▶ approved ──commit()──▶ committed (terminal)
10
+ * │ │
11
+ * ├──deny──▶ denied └── TTL ──▶ expired (terminal)
12
+ * └── TTL ──▶ expired
13
+ *
14
+ * Properties this module guarantees:
15
+ * - **No commit without an approval.** `commit()` on a pending request throws
16
+ * `approval/pending` SYNCHRONOUSLY; there is no promise to await, so a deployment
17
+ * with no approval UI fails promptly instead of hanging.
18
+ * - **One-shot commit.** The first successful commit moves the record to
19
+ * `committed`; every later commit throws `approval/already-committed`.
20
+ * - **Idempotent decisions.** Repeating the SAME decision returns the unchanged
21
+ * record (including its original decision timestamp); the opposite decision after a
22
+ * decision is `approval/already-decided`.
23
+ * - **Scope-bound.** The request stores the exact decision scope; a commit must name
24
+ * exactly that scope. An approval for one extension or one tool cannot authorize
25
+ * another.
26
+ * - **TTL on an injected clock.** Expiry is evaluated lazily on every read/mutation
27
+ * against `now()`; tests never depend on wall time.
28
+ * - **Plain-JSON durable-safe state.** Records contain only strings, numbers, nulls,
29
+ * booleans and one nested scope object. Unknown caller fields are dropped, so a
30
+ * token or API key passed by mistake is never stored or re-serialized.
31
+ * - **Deterministic ids.** By default the id is a hash of the request content and the
32
+ * injected request time, so the same request at the same instant has the same id.
33
+ *
34
+ * @module @try-works/dsh-tool-mode/approval
35
+ */
36
+ import { createHash } from 'node:crypto';
37
+ /** Every management-sensitive request kind this module admits. */
38
+ export const APPROVAL_KINDS = [
39
+ 'model-enable',
40
+ 'model-disable',
41
+ 'model-reset',
42
+ 'extension-install',
43
+ 'extension-activate',
44
+ 'extension-deactivate',
45
+ 'extension-uninstall',
46
+ 'extension-prepare',
47
+ 'extension-commit',
48
+ 'extension-rollback',
49
+ 'credential-revoke',
50
+ 'model-url-change',
51
+ 'model-provider-change',
52
+ ];
53
+ /** The terminal/non-terminal states a record can be in. */
54
+ export const APPROVAL_STATES = ['pending', 'approved', 'denied', 'committed', 'expired'];
55
+ /** What an approval is scoped to. */
56
+ export const APPROVAL_SCOPE_KINDS = ['model', 'extension', 'tool', 'credential', 'provider'];
57
+ /** A refusal with a stable machine-readable code. */
58
+ export class ApprovalError extends Error {
59
+ /** The stable refusal code. */
60
+ code;
61
+ /**
62
+ * @param code - the stable refusal code.
63
+ * @param message - the concrete explanation (the code is prefixed).
64
+ */
65
+ constructor(code, message) {
66
+ super(`approval/${code.replace(/^approval\//, '')}: ${message}`);
67
+ this.name = 'ApprovalError';
68
+ this.code = code;
69
+ }
70
+ }
71
+ /** The scope kinds each request kind may cover. */
72
+ const SCOPE_BY_KIND = Object.freeze({
73
+ 'model-enable': ['model', 'tool'],
74
+ 'model-disable': ['model', 'tool'],
75
+ 'model-reset': ['model', 'tool'],
76
+ 'model-url-change': ['model', 'tool'],
77
+ 'model-provider-change': ['model', 'provider', 'tool'],
78
+ 'extension-install': ['extension', 'tool'],
79
+ 'extension-activate': ['extension', 'tool'],
80
+ 'extension-deactivate': ['extension', 'tool'],
81
+ 'extension-uninstall': ['extension', 'tool'],
82
+ 'extension-prepare': ['extension', 'tool'],
83
+ 'extension-commit': ['extension', 'tool'],
84
+ 'extension-rollback': ['extension', 'tool'],
85
+ 'credential-revoke': ['credential'],
86
+ });
87
+ /** Five minutes: long enough for an operator, short enough to age out. */
88
+ const DEFAULT_TTL_MS = 5 * 60 * 1000;
89
+ /** Seven days: an absurd TTL is a configuration mistake, not a longer approval. */
90
+ const MAX_TTL_MS = 7 * 24 * 60 * 60 * 1000;
91
+ const MAX_ID_LENGTH = 200;
92
+ const MAX_OPERATOR_LENGTH = 200;
93
+ const MAX_REASON_LENGTH = 2000;
94
+ const MAX_SCOPE_ID_LENGTH = 200;
95
+ const ID_PATTERN = /^apr_[0-9a-f]{16}$/;
96
+ /** A plain object (arrays and null excluded). */
97
+ function isRecord(value) {
98
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
99
+ }
100
+ /** A finite timestamp. */
101
+ function isTimestamp(value) {
102
+ return typeof value === 'number' && Number.isFinite(value);
103
+ }
104
+ /** Trim and bound one required text field. */
105
+ function requireText(value, field, maxLength) {
106
+ if (typeof value !== 'string') {
107
+ throw new ApprovalError('approval/invalid-request', `${field} must be a string`);
108
+ }
109
+ const trimmed = value.trim();
110
+ if (trimmed.length === 0) {
111
+ throw new ApprovalError('approval/invalid-request', `${field} must not be empty`);
112
+ }
113
+ if (trimmed.length > maxLength) {
114
+ throw new ApprovalError('approval/invalid-request', `${field} must be at most ${String(maxLength)} characters`);
115
+ }
116
+ return trimmed;
117
+ }
118
+ /** Validate and normalise one scope. */
119
+ function normalizeScope(value, field = 'scope') {
120
+ if (!isRecord(value)) {
121
+ throw new ApprovalError('approval/invalid-request', `${field} must be an object`);
122
+ }
123
+ const kind = value['kind'];
124
+ // SAFETY: the value is a plain string and the membership test below proves it is
125
+ // one of the literal scope kinds before the assertion is reached.
126
+ const scopeKinds = APPROVAL_SCOPE_KINDS;
127
+ if (typeof kind !== 'string' || !scopeKinds.includes(kind)) {
128
+ throw new ApprovalError('approval/invalid-request', `${field}.kind must be one of ${APPROVAL_SCOPE_KINDS.join(', ')}`);
129
+ }
130
+ const id = requireText(value['id'], `${field}.id`, MAX_SCOPE_ID_LENGTH);
131
+ // SAFETY: membership in APPROVAL_SCOPE_KINDS was established immediately above.
132
+ return { kind: kind, id };
133
+ }
134
+ /** Validate one request kind and its scope together. */
135
+ function normalizeKindAndScope(kindValue, scopeValue) {
136
+ const kind = kindValue;
137
+ // SAFETY: the value is a plain string and the membership test below proves it is
138
+ // one of the literal approval kinds before any assertion is reached.
139
+ const approvalKinds = APPROVAL_KINDS;
140
+ if (typeof kind !== 'string' || !approvalKinds.includes(kind)) {
141
+ throw new ApprovalError('approval/invalid-request', `kind must be one of ${APPROVAL_KINDS.join(', ')}`);
142
+ }
143
+ const scope = normalizeScope(scopeValue);
144
+ // SAFETY: membership in APPROVAL_KINDS was established immediately above.
145
+ const permitted = SCOPE_BY_KIND[kind];
146
+ if (!permitted.includes(scope.kind)) {
147
+ throw new ApprovalError('approval/invalid-request', `${kind} cannot be scoped to ${scope.kind}; permitted scope kinds are ${permitted.join(', ')}`);
148
+ }
149
+ // SAFETY: membership in APPROVAL_KINDS was established immediately above.
150
+ return { kind: kind, scope };
151
+ }
152
+ /** Validate a TTL, or return undefined when absent. */
153
+ function normalizeTtl(value) {
154
+ if (value === undefined)
155
+ return undefined;
156
+ if (!isTimestamp(value) || value <= 0 || value > MAX_TTL_MS) {
157
+ throw new ApprovalError('approval/invalid-request', `ttlMs must be a positive number no greater than ${String(MAX_TTL_MS)}`);
158
+ }
159
+ return Math.floor(value);
160
+ }
161
+ /** The deterministic default id: request content + request time. */
162
+ function defaultIdFactory(input, requestedAt) {
163
+ const digest = createHash('sha256')
164
+ .update(JSON.stringify([input.kind, input.scope.kind, input.scope.id, input.operator, input.reason, requestedAt]))
165
+ .digest('hex');
166
+ return `apr_${digest.slice(0, 16)}`;
167
+ }
168
+ /** Validate a restored record; unknown keys are dropped by construction. */
169
+ function restoreRecord(value, index) {
170
+ const where = `records[${String(index)}]`;
171
+ if (!isRecord(value))
172
+ throw new ApprovalError('approval/invalid-serialization', `${where} must be an object`);
173
+ const id = value['id'];
174
+ if (typeof id !== 'string' || id.length === 0 || id.length > MAX_ID_LENGTH) {
175
+ throw new ApprovalError('approval/invalid-serialization', `${where}.id must be a non-empty bounded string`);
176
+ }
177
+ const { kind, scope } = (() => {
178
+ try {
179
+ return normalizeKindAndScope(value['kind'], value['scope']);
180
+ }
181
+ catch (error) {
182
+ throw new ApprovalError('approval/invalid-serialization', `${where} has an invalid kind/scope: ${error instanceof Error ? error.message : String(error)}`);
183
+ }
184
+ })();
185
+ const operator = (() => {
186
+ try {
187
+ return requireText(value['operator'], `${where}.operator`, MAX_OPERATOR_LENGTH);
188
+ }
189
+ catch (error) {
190
+ throw new ApprovalError('approval/invalid-serialization', error instanceof Error ? error.message : String(error));
191
+ }
192
+ })();
193
+ const reason = (() => {
194
+ try {
195
+ return requireText(value['reason'], `${where}.reason`, MAX_REASON_LENGTH);
196
+ }
197
+ catch (error) {
198
+ throw new ApprovalError('approval/invalid-serialization', error instanceof Error ? error.message : String(error));
199
+ }
200
+ })();
201
+ const requestedAt = value['requestedAt'];
202
+ const expiresAt = value['expiresAt'];
203
+ if (!isTimestamp(requestedAt) || !isTimestamp(expiresAt) || expiresAt <= requestedAt) {
204
+ throw new ApprovalError('approval/invalid-serialization', `${where} has invalid timestamps`);
205
+ }
206
+ const state = value['state'];
207
+ // SAFETY: the value is a plain string and the membership test below proves it is a
208
+ // declared approval state before the assertion is reached.
209
+ const states = APPROVAL_STATES;
210
+ if (typeof state !== 'string' || !states.includes(state)) {
211
+ throw new ApprovalError('approval/invalid-serialization', `${where}.state must be one of ${APPROVAL_STATES.join(', ')}`);
212
+ }
213
+ const decidedAt = value['decidedAt'];
214
+ const decidedBy = value['decidedBy'];
215
+ const decisionReason = value['decisionReason'];
216
+ const committedAt = value['committedAt'];
217
+ if (!(decidedAt === null || isTimestamp(decidedAt))) {
218
+ throw new ApprovalError('approval/invalid-serialization', `${where}.decidedAt must be a timestamp or null`);
219
+ }
220
+ if (!(decidedBy === null || (typeof decidedBy === 'string' && decidedBy.length > 0))) {
221
+ throw new ApprovalError('approval/invalid-serialization', `${where}.decidedBy must be a non-empty string or null`);
222
+ }
223
+ if ((decidedAt === null) !== (decidedBy === null)) {
224
+ throw new ApprovalError('approval/invalid-serialization', `${where} must carry decidedAt and decidedBy together`);
225
+ }
226
+ if (!(decisionReason === null || typeof decisionReason === 'string')) {
227
+ throw new ApprovalError('approval/invalid-serialization', `${where}.decisionReason must be a string or null`);
228
+ }
229
+ if (!(committedAt === null || isTimestamp(committedAt))) {
230
+ throw new ApprovalError('approval/invalid-serialization', `${where}.committedAt must be a timestamp or null`);
231
+ }
232
+ if (state === 'committed' && committedAt === null) {
233
+ throw new ApprovalError('approval/invalid-serialization', `${where} is committed without a commit time`);
234
+ }
235
+ if (state !== 'committed' && committedAt !== null) {
236
+ throw new ApprovalError('approval/invalid-serialization', `${where} has a commit time but is not committed`);
237
+ }
238
+ if ((state === 'approved' || state === 'denied' || state === 'committed') && decidedAt === null) {
239
+ throw new ApprovalError('approval/invalid-serialization', `${where} is ${state} without a decision`);
240
+ }
241
+ if (state === 'pending' && decidedAt !== null) {
242
+ throw new ApprovalError('approval/invalid-serialization', `${where} is pending but already has a decision`);
243
+ }
244
+ // SAFETY: membership in APPROVAL_STATES was established above; the state-dependent
245
+ // invariants below are checked before this record is returned.
246
+ return {
247
+ id,
248
+ kind,
249
+ scope,
250
+ operator,
251
+ reason,
252
+ requestedAt,
253
+ expiresAt,
254
+ state: state,
255
+ decidedAt,
256
+ decidedBy,
257
+ decisionReason,
258
+ committedAt,
259
+ };
260
+ }
261
+ /**
262
+ * The in-memory approval store. One instance per host process, restored from its
263
+ * snapshot at boot (see the wiring contract in the task report).
264
+ */
265
+ export class ApprovalStore {
266
+ #now;
267
+ #defaultTtlMs;
268
+ #idFactory;
269
+ #records = new Map();
270
+ /**
271
+ * @param options - clock, default TTL and id derivation (all injectable).
272
+ */
273
+ constructor(options = {}) {
274
+ const now = options.now ?? Date.now;
275
+ if (typeof now !== 'function')
276
+ throw new ApprovalError('approval/invalid-request', 'now must be a function');
277
+ this.#now = now;
278
+ const ttl = options.defaultTtlMs ?? DEFAULT_TTL_MS;
279
+ if (!isTimestamp(ttl) || ttl <= 0 || ttl > MAX_TTL_MS) {
280
+ throw new ApprovalError('approval/invalid-request', `defaultTtlMs must be positive and no greater than ${String(MAX_TTL_MS)}`);
281
+ }
282
+ this.#defaultTtlMs = Math.floor(ttl);
283
+ this.#idFactory = options.idFactory ?? defaultIdFactory;
284
+ }
285
+ /** The default lifetime new requests receive. */
286
+ get defaultTtlMs() {
287
+ return this.#defaultTtlMs;
288
+ }
289
+ /**
290
+ * Record a pending request.
291
+ *
292
+ * A repeated request (same content at the same injected instant) returns the
293
+ * EXISTING record rather than resetting its TTL or decision.
294
+ * @param input - the request facts (kind, scope, operator, reason, optional TTL).
295
+ * @returns the pending record (a plain-JSON copy).
296
+ */
297
+ request(input) {
298
+ if (!isRecord(input))
299
+ throw new ApprovalError('approval/invalid-request', 'a request must be an object');
300
+ const { kind, scope } = normalizeKindAndScope(input.kind, input.scope);
301
+ const operator = requireText(input.operator, 'operator', MAX_OPERATOR_LENGTH);
302
+ const reason = requireText(input.reason, 'reason', MAX_REASON_LENGTH);
303
+ const ttl = normalizeTtl(input.ttlMs) ?? this.#defaultTtlMs;
304
+ const requestedAt = this.#now();
305
+ if (!isTimestamp(requestedAt))
306
+ throw new ApprovalError('approval/invalid-request', 'now() must return a finite timestamp');
307
+ const id = this.#idFactory({ kind, scope, operator, reason }, requestedAt);
308
+ if (typeof id !== 'string' || id.length === 0 || id.length > MAX_ID_LENGTH) {
309
+ throw new ApprovalError('approval/invalid-request', 'the id factory must return a non-empty bounded string');
310
+ }
311
+ const existing = this.#records.get(id);
312
+ if (existing !== undefined)
313
+ return this.#view(existing);
314
+ const record = {
315
+ id,
316
+ kind,
317
+ scope,
318
+ operator,
319
+ reason,
320
+ requestedAt,
321
+ expiresAt: requestedAt + ttl,
322
+ state: 'pending',
323
+ decidedAt: null,
324
+ decidedBy: null,
325
+ decisionReason: null,
326
+ committedAt: null,
327
+ };
328
+ this.#records.set(id, record);
329
+ return this.#view(record);
330
+ }
331
+ /**
332
+ * Read one record, applying lazy TTL expiry.
333
+ * @param id - the approval id.
334
+ * @returns the record (a plain-JSON copy).
335
+ */
336
+ describe(id) {
337
+ return this.#view(this.#require(id));
338
+ }
339
+ /** Every record, oldest first (expiry applied). */
340
+ list() {
341
+ return [...this.#records.values()]
342
+ .map(record => this.#view(record))
343
+ .sort((left, right) => left.requestedAt - right.requestedAt || left.id.localeCompare(right.id));
344
+ }
345
+ /**
346
+ * Apply an explicit operator decision.
347
+ *
348
+ * Repeating the SAME decision is idempotent and returns the unchanged record; the
349
+ * opposite decision after a decision is `approval/already-decided`.
350
+ * @param id - the approval id.
351
+ * @param decision - approve/deny, the decider and an optional note.
352
+ * @returns the decided record.
353
+ */
354
+ decide(id, decision) {
355
+ const record = this.#require(id);
356
+ this.#expire(record);
357
+ if (!isRecord(decision) || typeof decision.approve !== 'boolean') {
358
+ throw new ApprovalError('approval/invalid-request', 'a decision must carry a boolean approve');
359
+ }
360
+ if (record.state === 'expired') {
361
+ throw new ApprovalError('approval/expired', `request ${record.id} expired at ${String(record.expiresAt)}; it cannot be decided`);
362
+ }
363
+ if (record.state === 'committed') {
364
+ throw new ApprovalError('approval/already-committed', `request ${record.id} was already committed at ${String(record.committedAt)}; it cannot be decided`);
365
+ }
366
+ const wanted = decision.approve ? 'approved' : 'denied';
367
+ if (record.state === wanted)
368
+ return this.#copy(record);
369
+ if (record.state === 'approved' || record.state === 'denied') {
370
+ throw new ApprovalError('approval/already-decided', `request ${record.id} is already ${record.state}; the opposite decision is refused`);
371
+ }
372
+ const decidedBy = requireText(decision.decidedBy, 'decidedBy', MAX_OPERATOR_LENGTH);
373
+ const decisionReason = decision.reason === undefined ? null : requireText(decision.reason, 'decision reason', MAX_REASON_LENGTH);
374
+ const decidedAt = this.#now();
375
+ if (!isTimestamp(decidedAt))
376
+ throw new ApprovalError('approval/invalid-request', 'now() must return a finite timestamp');
377
+ record.state = wanted;
378
+ record.decidedAt = decidedAt;
379
+ record.decidedBy = decidedBy;
380
+ record.decisionReason = decisionReason;
381
+ return this.#copy(record);
382
+ }
383
+ /**
384
+ * Consume an approved request for exactly its recorded scope.
385
+ *
386
+ * One-shot: the first successful call commits; every later call (and any call on a
387
+ * pending, denied or expired record) throws a named error WITHOUT waiting.
388
+ * @param id - the approval id.
389
+ * @param scope - the exact subject the caller is about to mutate.
390
+ * @returns the committed record.
391
+ */
392
+ commit(id, scope) {
393
+ const record = this.#require(id);
394
+ this.#expire(record);
395
+ if (record.state === 'pending') {
396
+ throw new ApprovalError('approval/pending', `request ${record.id} is pending; no operator has approved it`);
397
+ }
398
+ if (record.state === 'denied') {
399
+ throw new ApprovalError('approval/denied', `request ${record.id} was denied by ${String(record.decidedBy)}`);
400
+ }
401
+ if (record.state === 'expired') {
402
+ throw new ApprovalError('approval/expired', `request ${record.id} expired at ${String(record.expiresAt)}; it cannot be committed`);
403
+ }
404
+ if (record.state === 'committed') {
405
+ throw new ApprovalError('approval/already-committed', `request ${record.id} was already committed at ${String(record.committedAt)}`);
406
+ }
407
+ const requested = normalizeScope(scope, 'commit scope');
408
+ if (requested.kind !== record.scope.kind || requested.id !== record.scope.id) {
409
+ throw new ApprovalError('approval/scope-mismatch', `request ${record.id} is approved for ${record.scope.kind} ${record.scope.id}, not ${requested.kind} ${requested.id}`);
410
+ }
411
+ const committedAt = this.#now();
412
+ if (!isTimestamp(committedAt))
413
+ throw new ApprovalError('approval/invalid-request', 'now() must return a finite timestamp');
414
+ record.state = 'committed';
415
+ record.committedAt = committedAt;
416
+ return this.#copy(record);
417
+ }
418
+ /**
419
+ * The durable snapshot. Only the declared fields are serialized, so a caller that
420
+ * passed a token by mistake cannot leak it through this channel.
421
+ * @returns a plain-JSON snapshot.
422
+ */
423
+ toJSON() {
424
+ return {
425
+ version: 1,
426
+ defaultTtlMs: this.#defaultTtlMs,
427
+ records: this.list().map(record => this.#copy(record)),
428
+ };
429
+ }
430
+ /**
431
+ * Restore a store from {@link toJSON} output.
432
+ * @param value - the parsed snapshot.
433
+ * @param options - clock, optional TTL override and optional id factory.
434
+ * @returns the restored store.
435
+ */
436
+ static fromJSON(value, options = {}) {
437
+ if (!isRecord(value)) {
438
+ throw new ApprovalError('approval/invalid-serialization', 'snapshot must be an object with version 1 and a records array');
439
+ }
440
+ const version = value['version'];
441
+ const rawRecords = value['records'];
442
+ const snapshotTtl = value['defaultTtlMs'];
443
+ if (version !== 1 || !Array.isArray(rawRecords)) {
444
+ throw new ApprovalError('approval/invalid-serialization', 'snapshot must be an object with version 1 and a records array');
445
+ }
446
+ if (!isTimestamp(snapshotTtl) || snapshotTtl <= 0 || snapshotTtl > MAX_TTL_MS) {
447
+ throw new ApprovalError('approval/invalid-serialization', 'snapshot defaultTtlMs must be a valid TTL');
448
+ }
449
+ let store;
450
+ try {
451
+ store = new ApprovalStore({ ...options, defaultTtlMs: options.defaultTtlMs ?? snapshotTtl });
452
+ }
453
+ catch (error) {
454
+ throw new ApprovalError('approval/invalid-serialization', error instanceof Error ? error.message : String(error));
455
+ }
456
+ for (const [index, raw] of rawRecords.entries()) {
457
+ const record = restoreRecord(raw, index);
458
+ if (store.#records.has(record.id)) {
459
+ throw new ApprovalError('approval/invalid-serialization', `duplicate record id ${record.id}`);
460
+ }
461
+ store.#records.set(record.id, record);
462
+ }
463
+ return store;
464
+ }
465
+ /** Look up a record or throw the named unknown-id refusal. */
466
+ #require(id) {
467
+ if (typeof id !== 'string' || id.length === 0) {
468
+ throw new ApprovalError('approval/invalid-request', 'an approval id must be a non-empty string');
469
+ }
470
+ const record = this.#records.get(id);
471
+ if (record === undefined)
472
+ throw new ApprovalError('approval/unknown-id', `no approval record has id ${id}`);
473
+ return record;
474
+ }
475
+ /** Apply lazy TTL expiry to pending/approved records. */
476
+ #expire(record) {
477
+ if (record.state !== 'pending' && record.state !== 'approved')
478
+ return;
479
+ const now = this.#now();
480
+ if (isTimestamp(now) && now >= record.expiresAt)
481
+ record.state = 'expired';
482
+ }
483
+ /** A plain-JSON view, with expiry applied. */
484
+ #view(record) {
485
+ this.#expire(record);
486
+ return this.#copy(record);
487
+ }
488
+ /** A deep, plain-JSON copy of one record. */
489
+ #copy(record) {
490
+ return {
491
+ id: record.id,
492
+ kind: record.kind,
493
+ scope: { kind: record.scope.kind, id: record.scope.id },
494
+ operator: record.operator,
495
+ reason: record.reason,
496
+ requestedAt: record.requestedAt,
497
+ expiresAt: record.expiresAt,
498
+ state: record.state,
499
+ decidedAt: record.decidedAt,
500
+ decidedBy: record.decidedBy,
501
+ decisionReason: record.decisionReason,
502
+ committedAt: record.committedAt,
503
+ };
504
+ }
505
+ }
506
+ /** Whether a restored/default id has the module's deterministic shape. */
507
+ export function isDeterministicApprovalId(id) {
508
+ return typeof id === 'string' && ID_PATTERN.test(id);
509
+ }
510
+ //# sourceMappingURL=approval.js.map
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Verified atomic asset acquisition (RES-03, RES-07).
3
+ *
4
+ * The requirement's rules are all about what must NOT be observable:
5
+ *
6
+ * - **A partial download must never be usable.** Bytes are written to a temporary
7
+ * sibling, verified against the expected digest, and only then renamed into place.
8
+ * A file at the final path is therefore either absent or complete and correct —
9
+ * which is why the temp file is a sibling rather than somewhere else: a rename
10
+ * within one directory is atomic, and one across filesystems is not.
11
+ * - **A failed or interrupted preparation cannot become ready.** A digest mismatch
12
+ * deletes the partial rather than keeping it for a retry that would resume from
13
+ * bytes already known to be wrong.
14
+ * - **Uninstall and purge are separate** (RES-03). Acquisition records ownership; it
15
+ * never deletes. Deletion is `purgeCandidates`, which refuses to remove an asset
16
+ * another owner still holds.
17
+ * - **No source changes or binary builds on the end-user machine.** This acquires
18
+ * pinned bytes; there is no compile step here to disable.
19
+ *
20
+ * Everything that touches the network or the filesystem is INJECTED, so the failure
21
+ * paths — which are the ones that matter and the ones a real download makes hard to
22
+ * reach — are exercised by test.
23
+ *
24
+ * @module @try-works/dsh-tool-mode/asset-acquisition
25
+ */
26
+ import type { PlannedAsset } from './deployment-coordinator.ts';
27
+ /** Where an asset's bytes come from. */
28
+ export interface AcquisitionSource {
29
+ /**
30
+ * Fetch a byte range.
31
+ *
32
+ * `from` is the offset to resume from; `to` is inclusive. A source that cannot
33
+ * serve ranges reports `supportsRanges: false`, and the caller then restarts rather
34
+ * than assuming a partial is resumable.
35
+ * @param asset - the asset to fetch.
36
+ * @param from - the first byte to fetch.
37
+ * @param to - the last byte to fetch, inclusive.
38
+ * @param signal - cancellation.
39
+ * @returns the bytes.
40
+ */
41
+ fetchRange(asset: PlannedAsset, from: number, to: number, signal: AbortSignal): Promise<Uint8Array>;
42
+ /** Whether this source can serve byte ranges, which resumability depends on. */
43
+ readonly supportsRanges: boolean;
44
+ }
45
+ /** The filesystem operations acquisition needs. */
46
+ export interface AcquisitionStore {
47
+ /** Write bytes to a path, creating it if absent. */
48
+ write(path: string, bytes: Uint8Array): void;
49
+ /** Read a path's bytes, or undefined when absent. */
50
+ read(path: string): Uint8Array | undefined;
51
+ /** The size of a path in bytes, or 0 when absent. */
52
+ sizeOf(path: string): number;
53
+ /** Rename, which must be atomic within a directory. */
54
+ rename(from: string, to: string): void;
55
+ /** Remove a path, ignoring its absence. */
56
+ remove(path: string): void;
57
+ /** Whether a path exists. */
58
+ exists(path: string): boolean;
59
+ }
60
+ /** The outcome of an acquisition. */
61
+ export type AcquisitionResult = {
62
+ readonly acquired: true;
63
+ /** The content-addressed path the bytes now occupy. */
64
+ readonly path: string;
65
+ /** The verified digest. */
66
+ readonly digest: string;
67
+ /** How many bytes were transferred, which is less than the size after a resume. */
68
+ readonly transferredBytes: number;
69
+ /** Whether an existing partial was resumed. */
70
+ readonly resumed: boolean;
71
+ } | {
72
+ readonly acquired: false;
73
+ /** The reason, naming whether the bytes were wrong or the transfer failed. */
74
+ readonly reason: string;
75
+ /** Whether a retry could succeed. */
76
+ readonly retryable: boolean;
77
+ };
78
+ /**
79
+ * Whether two hex digests name the same content.
80
+ *
81
+ * HEX CASE IS NOT SEMANTIC. `crypto` emits lower case, while an extension lock may
82
+ * record either case (Laya's records upper case). Comparing the raw strings rejected
83
+ * a correctly seeded blob, so the acquisition fell through to the lock's prose source
84
+ * and failed with `Failed to parse URL` even though the verified bytes were on disk.
85
+ * @param left - one hex digest.
86
+ * @param right - the other hex digest.
87
+ * @returns true when they differ only in case.
88
+ */
89
+ export declare function sameDigest(left: string, right: string): boolean;
90
+ /**
91
+ * Acquire one asset, atomically and verified (RES-03).
92
+ *
93
+ * @param asset - the planned asset.
94
+ * @param options - the store, the source, the root and a cancellation signal.
95
+ * @returns the result, which never leaves a partial at the final path.
96
+ */
97
+ export declare function acquireAsset(asset: PlannedAsset, options: {
98
+ readonly store: AcquisitionStore;
99
+ readonly source: AcquisitionSource;
100
+ /** The directory assets are content-addressed under. */
101
+ readonly root: string;
102
+ readonly signal: AbortSignal;
103
+ /** Transfer chunk size; bounded so a large asset does not need one huge buffer. */
104
+ readonly chunkBytes?: number;
105
+ }): Promise<AcquisitionResult>;
106
+ /**
107
+ * A declared memory admission estimate (RES-07).
108
+ *
109
+ * RES-07 requires ENFORCED and ESTIMATED limits to be reported SEPARATELY, because
110
+ * conflating them is how a V8 heap cap gets mistaken for a process-tree cap: the heap
111
+ * cap bounds JavaScript objects and says nothing about the native memory an inference
112
+ * engine allocates outside it.
113
+ */
114
+ export interface MemoryEstimate {
115
+ /** Bytes the host will refuse to exceed, as far as it can enforce. */
116
+ readonly enforcedBytes: number | null;
117
+ /** What the deployment is expected to use, which is an estimate and not a bound. */
118
+ readonly estimatedBytes: number;
119
+ /**
120
+ * What the enforced figure actually covers.
121
+ *
122
+ * Named rather than implied, so a reader can tell a heap cap from a process-tree cap
123
+ * without reading the implementation.
124
+ */
125
+ readonly enforcedScope: 'process-tree' | 'worker' | 'v8-heap-only' | 'none';
126
+ /** Whether the estimate has been measured rather than predicted. */
127
+ readonly measured: boolean;
128
+ }
129
+ /**
130
+ * Describe a memory admission, without overstating what is enforced (RES-07).
131
+ * @param input - the enforced and estimated figures.
132
+ * @returns the estimate, with the scope stated.
133
+ */
134
+ export declare function describeMemory(input: {
135
+ readonly enforcedBytes: number | null;
136
+ readonly estimatedBytes: number;
137
+ readonly enforcedScope: MemoryEstimate['enforcedScope'];
138
+ readonly measured?: boolean;
139
+ }): MemoryEstimate;
140
+ /**
141
+ * Whether an enforced limit actually bounds the whole process tree (RES-07).
142
+ *
143
+ * A V8 heap cap does NOT, and treating it as though it did is the specific mistake the
144
+ * requirement names.
145
+ * @param estimate - the estimate.
146
+ * @returns whether the enforcement covers the process tree.
147
+ */
148
+ export declare function boundsProcessTree(estimate: MemoryEstimate): boolean;
149
+ //# sourceMappingURL=asset-acquisition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-acquisition.d.ts","sourceRoot":"","sources":["../src/asset-acquisition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAE/D,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAChC;;;;;;;;;;;OAWG;IACH,UAAU,CACR,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,CAAC,CAAA;IACtB,gFAAgF;IAChF,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;CACjC;AAED,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IAC5C,qDAAqD;IACrD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;IAC1C,qDAAqD;IACrD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5B,uDAAuD;IACvD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,2CAA2C;IAC3C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,6BAA6B;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qCAAqC;AACrC,MAAM,MAAM,iBAAiB,GACzB;IACA,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;IACvB,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,mFAAmF;IACnF,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B,GACC;IACA,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAA;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B,CAAA;AAsBH;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE;IACP,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;IAClC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,GACA,OAAO,CAAC,iBAAiB,CAAC,CA+E5B;AAWD;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,oFAAoF;IACpF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,cAAc,GAAG,QAAQ,GAAG,cAAc,GAAG,MAAM,CAAA;IAC3E,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAC5B,GAAG,cAAc,CAOjB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAEnE"}