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

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 (432) hide show
  1. package/LICENSE +205 -0
  2. package/README.md +303 -2
  3. package/bin/dsh-tool-mode-credentials.mjs +20 -0
  4. package/bin/dsh-tool-mode-mcp-stdio.mjs +80 -0
  5. package/bin/dsh-tool-mode.mjs +211 -0
  6. package/builtins.lock.json +26 -0
  7. package/catalog/desert-ant-models.json +693 -0
  8. package/catalog/playbooks.json +531 -0
  9. package/client/client.model-tools.js +1910 -0
  10. package/client/index.js +4158 -0
  11. package/cordis.patch.yml +39 -0
  12. package/lib/adapters/index.d.ts +61 -0
  13. package/lib/adapters/index.d.ts.map +1 -0
  14. package/lib/adapters/index.js +82 -0
  15. package/lib/adapters/types.d.ts +106 -0
  16. package/lib/adapters/types.d.ts.map +1 -0
  17. package/lib/adapters/types.js +85 -0
  18. package/lib/approval.d.ts +189 -0
  19. package/lib/approval.d.ts.map +1 -0
  20. package/lib/approval.js +510 -0
  21. package/lib/asset-acquisition.d.ts +149 -0
  22. package/lib/asset-acquisition.d.ts.map +1 -0
  23. package/lib/asset-acquisition.js +175 -0
  24. package/lib/authority.d.ts +185 -0
  25. package/lib/authority.d.ts.map +1 -0
  26. package/lib/authority.js +223 -0
  27. package/lib/bindings.d.ts +144 -0
  28. package/lib/bindings.d.ts.map +1 -0
  29. package/lib/bindings.js +314 -0
  30. package/lib/builtins.d.ts +27 -0
  31. package/lib/builtins.d.ts.map +1 -0
  32. package/lib/builtins.js +37 -0
  33. package/lib/capability.d.ts +58 -0
  34. package/lib/capability.d.ts.map +1 -0
  35. package/lib/capability.js +192 -0
  36. package/lib/capture-path.d.ts +97 -0
  37. package/lib/capture-path.d.ts.map +1 -0
  38. package/lib/capture-path.js +152 -0
  39. package/lib/catalog.d.ts +37 -0
  40. package/lib/catalog.d.ts.map +1 -0
  41. package/lib/catalog.js +274 -0
  42. package/lib/contract-payload.d.ts +39 -0
  43. package/lib/contract-payload.d.ts.map +1 -0
  44. package/lib/contract-payload.js +56 -0
  45. package/lib/custom-tools/compile.d.ts +25 -0
  46. package/lib/custom-tools/compile.d.ts.map +1 -0
  47. package/lib/custom-tools/compile.js +61 -0
  48. package/lib/custom-tools/composite-executor.d.ts +42 -0
  49. package/lib/custom-tools/composite-executor.d.ts.map +1 -0
  50. package/lib/custom-tools/composite-executor.js +113 -0
  51. package/lib/custom-tools/dispatch.d.ts +28 -0
  52. package/lib/custom-tools/dispatch.d.ts.map +1 -0
  53. package/lib/custom-tools/dispatch.js +34 -0
  54. package/lib/custom-tools/http-executor.d.ts +48 -0
  55. package/lib/custom-tools/http-executor.d.ts.map +1 -0
  56. package/lib/custom-tools/http-executor.js +241 -0
  57. package/lib/custom-tools/index.d.ts +12 -0
  58. package/lib/custom-tools/index.d.ts.map +1 -0
  59. package/lib/custom-tools/index.js +12 -0
  60. package/lib/custom-tools/mcp-surface.d.ts +14 -0
  61. package/lib/custom-tools/mcp-surface.d.ts.map +1 -0
  62. package/lib/custom-tools/mcp-surface.js +41 -0
  63. package/lib/custom-tools/prompt-executor.d.ts +39 -0
  64. package/lib/custom-tools/prompt-executor.d.ts.map +1 -0
  65. package/lib/custom-tools/prompt-executor.js +59 -0
  66. package/lib/custom-tools/registry.d.ts +69 -0
  67. package/lib/custom-tools/registry.d.ts.map +1 -0
  68. package/lib/custom-tools/registry.js +130 -0
  69. package/lib/custom-tools/schema.d.ts +26 -0
  70. package/lib/custom-tools/schema.d.ts.map +1 -0
  71. package/lib/custom-tools/schema.js +375 -0
  72. package/lib/custom-tools/service.d.ts +90 -0
  73. package/lib/custom-tools/service.d.ts.map +1 -0
  74. package/lib/custom-tools/service.js +203 -0
  75. package/lib/custom-tools/store.d.ts +61 -0
  76. package/lib/custom-tools/store.d.ts.map +1 -0
  77. package/lib/custom-tools/store.js +240 -0
  78. package/lib/custom-tools/types.d.ts +131 -0
  79. package/lib/custom-tools/types.d.ts.map +1 -0
  80. package/lib/custom-tools/types.js +11 -0
  81. package/lib/decision-combine.d.ts +113 -0
  82. package/lib/decision-combine.d.ts.map +1 -0
  83. package/lib/decision-combine.js +156 -0
  84. package/lib/decision-evaluate.d.ts +185 -0
  85. package/lib/decision-evaluate.d.ts.map +1 -0
  86. package/lib/decision-evaluate.js +227 -0
  87. package/lib/deployment-coordinator.d.ts +213 -0
  88. package/lib/deployment-coordinator.d.ts.map +1 -0
  89. package/lib/deployment-coordinator.js +274 -0
  90. package/lib/diagnostics.d.ts +169 -0
  91. package/lib/diagnostics.d.ts.map +1 -0
  92. package/lib/diagnostics.js +136 -0
  93. package/lib/discovery-contracts.d.ts +14 -0
  94. package/lib/discovery-contracts.d.ts.map +1 -0
  95. package/lib/discovery-contracts.js +90 -0
  96. package/lib/discovery-describe.d.ts +35 -0
  97. package/lib/discovery-describe.d.ts.map +1 -0
  98. package/lib/discovery-describe.js +99 -0
  99. package/lib/embedding-index.d.ts +55 -0
  100. package/lib/embedding-index.d.ts.map +1 -0
  101. package/lib/embedding-index.js +126 -0
  102. package/lib/extension-dependencies.d.ts +355 -0
  103. package/lib/extension-dependencies.d.ts.map +1 -0
  104. package/lib/extension-dependencies.js +987 -0
  105. package/lib/extension-dispatch.d.ts +150 -0
  106. package/lib/extension-dispatch.d.ts.map +1 -0
  107. package/lib/extension-dispatch.js +178 -0
  108. package/lib/extension-page-state.d.ts +69 -0
  109. package/lib/extension-page-state.d.ts.map +1 -0
  110. package/lib/extension-page-state.js +82 -0
  111. package/lib/extension-registrar.d.ts +116 -0
  112. package/lib/extension-registrar.d.ts.map +1 -0
  113. package/lib/extension-registrar.js +144 -0
  114. package/lib/extensions-api.d.ts +346 -0
  115. package/lib/extensions-api.d.ts.map +1 -0
  116. package/lib/extensions-api.js +17 -0
  117. package/lib/extensions-remote.d.ts +57 -0
  118. package/lib/extensions-remote.d.ts.map +1 -0
  119. package/lib/extensions-remote.js +69 -0
  120. package/lib/extensions-service.d.ts +568 -0
  121. package/lib/extensions-service.d.ts.map +1 -0
  122. package/lib/extensions-service.js +2552 -0
  123. package/lib/harness-budgets.d.ts +158 -0
  124. package/lib/harness-budgets.d.ts.map +1 -0
  125. package/lib/harness-budgets.js +152 -0
  126. package/lib/harness-llm.d.ts +138 -0
  127. package/lib/harness-llm.d.ts.map +1 -0
  128. package/lib/harness-llm.js +218 -0
  129. package/lib/harness-serving.d.ts +115 -0
  130. package/lib/harness-serving.d.ts.map +1 -0
  131. package/lib/harness-serving.js +176 -0
  132. package/lib/headless.d.ts +97 -0
  133. package/lib/headless.d.ts.map +1 -0
  134. package/lib/headless.js +407 -0
  135. package/lib/http-acquisition.d.ts +27 -0
  136. package/lib/http-acquisition.d.ts.map +1 -0
  137. package/lib/http-acquisition.js +140 -0
  138. package/lib/index.d.ts +546 -0
  139. package/lib/index.d.ts.map +1 -0
  140. package/lib/index.js +5273 -0
  141. package/lib/invocation-accounting.d.ts +169 -0
  142. package/lib/invocation-accounting.d.ts.map +1 -0
  143. package/lib/invocation-accounting.js +148 -0
  144. package/lib/jev.d.ts +218 -0
  145. package/lib/jev.d.ts.map +1 -0
  146. package/lib/jev.js +366 -0
  147. package/lib/legacy-migration.d.ts +95 -0
  148. package/lib/legacy-migration.d.ts.map +1 -0
  149. package/lib/legacy-migration.js +429 -0
  150. package/lib/license-basis.d.ts +29 -0
  151. package/lib/license-basis.d.ts.map +1 -0
  152. package/lib/license-basis.js +58 -0
  153. package/lib/managed-workers.d.ts +158 -0
  154. package/lib/managed-workers.d.ts.map +1 -0
  155. package/lib/managed-workers.js +269 -0
  156. package/lib/mcp/auth-selection.d.ts +35 -0
  157. package/lib/mcp/auth-selection.d.ts.map +1 -0
  158. package/lib/mcp/auth-selection.js +64 -0
  159. package/lib/mcp/client-grant.d.ts +89 -0
  160. package/lib/mcp/client-grant.d.ts.map +1 -0
  161. package/lib/mcp/client-grant.js +63 -0
  162. package/lib/mcp/credential-cli.d.ts +38 -0
  163. package/lib/mcp/credential-cli.d.ts.map +1 -0
  164. package/lib/mcp/credential-cli.js +148 -0
  165. package/lib/mcp/credential-store.d.ts +143 -0
  166. package/lib/mcp/credential-store.d.ts.map +1 -0
  167. package/lib/mcp/credential-store.js +461 -0
  168. package/lib/mcp/export-policy.d.ts +25 -0
  169. package/lib/mcp/export-policy.d.ts.map +1 -0
  170. package/lib/mcp/export-policy.js +31 -0
  171. package/lib/mcp/host-binding.d.ts +144 -0
  172. package/lib/mcp/host-binding.d.ts.map +1 -0
  173. package/lib/mcp/host-binding.js +280 -0
  174. package/lib/mcp/http.d.ts +180 -0
  175. package/lib/mcp/http.d.ts.map +1 -0
  176. package/lib/mcp/http.js +602 -0
  177. package/lib/mcp/oauth.d.ts +149 -0
  178. package/lib/mcp/oauth.d.ts.map +1 -0
  179. package/lib/mcp/oauth.js +396 -0
  180. package/lib/mcp/protocol.d.ts +329 -0
  181. package/lib/mcp/protocol.d.ts.map +1 -0
  182. package/lib/mcp/protocol.js +459 -0
  183. package/lib/mcp/rate-limit.d.ts +68 -0
  184. package/lib/mcp/rate-limit.d.ts.map +1 -0
  185. package/lib/mcp/rate-limit.js +114 -0
  186. package/lib/mcp/sdk-v2.d.ts +17 -0
  187. package/lib/mcp/sdk-v2.d.ts.map +1 -0
  188. package/lib/mcp/sdk-v2.js +204 -0
  189. package/lib/mcp/server.d.ts +149 -0
  190. package/lib/mcp/server.d.ts.map +1 -0
  191. package/lib/mcp/server.js +302 -0
  192. package/lib/mcp/stdio.d.ts +80 -0
  193. package/lib/mcp/stdio.d.ts.map +1 -0
  194. package/lib/mcp/stdio.js +184 -0
  195. package/lib/mcp/subscriptions.d.ts +177 -0
  196. package/lib/mcp/subscriptions.d.ts.map +1 -0
  197. package/lib/mcp/subscriptions.js +288 -0
  198. package/lib/mcp-status.d.ts +96 -0
  199. package/lib/mcp-status.d.ts.map +1 -0
  200. package/lib/mcp-status.js +70 -0
  201. package/lib/mcp-usage.d.ts +110 -0
  202. package/lib/mcp-usage.d.ts.map +1 -0
  203. package/lib/mcp-usage.js +189 -0
  204. package/lib/model-qualification.d.ts +192 -0
  205. package/lib/model-qualification.d.ts.map +1 -0
  206. package/lib/model-qualification.js +178 -0
  207. package/lib/model-runtime-lane.d.ts +69 -0
  208. package/lib/model-runtime-lane.d.ts.map +1 -0
  209. package/lib/model-runtime-lane.js +122 -0
  210. package/lib/model-runtime-recipe.d.ts +132 -0
  211. package/lib/model-runtime-recipe.d.ts.map +1 -0
  212. package/lib/model-runtime-recipe.js +291 -0
  213. package/lib/planning.d.ts +256 -0
  214. package/lib/planning.d.ts.map +1 -0
  215. package/lib/planning.js +471 -0
  216. package/lib/playbook.d.ts +42 -0
  217. package/lib/playbook.d.ts.map +1 -0
  218. package/lib/playbook.js +65 -0
  219. package/lib/prepared-assets.d.ts +269 -0
  220. package/lib/prepared-assets.d.ts.map +1 -0
  221. package/lib/prepared-assets.js +471 -0
  222. package/lib/provider-bridge.d.ts +107 -0
  223. package/lib/provider-bridge.d.ts.map +1 -0
  224. package/lib/provider-bridge.js +423 -0
  225. package/lib/ptc-authority.d.ts +154 -0
  226. package/lib/ptc-authority.d.ts.map +1 -0
  227. package/lib/ptc-authority.js +242 -0
  228. package/lib/ptc-confinement.d.ts +60 -0
  229. package/lib/ptc-confinement.d.ts.map +1 -0
  230. package/lib/ptc-confinement.js +212 -0
  231. package/lib/ptc-runtime.d.ts +166 -0
  232. package/lib/ptc-runtime.d.ts.map +1 -0
  233. package/lib/ptc-runtime.js +231 -0
  234. package/lib/publication.d.ts +161 -0
  235. package/lib/publication.d.ts.map +1 -0
  236. package/lib/publication.js +181 -0
  237. package/lib/receipt-store.d.ts +57 -0
  238. package/lib/receipt-store.d.ts.map +1 -0
  239. package/lib/receipt-store.js +143 -0
  240. package/lib/receipt.d.ts +231 -0
  241. package/lib/receipt.d.ts.map +1 -0
  242. package/lib/receipt.js +165 -0
  243. package/lib/registrar.d.ts +75 -0
  244. package/lib/registrar.d.ts.map +1 -0
  245. package/lib/registrar.js +152 -0
  246. package/lib/resource-governance.d.ts +204 -0
  247. package/lib/resource-governance.d.ts.map +1 -0
  248. package/lib/resource-governance.js +213 -0
  249. package/lib/server-lifecycle.d.ts +175 -0
  250. package/lib/server-lifecycle.d.ts.map +1 -0
  251. package/lib/server-lifecycle.js +269 -0
  252. package/lib/skills.d.ts +31 -0
  253. package/lib/skills.d.ts.map +1 -0
  254. package/lib/skills.js +170 -0
  255. package/lib/speech-bridge.d.ts +74 -0
  256. package/lib/speech-bridge.d.ts.map +1 -0
  257. package/lib/speech-bridge.js +115 -0
  258. package/lib/state.d.ts +100 -0
  259. package/lib/state.d.ts.map +1 -0
  260. package/lib/state.js +160 -0
  261. package/lib/title-proposal.d.ts +194 -0
  262. package/lib/title-proposal.d.ts.map +1 -0
  263. package/lib/title-proposal.js +244 -0
  264. package/lib/tool-inventory.d.ts +90 -0
  265. package/lib/tool-inventory.d.ts.map +1 -0
  266. package/lib/tool-inventory.js +102 -0
  267. package/lib/tool-mode-run.d.ts +310 -0
  268. package/lib/tool-mode-run.d.ts.map +1 -0
  269. package/lib/tool-mode-run.js +411 -0
  270. package/lib/tool-sources.d.ts +80 -0
  271. package/lib/tool-sources.d.ts.map +1 -0
  272. package/lib/tool-sources.js +123 -0
  273. package/lib/tool-usage-projection.d.ts +390 -0
  274. package/lib/tool-usage-projection.d.ts.map +1 -0
  275. package/lib/tool-usage-projection.js +1038 -0
  276. package/lib/tool-usage-report.d.ts +153 -0
  277. package/lib/tool-usage-report.d.ts.map +1 -0
  278. package/lib/tool-usage-report.js +274 -0
  279. package/lib/transport.d.ts +158 -0
  280. package/lib/transport.d.ts.map +1 -0
  281. package/lib/transport.js +332 -0
  282. package/lib/types.d.ts +134 -0
  283. package/lib/types.d.ts.map +1 -0
  284. package/lib/types.js +8 -0
  285. package/lib/update-surface.d.ts +79 -0
  286. package/lib/update-surface.d.ts.map +1 -0
  287. package/lib/update-surface.js +224 -0
  288. package/lib/version.d.ts +3 -0
  289. package/lib/version.d.ts.map +1 -0
  290. package/lib/version.js +27 -0
  291. package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.d.ts +13 -0
  292. package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.d.ts.map +1 -0
  293. package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.js +85 -0
  294. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts +16 -0
  295. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts.map +1 -0
  296. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.js +87 -0
  297. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
  298. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
  299. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
  300. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts +20 -0
  301. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts.map +1 -0
  302. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.js +112 -0
  303. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
  304. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
  305. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
  306. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
  307. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
  308. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
  309. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts +82 -0
  310. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -0
  311. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +274 -0
  312. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +26 -0
  313. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -0
  314. package/node_modules/@try-works/tool-mode-contracts/lib/index.js +53 -0
  315. package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts +133 -0
  316. package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts.map +1 -0
  317. package/node_modules/@try-works/tool-mode-contracts/lib/meta.js +64 -0
  318. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +121 -0
  319. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -0
  320. package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +246 -0
  321. package/node_modules/@try-works/tool-mode-contracts/package.json +35 -0
  322. package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
  323. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
  324. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
  325. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
  326. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +86 -0
  327. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
  328. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +145 -0
  329. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
  330. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
  331. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
  332. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
  333. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
  334. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
  335. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +33 -0
  336. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
  337. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +33 -0
  338. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
  339. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
  340. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +191 -0
  341. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +137 -0
  342. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
  343. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +349 -0
  344. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +274 -0
  345. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
  346. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +932 -0
  347. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
  348. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
  349. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
  350. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
  351. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
  352. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
  353. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
  354. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
  355. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
  356. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
  357. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
  358. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +299 -0
  359. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +395 -0
  360. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
  361. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +839 -0
  362. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts +44 -0
  363. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts.map +1 -0
  364. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.js +255 -0
  365. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
  366. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
  367. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
  368. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
  369. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
  370. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
  371. package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.d.ts +221 -0
  372. package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.d.ts.map +1 -0
  373. package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.js +188 -0
  374. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
  375. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
  376. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
  377. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
  378. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
  379. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
  380. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
  381. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
  382. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
  383. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +128 -0
  384. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
  385. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
  386. package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.d.ts +41 -0
  387. package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.d.ts.map +1 -0
  388. package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.js +52 -0
  389. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
  390. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
  391. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
  392. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +157 -0
  393. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
  394. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +688 -0
  395. package/node_modules/@try-works/tool-mode-extension-sdk/package.json +54 -0
  396. package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
  397. package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
  398. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +460 -0
  399. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
  400. package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +647 -0
  401. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +61 -0
  402. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
  403. package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +1106 -0
  404. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
  405. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
  406. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +205 -0
  407. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
  408. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
  409. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
  410. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +119 -0
  411. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
  412. package/node_modules/@try-works/tool-mode-recipes/lib/images.js +201 -0
  413. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
  414. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
  415. package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
  416. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +345 -0
  417. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
  418. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1465 -0
  419. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
  420. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
  421. package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
  422. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +231 -0
  423. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
  424. package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +435 -0
  425. package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
  426. package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
  427. package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
  428. package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
  429. package/package.json +127 -4
  430. package/remote/spec.mjs +993 -0
  431. package/remote/typert.host.mjs +14 -0
  432. package/remote/typert.remote-client.mjs +16 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * The REAL headless `serve` composition entry (RUN-03, task-74).
