@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,461 @@
1
+ /**
2
+ * The operator-owned client credential store (SEC-01).
3
+ *
4
+ * SEC-01's generation clause: credentials are generated with high-entropy secrets,
5
+ * stored with suitable host protection (owner-only), and revocable independently per
6
+ * application. Before this module the OAuth client registry was in-memory only and the
7
+ * static-token mode accepted exactly one configured token — nothing could GENERATE a
8
+ * credential and nothing persisted it, so a restart lost every client and a generated
9
+ * secret could not exist.
10
+ *
11
+ * This store is the durable half. The security properties it now holds, each pinned
12
+ * by test:
13
+ *
14
+ * - one JSON document per deployment (`credentials.json`), written to a CRYPTO-RANDOM
15
+ * temp name opened EXCLUSIVELY (`wx`) — a predictable temp name is a hardlink target
16
+ * an attacker on the same account can pre-plant, so the name is unguessable and a
17
+ * pre-existing name FAILS instead of being overwritten — then fsync'd and atomically
18
+ * renamed over the document. A rename replaces a planted SYMLINK at the target rather
19
+ * than following it;
20
+ * - Windows: an EXPLICIT owner-only DACL is applied to the temp file BEFORE the rename
21
+ * (inheritance removed, the owner alone granted full control) and the store fails
22
+ * closed when the ACL cannot be secured. POSIX mode 0600 alone is not sufficient on
23
+ * Windows, and "the profile directory inherits it" is not a control;
24
+ * - MUTATIONS serialize through an in-process mutex AND an exclusive sidecar lock file,
25
+ * and re-read the document inside the critical section — two concurrent writers can
26
+ * no longer each persist a snapshot that silently drops the other's entry;
27
+ * - a CORRUPT or unreadable document makes MUTATIONS fail closed (a generation refused,
28
+ * the bytes untouched) while READS deny: authentication cannot succeed on a store
29
+ * the host cannot vouch for, and a generation can never overwrite a malformed
30
+ * document "as if empty". A MISSING document is the only empty start;
31
+ * - reads are served from the FILE, fresh on every lookup, so a revocation through any
32
+ * surface takes effect on the very next request;
33
+ * - `bySecret` matches STATIC-TOKEN credentials only: an OAuth resource-server secret
34
+ * presented as a static bearer must never authenticate through this path (scheme
35
+ * confusion);
36
+ * - the secret is compared CONSTANT-TIME (SHA-256 digests over equal-length input);
37
+ * - every mutation throws when it cannot persist: a generation that cannot be written
38
+ * must leave nothing usable rather than an in-memory-only credential that a restart
39
+ * silently forgets (fail-closed, SEC-01).
40
+ *
41
+ * @module @try-works/dsh-tool-mode/mcp/credential-store
42
+ */
43
+ import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
44
+ import { closeSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'node:fs';
45
+ import { spawnSync } from 'node:child_process';
46
+ import { basename, dirname, join, parse } from 'node:path';
47
+ import { homedir } from 'node:os';
48
+ /** A document that EXISTS but cannot be vouched for. Mutations refuse; reads deny. */
49
+ export class CorruptCredentialStoreError extends Error {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = 'CorruptCredentialStoreError';
53
+ }
54
+ }
55
+ /**
56
+ * Generate a fresh client credential directly over the store (the primitive
57
+ * the human-only CLI and tests use — the model-visible `model_tools` surface
58
+ * refuses generation entirely, SEC-01: the secret must never reach a model).
59
+ * @param store - the durable store.
60
+ * @param options - clientId (≤64 chars), scheme, scope.
61
+ * @returns the credential with the secret exactly once.
62
+ */
63
+ export function generateCredential(store, options) {
64
+ if (typeof options.clientId !== 'string' || options.clientId.length === 0 || options.clientId.length > 64) {
65
+ throw new Error('clientId must be a non-empty string of at most 64 characters');
66
+ }
67
+ if (options.scheme !== 'static-token' && options.scheme !== 'oauth-resource-server') {
68
+ throw new Error('scheme must be static-token or oauth-resource-server');
69
+ }
70
+ if (store.get(options.clientId) !== undefined) {
71
+ throw new Error(`a credential for ${JSON.stringify(options.clientId)} already exists; revoke it first`);
72
+ }
73
+ const secret = randomBytes(32).toString('base64url');
74
+ const scope = options.scope === undefined || options.scope.length === 0 ? ['mcp:call'] : [...options.scope];
75
+ const createdAt = new Date().toISOString();
76
+ store.upsert({ clientId: options.clientId, secret, scheme: options.scheme, scope, createdAt });
77
+ return { clientId: options.clientId, secret, scheme: options.scheme, scope, createdAt };
78
+ }
79
+ /**
80
+ * Derive the default credential-store file, next to the host's own state
81
+ * (SEC-01: owner-only home protection).
82
+ * @param env - the environment to read; defaults to the process environment.
83
+ * @returns the absolute path.
84
+ */
85
+ export function defaultCredentialStoreFile(env = process.env) {
86
+ const home = env.DSH_HOME !== undefined && env.DSH_HOME.length > 0
87
+ ? env.DSH_HOME
88
+ : join(homedir(), '.dsh');
89
+ return join(home, 'model-as-tool', 'credentials.json');
90
+ }
91
+ /**
92
+ * Apply an explicit owner-only DACL to one file on Windows (icacls: inheritance
93
+ * removed, the current owner alone granted full control), and fail closed when
94
+ * the ACL cannot be secured. On POSIX the caller's 0600 mode bits are the
95
+ * control and this is a no-op.
96
+ * @param file - the file to secure, BEFORE it is published (renamed) into place.
97
+ */
98
+ export function applyOwnerOnlyDacl(file) {
99
+ if (process.platform !== 'win32')
100
+ return;
101
+ const owner = process.env.USERNAME;
102
+ if (owner === undefined || owner.length === 0) {
103
+ throw new Error('the credential file ACL cannot be secured: no Windows USERNAME to grant ownership to');
104
+ }
105
+ const result = spawnSync('icacls', [file, '/inheritance:r', '/grant:r', `${owner}:(F)`], {
106
+ windowsHide: true,
107
+ encoding: 'utf8',
108
+ });
109
+ if (result.status !== 0) {
110
+ throw new Error(`the credential file ACL cannot be secured: icacls failed with status ${result.status ?? 'unknown'}`
111
+ + `: ${(result.stderr ?? result.stdout ?? '').trim()}`);
112
+ }
113
+ }
114
+ /**
115
+ * Refuse a reparse point (symlink or Windows junction) at a path the store is
116
+ * about to write THROUGH: a junctioned credential home is an untrusted target,
117
+ * and the store fails closed rather than persisting plaintext secrets into a
118
+ * location the operator did not own by construction.
119
+ * @param path - the directory (or file) to check.
120
+ */
121
+ function assertNoReparsePoint(path) {
122
+ try {
123
+ if (lstatSync(path).isSymbolicLink()) {
124
+ throw new Error(`the credential store refuses ${path}: it is a symbolic link or junction (untrusted target)`);
125
+ }
126
+ }
127
+ catch (error) {
128
+ if (error.code === 'ENOENT')
129
+ return;
130
+ throw error;
131
+ }
132
+ }
133
+ /**
134
+ * The trusted root the credential store lives under by default: DSH_HOME when
135
+ * set, otherwise `~/.dsh`. Ancestor validation walks from HERE down to the
136
+ * store directory — system junctions ABOVE the trusted root are never part of
137
+ * the trust question. A store outside the trusted root (an explicit --store)
138
+ * is validated from the filesystem root instead, and any reparse point in the
139
+ * chain fails it closed.
140
+ */
141
+ function trustedCredentialRoot(env = process.env) {
142
+ return env.DSH_HOME !== undefined && env.DSH_HOME.length > 0
143
+ ? env.DSH_HOME
144
+ : join(homedir(), '.dsh');
145
+ }
146
+ /**
147
+ * Walk EVERY ancestor component from the bounded trusted root down to the
148
+ * store directory and refuse any reparse point — not just the immediate parent:
149
+ * a junction higher in the chain redirects the whole write just as surely.
150
+ * @param file - the credential document path.
151
+ */
152
+ function assertTrustedStoreAncestors(file) {
153
+ const dir = dirname(file);
154
+ const root = trustedCredentialRoot();
155
+ const start = dir === root || dir.startsWith(root + '\\') || dir.startsWith(root + '/')
156
+ ? root
157
+ : parse(dir).root;
158
+ // Collect the ancestor chain from `start` down to `dir` (bounded by the path
159
+ // depth, which is small), then check each component that EXISTS.
160
+ const chain = [];
161
+ let cursor = dir;
162
+ while (cursor !== start && cursor !== parse(cursor).root && cursor.length > 0) {
163
+ chain.push(cursor);
164
+ const parent = dirname(cursor);
165
+ if (parent === cursor)
166
+ break;
167
+ cursor = parent;
168
+ }
169
+ chain.push(cursor);
170
+ for (const component of chain.reverse()) {
171
+ assertNoReparsePoint(component);
172
+ }
173
+ }
174
+ /** Is the pid alive? `undefined` means "cannot tell" — callers fail closed. */
175
+ function isProcessAlive(pid) {
176
+ if (!Number.isInteger(pid) || pid <= 0)
177
+ return undefined;
178
+ try {
179
+ process.kill(pid, 0);
180
+ return true;
181
+ }
182
+ catch (error) {
183
+ if (error.code === 'ESRCH')
184
+ return false;
185
+ return undefined;
186
+ }
187
+ }
188
+ /** Read a lock record; undefined when the lock is unreadable or corrupt. */
189
+ function readLockRecord(lockPath) {
190
+ try {
191
+ const parsed = JSON.parse(readFileSync(lockPath, 'utf8'));
192
+ if (typeof parsed !== 'object' || parsed === null)
193
+ return undefined;
194
+ const candidate = parsed;
195
+ if (typeof candidate.token !== 'string' || candidate.token.length === 0
196
+ || typeof candidate.pid !== 'number' || typeof candidate.at !== 'number') {
197
+ return undefined;
198
+ }
199
+ return { token: candidate.token, pid: candidate.pid, at: candidate.at };
200
+ }
201
+ catch {
202
+ return undefined;
203
+ }
204
+ }
205
+ /** A real blocking sleep, without burning the CPU. */
206
+ function sleep(ms) {
207
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
208
+ }
209
+ /**
210
+ * Create (or open) the file-backed credential store.
211
+ * @param file - the absolute path of the credentials document.
212
+ * @param hooks - TEST-ONLY lock hooks; production passes nothing.
213
+ * @returns the store.
214
+ */
215
+ export function createFileCredentialStore(file, hooks = {}) {
216
+ const staleLockMs = hooks.staleLockMs ?? 30_000;
217
+ const lockDeadlineMs = hooks.lockDeadlineMs ?? 10_000;
218
+ const probeAlive = hooks.isProcessAlive ?? isProcessAlive;
219
+ /**
220
+ * The cross-process lock: an unguessable ownership token plus the holder's
221
+ * pid, so a stale lock is only ever stolen from a holder PROVEN DEAD. A live
222
+ * holder is never stolen from, unknown liveness fails closed (the contender
223
+ * keeps waiting, then refuses), and release removes ONLY a token-owned lock
224
+ * — a successor's lock is never touched.
225
+ */
226
+ const acquireFileLock = () => {
227
+ const lockPath = `${file}.lock`;
228
+ const token = randomBytes(16).toString('hex');
229
+ const deadline = Date.now() + lockDeadlineMs;
230
+ for (;;) {
231
+ try {
232
+ const fd = openSync(lockPath, 'wx');
233
+ try {
234
+ writeFileSync(fd, JSON.stringify({ token, pid: process.pid, at: Date.now() }), 'utf8');
235
+ }
236
+ finally {
237
+ closeSync(fd);
238
+ }
239
+ const release = () => {
240
+ // Release ONLY a token-owned lock: if the record no longer carries OUR
241
+ // token, the lock is a successor's (or was removed) — never remove it.
242
+ const held = readLockRecord(lockPath);
243
+ if (held === undefined || held.token !== token)
244
+ return;
245
+ try {
246
+ rmSync(lockPath, { force: true });
247
+ }
248
+ catch {
249
+ // Already gone: nothing to release.
250
+ }
251
+ };
252
+ return { token, release };
253
+ }
254
+ catch (error) {
255
+ const code = error.code;
256
+ /**
257
+ * Windows reports EPERM rather than EEXIST when `open(..., 'wx')` loses the
258
+ * race to an existing lock file (the two-process test caught this as an
259
+ * occasional hard failure). Both mean "somebody holds it": treat EPERM as
260
+ * contention and let the normal holder/stale logic decide, never as a
261
+ * permanent failure that drops a writer.
262
+ */
263
+ if (code !== 'EEXIST' && code !== 'EPERM')
264
+ throw error;
265
+ // A held lock: examine WHO holds it before even considering theft.
266
+ const held = readLockRecord(lockPath);
267
+ if (held !== undefined) {
268
+ const age = Date.now() - held.at;
269
+ const alive = probeAlive(held.pid);
270
+ if (alive === false && age > staleLockMs) {
271
+ // The holder is PROVEN DEAD and the lock is stale: take it over.
272
+ // (An unreadable/corrupt record is NOT this case — fail closed below.)
273
+ try {
274
+ rmSync(lockPath, { force: true });
275
+ }
276
+ catch {
277
+ // Released between the read and the removal: retry the acquire.
278
+ }
279
+ continue;
280
+ }
281
+ // A LIVE holder (or unknown liveness) is never stolen from — the
282
+ // contender waits, then fails closed at the deadline.
283
+ }
284
+ if (Date.now() > deadline) {
285
+ throw new Error('the credential store is locked by another writer; the mutation was not attempted');
286
+ }
287
+ sleep(25);
288
+ }
289
+ }
290
+ };
291
+ /** Read the CURRENT document. STRICT for mutations: corruption refuses them. */
292
+ const read = (strict) => {
293
+ let text;
294
+ try {
295
+ text = readFileSync(file, 'utf8');
296
+ }
297
+ catch (error) {
298
+ if (error.code === 'ENOENT') {
299
+ // A MISSING document is the only empty start. Nothing else is.
300
+ return new Map();
301
+ }
302
+ if (strict) {
303
+ throw new CorruptCredentialStoreError(`the credentials document cannot be read and no mutation will guess its contents: `
304
+ + `${error instanceof Error ? error.message : String(error)}`);
305
+ }
306
+ return new Map();
307
+ }
308
+ let parsed;
309
+ try {
310
+ parsed = JSON.parse(text);
311
+ }
312
+ catch (error) {
313
+ if (strict) {
314
+ throw new CorruptCredentialStoreError(`the credentials document is not valid JSON and will not be overwritten as if empty: `
315
+ + `${error instanceof Error ? error.message : String(error)}`);
316
+ }
317
+ return new Map();
318
+ }
319
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
320
+ if (strict)
321
+ throw new CorruptCredentialStoreError('the credentials document is not a JSON object');
322
+ return new Map();
323
+ }
324
+ const document = parsed;
325
+ if (!Array.isArray(document.clients)) {
326
+ if (strict)
327
+ throw new CorruptCredentialStoreError('the credentials document has no clients array');
328
+ return new Map();
329
+ }
330
+ const next = new Map();
331
+ for (const entry of document.clients) {
332
+ const candidate = entry;
333
+ if (typeof candidate.clientId !== 'string' || typeof candidate.secret !== 'string'
334
+ || (candidate.scheme !== 'static-token' && candidate.scheme !== 'oauth-resource-server')
335
+ || !Array.isArray(candidate.scope)) {
336
+ // A malformed ENTRY corrupts the document: a mutation would silently drop
337
+ // it on the next persist, and authentication cannot vouch for it either.
338
+ if (strict) {
339
+ throw new CorruptCredentialStoreError(`the credentials document carries a malformed client entry (id ${JSON.stringify(candidate.clientId)})`);
340
+ }
341
+ return new Map();
342
+ }
343
+ next.set(candidate.clientId, candidate);
344
+ }
345
+ return next;
346
+ };
347
+ const persist = (clients, token) => {
348
+ const document = {
349
+ version: 1,
350
+ clients: [...clients.values()],
351
+ };
352
+ // SEC-01: the temp name is crypto-random and opened EXCLUSIVELY — a planted
353
+ // hardlink/symlink at a predictable name cannot be overwritten, and a
354
+ // pre-existing name fails the write instead of clobbering an unrelated file.
355
+ const temp = join(dirname(file), `.${basename(file)}.tmp-${randomBytes(12).toString('hex')}`);
356
+ const fd = openSync(temp, 'wx', 0o600);
357
+ try {
358
+ // The file WE created must be a regular file: 'wx' already excludes
359
+ // pre-existing entries (hardlinks and junctions included); this is the
360
+ // belt-and-braces check.
361
+ const created = lstatSync(temp);
362
+ if (!created.isFile() || created.isSymbolicLink()) {
363
+ throw new Error(`the credential temp file is not a regular file: refusing to write plaintext secrets through it`);
364
+ }
365
+ // Owner-only BEFORE the first secret byte: the empty file's ACL is
366
+ // secured while it holds NOTHING, so no plaintext ever exists under an
367
+ // inherited broad ACL (the reviewer's inherited Everyone:R +
368
+ // Authenticated Users:M finding).
369
+ applyOwnerOnlyDacl(temp);
370
+ writeFileSync(fd, JSON.stringify(document, null, 2), 'utf8');
371
+ fsyncSync(fd);
372
+ }
373
+ finally {
374
+ closeSync(fd);
375
+ }
376
+ // The publish is refused unless OUR token still owns the lock: a writer
377
+ // that somehow lost its lock must never publish a stale snapshot over the
378
+ // successor's state.
379
+ const held = readLockRecord(`${file}.lock`);
380
+ if (held === undefined || held.token !== token) {
381
+ rmSync(temp, { force: true });
382
+ throw new Error('the credential store lost its write lock; the publish is refused');
383
+ }
384
+ renameSync(temp, file);
385
+ };
386
+ /**
387
+ * One serialized mutation: the ancestor chain is checked for reparse points
388
+ * BEFORE anything (lock file included) is written through it, the parent
389
+ * directory is created (a first-generation store starts from nothing), then
390
+ * the file lock excludes other processes and the read-modify-write runs
391
+ * fully SYNCHRONOUSLY inside it — Node's single thread makes the section
392
+ * atomic for this process too, so two concurrent writers cannot each persist
393
+ * a snapshot that drops the other's entry or resurrects a just-revoked
394
+ * credential.
395
+ */
396
+ const mutation = (body) => {
397
+ assertTrustedStoreAncestors(file);
398
+ mkdirSync(dirname(file), { recursive: true });
399
+ const { token, release } = acquireFileLock();
400
+ try {
401
+ const clients = read(true);
402
+ // TEST-ONLY: simulate a writer paused after its strict read, holding the
403
+ // lock while other processes contend (the reviewer's 31 s repro, without
404
+ // the wait).
405
+ if (hooks.holdLockAfterReadMs !== undefined)
406
+ sleep(hooks.holdLockAfterReadMs);
407
+ return body(clients, token);
408
+ }
409
+ finally {
410
+ release();
411
+ }
412
+ };
413
+ return {
414
+ file,
415
+ list() {
416
+ // Reads DENY on corruption (empty list) rather than crash the auth path.
417
+ return [...read(false).values()];
418
+ },
419
+ get(clientId) {
420
+ return read(false).get(clientId);
421
+ },
422
+ bySecret(secret) {
423
+ // CONSTANT-TIME over the STATIC-TOKEN entries: the digest equalizes lengths,
424
+ // and the loop never exits early on a match. OAuth resource-server secrets
425
+ // are NEVER matched here — scheme confusion would let an OAuth secret pass
426
+ // as a static bearer.
427
+ const digest = createHash('sha256').update(secret).digest();
428
+ let found;
429
+ for (const candidate of read(false).values()) {
430
+ if (candidate.scheme !== 'static-token')
431
+ continue;
432
+ const candidateDigest = createHash('sha256').update(candidate.secret).digest();
433
+ if (timingSafeEqual(digest, candidateDigest))
434
+ found = candidate;
435
+ }
436
+ return found;
437
+ },
438
+ upsert(credential) {
439
+ mutation((clients, token) => {
440
+ // PERSIST FIRST inside the critical section: a credential that cannot be
441
+ // written must never be registered as usable anywhere (SEC-01).
442
+ clients.set(credential.clientId, credential);
443
+ persist(clients, token);
444
+ });
445
+ },
446
+ delete(clientId) {
447
+ mutation((clients, token) => {
448
+ if (!clients.has(clientId))
449
+ return;
450
+ clients.delete(clientId);
451
+ persist(clients, token);
452
+ });
453
+ },
454
+ };
455
+ }
456
+ /** Remove a credential store file, for tests that need a fresh deployment. */
457
+ export function removeCredentialStoreFile(file) {
458
+ rmSync(file, { force: true });
459
+ rmSync(`${file}.lock`, { force: true });
460
+ }
461
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * BASE-06 — the MCP export allowlist is a separate control from the native
3
+ * `models` selection.
4
+ *
5
+ * `undefined` or a list containing `*` means the deployment did not configure a
6
+ * separate MCP allowlist and preserves the existing surface. An EMPTY allowlist is
7
+ * meaningful: it exports no inference tools. A named allowlist admits exactly those
8
+ * names.
9
+ *
10
+ * Denied rows are returned as WITHHELD rows (with a reason) rather than removed,
11
+ * so the existing MCP host status surface can explain why a tool is absent.
12
+ *
13
+ * @module @try-works/dsh-tool-mode/mcp/export-policy
14
+ */
15
+ import type { PublishedTool } from './host-binding.ts';
16
+ /** The stable reason recorded for a tool denied by the allowlist. */
17
+ export declare const MCP_EXPORT_DENIED_REASON = "the MCP export allowlist does not name this tool";
18
+ /**
19
+ * Apply the operator's MCP export allowlist to the assembled publication surface.
20
+ * @param published - every tool the host could publish.
21
+ * @param allowlist - configured names; undefined means no separate MCP restriction.
22
+ * @returns the same rows, with denied rows carrying a withholding reason.
23
+ */
24
+ export declare function applyMcpExportPolicy(published: readonly PublishedTool[], allowlist: readonly string[] | undefined): readonly PublishedTool[];
25
+ //# sourceMappingURL=export-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-policy.d.ts","sourceRoot":"","sources":["../../src/mcp/export-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,qDAAqD,CAAA;AAE1F;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,aAAa,EAAE,EACnC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACvC,SAAS,aAAa,EAAE,CAM1B"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * BASE-06 — the MCP export allowlist is a separate control from the native
3
+ * `models` selection.
4
+ *
5
+ * `undefined` or a list containing `*` means the deployment did not configure a
6
+ * separate MCP allowlist and preserves the existing surface. An EMPTY allowlist is
7
+ * meaningful: it exports no inference tools. A named allowlist admits exactly those
8
+ * names.
9
+ *
10
+ * Denied rows are returned as WITHHELD rows (with a reason) rather than removed,
11
+ * so the existing MCP host status surface can explain why a tool is absent.
12
+ *
13
+ * @module @try-works/dsh-tool-mode/mcp/export-policy
14
+ */
15
+ /** The stable reason recorded for a tool denied by the allowlist. */
16
+ export const MCP_EXPORT_DENIED_REASON = 'the MCP export allowlist does not name this tool';
17
+ /**
18
+ * Apply the operator's MCP export allowlist to the assembled publication surface.
19
+ * @param published - every tool the host could publish.
20
+ * @param allowlist - configured names; undefined means no separate MCP restriction.
21
+ * @returns the same rows, with denied rows carrying a withholding reason.
22
+ */
23
+ export function applyMcpExportPolicy(published, allowlist) {
24
+ if (allowlist === undefined || allowlist.includes('*'))
25
+ return published;
26
+ const allowed = new Set(allowlist);
27
+ return published.map(tool => allowed.has(tool.toolName)
28
+ ? tool
29
+ : { ...tool, notExportableReason: MCP_EXPORT_DENIED_REASON });
30
+ }
31
+ //# sourceMappingURL=export-policy.js.map
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Binding the MCP surface to the real DSH tool registry (MCP-08, MCP-09, MCP-12).
3
+ *
4
+ * Two requirements shape this module, and both are about where data comes from
5
+ * rather than what it looks like:
6
+ *
7
+ * - **MCP-09**: DSH's model-facing `schemas()` projection INTENTIONALLY omits the
8
+ * output schema, so an export built from it would publish a tool with no declared
9
+ * result shape. The canonical schemas therefore come from the CONTRACTS, which is
10
+ * the only place that has them; `schemas()` is never consulted for a schema.
11
+ * - **MCP-08**: invocation goes through the host's `execute` path with a
12
+ * server-issued call identity and the caller's abort signal. Resolving a tool and
13
+ * calling it directly would bypass the grant, the receipt and the result policy —
14
+ * the three things the host path exists to apply — so this module is given an
15
+ * executor rather than a registry to reach into.
16
+ *
17
+ * §16.4 defines the payload derivation precisely: an implementation returns the
18
+ * domain payload with the reserved root `meta` OMITTED, and the payload schema is
19
+ * the final tool schema with only that property and its required entry removed.
20
+ * Everything else is preserved, because a schema that quietly dropped more would
21
+ * under-declare the result.
22
+ *
23
+ * @module @try-works/dsh-tool-mode/mcp/host-binding
24
+ */
25
+ import type { ToolContract } from '@try-works/tool-mode-contracts';
26
+ import type { ExternalCaller } from './client-grant.ts';
27
+ import type { McpHost } from './server.ts';
28
+ import { type InvocationAccounting } from '../invocation-accounting.ts';
29
+ /**
30
+ * Derive the payload schema from a contract's final output schema (§16.4).
31
+ *
32
+ * Only the reserved `meta` property and its `required` entry are removed. The rest
33
+ * of the schema — including constraints on the remaining properties — is preserved
34
+ * verbatim, because removing anything else would advertise a looser result than the
35
+ * contract actually enforces.
36
+ * @param outputSchema - the contract's output schema, including `meta`.
37
+ * @returns the payload schema.
38
+ */
39
+ export declare function derivePayloadSchema(outputSchema: Readonly<Record<string, unknown>>): Record<string, unknown>;
40
+ /** One published tool as the host knows it. */
41
+ export interface PublishedTool {
42
+ /** The tool name a caller uses. */
43
+ readonly toolName: string;
44
+ /** The contract it implements, which carries the canonical schemas. */
45
+ readonly contract: ToolContract;
46
+ /**
47
+ * Why this tool is not exportable, when it is not (MCP-12).
48
+ *
49
+ * A host tool using a non-JSON callback, a UI-only API, an unsupported attachment
50
+ * or a non-exportable policy must be REJECTED WITH A REASON rather than partly
51
+ * serialized, so the reason travels with the tool instead of being discovered by a
52
+ * caller whose call fails in a way nobody can explain.
53
+ */
54
+ readonly notExportableReason?: string;
55
+ }
56
+ /** What the binding needs from the host. */
57
+ export interface HostSurface {
58
+ /** The tools the host currently publishes. */
59
+ readonly published: readonly PublishedTool[];
60
+ /**
61
+ * Tools the host deliberately WITHHELD, by name, with the recorded reason (MCP-12).
62
+ *
63
+ * A caller that guesses a withheld name must learn why it is absent rather than
64
+ * receiving the same `unknown tool` answer as a name that never existed. The map
65
+ * is the publication decision, not a second lookup: it may include names omitted
66
+ * from `published` entirely.
67
+ */
68
+ readonly withheld?: ReadonlyMap<string, string>;
69
+ /**
70
+ * Execute one tool through the host path (MCP-08).
71
+ *
72
+ * Takes a server-issued call identity and the caller's signal; the implementation
73
+ * MUST route this through the same execution path a native call uses.
74
+ */
75
+ execute(request: {
76
+ readonly name: string;
77
+ readonly arguments: Readonly<Record<string, unknown>>;
78
+ readonly signal: AbortSignal;
79
+ /** Server-issued. A caller-supplied id would let a caller forge a receipt. */
80
+ readonly callId: string;
81
+ /**
82
+ * The AUTHENTICATED external caller and its derived grant (SEC-04).
83
+ *
84
+ * Absent for calls with no client identity (native paths). When present, the
85
+ * implementation MUST authorize the call against THIS caller's grant rather than
86
+ * the host's own — an external client is not the operator.
87
+ */
88
+ readonly caller?: ExternalCaller;
89
+ }): Promise<{
90
+ readonly isError: boolean;
91
+ readonly value?: unknown;
92
+ readonly message?: string;
93
+ }>;
94
+ }
95
+ /**
96
+ * Build the MCP host surface over a DSH tool surface.
97
+ *
98
+ * @param options - the host surface and this server's identity.
99
+ * @returns the MCP host the dispatch layer consumes.
100
+ */
101
+ export declare function createMcpHost(options: {
102
+ readonly surface: HostSurface;
103
+ readonly serverInfo: {
104
+ readonly name: string;
105
+ readonly version: string;
106
+ };
107
+ /** Called for each tool withheld, so a reason is recorded rather than lost. */
108
+ readonly onWithheld?: (tool: PublishedTool) => void;
109
+ /**
110
+ * Called once per EXTERNAL invocation, with its accounting (OBS-02).
111
+ *
112
+ * Wired EXPLICITLY because an external call is not automatically an agent-loop
113
+ * transcript: DSH observes `ctx.tools.execute`, and an MCP caller reaches the same
114
+ * pipeline through a different door. Without this the external half of the traffic has
115
+ * no receipt at all.
116
+ *
117
+ * It receives TIMINGS, A CLASS and SIZES — never the payload. The result is deliberately
118
+ * NOT passed in, so an implementation of this hook cannot duplicate a large result into a
119
+ * second log, which is the other half of what OBS-02 forbids.
120
+ *
121
+ * The invoked TOOL NAME rides alongside the accounting (task-13): external MCP calls are
122
+ * not session events, so a ledger that answers "which tools were used over MCP" needs
123
+ * the name here rather than re-deriving it from a session log that does not exist.
124
+ */
125
+ readonly onAccounted?: (accounting: InvocationAccounting, toolName: string) => void;
126
+ /** The engine that served the call, recorded WITH the measurement (OBS-05). */
127
+ readonly engineVersion?: string;
128
+ /** Operator-blocked confidential tools (MCP-11); refused before lookup/execution. */
129
+ readonly confidentialTools?: readonly string[];
130
+ /**
131
+ * The catalog caching policy carried on `tools/list` and `server/discover` (P26-14).
132
+ *
133
+ * Accepted as the UNVALIDATED config shape and validated HERE, once, so a bad
134
+ * operator value is refused with a named error at construction rather than surfacing
135
+ * as a per-request failure. Absent = private/0.
136
+ */
137
+ readonly cachePolicy?: {
138
+ readonly ttlMs?: number;
139
+ readonly cacheScope?: string;
140
+ };
141
+ /** Explicit catalog facts attached to discovery results (P26-14). */
142
+ readonly catalogFacts?: () => Record<string, unknown>;
143
+ }): McpHost;
144
+ //# sourceMappingURL=host-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-binding.d.ts","sourceRoot":"","sources":["../../src/mcp/host-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAA4C,MAAM,aAAa,CAAA;AACpF,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAA;AAsBpC;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC9C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAED,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CACtC;AA+CD,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAA;IAC5C;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE;QACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;QACrD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;QAC5B,8EAA8E;QAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB;;;;;;WAMG;QACH,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAA;KACjC,GAAG,OAAO,CAAC;QACV,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;QACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAC1B,CAAC,CAAA;CACH;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACrC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACxE,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAA;IACnD;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACnF,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,qFAAqF;IACrF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,qEAAqE;IACrE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACtD,GAAG,OAAO,CA2JV"}