@try-works/dsh-model-as-tool 0.1.3 → 0.4.0

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 (260) hide show
  1. package/bin/dsh-tool-mode-credentials.mjs +20 -0
  2. package/bin/dsh-tool-mode.mjs +202 -0
  3. package/catalog/desert-ant-models.json +693 -693
  4. package/client/client.model-tools.js +614 -0
  5. package/client/index.js +1717 -0
  6. package/lib/adapters/index.d.ts.map +1 -1
  7. package/lib/adapters/index.js +4 -4
  8. package/lib/bindings.d.ts.map +1 -1
  9. package/lib/bindings.js +26 -25
  10. package/lib/capability.d.ts.map +1 -1
  11. package/lib/capability.js +17 -0
  12. package/lib/capture-path.d.ts +97 -0
  13. package/lib/capture-path.d.ts.map +1 -0
  14. package/lib/capture-path.js +152 -0
  15. package/lib/diagnostics.d.ts +166 -0
  16. package/lib/diagnostics.d.ts.map +1 -0
  17. package/lib/diagnostics.js +135 -0
  18. package/lib/extension-dependencies.d.ts +325 -0
  19. package/lib/extension-dependencies.d.ts.map +1 -0
  20. package/lib/extension-dependencies.js +858 -0
  21. package/lib/extension-dispatch.d.ts +117 -0
  22. package/lib/extension-dispatch.d.ts.map +1 -0
  23. package/lib/extension-dispatch.js +124 -0
  24. package/lib/extension-registrar.d.ts +100 -0
  25. package/lib/extension-registrar.d.ts.map +1 -0
  26. package/lib/extension-registrar.js +134 -0
  27. package/lib/extensions-api.d.ts +221 -0
  28. package/lib/extensions-api.d.ts.map +1 -0
  29. package/lib/extensions-api.js +17 -0
  30. package/lib/extensions-remote.d.ts +54 -0
  31. package/lib/extensions-remote.d.ts.map +1 -0
  32. package/lib/extensions-remote.js +66 -0
  33. package/lib/extensions-service.d.ts +367 -0
  34. package/lib/extensions-service.d.ts.map +1 -0
  35. package/lib/extensions-service.js +1527 -0
  36. package/lib/harness-llm.d.ts +138 -0
  37. package/lib/harness-llm.d.ts.map +1 -0
  38. package/lib/harness-llm.js +218 -0
  39. package/lib/harness-serving.d.ts +95 -0
  40. package/lib/harness-serving.d.ts.map +1 -0
  41. package/lib/harness-serving.js +157 -0
  42. package/lib/headless.d.ts +97 -0
  43. package/lib/headless.d.ts.map +1 -0
  44. package/lib/headless.js +349 -0
  45. package/lib/http-acquisition.d.ts +27 -0
  46. package/lib/http-acquisition.d.ts.map +1 -0
  47. package/lib/http-acquisition.js +136 -0
  48. package/lib/index.d.ts +271 -7
  49. package/lib/index.d.ts.map +1 -1
  50. package/lib/index.js +2644 -70
  51. package/lib/invocation-accounting.d.ts +169 -0
  52. package/lib/invocation-accounting.d.ts.map +1 -0
  53. package/lib/invocation-accounting.js +148 -0
  54. package/lib/legacy-migration.d.ts +95 -0
  55. package/lib/legacy-migration.d.ts.map +1 -0
  56. package/lib/legacy-migration.js +429 -0
  57. package/lib/managed-workers.d.ts +151 -0
  58. package/lib/managed-workers.d.ts.map +1 -0
  59. package/lib/managed-workers.js +249 -0
  60. package/lib/mcp/client-grant.d.ts +74 -0
  61. package/lib/mcp/client-grant.d.ts.map +1 -0
  62. package/lib/mcp/client-grant.js +60 -0
  63. package/lib/mcp/credential-cli.d.ts +38 -0
  64. package/lib/mcp/credential-cli.d.ts.map +1 -0
  65. package/lib/mcp/credential-cli.js +148 -0
  66. package/lib/mcp/credential-store.d.ts +143 -0
  67. package/lib/mcp/credential-store.d.ts.map +1 -0
  68. package/lib/mcp/credential-store.js +454 -0
  69. package/lib/mcp/host-binding.d.ts +25 -0
  70. package/lib/mcp/host-binding.d.ts.map +1 -1
  71. package/lib/mcp/host-binding.js +107 -14
  72. package/lib/mcp/http.d.ts +68 -18
  73. package/lib/mcp/http.d.ts.map +1 -1
  74. package/lib/mcp/http.js +390 -62
  75. package/lib/mcp/oauth.d.ts +149 -0
  76. package/lib/mcp/oauth.d.ts.map +1 -0
  77. package/lib/mcp/oauth.js +396 -0
  78. package/lib/mcp/protocol.d.ts +46 -7
  79. package/lib/mcp/protocol.d.ts.map +1 -1
  80. package/lib/mcp/protocol.js +63 -16
  81. package/lib/mcp/rate-limit.d.ts +68 -0
  82. package/lib/mcp/rate-limit.d.ts.map +1 -0
  83. package/lib/mcp/rate-limit.js +114 -0
  84. package/lib/mcp/sdk-v2.d.ts +17 -0
  85. package/lib/mcp/sdk-v2.d.ts.map +1 -0
  86. package/lib/mcp/sdk-v2.js +181 -0
  87. package/lib/mcp/server.d.ts +11 -1
  88. package/lib/mcp/server.d.ts.map +1 -1
  89. package/lib/mcp/server.js +80 -13
  90. package/lib/mcp/stdio.d.ts.map +1 -1
  91. package/lib/mcp/stdio.js +9 -1
  92. package/lib/mcp/subscriptions.d.ts +43 -1
  93. package/lib/mcp/subscriptions.d.ts.map +1 -1
  94. package/lib/mcp/subscriptions.js +90 -9
  95. package/lib/model-qualification.d.ts +192 -0
  96. package/lib/model-qualification.d.ts.map +1 -0
  97. package/lib/model-qualification.js +178 -0
  98. package/lib/planning.d.ts +246 -0
  99. package/lib/planning.d.ts.map +1 -0
  100. package/lib/planning.js +457 -0
  101. package/lib/prepared-assets.d.ts +178 -0
  102. package/lib/prepared-assets.d.ts.map +1 -0
  103. package/lib/prepared-assets.js +286 -0
  104. package/lib/provider-bridge.d.ts +37 -0
  105. package/lib/provider-bridge.d.ts.map +1 -1
  106. package/lib/provider-bridge.js +189 -12
  107. package/lib/ptc-authority.d.ts +140 -0
  108. package/lib/ptc-authority.d.ts.map +1 -0
  109. package/lib/ptc-authority.js +216 -0
  110. package/lib/ptc-runtime.d.ts +156 -0
  111. package/lib/ptc-runtime.d.ts.map +1 -0
  112. package/lib/ptc-runtime.js +191 -0
  113. package/lib/publication.d.ts +2 -1
  114. package/lib/publication.d.ts.map +1 -1
  115. package/lib/publication.js +13 -5
  116. package/lib/receipt.d.ts.map +1 -1
  117. package/lib/receipt.js +8 -0
  118. package/lib/title-proposal.d.ts +194 -0
  119. package/lib/title-proposal.d.ts.map +1 -0
  120. package/lib/title-proposal.js +244 -0
  121. package/lib/tool-mode-run.d.ts +235 -0
  122. package/lib/tool-mode-run.d.ts.map +1 -0
  123. package/lib/tool-mode-run.js +283 -0
  124. package/lib/types.d.ts +3 -1
  125. package/lib/types.d.ts.map +1 -1
  126. package/lib/update-surface.d.ts +79 -0
  127. package/lib/update-surface.d.ts.map +1 -0
  128. package/lib/update-surface.js +224 -0
  129. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
  130. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
  131. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
  132. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
  133. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
  134. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
  135. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
  136. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
  137. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
  138. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -1
  139. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +69 -55
  140. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +4 -1
  141. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -1
  142. package/node_modules/@try-works/tool-mode-contracts/lib/index.js +26 -2
  143. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +28 -2
  144. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -1
  145. package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +93 -10
  146. package/node_modules/@try-works/tool-mode-contracts/package.json +0 -1
  147. package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
  148. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
  149. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
  150. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
  151. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +83 -0
  152. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
  153. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +125 -0
  154. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
  155. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
  156. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
  157. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
  158. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
  159. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
  160. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +32 -0
  161. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
  162. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +32 -0
  163. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
  164. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
  165. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +191 -0
  166. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +126 -0
  167. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
  168. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +297 -0
  169. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +216 -0
  170. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
  171. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +800 -0
  172. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
  173. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
  174. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
  175. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
  176. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
  177. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
  178. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
  179. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
  180. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
  181. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
  182. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
  183. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +235 -0
  184. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +367 -0
  185. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
  186. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +807 -0
  187. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts +44 -0
  188. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts.map +1 -0
  189. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.js +243 -0
  190. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
  191. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
  192. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
  193. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
  194. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
  195. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
  196. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
  197. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
  198. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
  199. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
  200. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
  201. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
  202. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
  203. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
  204. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
  205. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +118 -0
  206. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
  207. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
  208. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
  209. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
  210. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
  211. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +150 -0
  212. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
  213. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +670 -0
  214. package/node_modules/@try-works/tool-mode-extension-sdk/package.json +53 -0
  215. package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
  216. package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
  217. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +427 -0
  218. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
  219. package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +592 -0
  220. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +60 -0
  221. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
  222. package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +936 -0
  223. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
  224. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
  225. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +200 -0
  226. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
  227. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
  228. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
  229. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +105 -0
  230. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
  231. package/node_modules/@try-works/tool-mode-recipes/lib/images.js +129 -0
  232. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
  233. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
  234. package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
  235. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +325 -0
  236. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
  237. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1310 -0
  238. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
  239. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
  240. package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
  241. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +227 -0
  242. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
  243. package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +407 -0
  244. package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
  245. package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
  246. package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
  247. package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
  248. package/package.json +43 -15
  249. package/remote/spec.mjs +462 -0
  250. package/remote/typert.host.mjs +14 -0
  251. package/remote/typert.remote-client.mjs +16 -0
  252. package/lib/adapters/tongue.d.ts +0 -31
  253. package/lib/adapters/tongue.d.ts.map +0 -1
  254. package/lib/adapters/tongue.js +0 -93
  255. package/lib/adapters/voz.d.ts +0 -28
  256. package/lib/adapters/voz.d.ts.map +0 -1
  257. package/lib/adapters/voz.js +0 -102
  258. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts +0 -0
  259. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts.map +0 -0
  260. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.js +0 -0