3
+ *
4
+ * Composes the host services the plugin needs WITHOUT the DSH CLI context:
5
+ * config load (file/env), the extension-store-less operator surface, the model
6
+ * catalog with capability resolution, the standard-contract bindings with the
7
+ * SAME selection rule the plugin applies (providers override, else the first
8
+ * eligible implementation), the MCP host over those bindings plus `model_tools`
9
+ * and the `tool_mode_run` contract, and a bounded graceful shutdown on
10
+ * SIGINT/SIGTERM.
11
+ *
12
+ * Two boundaries are deliberate and named, not faked:
13
+ * - `tool_mode_run` is REGISTERED (its contract appears on tools/list) but its
14
+ * execution refuses: a headless process composes no DSH hosted-code runtime
15
+ * (the plugin's ProgramRunner needs the DSH PtcHostContext), and pretending
16
+ * otherwise would claim a confinement the deployment does not have.
17
+ * - Extension-routed models resolve through the same bridge as the plugin; a
18
+ * model the headless deployment cannot run simply has no tool, exactly like
19
+ * the plugin.
20
+ *
21
+ * @module @try-works/dsh-tool-mode/headless
22
+ */
23
+ import { readFileSync } from 'node:fs';
24
+ import { resolve } from 'node:path';
25
+ import { STANDARD_CONTRACTS } from '@try-works/tool-mode-contracts';
26
+ import { assertValidContract, assertValidInput, assertValidOutput, crossFieldRules, } from '@try-works/tool-mode-contracts';
27
+ import { createGrant, authorizeTool, createInvocationAuthority } from "./authority.js";
28
+ import { buildMeta, buildReceipt } from "./bindings.js";
29
+ import { DEFAULT_CATALOG_FILE, loadCatalog } from "./catalog.js";
30
+ import { resolveCapability } from "./capability.js";
31
+ import { toContractPayload, toNativeArgs } from "./contract-payload.js";
32
+ import { createAdapter } from "./adapters/index.js";
33
+ import { ProviderBridge } from "./provider-bridge.js";
34
+ import { assertConfigV3DisabledFlags, describeModels, repairCeilingOf } from "./index.js";
35
+ import { TOOL_MODE_RUN_CONTRACT } from "./tool-mode-run.js";
36
+ import { createMcpHost } from "./mcp/host-binding.js";
37
+ import { ServerLifecycle } from "./server-lifecycle.js";
38
+ import { startHttpServer } from "./mcp/http.js";
39
+ import { commandExists } from "./transport.js";
40
+ /** A named headless-configuration error. */
41
+ export class HeadlessConfigError extends Error {
42
+ name = 'HeadlessConfigError';
43
+ }
44
+ /** Read and validate the headless config document. */
45
+ export function readHeadlessConfig(configPath, env) {
46
+ const target = configPath ?? env.DSH_TOOL_MODE_CONFIG ?? './tool-mode.json';
47
+ let text;
48
+ try {
49
+ text = readFileSync(target, 'utf8');
50
+ }
51
+ catch (error) {
52
+ throw new HeadlessConfigError(`the config file ${target} could not be read: ${error instanceof Error ? error.message : String(error)}. `
53
+ + 'serve requires a config (--config <path> or DSH_TOOL_MODE_CONFIG).');
54
+ }
55
+ let parsed;
56
+ try {
57
+ parsed = JSON.parse(text);
58
+ }
59
+ catch (error) {
60
+ throw new HeadlessConfigError(`the config file ${target} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
61
+ }
62
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
63
+ throw new HeadlessConfigError(`the config file ${target} is not a JSON object`);
64
+ }
65
+ const config = parsed;
66
+ // The same fixed-false gate the plugin applies: unsupported values REFUSE.
67
+ try {
68
+ assertConfigV3DisabledFlags(config);
69
+ }
70
+ catch (error) {
71
+ throw new HeadlessConfigError(error instanceof Error ? error.message : String(error));
72
+ }
73
+ // The CODE-11 repair ceiling validates here too: the flat `repairAttempts`
74
+ // key drives, the v3 nested spelling is its equivalent, and an out-of-range
75
+ // value refuses at config load rather than silently clamping.
76
+ try {
77
+ repairCeilingOf(config);
78
+ }
79
+ catch (error) {
80
+ throw new HeadlessConfigError(error instanceof Error ? error.message : String(error));
81
+ }
82
+ return { config, path: resolve(target) };
83
+ }
84
+ /** Resolve the contract bindings exactly like the plugin's selection rule. */
85
+ function resolveBindings(config) {
86
+ const entries = loadCatalog(config.catalogFile ?? DEFAULT_CATALOG_FILE);
87
+ const cliCommand = config.cli?.command ?? 'desertant';
88
+ const cliAvailable = (config.cli?.enabled ?? true) && commandExists(cliCommand);
89
+ const remoteEndpoint = config.remote?.endpoint;
90
+ const transportOptions = {
91
+ cliCommand,
92
+ ...remoteEndpoint !== undefined ? { endpoint: remoteEndpoint } : {},
93
+ ...config.remote?.token !== undefined ? { token: config.remote.token } : {},
94
+ };
95
+ const resolved = entries.map(entry => ({
96
+ entry,
97
+ verdict: resolveCapability(entry, {
98
+ cliAvailable,
99
+ remoteEndpoint,
100
+ ...config.allowNpm !== undefined ? { allowNpm: config.allowNpm } : {},
101
+ }),
102
+ }));
103
+ const grant = createGrant({
104
+ grantId: config.grantId ?? 'local-interactive',
105
+ allowedTools: [...STANDARD_CONTRACTS.map(contract => contract.toolName), 'model_tools', 'tool_mode_run'],
106
+ approvedRoots: config.approvedRoots ?? [],
107
+ hostedCode: false,
108
+ recordingPolicy: config.recordReceipts === false ? 'none' : 'receipts',
109
+ });
110
+ const bridge = new ProviderBridge({
111
+ grant,
112
+ activationGeneration: 1,
113
+ log: () => { },
114
+ });
115
+ const bindings = new Map();
116
+ for (const contract of STANDARD_CONTRACTS) {
117
+ const eligible = resolved.filter(item => item.entry.contract === contract.contract && item.verdict.runnable);
118
+ if (eligible.length === 0)
119
+ continue;
120
+ const override = config.providers?.[contract.contract];
121
+ const chosen = eligible.find(item => item.entry.id === override) ?? eligible[0];
122
+ if (chosen === undefined)
123
+ continue;
124
+ const adapter = createAdapter(chosen.entry, { route: chosen.verdict.route, ...transportOptions }, undefined, bridge);
125
+ if (adapter === undefined)
126
+ continue;
127
+ bindings.set(contract.contract, {
128
+ contract,
129
+ implementation: chosen.entry,
130
+ adapter,
131
+ route: chosen.verdict.route,
132
+ alternatives: eligible.filter(item => item.entry.id !== chosen.entry.id).map(item => item.entry.id),
133
+ });
134
+ }
135
+ return bindings;
136
+ }
137
+ /**
138
+ * Start the headless serve composition (RUN-03).
139
+ *
140
+ * @param configPath - the config file path; falls back to DSH_TOOL_MODE_CONFIG
141
+ * then ./tool-mode.json.
142
+ * @returns the bound endpoint and a shutdown handle.
143
+ * @throws HeadlessConfigError for a missing/invalid configuration.
144
+ */
145
+ export async function startHeadlessServe(configPath) {
146
+ const { config } = readHeadlessConfig(configPath, process.env);
147
+ const bindings = resolveBindings(config);
148
+ // The MCP surface is NEVER unauthenticated (SEC-01): the headless serve
149
+ // requires a credential exactly like the stdio relay does.
150
+ const token = process.env.DSH_TOOL_MODE_MCP_TOKEN;
151
+ if (token === undefined || token.length === 0) {
152
+ throw new HeadlessConfigError('serve requires a credential (DSH_TOOL_MODE_MCP_TOKEN); the MCP surface is never unauthenticated (SEC-01)');
153
+ }
154
+ const models = (() => {
155
+ const entries = loadCatalog(config.catalogFile ?? DEFAULT_CATALOG_FILE);
156
+ const cliCommand = config.cli?.command ?? 'desertant';
157
+ const cliAvailable = (config.cli?.enabled ?? true) && commandExists(cliCommand);
158
+ const remoteEndpoint = config.remote?.endpoint;
159
+ return entries.map(entry => ({
160
+ entry,
161
+ verdict: resolveCapability(entry, {
162
+ cliAvailable,
163
+ remoteEndpoint,
164
+ ...config.allowNpm !== undefined ? { allowNpm: config.allowNpm } : {},
165
+ }),
166
+ }));
167
+ })();
168
+ let receiptCounter = 0;
169
+ const host = {
170
+ extension: '@try-works/dsh-tool-mode',
171
+ extensionVersion: '0.1.1',
172
+ activationGeneration: 1,
173
+ nextReceiptId: () => `rcpt_${(++receiptCounter).toString(36).padStart(6, '0')}`,
174
+ grant: createGrant({
175
+ grantId: config.grantId ?? 'local-interactive',
176
+ allowedTools: [...STANDARD_CONTRACTS.map(contract => contract.toolName), 'model_tools', 'tool_mode_run'],
177
+ approvedRoots: config.approvedRoots ?? [],
178
+ hostedCode: false,
179
+ recordingPolicy: config.recordReceipts === false ? 'none' : 'receipts',
180
+ }),
181
+ callerKind: 'interactive',
182
+ };
183
+ const published = [];
184
+ for (const binding of bindings.values()) {
185
+ /**
186
+ * Registration is what compiles a contract's validators. The plugin path gets
187
+ * this from registerContractTool; the headless surface builds the published
188
+ * list directly, so it must register each contract here or every real call
189
+ * fails with "input was validated before the contract was registered".
190
+ */
191
+ assertValidContract(binding.contract);
192
+ published.push({ toolName: binding.contract.toolName, contract: binding.contract });
193
+ }
194
+ if (config.registerControlTool !== false) {
195
+ published.push({ toolName: 'model_tools', contract: modelToolsContract() });
196
+ }
197
+ published.push({ toolName: 'tool_mode_run', contract: TOOL_MODE_RUN_CONTRACT });
198
+ const mcpHost = createMcpHost({
199
+ serverInfo: { name: '@try-works/dsh-tool-mode', version: '0.1.1' },
200
+ surface: {
201
+ get published() {
202
+ return published;
203
+ },
204
+ async execute(request) {
205
+ if (request.caller !== undefined) {
206
+ try {
207
+ authorizeTool({
208
+ grantId: request.caller.grantId,
209
+ allowedTools: request.caller.allowedTools,
210
+ approvedRoots: [],
211
+ remoteDestinations: [],
212
+ allowedHarnessProfiles: request.caller.allowedHarnessProfiles,
213
+ modelCapabilities: request.caller.modelCapabilities,
214
+ hostedCode: false,
215
+ recordingPolicy: request.caller.recordingPolicy,
216
+ limits: request.caller.limits,
217
+ }, request.name);
218
+ }
219
+ catch (error) {
220
+ return { isError: true, message: error instanceof Error ? error.message : String(error) };
221
+ }
222
+ }
223
+ if (request.name === 'model_tools') {
224
+ return { isError: false, value: { models: describeModels(models) } };
225
+ }
226
+ if (request.name === 'tool_mode_run') {
227
+ return {
228
+ isError: true,
229
+ message: 'tool_mode_run is registered but refused in the headless serve: this process composes no DSH hosted-code '
230
+ + 'runtime (the ProgramRunner needs the DSH PtcHostContext), and the refusal is reported rather than a '
231
+ + 'confinement the deployment does not have being claimed (CODE-10)',
232
+ };
233
+ }
234
+ const binding = [...bindings.values()].find(candidate => candidate.contract.toolName === request.name);
235
+ if (binding === undefined) {
236
+ return { isError: true, message: `unknown tool ${JSON.stringify(request.name)}` };
237
+ }
238
+ const { contract, adapter } = binding;
239
+ assertValidInput(contract, request.arguments);
240
+ for (const rule of crossFieldRules(contract)) {
241
+ const violation = rule(request.arguments);
242
+ if (violation !== undefined) {
243
+ return { isError: true, message: `${contract.toolName}: ${violation}` };
244
+ }
245
+ }
246
+ authorizeTool(host.grant, contract.toolName);
247
+ const nativeArgs = toNativeArgs(contract.contract, request.arguments);
248
+ const native = await adapter.invoke({
249
+ args: nativeArgs,
250
+ signal: request.signal,
251
+ authority: createInvocationAuthority(host.grant, host.callerKind),
252
+ });
253
+ const payload = toContractPayload(contract.contract, native, request.arguments);
254
+ const meta = buildMeta(binding, host);
255
+ const value = { ...payload, meta };
256
+ assertValidOutput(contract, value);
257
+ host.recordReceipt?.(buildReceipt(binding, host, meta));
258
+ return { isError: false, value };
259
+ },
260
+ },
261
+ });
262
+ let endpoint;
263
+ let closing = false;
264
+ const inflight = new Set();
265
+ const trackedHost = {
266
+ ...mcpHost,
267
+ async callTool(name, args, signal, caller) {
268
+ if (closing || lifecycle.state === 'stopping' || lifecycle.state === 'stopped') {
269
+ return { isError: true, message: 'the headless server is stopping; no new invocation is accepted' };
270
+ }
271
+ const controller = new AbortController();
272
+ let settled = false;
273
+ let resolve = () => { };
274
+ const done = new Promise(finish => { resolve = finish; });
275
+ const entry = {
276
+ abort: () => controller.abort(),
277
+ done,
278
+ settled: () => settled,
279
+ };
280
+ // Refused after shutdown began: it would otherwise be left running.
281
+ if (!lifecycle.adopt({
282
+ id: `call:${name}`,
283
+ owner: 'headless-serve',
284
+ cancel: () => { controller.abort(); return done; },
285
+ terminate: () => controller.abort(),
286
+ })) {
287
+ return { isError: true, message: 'the headless server is stopping; no new invocation is accepted' };
288
+ }
289
+ inflight.add(entry);
290
+ try {
291
+ return await mcpHost.callTool(name, args, AbortSignal.any([signal, controller.signal]), caller);
292
+ }
293
+ finally {
294
+ if (!settled) {
295
+ settled = true;
296
+ resolve();
297
+ }
298
+ inflight.delete(entry);
299
+ }
300
+ },
301
+ };
302
+ const lifecycle = new ServerLifecycle({
303
+ async bind() {
304
+ endpoint = await startHttpServer({
305
+ path: config.mcpV3?.path ?? '/mcp',
306
+ host: config.mcpV3?.host ?? '127.0.0.1',
307
+ port: config.mcpV3?.port ?? 3765,
308
+ maxBodyBytes: 16 * 1024 * 1024,
309
+ allowedOrigins: [],
310
+ auth: { scheme: 'static-token', token, clientId: 'headless-serve' },
311
+ }, trackedHost);
312
+ return { port: endpoint.port, close: endpoint.close };
313
+ },
314
+ async initialise() { },
315
+ onReady() { },
316
+ log(message) {
317
+ console.error(`[headless-serve] ${message}`);
318
+ },
319
+ });
320
+ const started = await lifecycle.start();
321
+ if (!started.ok)
322
+ throw new HeadlessConfigError(started.failure.message);
323
+ if (endpoint === undefined)
324
+ throw new HeadlessConfigError('the headless listener did not bind');
325
+ return {
326
+ url: endpoint.url,
327
+ host: endpoint.host,
328
+ port: endpoint.port,
329
+ async close() {
330
+ if (closing)
331
+ return;
332
+ closing = true;
333
+ // RUN-07 order: refuse new work, cancel owned calls within the grace, terminate
334
+ // what remains, close the transport and release the port.
335
+ await lifecycle.stop({ ownedBy: 'headless-serve' });
336
+ // No registration survives the stopped server.
337
+ published.length = 0;
338
+ },
339
+ };
340
+ }
341
+ /** The `model_tools` control contract, rendered for the headless MCP surface. */
342
+ function modelToolsContract() {
343
+ return {
344
+ contract: 'model.tools',
345
+ version: '1.0.0',
346
+ toolName: 'model_tools',
347
+ description: 'Inspect the models this headless deployment can run.',
348
+ inputSchema: { type: 'object', additionalProperties: false, properties: {} },
349
+ outputSchema: {
350
+ type: 'object',
351
+ additionalProperties: false,
352
+ required: ['models'],
353
+ properties: {
354
+ models: { type: 'array', items: { type: 'object', additionalProperties: true } },
355
+ },
356
+ },
357
+ semantics: { scoreKind: 'none' },
358
+ limits: {},
359
+ unsupported: ['Changing the catalog: this is an inspection surface.'],
360
+ };
361
+ }
362
+ /**
363
+ * Run the headless serve as a PROCESS (the launcher entry): prints the bound
364
+ * endpoint and waits for SIGINT/SIGTERM, then exits 0 after a bounded shutdown.
365
+ *
366
+ * @param options - the config path and the JSON-mode flag.
367
+ * @param io - output sinks (injected for tests).
368
+ * @returns the process exit code.
369
+ */
370
+ export async function runHeadlessServe(options, io, signals = process) {
371
+ try {
372
+ const serve = await startHeadlessServe(options.configPath);
373
+ if (options.json === true) {
374
+ io.out(JSON.stringify({ ok: true, listening: true, url: serve.url }));
375
+ }
376
+ else {
377
+ io.out(`dsh-tool-mode serve: listening on ${serve.url}`);
378
+ }
379
+ return await new Promise(resolve => {
380
+ let shuttingDown = false;
381
+ const shutdown = () => {
382
+ if (shuttingDown)
383
+ return;
384
+ shuttingDown = true;
385
+ void serve.close().finally(() => resolve(0));
386
+ };
387
+ signals.once('SIGINT', shutdown);
388
+ signals.once('SIGTERM', shutdown);
389
+ });
390
+ }
391
+ catch (error) {
392
+ if (error instanceof HeadlessConfigError) {
393
+ if (options.json === true)
394
+ io.out(JSON.stringify({ ok: false, error: error.message }));
395
+ else
396
+ io.err(`dsh-tool-mode serve: ${error.message}`);
397
+ return 2;
398
+ }
399
+ const message = error instanceof Error ? error.message : String(error);
400
+ if (options.json === true)
401
+ io.out(JSON.stringify({ ok: false, error: message }));
402
+ else
403
+ io.err(`dsh-tool-mode serve: ${message}`);
404
+ return 1;
405
+ }
406
+ }
407
+ //# sourceMappingURL=headless.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The HTTP acquisition source for pinned asset downloads (RES-03).
3
+ *
4
+ * `acquireAsset` is source-agnostic and its tests inject fakes, which is right
5
+ * for the failure paths — but a source nobody wires means the host-driven
6
+ * acquisition path NDL-01 names was never exercised against a real URL. This
7
+ * module is the real source: fetch with byte ranges, bounded redirect
8
+ * handling, and no writes outside the injected store.
9
+ *
10
+ * @module @try-works/dsh-tool-mode/http-acquisition
11
+ */
12
+ import type { AcquisitionSource } from './asset-acquisition.ts';
13
+ /**
14
+ * Create an HTTP acquisition source.
15
+ *
16
+ * Uses the platform fetch, which supports HTTPS and HTTP on Node 18+. Ranges
17
+ * are requested per chunk; a server that ignores the Range header is detected
18
+ * by the returned byte count and the transfer fails rather than resuming from
19
+ * wrong offsets.
20
+ * @param options - redirect budget and optional fetch override (for tests).
21
+ * @returns the source.
22
+ */
23
+ export declare function createHttpSource(options?: {
24
+ readonly maxRedirects?: number;
25
+ readonly fetchImpl?: typeof fetch;
26
+ }): AcquisitionSource;
27
+ //# sourceMappingURL=http-acquisition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-acquisition.d.ts","sourceRoot":"","sources":["../src/http-acquisition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAS/D;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE;IACxC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAC7B,GAAG,iBAAiB,CAsEzB"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The HTTP acquisition source for pinned asset downloads (RES-03).
3
+ *
4
+ * `acquireAsset` is source-agnostic and its tests inject fakes, which is right
5
+ * for the failure paths — but a source nobody wires means the host-driven
6
+ * acquisition path NDL-01 names was never exercised against a real URL. This
7
+ * module is the real source: fetch with byte ranges, bounded redirect
8
+ * handling, and no writes outside the injected store.
9
+ *
10
+ * @module @try-works/dsh-tool-mode/http-acquisition
11
+ */
12
+ /** Maximum redirects followed, so a download cannot bounce forever. */
13
+ const MAX_REDIRECTS = 5;
14
+ /** Maximum response size a single range fetch admits, as a guard above the chunk size. */
15
+ const MAX_CHUNK_BYTES = 16 * 1024 * 1024;
16
+ /**
17
+ * Create an HTTP acquisition source.
18
+ *
19
+ * Uses the platform fetch, which supports HTTPS and HTTP on Node 18+. Ranges
20
+ * are requested per chunk; a server that ignores the Range header is detected
21
+ * by the returned byte count and the transfer fails rather than resuming from
22
+ * wrong offsets.
23
+ * @param options - redirect budget and optional fetch override (for tests).
24
+ * @returns the source.
25
+ */
26
+ export function createHttpSource(options = {}) {
27
+ const maxRedirects = options.maxRedirects ?? MAX_REDIRECTS;
28
+ const fetchImpl = options.fetchImpl ?? fetch;
29
+ return {
30
+ supportsRanges: true,
31
+ async fetchRange(asset, from, to, signal) {
32
+ if (to - from + 1 > MAX_CHUNK_BYTES) {
33
+ throw new Error(`a range fetch of ${to - from + 1} bytes exceeds the ${MAX_CHUNK_BYTES} cap`);
34
+ }
35
+ let url = asset.source;
36
+ for (let redirect = 0; redirect <= maxRedirects; redirect += 1) {
37
+ const response = await fetchImpl(url, {
38
+ headers: { range: `bytes=${from}-${to}` },
39
+ signal,
40
+ // Redirects are followed MANUALLY so each hop is counted: a redirect
41
+ // loop is an error, not a hang.
42
+ redirect: 'manual',
43
+ });
44
+ if (response.status >= 300 && response.status < 400) {
45
+ const location = response.headers.get('location');
46
+ if (location === null) {
47
+ throw new Error(`${asset.assetId}: a redirect carried no location`);
48
+ }
49
+ const next = new URL(location, url);
50
+ if (next.protocol !== 'http:' && next.protocol !== 'https:') {
51
+ throw new Error(`${asset.assetId}: a redirect to ${next.protocol} is not an HTTP(S) asset source`);
52
+ }
53
+ url = next.href;
54
+ continue;
55
+ }
56
+ if (!response.ok) {
57
+ throw new Error(`${asset.assetId}: HTTP ${response.status} fetching ${asset.source}`);
58
+ }
59
+ // RFC 9110 §14.2 permits a server to IGNORE the Range header entirely and
60
+ // answer 200 with the full body. That is a legal response, so it is
61
+ // handled rather than rejected: the wanted window is sliced out of the
62
+ // full body at ITS absolute offset, and the caller's offset math stays
63
+ // correct whether the server honored the Range or not. The budget admits
64
+ // exactly the bytes up to the window's end — the server chose to send
65
+ // them, and the operator already approved the asset's declared size.
66
+ const wanted = to - from + 1;
67
+ if (response.status === 200) {
68
+ // The budget is the operator-approved asset size: a 200 IS the full
69
+ // asset, which the approval already disclosed; anything beyond it is a
70
+ // server that cannot be trusted.
71
+ const body = await readBoundedBody(response, asset.bytes, `${asset.assetId}: full-body`);
72
+ if (body.byteLength < from + wanted) {
73
+ throw new Error(`${asset.assetId}: a 200 response carried ${body.byteLength} bytes, fewer than the ${from + wanted} the requested window requires`);
74
+ }
75
+ return body.subarray(from, from + wanted);
76
+ }
77
+ if (response.status === 206) {
78
+ const body = await readBoundedBody(response, wanted, `${asset.assetId}: range body`);
79
+ if (body.byteLength !== wanted) {
80
+ // A 206 must carry exactly the range the Content-Range describes; a
81
+ // short body means the server truncated, and trusting it would corrupt
82
+ // the resume offsets.
83
+ throw new Error(`${asset.assetId}: requested ${wanted} bytes at ${from}, received ${body.byteLength}`);
84
+ }
85
+ return body;
86
+ }
87
+ throw new Error(`${asset.assetId}: unexpected HTTP ${response.status}`);
88
+ }
89
+ throw new Error(`${asset.assetId}: more than ${maxRedirects} redirects`);
90
+ },
91
+ };
92
+ }
93
+ /**
94
+ * Read a response body under a HARD byte budget.
95
+ *
96
+ * The budget bounds MEMORY before any byte is buffered: the reader is streamed
97
+ * chunk by chunk and refuses the moment the running total would exceed the cap,
98
+ * so a Range-ignoring server cannot push an entire multi-GB asset into a single
99
+ * buffer (the round-48 review's finding 2).
100
+ * @param response - the response to read.
101
+ * @param budget - the maximum bytes admitted.
102
+ * @param label - what is being read, for the error.
103
+ * @returns the buffered bytes.
104
+ */
105
+ async function readBoundedBody(response, budget, label) {
106
+ if (response.body === null) {
107
+ // No stream (rare: opaque or empty responses). Read with a guard anyway.
108
+ const buffer = new Uint8Array(await response.arrayBuffer());
109
+ if (buffer.byteLength > budget)
110
+ throw new Error(`${label} exceeded the ${budget} byte budget`);
111
+ return buffer;
112
+ }
113
+ const reader = response.body.getReader();
114
+ const chunks = [];
115
+ let total = 0;
116
+ try {
117
+ for (;;) {
118
+ const { done, value } = await reader.read();
119
+ if (done)
120
+ break;
121
+ total += value.byteLength;
122
+ if (total > budget) {
123
+ await reader.cancel();
124
+ throw new Error(`${label} exceeded the ${budget} byte budget`);
125
+ }
126
+ chunks.push(value);
127
+ }
128
+ }
129
+ finally {
130
+ reader.releaseLock();
131
+ }
132
+ const out = new Uint8Array(total);
133
+ let offset = 0;
134
+ for (const chunk of chunks) {
135
+ out.set(chunk, offset);
136
+ offset += chunk.byteLength;
137
+ }
138
+ return out;
139
+ }
140
+ //# sourceMappingURL=http-acquisition.js.map