@@ -0,0 +1,283 @@
1
+ /**
2
+ * The ONE authorized program-execution pipeline (CODE-02, CODE-03, CODE-08, ARCH-05).
3
+ *
4
+ * THE DEFECT THIS FIXES, found by adversarial review rather than by a test:
5
+ * `ptc-authority.ts` and `ptc-runtime.ts` had **zero callers outside tests**. Everything in
6
+ * them was correct and thoroughly covered — `buildToolBindings`, the guarded mount,
7
+ * `mayExposeToClients()` — and none of it ran in production. `tool_mode_run` did not exist,
8
+ * the mount guard never executed, and the exposure gate guarded nothing because there was
9
+ * no caller to refuse.
10
+ *
11
+ * A security control with no callers is not a control; it is a symbol. This module is the
12
+ * caller.
13
+ *
14
+ * The wiring enforces three things the directive requires and nothing else did:
15
+ *
16
+ * 1. **ONE pipeline.** Native PTC and any external `tool_mode_run` reach tools through the
17
+ * SAME `buildToolBindings` call, so authorization cannot differ between the two doors.
18
+ * 2. **The grant is the grant.** The requested names are intersected with the host's own
19
+ * `allowedTools` and the live registry, and the whole request is refused if anything is
20
+ * unattainable.
21
+ * 3. **The exposure gate has a caller.** `mayExposeToClients()` returning false now
22
+ * actually refuses something, with the reason attached.
23
+ *
24
+ * @module @try-works/dsh-model-as-tool/tool-mode-run
25
+ */
26
+ import { admitTimeout, buildToolBindings, exposureWithheldReason, mayExposeToClients, mountPtcRuntimeIfAbsent, PTC_SERVICE, } from "./ptc-runtime.js";
27
+ import { AsyncLocalStorage } from 'node:async_hooks';
28
+ /** Create the per-call external grant carrier. */
29
+ export function createExternalGrantContext() {
30
+ const store = new AsyncLocalStorage();
31
+ return {
32
+ run(grant, work) {
33
+ return store.run(grant, work);
34
+ },
35
+ current() {
36
+ return store.getStore();
37
+ },
38
+ };
39
+ }
40
+ /**
41
+ * Create the runner.
42
+ *
43
+ * @param environment - how to reach tools and the runtime.
44
+ * @returns the runner.
45
+ */
46
+ export function createProgramRunner(environment) {
47
+ let prepared;
48
+ /** Materialized backend, resolved lazily at most once. */
49
+ let backend;
50
+ const materializeBackend = () => {
51
+ backend ??= (async () => {
52
+ // A FUNCTION backend is a lazy resolver; a CLASS is a plugin constructor and
53
+ // must not be invoked here (the mount does the construction). The source
54
+ // prefix distinguishes the two, which is exact for native classes. Wrapped
55
+ // constructors (bound/proxied/transpiled) can slip through as resolvers; the
56
+ // try/catch converts their invocation error into the SAME undefined the
57
+ // designed 'backend-unavailable' refusal reports, so no caller sees an
58
+ // opaque TypeError instead of the documented deployment fact.
59
+ const value = environment.backend;
60
+ const isClass = typeof value === 'function' && /^class\s/.test(Function.prototype.toString.call(value));
61
+ if (typeof value !== 'function' || isClass)
62
+ return value;
63
+ try {
64
+ return await value();
65
+ }
66
+ catch {
67
+ // The failure is reported through prepare()'s 'backend-unavailable'
68
+ // reason, which is the designed channel; the detail does not need a
69
+ // second logger the runner does not own.
70
+ return undefined;
71
+ }
72
+ })();
73
+ return backend;
74
+ };
75
+ return {
76
+ async prepare() {
77
+ // Idempotent: the guard is inside, and re-running it must not double-mount.
78
+ if (prepared !== undefined)
79
+ return prepared;
80
+ prepared = await mountPtcRuntimeIfAbsent(environment.context, await materializeBackend(), {
81
+ timeoutMs: 120_000,
82
+ maxTimeoutMs: 600_000,
83
+ });
84
+ return prepared;
85
+ },
86
+ externalExposurePermitted() {
87
+ return mayExposeToClients(environment.operatorGranted());
88
+ },
89
+ externalExposureReason() {
90
+ return exposureWithheldReason(environment.operatorGranted());
91
+ },
92
+ async run(request) {
93
+ const runtime = environment.runtime();
94
+ if (runtime === undefined) {
95
+ return {
96
+ ok: false,
97
+ code: 'unavailable',
98
+ message: 'no PTC runtime is mounted, so no program can run',
99
+ };
100
+ }
101
+ /**
102
+ * THE AUTHORIZED PIPELINE, and the only place bindings are built.
103
+ *
104
+ * `buildToolBindings` intersects the request with the GRANT and the live registry and
105
+ * refuses the whole thing if any name is unattainable. Both doors — native PTC and any
106
+ * external surface — come through here, which is what makes them the same pipeline
107
+ * rather than two implementations that happen to agree today.
108
+ */
109
+ let toolCalls = 0;
110
+ const countedResolve = (name) => {
111
+ const binding = environment.resolve(name);
112
+ if (binding === undefined)
113
+ return undefined;
114
+ // A counter wrapper, not a permission change: the program's binding call is
115
+ // counted so the CODE-02 meta reports real usage rather than a fabricated 0.
116
+ return async (args) => {
117
+ toolCalls += 1;
118
+ return binding(args);
119
+ };
120
+ };
121
+ const bindings = buildToolBindings({
122
+ requested: request.requested,
123
+ // THE GRANT IS READ PER RUN: an external client's call composes under the
124
+ // CLIENT's grant (SEC-04), the host path under the host's own.
125
+ authority: { granted: environment.grant(), visible: environment.visible() },
126
+ resolve: countedResolve,
127
+ });
128
+ if (!bindings.ok) {
129
+ return { ok: false, code: 'unauthorized', message: bindings.message };
130
+ }
131
+ try {
132
+ const result = await runtime.run(runtime.resolve({
133
+ program: request.program,
134
+ bindings: [bindings.namespace],
135
+ // The budget is CLAMPED here, not passed through: `null` means "no deadline" in
136
+ // the runtime's vocabulary, which is a request to opt out of budgeting entirely.
137
+ timeoutMs: admitTimeout(request.timeoutMs),
138
+ ...request.cwd === undefined ? {} : { cwd: request.cwd },
139
+ ...request.signal === undefined ? {} : { signal: request.signal },
140
+ }));
141
+ if (result.error !== undefined && result.error !== null) {
142
+ // A cancelled run is NOT a failure, and the distinction reaches the caller rather
143
+ // than being flattened.
144
+ const kind = result.error.kind;
145
+ return {
146
+ ok: false,
147
+ code: kind === 'abort' ? 'cancelled' : 'failed',
148
+ message: result.error.message ?? `the program ended with ${String(kind)}`,
149
+ };
150
+ }
151
+ return { ok: true, value: result.value, logs: result.logs ?? [], toolCalls };
152
+ }
153
+ catch (error) {
154
+ return {
155
+ ok: false,
156
+ code: 'failed',
157
+ message: error instanceof Error ? error.message : String(error),
158
+ };
159
+ }
160
+ },
161
+ };
162
+ }
163
+ /**
164
+ * The refusal an EXTERNAL caller receives (CODE-08).
165
+ *
166
+ * A separate function so the gate has a single enforcement point rather than a condition
167
+ * repeated at each call site — the shape that let the original gate go unused.
168
+ * @param runner - the runner.
169
+ * @returns the refusal, or undefined when exposure is permitted.
170
+ */
171
+ export function externalRefusal(runner) {
172
+ if (runner.externalExposurePermitted())
173
+ return undefined;
174
+ return { message: runner.externalExposureReason() };
175
+ }
176
+ /** The service key the runner depends on, re-exported so a caller need not import both. */
177
+ export { PTC_SERVICE };
178
+ /**
179
+ * The `tool_mode_run` MCP contract, in the ToolContract shape (CODE-02).
180
+ *
181
+ * ONE definition serves the MCP export surface and the conformance test, so the
182
+ * two cannot drift the way an inline object at the export site would: the test
183
+ * validates this shape's MCP projection against the pinned schema before it ever
184
+ * ships on a live tools/list.
185
+ */
186
+ export const TOOL_MODE_RUN_CONTRACT = {
187
+ contract: 'hosted.tool_mode_run',
188
+ version: '1.0.0',
189
+ toolName: 'tool_mode_run',
190
+ description: 'Run a program that calls Tool Mode tools (CODE-02).',
191
+ inputSchema: {
192
+ type: 'object',
193
+ additionalProperties: false,
194
+ required: ['description', 'code', 'tools'],
195
+ properties: {
196
+ description: { type: 'string' },
197
+ code: { type: 'string' },
198
+ input: {},
199
+ tools: { type: 'array', items: { type: 'string' } },
200
+ timeout_ms: { type: 'integer' },
201
+ },
202
+ },
203
+ outputSchema: {
204
+ type: 'object',
205
+ additionalProperties: false,
206
+ properties: {
207
+ result: {},
208
+ logs: { type: 'array', items: { type: 'string' } },
209
+ meta: { type: 'object' },
210
+ },
211
+ },
212
+ semantics: { deterministic: false, readsInputs: true },
213
+ limits: {},
214
+ unsupported: ['no access to management or installer bindings'],
215
+ };
216
+ /**
217
+ * Serve one CODE-02 request through the authorized pipeline (CODE-02/04).
218
+ *
219
+ * This is the `tool_mode_run` served path: the caller's arguments are validated
220
+ * into the CODE-02 shape, the program runs through the SAME runner native PTC
221
+ * uses, and the report carries the receipt, elapsed time, call count, catalog
222
+ * revision and warnings the interface promises.
223
+ *
224
+ * `input` is refused when the pinned runtime cannot bind it structurally: CODE-04
225
+ * forbids string interpolation into source, and the current PTC runtime has no
226
+ * data-global path, so an input-bearing program gets a precise refusal naming
227
+ * that limitation rather than a silently interpolated program.
228
+ * @param args - the caller's arguments.
229
+ * @param runner - the prepared runner.
230
+ * @param report - the report-shaped facts the host owns (receipt id, revision).
231
+ * @returns the report.
232
+ */
233
+ export async function serveProgram(args, runner, report) {
234
+ const description = typeof args.description === 'string' ? args.description : '';
235
+ const code = typeof args.code === 'string' ? args.code : '';
236
+ if (code.trim().length === 0) {
237
+ throw new Error('`code` must be a non-empty program body');
238
+ }
239
+ void description;
240
+ const requested = Array.isArray(args.tools)
241
+ ? args.tools.filter((name) => typeof name === 'string')
242
+ : [];
243
+ if (requested.length === 0) {
244
+ throw new Error('`tools` must name at least one tool the program will call');
245
+ }
246
+ if (args.input !== undefined && args.input !== null) {
247
+ /**
248
+ * CODE-04: `input` is bound through a supported structured-data path, never
249
+ * interpolated into source. The pinned PTC runtime materialises FUNCTION
250
+ * namespaces only, so there is no data path to bind it through today. Refusing
251
+ * with that fact is the honest outcome; interpolating JSON into the program
252
+ * would be the silent violation the requirement names.
253
+ */
254
+ throw new Error('`input` cannot be bound: the pinned PTC runtime has no structured-data path, '
255
+ + 'and CODE-04 forbids interpolating it into source. Use a program that takes '
256
+ + 'no input data, or run against a runtime that supports data binding.');
257
+ }
258
+ const prepared = await runner.prepare();
259
+ if (!prepared.mounted && prepared.reason === 'backend-unavailable') {
260
+ throw new Error('the Node PTC backend is unavailable on this deployment, so no program can run');
261
+ }
262
+ const started = Date.now();
263
+ const outcome = await runner.run({
264
+ program: code,
265
+ requested,
266
+ ...typeof args.timeout_ms === 'number' ? { timeoutMs: args.timeout_ms } : {},
267
+ });
268
+ if (!outcome.ok) {
269
+ throw new Error(`${outcome.code}: ${outcome.message}`);
270
+ }
271
+ return {
272
+ result: outcome.value ?? null,
273
+ logs: outcome.logs,
274
+ meta: {
275
+ receiptId: report.receiptId,
276
+ elapsedMs: Date.now() - started,
277
+ toolCalls: outcome.toolCalls,
278
+ catalogRevision: report.catalogRevision,
279
+ warnings: [],
280
+ },
281
+ };
282
+ }
283
+ //# sourceMappingURL=tool-mode-run.js.map
package/lib/types.d.ts CHANGED
@@ -107,8 +107,10 @@ export interface ModelCatalogEntry {
107
107
  }
108
108
  /** How an adapter reaches a model at run time. */
109
109
  export type ModelRoute =
110
+ /** A Tool Mode extension package loaded in this process. */
111
+ 'extension'
110
112
  /** An npm package loaded in this process. */
111
- 'npm-native'
113
+ | 'npm-native'
112
114
  /** An npm package plus a caller-supplied ONNX Runtime module. */
113
115
  | 'npm-onnxruntime'
114
116
  /** The Desert Ant CLI, run as a child process (macOS and Linux). */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The host's UpdateHostSurface (EXT-30, slice 3): the operator approval
3
+ * surface, the two-phase commit with quiesce/rebind hooks, and the standalone
4
+ * rollback with a bounded rebindRestored.
5
+ *
6
+ * The SDK owns the durable mechanics (staging, validation reports, approval
7
+ * RECORDS, the atomic pointer, the auto-rollback); this module owns the HOST
8
+ * decisions the SDK refuses to invent (design doc §6):
9
+ *
10
+ * - the pending listing + approve/deny over the SDK's approval records;
11
+ * - the quiesce (stop old-generation admissions) and the rebind (republish the
12
+ * new generation) — supplied as closures so the index wiring passes the
13
+ * lifecycle/registrar pair and tests can pass recorded fakes;
14
+ * - the ALL-OR-NOTHING rebind wrapper: the SDK's auto-rollback re-runs NO
15
+ * hooks (the REBIND-REVERT contract), so a rebind failure restores the
16
+ * previous surface HERE, before the pointer rollback lands;
17
+ * - the host-side timeout bound on rebindRestored (the SDK awaits it with no
18
+ * bound; only the management caller must not hang).
19
+ *
20
+ * The management channel stays the ONLY caller of this surface (AT-39).
21
+ *
22
+ * @module @dsh-model-as-tool/update-surface
23
+ */
24
+ import type { UpdateCommitResult, UpdateRollbackResult, UpdateValidationReport } from '@try-works/tool-mode-extension-sdk';
25
+ /** One pending staged update, from the staging directory + the approval record. */
26
+ export interface PendingUpdateEntry {
27
+ readonly extensionId: string;
28
+ readonly stagedVersion: string;
29
+ /** The version the report was computed against. */
30
+ readonly currentVersion: string;
31
+ readonly stagedAt: string;
32
+ readonly report: UpdateValidationReport;
33
+ /** The persisted approval, when one was recorded. */
34
+ readonly approval?: {
35
+ readonly approved: boolean;
36
+ readonly reason?: string;
37
+ };
38
+ }
39
+ /** The host-side lifecycle closures the surface drives. */
40
+ export interface UpdateHostHooks {
41
+ /** Stop old-generation admissions (withdraw handles, stop admitting). */
42
+ readonly quiesce: (extensionId: string) => Promise<void>;
43
+ /** Publish the new generation's surface (must be all-or-nothing per the SDK contract). */
44
+ readonly rebind: (extensionId: string, version: string) => Promise<void>;
45
+ }
46
+ /** The operator approval surface + commit/rollback. */
47
+ export interface UpdateHostSurface {
48
+ /** The pending staged updates with their reports and approval records. */
49
+ listPendingUpdates(): PendingUpdateEntry[];
50
+ /** Record ONE approval decision (write-once per staged version). */
51
+ decide(extensionId: string, stagedVersion: string, decision: {
52
+ approved: true;
53
+ } | {
54
+ approved: false;
55
+ reason: string;
56
+ }): void;
57
+ /**
58
+ * Commit a staged update through the two-phase seam.
59
+ * @throws when the SDK refuses (no approved record, integrity, quiesce, rebind).
60
+ */
61
+ commit(extensionId: string, stagedVersion: string): Promise<UpdateCommitResult>;
62
+ /** Roll the pointer back with a TIME-BOUNDED rebindRestored. */
63
+ rollback(extensionId: string): Promise<UpdateRollbackResult>;
64
+ }
65
+ /** The surface options. */
66
+ export interface UpdateHostSurfaceOptions {
67
+ readonly storeDir: string;
68
+ readonly profile: string;
69
+ readonly hooks: UpdateHostHooks;
70
+ /** The host-side bound on rebindRestored; default 30 s. */
71
+ readonly rebindTimeoutMs?: number;
72
+ }
73
+ /**
74
+ * Create the host update surface.
75
+ * @param options - the store location, profile, lifecycle hooks and the timeout bound.
76
+ * @returns the surface.
77
+ */
78
+ export declare function createUpdateHostSurface(options: UpdateHostSurfaceOptions): UpdateHostSurface;
79
+ //# sourceMappingURL=update-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-surface.d.ts","sourceRoot":"","sources":["../src/update-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,oCAAoC,CAAA;AAI3C,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAA;IACvC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7E;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACzE;AAED,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,kBAAkB,IAAI,kBAAkB,EAAE,CAAA;IAC1C,oEAAoE;IACpE,MAAM,CACJ,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,QAAQ,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACjE,IAAI,CAAA;IACP;;;OAGG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC/E,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;CAC7D;AAED,2BAA2B;AAC3B,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAClC;AA6CD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAsJ5F"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The host's UpdateHostSurface (EXT-30, slice 3): the operator approval
3
+ * surface, the two-phase commit with quiesce/rebind hooks, and the standalone
4
+ * rollback with a bounded rebindRestored.
5
+ *
6
+ * The SDK owns the durable mechanics (staging, validation reports, approval
7
+ * RECORDS, the atomic pointer, the auto-rollback); this module owns the HOST
8
+ * decisions the SDK refuses to invent (design doc §6):
9
+ *
10
+ * - the pending listing + approve/deny over the SDK's approval records;
11
+ * - the quiesce (stop old-generation admissions) and the rebind (republish the
12
+ * new generation) — supplied as closures so the index wiring passes the
13
+ * lifecycle/registrar pair and tests can pass recorded fakes;
14
+ * - the ALL-OR-NOTHING rebind wrapper: the SDK's auto-rollback re-runs NO
15
+ * hooks (the REBIND-REVERT contract), so a rebind failure restores the
16
+ * previous surface HERE, before the pointer rollback lands;
17
+ * - the host-side timeout bound on rebindRestored (the SDK awaits it with no
18
+ * bound; only the management caller must not hang).
19
+ *
20
+ * The management channel stays the ONLY caller of this surface (AT-39).
21
+ *
22
+ * @module @dsh-model-as-tool/update-surface
23
+ */
24
+ import { commitUpdate, recordApproval, rollback, ExtensionStore } from '@try-works/tool-mode-extension-sdk';
25
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
26
+ import { join } from 'node:path';
27
+ /** The current pointer for one extension, read from the profile pointers. */
28
+ function currentPointer(store, profile, extensionId) {
29
+ const pointers = store.readProfilePointers(profile);
30
+ if (pointers.corrupt) {
31
+ throw new Error(`the profile pointers are unreadable: ${pointers.diagnostic ?? 'unknown reason'}`);
32
+ }
33
+ return pointers.value.activeVersions[extensionId];
34
+ }
35
+ /** The staged-update metadata file for one staged directory. */
36
+ const stageMetadataPath = (stagedDir) => join(stagedDir, 'update-stage.json');
37
+ /**
38
+ * A rebind failure whose PREVIOUS surface the wrapper already restored.
39
+ *
40
+ * The commit catch would otherwise restore the previous surface a second time
41
+ * (the REBIND-REVERT contract: the wrapper owns the revert; the catch owns the
42
+ * post-quiesce-failure restore, which is a different situation).
43
+ */
44
+ class RebindRestoredFailure extends Error {
45
+ constructor(message, cause) {
46
+ super(message, { cause });
47
+ this.name = 'RebindRestoredFailure';
48
+ }
49
+ }
50
+ /** Bound one promise host-side: the caller stops waiting, the work may continue. */
51
+ async function withTimeout(promise, timeoutMs, label) {
52
+ let timer;
53
+ const bound = new Promise((_resolve, reject) => {
54
+ timer = setTimeout(() => reject(new Error(`${label} timed out after ${timeoutMs} ms (host-side bound)`)), timeoutMs);
55
+ if (typeof timer === 'object' && timer !== null && 'unref' in timer && typeof timer.unref === 'function') {
56
+ // Kept REFERENCED deliberately: a hanging rebind must not let the process
57
+ // exit mid-update; the timeout is what bounds it.
58
+ }
59
+ });
60
+ try {
61
+ return await Promise.race([promise, bound]);
62
+ }
63
+ finally {
64
+ if (timer !== undefined)
65
+ clearTimeout(timer);
66
+ }
67
+ }
68
+ /**
69
+ * Create the host update surface.
70
+ * @param options - the store location, profile, lifecycle hooks and the timeout bound.
71
+ * @returns the surface.
72
+ */
73
+ export function createUpdateHostSurface(options) {
74
+ const store = new ExtensionStore(options.storeDir);
75
+ const timeoutMs = options.rebindTimeoutMs ?? 30_000;
76
+ const { profile, hooks } = options;
77
+ /**
78
+ * The surfaces the rebind wrapper ALREADY restored. The SDK wraps a failed
79
+ * rebind into its own ManagementError, so the commit catch cannot see the
80
+ * marker on the error itself; this in-surface set carries it instead (the
81
+ * REBIND-REVERT contract: the wrapper's revert is never duplicated).
82
+ */
83
+ const wrapperRestored = new Set();
84
+ return {
85
+ listPendingUpdates() {
86
+ const staging = join(options.storeDir, 'staging');
87
+ if (!existsSync(staging))
88
+ return [];
89
+ const entries = [];
90
+ for (const name of readdirSync(staging)) {
91
+ if (!name.endsWith('.staged'))
92
+ continue;
93
+ const stagedDir = join(staging, name);
94
+ const metadataPath = stageMetadataPath(stagedDir);
95
+ if (!existsSync(metadataPath))
96
+ continue; // an aborted stage attempt; never listed
97
+ let metadata;
98
+ try {
99
+ metadata = JSON.parse(readFileSync(metadataPath, 'utf8'));
100
+ }
101
+ catch {
102
+ continue; // a corrupt metadata record fails closed: not listed, never committed
103
+ }
104
+ if (typeof metadata.extensionId !== 'string' || typeof metadata.stagedVersion !== 'string'
105
+ || typeof metadata.report !== 'object' || metadata.report === null) {
106
+ continue;
107
+ }
108
+ const approval = store.readApproval(metadata.extensionId, metadata.stagedVersion);
109
+ if (approval.corrupt) {
110
+ entries.push({ ...metadata, approval: { approved: false, reason: `the approval record is unreadable: ${approval.diagnostic ?? 'unknown reason'}` } });
111
+ continue;
112
+ }
113
+ entries.push({
114
+ extensionId: metadata.extensionId,
115
+ stagedVersion: metadata.stagedVersion,
116
+ currentVersion: metadata.currentVersion,
117
+ stagedAt: metadata.stagedAt,
118
+ report: metadata.report,
119
+ ...approval.value === undefined ? {} : {
120
+ approval: {
121
+ approved: approval.value.approved,
122
+ ...('reason' in approval.value && typeof approval.value.reason === 'string'
123
+ ? { reason: approval.value.reason }
124
+ : {}),
125
+ },
126
+ },
127
+ });
128
+ }
129
+ return entries;
130
+ },
131
+ decide(extensionId, stagedVersion, decision) {
132
+ recordApproval({ storeDir: options.storeDir, extensionId, stagedVersion, decision });
133
+ },
134
+ async commit(extensionId, stagedVersion) {
135
+ // The pointer BEFORE the commit: the restore target when a post-quiesce
136
+ // failure withdraws the old surface.
137
+ const previous = currentPointer(store, profile, extensionId);
138
+ /** True once the quiesce hook was INVOKED: after that a failure owes a restore. */
139
+ let quiesced = false;
140
+ const quiescePrevious = async () => {
141
+ // Set BEFORE the hook runs: a quiesce that threw may have withdrawn the
142
+ // surface partially, and the restore is the safe recovery either way.
143
+ quiesced = true;
144
+ await hooks.quiesce(extensionId);
145
+ };
146
+ /**
147
+ * ALL-OR-NOTHING with the revert INSIDE the wrapper (the REBIND-REVERT
148
+ * contract): the SDK's auto-rollback re-runs no hooks, so a rebind that
149
+ * partially published must restore the previous surface itself before
150
+ * rethrowing. The previous pointer is still recorded under the rolled-back
151
+ * value after the SDK's auto-rollback, so re-activating it lands on the
152
+ * version the pointer will name.
153
+ */
154
+ const rebindNext = async (nextVersion) => {
155
+ try {
156
+ await withTimeout(hooks.rebind(extensionId, nextVersion), timeoutMs, `rebind ${extensionId}@${nextVersion}`);
157
+ }
158
+ catch (error) {
159
+ if (previous !== undefined) {
160
+ try {
161
+ await withTimeout(hooks.rebind(extensionId, previous), timeoutMs, `rebind-restore ${extensionId}@${previous}`);
162
+ wrapperRestored.add(`${extensionId}@${previous}`);
163
+ }
164
+ catch (restoreError) {
165
+ // The restore failure rides along: the primary rebind error is the
166
+ // named reason; the restore failure is recorded in the message.
167
+ throw new Error(`${error instanceof Error ? error.message : String(error)} (and restoring ${extensionId}@${previous} also failed: `
168
+ + `${restoreError instanceof Error ? restoreError.message : String(restoreError)})`);
169
+ }
170
+ }
171
+ // The previous surface is restored; the commit catch must NOT restore
172
+ // it again — the marker distinguishes this path.
173
+ throw new RebindRestoredFailure(error instanceof Error ? error.message : String(error), error);
174
+ }
175
+ };
176
+ try {
177
+ return await commitUpdate({
178
+ storeDir: options.storeDir,
179
+ profile,
180
+ extensionId,
181
+ stagedVersion,
182
+ hooks: { quiescePrevious, rebindNext },
183
+ });
184
+ }
185
+ catch (error) {
186
+ /**
187
+ * A failure AFTER the quiesce (pointer write failure, an integrity
188
+ * refusal after the quiesce, or the auto-rollback after a rebind the
189
+ * wrapper could NOT restore) left the old surface withdrawn while the
190
+ * pointer names a version nothing republished. Restore the recorded
191
+ * pointer's surface here; when the restore itself fails, name BOTH
192
+ * failures. A rebind the wrapper ALREADY restored is skipped — it was
193
+ * the wrapper's own revert (the REBIND-REVERT contract).
194
+ */
195
+ if (quiesced && !(error instanceof RebindRestoredFailure)) {
196
+ const restored = currentPointer(store, profile, extensionId);
197
+ if (restored !== undefined && !wrapperRestored.delete(`${extensionId}@${restored}`)) {
198
+ try {
199
+ await withTimeout(hooks.rebind(extensionId, restored), timeoutMs, `commit-restore ${extensionId}@${restored}`);
200
+ }
201
+ catch (restoreError) {
202
+ throw new Error(`${error instanceof Error ? error.message : String(error)} (and restoring ${extensionId}@${restored} also failed: `
203
+ + `${restoreError instanceof Error ? restoreError.message : String(restoreError)})`);
204
+ }
205
+ }
206
+ }
207
+ throw error;
208
+ }
209
+ },
210
+ async rollback(extensionId) {
211
+ // rebindRestored is bound HOST-side (the SDK awaits it unbounded after the
212
+ // restore is durable); a timeout surfaces as the SDK's hookFailure.
213
+ return await rollback({
214
+ storeDir: options.storeDir,
215
+ profile,
216
+ extensionId,
217
+ rebindRestored: async (restoredVersion) => {
218
+ await withTimeout(hooks.rebind(extensionId, restoredVersion), timeoutMs, `rebind-restored ${extensionId}@${restoredVersion}`);
219
+ },
220
+ });
221
+ },
222
+ };
223
+ }
224
+ //# sourceMappingURL=update-surface.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The remaining standard tool contracts (EXT-21, task-69).
3
+ *
4
+ * These descriptors are SCHEMAS AND SEMANTICS ONLY — no model bindings, no
5
+ * weights, no host code (EXT-17). Each is a closed schema with honest
6
+ * `semantics`, `limits` and `unsupported` records, matching the vocabulary the
7
+ * host registers and the extension packages implement against.
8
+ *
9
+ * @module @try-works/tool-mode-contracts/contracts/standard
10
+ */
11
+ import type { ToolContract } from '../registry.ts';
12
+ /** The `text.title` contract at version 1.0.0 (RCP-12). */
13
+ export declare const textTitle: ToolContract;
14
+ /** The `image.describe` contract at version 1.0.0 (HLM-12). */
15
+ export declare const imageDescribe: ToolContract;
16
+ /** The `embed.multimodal` contract at version 1.0.0 (EmbeddingGemma family). */
17
+ export declare const multimodalEmbed: ToolContract;
18
+ /** The `semantic.similarity` contract at version 1.0.0. */
19
+ export declare const semanticSimilarity: ToolContract;
20
+ /** The `semantic.rank` contract at version 1.0.0. */
21
+ export declare const semanticRank: ToolContract;
22
+ /** The `semantic.classify` contract at version 1.0.0. */
23
+ export declare const semanticClassify: ToolContract;
24
+ /** The `semantic.deduplicate` contract at version 1.0.0. */
25
+ export declare const semanticDeduplicate: ToolContract;
26
+ /** The `media.find_moments` contract at version 1.0.0. */
27
+ export declare const mediaFindMoments: ToolContract;
28
+ /** The `decision.choose` contract at version 1.0.0 (Laya family). */
29
+ export declare const decisionChoose: ToolContract;
30
+ /** The `decision.test` contract at version 1.0.0. */
31
+ export declare const decisionTest: ToolContract;
32
+ /** The `decision.score` contract at version 1.0.0. */
33
+ export declare const decisionScore: ToolContract;
34
+ /** The `structured.extract` contract at version 1.0.0 (Needle family). */
35
+ export declare const structuredExtract: ToolContract;
36
+ /** The `plan.tools` contract at version 1.0.0 (Needle family). */
37
+ export declare const toolsPlan: ToolContract;
38
+ //# sourceMappingURL=standard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard.d.ts","sourceRoot":"","sources":["../../src/contracts/standard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,2DAA2D;AAC3D,eAAO,MAAM,SAAS,EAAE,YAuCvB,CAAA;AAED,+DAA+D;AAC/D,eAAO,MAAM,aAAa,EAAE,YAmC3B,CAAA;AAGD,gFAAgF;AAChF,eAAO,MAAM,eAAe,EAAE,YAwC7B,CAAA;AAED,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,EAAE,YA0BhC,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,YAAY,EAAE,YAuC1B,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,YA8B9B,CAAA;AAED,4DAA4D;AAC5D,eAAO,MAAM,mBAAmB,EAAE,YAmCjC,CAAA;AAED,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,EAAE,YAwC9B,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,EAAE,YA8B5B,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,YAAY,EAAE,YA8B1B,CAAA;AAED,sDAAsD;AACtD,eAAO,MAAM,aAAa,EAAE,YAoC3B,CAAA;AAED,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,EAAE,YA4B/B,CAAA;AAED,kEAAkE;AAClE,eAAO,MAAM,SAAS,EAAE,YAwCvB,CAAA"}