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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/bin/dsh-tool-mode-credentials.mjs +20 -0
  2. package/bin/dsh-tool-mode.mjs +202 -0
  3. package/catalog/desert-ant-models.json +693 -693
  4. package/client/client.model-tools.js +592 -0
  5. package/client/index.js +1679 -0
  6. package/lib/adapters/index.d.ts.map +1 -1
  7. package/lib/adapters/index.js +4 -4
  8. package/lib/bindings.d.ts.map +1 -1
  9. package/lib/bindings.js +26 -25
  10. package/lib/capability.d.ts.map +1 -1
  11. package/lib/capability.js +17 -0
  12. package/lib/capture-path.d.ts +97 -0
  13. package/lib/capture-path.d.ts.map +1 -0
  14. package/lib/capture-path.js +152 -0
  15. package/lib/diagnostics.d.ts +166 -0
  16. package/lib/diagnostics.d.ts.map +1 -0
  17. package/lib/diagnostics.js +135 -0
  18. package/lib/extension-dependencies.d.ts +197 -0
  19. package/lib/extension-dependencies.d.ts.map +1 -0
  20. package/lib/extension-dependencies.js +369 -0
  21. package/lib/extension-dispatch.d.ts +117 -0
  22. package/lib/extension-dispatch.d.ts.map +1 -0
  23. package/lib/extension-dispatch.js +124 -0
  24. package/lib/extension-registrar.d.ts +100 -0
  25. package/lib/extension-registrar.d.ts.map +1 -0
  26. package/lib/extension-registrar.js +134 -0
  27. package/lib/extensions-api.d.ts +217 -0
  28. package/lib/extensions-api.d.ts.map +1 -0
  29. package/lib/extensions-api.js +17 -0
  30. package/lib/extensions-remote.d.ts +54 -0
  31. package/lib/extensions-remote.d.ts.map +1 -0
  32. package/lib/extensions-remote.js +66 -0
  33. package/lib/extensions-service.d.ts +334 -0
  34. package/lib/extensions-service.d.ts.map +1 -0
  35. package/lib/extensions-service.js +1351 -0
  36. package/lib/harness-llm.d.ts +138 -0
  37. package/lib/harness-llm.d.ts.map +1 -0
  38. package/lib/harness-llm.js +218 -0
  39. package/lib/harness-serving.d.ts +95 -0
  40. package/lib/harness-serving.d.ts.map +1 -0
  41. package/lib/harness-serving.js +157 -0
  42. package/lib/headless.d.ts +97 -0
  43. package/lib/headless.d.ts.map +1 -0
  44. package/lib/headless.js +349 -0
  45. package/lib/http-acquisition.d.ts +27 -0
  46. package/lib/http-acquisition.d.ts.map +1 -0
  47. package/lib/http-acquisition.js +136 -0
  48. package/lib/index.d.ts +250 -7
  49. package/lib/index.d.ts.map +1 -1
  50. package/lib/index.js +2625 -70
  51. package/lib/invocation-accounting.d.ts +169 -0
  52. package/lib/invocation-accounting.d.ts.map +1 -0
  53. package/lib/invocation-accounting.js +148 -0
  54. package/lib/legacy-migration.d.ts +95 -0
  55. package/lib/legacy-migration.d.ts.map +1 -0
  56. package/lib/legacy-migration.js +429 -0
  57. package/lib/managed-workers.d.ts +151 -0
  58. package/lib/managed-workers.d.ts.map +1 -0
  59. package/lib/managed-workers.js +249 -0
  60. package/lib/mcp/client-grant.d.ts +74 -0
  61. package/lib/mcp/client-grant.d.ts.map +1 -0
  62. package/lib/mcp/client-grant.js +60 -0
  63. package/lib/mcp/credential-cli.d.ts +38 -0
  64. package/lib/mcp/credential-cli.d.ts.map +1 -0
  65. package/lib/mcp/credential-cli.js +148 -0
  66. package/lib/mcp/credential-store.d.ts +143 -0
  67. package/lib/mcp/credential-store.d.ts.map +1 -0
  68. package/lib/mcp/credential-store.js +454 -0
  69. package/lib/mcp/host-binding.d.ts +25 -0
  70. package/lib/mcp/host-binding.d.ts.map +1 -1
  71. package/lib/mcp/host-binding.js +107 -14
  72. package/lib/mcp/http.d.ts +68 -18
  73. package/lib/mcp/http.d.ts.map +1 -1
  74. package/lib/mcp/http.js +390 -62
  75. package/lib/mcp/oauth.d.ts +149 -0
  76. package/lib/mcp/oauth.d.ts.map +1 -0
  77. package/lib/mcp/oauth.js +396 -0
  78. package/lib/mcp/protocol.d.ts +46 -7
  79. package/lib/mcp/protocol.d.ts.map +1 -1
  80. package/lib/mcp/protocol.js +63 -16
  81. package/lib/mcp/rate-limit.d.ts +68 -0
  82. package/lib/mcp/rate-limit.d.ts.map +1 -0
  83. package/lib/mcp/rate-limit.js +114 -0
  84. package/lib/mcp/sdk-v2.d.ts +17 -0
  85. package/lib/mcp/sdk-v2.d.ts.map +1 -0
  86. package/lib/mcp/sdk-v2.js +181 -0
  87. package/lib/mcp/server.d.ts +11 -1
  88. package/lib/mcp/server.d.ts.map +1 -1
  89. package/lib/mcp/server.js +80 -13
  90. package/lib/mcp/stdio.d.ts.map +1 -1
  91. package/lib/mcp/stdio.js +9 -1
  92. package/lib/mcp/subscriptions.d.ts +43 -1
  93. package/lib/mcp/subscriptions.d.ts.map +1 -1
  94. package/lib/mcp/subscriptions.js +90 -9
  95. package/lib/model-qualification.d.ts +192 -0
  96. package/lib/model-qualification.d.ts.map +1 -0
  97. package/lib/model-qualification.js +178 -0
  98. package/lib/planning.d.ts +246 -0
  99. package/lib/planning.d.ts.map +1 -0
  100. package/lib/planning.js +457 -0
  101. package/lib/prepared-assets.d.ts +178 -0
  102. package/lib/prepared-assets.d.ts.map +1 -0
  103. package/lib/prepared-assets.js +286 -0
  104. package/lib/provider-bridge.d.ts +37 -0
  105. package/lib/provider-bridge.d.ts.map +1 -1
  106. package/lib/provider-bridge.js +189 -12
  107. package/lib/ptc-authority.d.ts +140 -0
  108. package/lib/ptc-authority.d.ts.map +1 -0
  109. package/lib/ptc-authority.js +216 -0
  110. package/lib/ptc-runtime.d.ts +156 -0
  111. package/lib/ptc-runtime.d.ts.map +1 -0
  112. package/lib/ptc-runtime.js +191 -0
  113. package/lib/publication.d.ts +2 -1
  114. package/lib/publication.d.ts.map +1 -1
  115. package/lib/publication.js +13 -5
  116. package/lib/receipt.d.ts.map +1 -1
  117. package/lib/receipt.js +8 -0
  118. package/lib/title-proposal.d.ts +194 -0
  119. package/lib/title-proposal.d.ts.map +1 -0
  120. package/lib/title-proposal.js +244 -0
  121. package/lib/tool-mode-run.d.ts +235 -0
  122. package/lib/tool-mode-run.d.ts.map +1 -0
  123. package/lib/tool-mode-run.js +283 -0
  124. package/lib/types.d.ts +3 -1
  125. package/lib/types.d.ts.map +1 -1
  126. package/lib/update-surface.d.ts +79 -0
  127. package/lib/update-surface.d.ts.map +1 -0
  128. package/lib/update-surface.js +224 -0
  129. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/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 +31 -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 +31 -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 +185 -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/update-flow.d.ts +185 -0
  188. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
  189. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
  190. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
  191. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
  192. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
  193. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
  194. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
  195. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
  196. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
  197. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
  198. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
  199. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
  200. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
  201. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
  202. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +118 -0
  203. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
  204. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
  205. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
  206. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
  207. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
  208. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +150 -0
  209. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
  210. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +670 -0
  211. package/node_modules/@try-works/tool-mode-extension-sdk/package.json +53 -0
  212. package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
  213. package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
  214. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +427 -0
  215. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
  216. package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +592 -0
  217. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +60 -0
  218. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
  219. package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +936 -0
  220. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
  221. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
  222. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +200 -0
  223. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
  224. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
  225. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
  226. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +105 -0
  227. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
  228. package/node_modules/@try-works/tool-mode-recipes/lib/images.js +129 -0
  229. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
  230. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
  231. package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
  232. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +325 -0
  233. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
  234. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1310 -0
  235. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
  236. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
  237. package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
  238. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +227 -0
  239. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
  240. package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +407 -0
  241. package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
  242. package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
  243. package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
  244. package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
  245. package/package.json +43 -15
  246. package/remote/spec.mjs +439 -0
  247. package/remote/typert.host.mjs +14 -0
  248. package/remote/typert.remote-client.mjs +16 -0
  249. package/lib/adapters/tongue.d.ts +0 -31
  250. package/lib/adapters/tongue.d.ts.map +0 -1
  251. package/lib/adapters/tongue.js +0 -93
  252. package/lib/adapters/voz.d.ts +0 -28
  253. package/lib/adapters/voz.d.ts.map +0 -1
  254. package/lib/adapters/voz.js +0 -102
  255. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts +0 -0
  256. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts.map +0 -0
  257. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.js +0 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * The HOST-side injection seam for the DSH-backed harness provider (HLM-01/02/03).
3
+ *
4
+ * The recipes package ships {@link DshLlmProvider} — a REAL `LlmProvider` over the DSH
5
+ * harness's own LLM surface (`ctx.llm`), with capabilities read from the model's own
6
+ * descriptor and images transported through a deployment-supplied hook. What the host
7
+ * adds here is the COMPOSITION, and it is deliberately narrow:
8
+ *
9
+ * - the surface is reached STRUCTURALLY, so the host never imports the DSH packages at
10
+ * this boundary (they are the deployment's peers, and this module reads exactly the
11
+ * two members the adapter consumes);
12
+ * - the image transport is minted ONLY when the deployment can actually reach the DSH
13
+ * attachment service (`ctx.attachments.saveImage`): without it the provider is built
14
+ * WITHOUT the hook, so an image-capable model honestly reports `images: 'unknown'`
15
+ * and the broker refuses image recipes with EXECUTOR_CAPABILITY_UNKNOWN — never a
16
+ * silent drop (HLM-11);
17
+ * - every failure fails CLOSED: an unreachable surface, a descriptor that cannot be
18
+ * resolved, or a descriptor naming another route yields `undefined` plus a diagnostic,
19
+ * so the deployment runs as if the option were absent rather than half-wired.
20
+ *
21
+ * @module @try-works/dsh-model-as-tool/harness-llm
22
+ */
23
+ import { type LlmProvider } from '@try-works/tool-mode-recipes';
24
+ /** The opt-in configuration naming one DSH provider route and model. */
25
+ export interface HarnessModelConfig {
26
+ /** The registered adapter route, e.g. `deepseek`. */
27
+ readonly provider: string;
28
+ /** The exact model id, e.g. `deepseek-chat`. */
29
+ readonly model: string;
30
+ }
31
+ /** One discovered default route/model (the AUTO step's product). */
32
+ export interface HarnessModelDiscovery {
33
+ readonly provider: string;
34
+ readonly model: string;
35
+ }
36
+ /**
37
+ * Discover the deployment's default/selected model for the AUTO composition
38
+ * (task-93 + task-97). DEFAULT-SAFE: any ambiguity or malformed entry yields
39
+ * `undefined` — never a guessed route.
40
+ *
41
+ * Probes, in order:
42
+ * 1. the settings service's `describe()` descriptor list: the descriptor whose
43
+ * `ns` is `agent-default-model` (the live web profile's settings namespace),
44
+ * with the resolved `{provider, model}` read from its `value` — the actual
45
+ * SettingsForms API (there is no synchronous `get(ns)`, which was live bug
46
+ * #2);
47
+ * 2. the root config's `model.default` as the `provider/model` string.
48
+ * @param ctx - the surfaces to probe, read structurally.
49
+ * @returns the discovered route/model, or undefined when none is unambiguous.
50
+ */
51
+ export declare function discoverDefaultHarnessModel(ctx: {
52
+ readonly settings?: unknown;
53
+ readonly config?: {
54
+ readonly model?: {
55
+ readonly default?: unknown;
56
+ };
57
+ };
58
+ }): HarnessModelDiscovery | undefined;
59
+ /** The attachment-minting surface `ctx.attachments` satisfies structurally. */
60
+ interface DshAttachmentsSurface {
61
+ saveImage(input: {
62
+ readonly data: Uint8Array;
63
+ readonly mediaType: string;
64
+ }): Promise<unknown>;
65
+ }
66
+ /**
67
+ * The LlmRuntime contract the AUTO composition resolves through (read from
68
+ * D:\deepseek-harness\packages\llm\llm\lib\types\index.d.ts):
69
+ * - `resolveModelInfo(provider, model)` keys on the REGISTERED ROUTE id
70
+ * (LlmRuntime.resolveModelInfo → registration(provider) → the adapter),
71
+ * - `listProviders(): LlmProviderInfo[]` (sync) — the registered routes,
72
+ * - `listConfigurableProviders(): LlmConfigurableProvider[]` (sync) — the
73
+ * directory mapping a settings namespace to the route it activates
74
+ * (`{provider, displayName, settingsNs, settingsPath}`),
75
+ * - `listModels(provider): Promise<LlmModelInfo[]>` — the per-route catalog.
76
+ */
77
+ export interface HarnessLlmRuntimeSurface {
78
+ resolveModelInfo(provider: string, model: string, signal?: AbortSignal): Promise<unknown>;
79
+ listProviders?(): readonly {
80
+ id: string;
81
+ name: string;
82
+ }[];
83
+ listConfigurableProviders?(): readonly {
84
+ provider: string;
85
+ displayName: string;
86
+ settingsNs?: string;
87
+ settingsPath?: readonly string[];
88
+ }[];
89
+ listModels?(provider: string): Promise<readonly {
90
+ provider?: string;
91
+ id: string;
92
+ name: string;
93
+ }[]>;
94
+ }
95
+ /** One resolution outcome (task-98): the runnable pair, or the exact refusal. */
96
+ export type HarnessModelResolution = {
97
+ readonly ok: true;
98
+ readonly route: string;
99
+ readonly model: string;
100
+ } | {
101
+ readonly ok: false;
102
+ readonly kind: 'not-ready-yet' | 'not-configured';
103
+ readonly reason: string;
104
+ };
105
+ /**
106
+ * Resolve a RUNNABLE (route, model) pair the way the runtime does (task-98):
107
+ * the configured provider may be a settings namespace or display name rather
108
+ * than the registered ROUTE id, so a direct resolveModelInfo failure is not
109
+ * 'not configured' — the runtime's own listings map the configured provider to
110
+ * its route and confirm the model through the route's catalog. An EMPTY route
111
+ * registry is 'not ready yet' (the adapter plugins register after this plugin
112
+ * in the composition order), which is retryable — never locked in as 'none'.
113
+ * @param llm - the LLM surface, read structurally (the listings are optional).
114
+ * @param desired - the configured provider/model (the agent-default-model pair).
115
+ * @param log - the diagnostic sink.
116
+ * @returns the runnable pair, or the exact not-ready-yet/not-configured reason.
117
+ */
118
+ export declare function resolveRunnableHarnessModel(llm: HarnessLlmRuntimeSurface, desired: {
119
+ readonly provider: string;
120
+ readonly model: string;
121
+ }, log?: (message: string) => void): Promise<HarnessModelResolution>;
122
+ /**
123
+ * Build the DSH-backed harness provider for one opt-in route/model.
124
+ *
125
+ * DEFAULT OFF: this runs only when the operator set {@link HarnessModelConfig}, and it
126
+ * returns `undefined` (with a diagnostic) whenever the DSH surface cannot actually
127
+ * serve the named model.
128
+ * @param ctx - the host context, read structurally.
129
+ * @param config - the operator's provider/model selection.
130
+ * @param log - a diagnostic sink for the fail-closed reasons.
131
+ * @returns the provider, or undefined when the deployment cannot build one.
132
+ */
133
+ export declare function buildHarnessLlmProvider(ctx: {
134
+ readonly llm?: unknown;
135
+ readonly attachments?: DshAttachmentsSurface;
136
+ }, config: HarnessModelConfig, log?: (message: string) => void): Promise<LlmProvider | undefined>;
137
+ export {};
138
+ //# sourceMappingURL=harness-llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-llm.d.ts","sourceRoot":"","sources":["../src/harness-llm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAA8D,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAE3H,wEAAwE;AACxE,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,oEAAoE;AACpE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;CACtE,GAAG,qBAAqB,GAAG,SAAS,CAiCpC;AAED,+EAA+E;AAC/E,UAAU,qBAAqB;IAC7B,SAAS,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9F;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,wBAAwB;IACvC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACzF,aAAa,CAAC,IAAI,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzD,yBAAyB,CAAC,IAAI,SAAS;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAA;IACzI,UAAU,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAA;CACnG;AAED,iFAAiF;AACjF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtG;;;;;;;;;;;;GAYG;AACH,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,wBAAwB,EAC7B,OAAO,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC9D,GAAG,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GACxC,OAAO,CAAC,sBAAsB,CAAC,CAwFjC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,qBAAqB,CAAA;CAC7C,EACD,MAAM,EAAE,kBAAkB,EAC1B,GAAG,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GACxC,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAiClC"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * The HOST-side injection seam for the DSH-backed harness provider (HLM-01/02/03).
3
+ *
4
+ * The recipes package ships {@link DshLlmProvider} — a REAL `LlmProvider` over the DSH
5
+ * harness's own LLM surface (`ctx.llm`), with capabilities read from the model's own
6
+ * descriptor and images transported through a deployment-supplied hook. What the host
7
+ * adds here is the COMPOSITION, and it is deliberately narrow:
8
+ *
9
+ * - the surface is reached STRUCTURALLY, so the host never imports the DSH packages at
10
+ * this boundary (they are the deployment's peers, and this module reads exactly the
11
+ * two members the adapter consumes);
12
+ * - the image transport is minted ONLY when the deployment can actually reach the DSH
13
+ * attachment service (`ctx.attachments.saveImage`): without it the provider is built
14
+ * WITHOUT the hook, so an image-capable model honestly reports `images: 'unknown'`
15
+ * and the broker refuses image recipes with EXECUTOR_CAPABILITY_UNKNOWN — never a
16
+ * silent drop (HLM-11);
17
+ * - every failure fails CLOSED: an unreachable surface, a descriptor that cannot be
18
+ * resolved, or a descriptor naming another route yields `undefined` plus a diagnostic,
19
+ * so the deployment runs as if the option were absent rather than half-wired.
20
+ *
21
+ * @module @try-works/dsh-model-as-tool/harness-llm
22
+ */
23
+ import { DshLlmProvider } from '@try-works/tool-mode-recipes';
24
+ /**
25
+ * Discover the deployment's default/selected model for the AUTO composition
26
+ * (task-93 + task-97). DEFAULT-SAFE: any ambiguity or malformed entry yields
27
+ * `undefined` — never a guessed route.
28
+ *
29
+ * Probes, in order:
30
+ * 1. the settings service's `describe()` descriptor list: the descriptor whose
31
+ * `ns` is `agent-default-model` (the live web profile's settings namespace),
32
+ * with the resolved `{provider, model}` read from its `value` — the actual
33
+ * SettingsForms API (there is no synchronous `get(ns)`, which was live bug
34
+ * #2);
35
+ * 2. the root config's `model.default` as the `provider/model` string.
36
+ * @param ctx - the surfaces to probe, read structurally.
37
+ * @returns the discovered route/model, or undefined when none is unambiguous.
38
+ */
39
+ export function discoverDefaultHarnessModel(ctx) {
40
+ // 1. The agent-default-model settings descriptor (what the Web composer
41
+ // writes into the profile patch; its ns is 'agent-default-model').
42
+ const settings = ctx.settings;
43
+ const described = settings?.describe?.();
44
+ if (Array.isArray(described)) {
45
+ for (const descriptor of described) {
46
+ if (descriptor === null || typeof descriptor !== 'object')
47
+ continue;
48
+ const entry = descriptor;
49
+ if (entry.ns !== 'agent-default-model')
50
+ continue;
51
+ const value = entry.value;
52
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
53
+ const resolved = value;
54
+ const provider = resolved['provider'];
55
+ const model = resolved['model'];
56
+ if (typeof provider === 'string' && provider.length > 0 && typeof model === 'string' && model.length > 0) {
57
+ return { provider, model };
58
+ }
59
+ }
60
+ // The matching descriptor carries no unambiguous pair: refuse rather
61
+ // than continue probing a malformed entry.
62
+ return undefined;
63
+ }
64
+ }
65
+ // 2. The root config's model.default, the `provider/model` string.
66
+ const declared = ctx.config?.model?.default;
67
+ if (typeof declared === 'string') {
68
+ const slash = declared.indexOf('/');
69
+ if (slash > 0 && slash < declared.length - 1) {
70
+ return { provider: declared.slice(0, slash), model: declared.slice(slash + 1) };
71
+ }
72
+ }
73
+ return undefined;
74
+ }
75
+ /**
76
+ * Resolve a RUNNABLE (route, model) pair the way the runtime does (task-98):
77
+ * the configured provider may be a settings namespace or display name rather
78
+ * than the registered ROUTE id, so a direct resolveModelInfo failure is not
79
+ * 'not configured' — the runtime's own listings map the configured provider to
80
+ * its route and confirm the model through the route's catalog. An EMPTY route
81
+ * registry is 'not ready yet' (the adapter plugins register after this plugin
82
+ * in the composition order), which is retryable — never locked in as 'none'.
83
+ * @param llm - the LLM surface, read structurally (the listings are optional).
84
+ * @param desired - the configured provider/model (the agent-default-model pair).
85
+ * @param log - the diagnostic sink.
86
+ * @returns the runnable pair, or the exact not-ready-yet/not-configured reason.
87
+ */
88
+ export async function resolveRunnableHarnessModel(llm, desired, log = () => { }) {
89
+ // 1. The direct pair: the config's provider IS the route.
90
+ try {
91
+ await llm.resolveModelInfo(desired.provider, desired.model);
92
+ return { ok: true, route: desired.provider, model: desired.model };
93
+ }
94
+ catch (error) {
95
+ log(`direct ${desired.provider}/${desired.model} does not resolve: ${error instanceof Error ? error.message : String(error)}`);
96
+ }
97
+ // 2. Map the configured provider to a registered route.
98
+ const providers = llm.listProviders?.() ?? [];
99
+ if (providers.length === 0) {
100
+ return {
101
+ ok: false,
102
+ kind: 'not-ready-yet',
103
+ reason: 'the deployment\'s LLM surface has not registered its provider routes yet; retry once the deployment '
104
+ + 'finishes starting (this is not a configuration error)',
105
+ };
106
+ }
107
+ const byId = providers.find(entry => entry.id === desired.provider);
108
+ const byName = providers.find(entry => entry.name === desired.provider);
109
+ let route = byId?.id ?? byName?.id;
110
+ const directory = llm.listConfigurableProviders?.() ?? [];
111
+ if (route === undefined) {
112
+ const entry = directory.find(candidate => (candidate.provider === desired.provider
113
+ || candidate.settingsNs === desired.provider
114
+ || candidate.displayName === desired.provider));
115
+ route = entry?.provider;
116
+ }
117
+ if (route === undefined) {
118
+ /**
119
+ * TASK-100: an EMPTY configurable-provider directory means the runtime is
120
+ * still registering — the adapter routes appear FIRST and the directory
121
+ * entries land after, so a provider the directory cannot map yet is
122
+ * not-ready-yet, never a terminal not-configured (the live 0.3.4
123
+ * regression finalized exactly this too early). The retry keeps polling.
124
+ */
125
+ if (directory.length === 0) {
126
+ return {
127
+ ok: false,
128
+ kind: 'not-ready-yet',
129
+ reason: 'the deployment\'s LLM surface has not registered its provider routes yet; retry once the deployment '
130
+ + 'finishes starting (this is not a configuration error)',
131
+ };
132
+ }
133
+ return {
134
+ ok: false,
135
+ kind: 'not-configured',
136
+ reason: `the configured provider ${JSON.stringify(desired.provider)} is not a registered LLM route in this `
137
+ + 'deployment; set config.harnessModel to a runnable route',
138
+ };
139
+ }
140
+ // 3. Confirm the model through the route's own catalog, then a direct probe.
141
+ if (llm.listModels !== undefined) {
142
+ try {
143
+ const catalog = await llm.listModels(route);
144
+ if (catalog.some(entry => entry.id === desired.model)) {
145
+ return { ok: true, route, model: desired.model };
146
+ }
147
+ if (catalog.length > 0) {
148
+ return {
149
+ ok: false,
150
+ kind: 'not-configured',
151
+ reason: `the model ${JSON.stringify(desired.model)} is not served by the ${route} route (its catalog lists `
152
+ + `${catalog.map(entry => entry.id).join(', ')}); set config.harnessModel to a served model`,
153
+ };
154
+ }
155
+ }
156
+ catch (error) {
157
+ log(`the ${route} catalog could not be listed: ${error instanceof Error ? error.message : String(error)}`);
158
+ }
159
+ }
160
+ try {
161
+ await llm.resolveModelInfo(route, desired.model);
162
+ return { ok: true, route, model: desired.model };
163
+ }
164
+ catch {
165
+ return {
166
+ ok: false,
167
+ kind: 'not-configured',
168
+ reason: `the ${route} route does not serve the model ${JSON.stringify(desired.model)}; set config.harnessModel `
169
+ + 'to a served model',
170
+ };
171
+ }
172
+ }
173
+ /**
174
+ * Build the DSH-backed harness provider for one opt-in route/model.
175
+ *
176
+ * DEFAULT OFF: this runs only when the operator set {@link HarnessModelConfig}, and it
177
+ * returns `undefined` (with a diagnostic) whenever the DSH surface cannot actually
178
+ * serve the named model.
179
+ * @param ctx - the host context, read structurally.
180
+ * @param config - the operator's provider/model selection.
181
+ * @param log - a diagnostic sink for the fail-closed reasons.
182
+ * @returns the provider, or undefined when the deployment cannot build one.
183
+ */
184
+ export async function buildHarnessLlmProvider(ctx, config, log = () => { }) {
185
+ if (ctx.llm === undefined) {
186
+ log('the DSH LLM surface is not mounted in this deployment, so the harness provider is not wired');
187
+ return undefined;
188
+ }
189
+ // HLM-11: the image transport exists only when the attachment service does. Without
190
+ // it the adapter reports images 'unknown' and the broker refuses rather than drops.
191
+ const attachments = ctx.attachments;
192
+ let images;
193
+ if (attachments !== undefined) {
194
+ images = async (image) => ({
195
+ type: 'image',
196
+ attachment: await attachments.saveImage({ data: image.bytes, mediaType: image.mediaType }),
197
+ });
198
+ }
199
+ else {
200
+ log('the DSH attachment service is not mounted, so image recipes will refuse with EXECUTOR_CAPABILITY_UNKNOWN');
201
+ }
202
+ try {
203
+ return await DshLlmProvider.create({
204
+ llm: ctx.llm,
205
+ provider: config.provider,
206
+ model: config.model,
207
+ ...images === undefined ? {} : { images },
208
+ });
209
+ }
210
+ catch (error) {
211
+ // Fail closed: a descriptor that cannot be resolved (route not registered) or one
212
+ // naming another model leaves the deployment as if the option were absent.
213
+ log(`could not build the harness provider for ${config.provider}/${config.model}: `
214
+ + `${error instanceof Error ? error.message : String(error)}`);
215
+ return undefined;
216
+ }
217
+ }
218
+ //# sourceMappingURL=harness-llm.js.map
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Serving a declarative package's recipes through a deployment-supplied harness provider.
3
+ *
4
+ * THE LAST LINK OF SLICE 3, and the reason it is a module rather than a few lines in the host:
5
+ * this is where a resolved RECIPE becomes a callable TOOL, and the pieces have to be joined in a
6
+ * specific order for the authorization to mean anything.
7
+ *
8
+ * WHAT THIS DELIBERATELY IS NOT. It does not construct an `LlmProvider`. Which model answers a
9
+ * harness call is a deployment's business, and this plugin holds no model-specific code — that
10
+ * is an architectural rule the repository enforces with a gate. Instead a deployment SUPPLIES a
11
+ * provider and this module does the joining: authorize the recipe's tool name, run through the
12
+ * broker, and refuse honestly when no provider was supplied.
13
+ *
14
+ * WHY THE REFUSAL IS STILL THE DEFAULT. A declarative package resolves and its recipes parse,
15
+ * and without a provider nothing can call a model. Serving the tool anyway would present a tool
16
+ * that fails at invocation, so the refusal happens at RESOLUTION — where a reader can see why —
17
+ * rather than at the first call.
18
+ *
19
+ * @module @try-works/dsh-model-as-tool/harness-serving
20
+ */
21
+ import { type BrokerRecord, type LlmProvider } from '@try-works/tool-mode-recipes';
22
+ /** A deployment's harness composition. */
23
+ export interface HarnessComposition {
24
+ /**
25
+ * The provider that answers harness calls, supplied by the DEPLOYMENT.
26
+ *
27
+ * Absent when a deployment composes none — which is the state this plugin ships in, and the
28
+ * state the refusal exists for.
29
+ */
30
+ readonly provider?: LlmProvider;
31
+ /**
32
+ * Where invocation records go.
33
+ *
34
+ * The broker REFUSES TO CONSTRUCT without one, because a broker that records nothing cannot be
35
+ * audited. Making it required here means a caller cannot compose a harness path that silently
36
+ * reports nothing — the failure is at construction rather than at audit time.
37
+ */
38
+ readonly journal: (record: BrokerRecord) => void;
39
+ }
40
+ /**
41
+ * A harness call the caller CANCELLED.
42
+ *
43
+ * Distinct from `HarnessFailedError` on purpose: a caller who walked away is not a malfunction,
44
+ * and conflating the two makes every cancellation look like a fault. The same discipline the
45
+ * invocation accounting applies to `cancelled`.
46
+ */
47
+ export declare class HarnessCancelledError extends Error {
48
+ readonly toolName: string;
49
+ readonly reason: string;
50
+ readonly name = "HarnessCancelledError";
51
+ constructor(toolName: string, reason: string);
52
+ }
53
+ /**
54
+ * A harness call that FAILED, carrying the broker's machine-readable code.
55
+ *
56
+ * The code is preserved rather than flattened into a message, so a caller branches on the CAUSE
57
+ * instead of matching prose.
58
+ */
59
+ export declare class HarnessFailedError extends Error {
60
+ readonly toolName: string;
61
+ readonly code: string;
62
+ readonly reason: string;
63
+ readonly name = "HarnessFailedError";
64
+ constructor(toolName: string, code: string, reason: string);
65
+ }
66
+ /** A recipe made callable. */
67
+ export interface ServedRecipe {
68
+ readonly implementationId: string;
69
+ readonly contractId: string;
70
+ readonly toolName: string;
71
+ /** Run the recipe. Throws with the broker's own reason when it cannot. */
72
+ readonly invoke: (args: Record<string, unknown>, signal?: AbortSignal) => Promise<unknown>;
73
+ }
74
+ /** The outcome of preparing a declarative package's recipes. */
75
+ export type ServeOutcome = {
76
+ readonly ok: true;
77
+ readonly served: readonly ServedRecipe[];
78
+ } | {
79
+ readonly ok: false;
80
+ readonly code: 'no-provider' | 'recipe-rejected';
81
+ readonly detail: string;
82
+ };
83
+ /**
84
+ * Prepare a declarative package's resolved recipes for serving.
85
+ *
86
+ * @param composition - the deployment's harness composition.
87
+ * @param resolved - the recipes resolved through the convention.
88
+ * @returns the served recipes, or the reason none can be served.
89
+ */
90
+ export declare function prepareDeclarative(composition: HarnessComposition, resolved: readonly {
91
+ readonly id: string;
92
+ readonly contractId: string;
93
+ readonly recipe: unknown;
94
+ }[]): ServeOutcome;
95
+ //# sourceMappingURL=harness-serving.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-serving.d.ts","sourceRoot":"","sources":["../src/harness-serving.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,WAAW,EAEjB,MAAM,8BAA8B,CAAA;AAErC,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAA;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;CACjD;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAElC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM;IAD9D,SAAkB,IAAI,2BAA0B;gBAC3B,QAAQ,EAAE,MAAM,EAAW,MAAM,EAAE,MAAM;CAG/D;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAE/B,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM;IADrF,SAAkB,IAAI,wBAAuB;gBACxB,QAAQ,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,EAAW,MAAM,EAAE,MAAM;CAGtF;AAED,8BAA8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3F;AAED,gEAAgE;AAChE,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErG;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,kBAAkB,EAC/B,QAAQ,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,GAClG,YAAY,CA+Fd"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Serving a declarative package's recipes through a deployment-supplied harness provider.
3
+ *
4
+ * THE LAST LINK OF SLICE 3, and the reason it is a module rather than a few lines in the host:
5
+ * this is where a resolved RECIPE becomes a callable TOOL, and the pieces have to be joined in a
6
+ * specific order for the authorization to mean anything.
7
+ *
8
+ * WHAT THIS DELIBERATELY IS NOT. It does not construct an `LlmProvider`. Which model answers a
9
+ * harness call is a deployment's business, and this plugin holds no model-specific code — that
10
+ * is an architectural rule the repository enforces with a gate. Instead a deployment SUPPLIES a
11
+ * provider and this module does the joining: authorize the recipe's tool name, run through the
12
+ * broker, and refuse honestly when no provider was supplied.
13
+ *
14
+ * WHY THE REFUSAL IS STILL THE DEFAULT. A declarative package resolves and its recipes parse,
15
+ * and without a provider nothing can call a model. Serving the tool anyway would present a tool
16
+ * that fails at invocation, so the refusal happens at RESOLUTION — where a reader can see why —
17
+ * rather than at the first call.
18
+ *
19
+ * @module @try-works/dsh-model-as-tool/harness-serving
20
+ */
21
+ import { HarnessBroker, parseRecipe, } from '@try-works/tool-mode-recipes';
22
+ /**
23
+ * A harness call the caller CANCELLED.
24
+ *
25
+ * Distinct from `HarnessFailedError` on purpose: a caller who walked away is not a malfunction,
26
+ * and conflating the two makes every cancellation look like a fault. The same discipline the
27
+ * invocation accounting applies to `cancelled`.
28
+ */
29
+ export class HarnessCancelledError extends Error {
30
+ toolName;
31
+ reason;
32
+ name = 'HarnessCancelledError';
33
+ constructor(toolName, reason) {
34
+ super(`the harness recipe ${toolName} was cancelled: ${reason}`);
35
+ this.toolName = toolName;
36
+ this.reason = reason;
37
+ }
38
+ }
39
+ /**
40
+ * A harness call that FAILED, carrying the broker's machine-readable code.
41
+ *
42
+ * The code is preserved rather than flattened into a message, so a caller branches on the CAUSE
43
+ * instead of matching prose.
44
+ */
45
+ export class HarnessFailedError extends Error {
46
+ toolName;
47
+ code;
48
+ reason;
49
+ name = 'HarnessFailedError';
50
+ constructor(toolName, code, reason) {
51
+ super(`the harness recipe ${toolName} failed (${code}): ${reason}`);
52
+ this.toolName = toolName;
53
+ this.code = code;
54
+ this.reason = reason;
55
+ }
56
+ }
57
+ /**
58
+ * Prepare a declarative package's resolved recipes for serving.
59
+ *
60
+ * @param composition - the deployment's harness composition.
61
+ * @param resolved - the recipes resolved through the convention.
62
+ * @returns the served recipes, or the reason none can be served.
63
+ */
64
+ export function prepareDeclarative(composition, resolved) {
65
+ /**
66
+ * NO PROVIDER MEANS NO SERVING, and the refusal names the composition rather than the package.
67
+ * A reader who is told "the package is declarative" would look in the wrong place: the package
68
+ * is complete and its recipes resolve.
69
+ */
70
+ if (composition.provider === undefined) {
71
+ return {
72
+ ok: false,
73
+ code: 'no-provider',
74
+ detail: 'this deployment composes no harness LlmProvider, so a declarative package\'s recipes '
75
+ + 'cannot be executed. The recipes resolved and the broker is available; what is absent '
76
+ + 'is the provider that would answer a model call.',
77
+ };
78
+ }
79
+ const broker = new HarnessBroker({ record: composition.journal });
80
+ const served = [];
81
+ for (const entry of resolved) {
82
+ /**
83
+ * THE RECIPE IS VALIDATED HERE, and it previously was not — a HIGH-severity gap found by
84
+ * adversarial review.
85
+ *
86
+ * This line used to be a bare cast: `entry.recipe as RecipeManifest`. The production resolver
87
+ * hands over raw `JSON.parse` output, so NOTHING validated the file between disk and
88
+ * execution. The review took `text-title.json` and applied one mutation at a time — an
89
+ * unexpected `tools` array, a `systemPrompt`, a `${process.env.SECRET_KEY}` interpolation, an
90
+ * uppercase or path-like tool name, `__proto__`, an absurd `maxOutputTokens`, a missing
91
+ * `policy`, a missing `inputs`. `parseRecipe` REFUSED ALL TEN; `prepareDeclarative` SERVED ALL
92
+ * TEN, and they executed. The validator was available and imported by the test that was
93
+ * supposed to cover this path — and bypassed by the only path that runs a recipe.
94
+ *
95
+ * A cast is a claim about a value the compiler cannot check, and here the claim was false for
96
+ * exactly the inputs an untrusted package would supply.
97
+ */
98
+ const parsed = parseRecipe(entry.recipe);
99
+ if (!parsed.ok) {
100
+ return {
101
+ ok: false,
102
+ code: 'recipe-rejected',
103
+ detail: `${entry.id}: the recipe did not validate: ${JSON.stringify(parsed).slice(0, 300)}`,
104
+ };
105
+ }
106
+ const recipe = parsed.recipe;
107
+ /**
108
+ * AUTHORIZATION IS PER TOOL NAME, and it happens BEFORE anything is served. A recipe whose
109
+ * name was never authorized must not become callable, or the broker would refuse at
110
+ * invocation — a failure far from its cause.
111
+ */
112
+ const toolName = recipe.tool.name;
113
+ try {
114
+ broker.authorize(toolName, composition.provider);
115
+ }
116
+ catch (error) {
117
+ return {
118
+ ok: false,
119
+ code: 'recipe-rejected',
120
+ detail: `${entry.id}: the broker refused to authorize ${toolName}: `
121
+ + `${error instanceof Error ? error.message : String(error)}`,
122
+ };
123
+ }
124
+ served.push({
125
+ implementationId: entry.id,
126
+ contractId: entry.contractId,
127
+ toolName,
128
+ async invoke(args, signal) {
129
+ const outcome = await broker.run(recipe, args, signal === undefined ? {} : { signal });
130
+ if (outcome.kind === 'completed')
131
+ return outcome.text;
132
+ /**
133
+ * THE BROKER'S NON-COMPLETED VARIANTS ARE `failed` AND `cancelled` — and an earlier
134
+ * version of this comment named `refused`, `truncated` and `tool_call` instead.
135
+ *
136
+ * Those are variants of `LlmCompletion`, the PROVIDER's reply, not of `BrokerOutcome`,
137
+ * what `run` returns. They were plausible and wrong, and the difference is not academic:
138
+ * a reader trusting the comment would handle cases that cannot occur here and miss the
139
+ * one that can.
140
+ *
141
+ * CANCELLATION IS NOT A FAILURE, and it used to be thrown as an indistinguishable Error.
142
+ * The same discipline applies here as in the invocation accounting: a caller who walked
143
+ * away must be able to tell that from a malfunction, or every cancellation inflates the
144
+ * error rate. `HarnessCancelledError` exists so it can.
145
+ */
146
+ if (outcome.kind === 'cancelled') {
147
+ throw new HarnessCancelledError(toolName, outcome.reason);
148
+ }
149
+ // `failed` carries the broker's own machine-readable code, so a caller can branch on the
150
+ // CAUSE rather than matching on a message.
151
+ throw new HarnessFailedError(toolName, outcome.code, outcome.reason);
152
+ },
153
+ });
154
+ }
155
+ return { ok: true, served };
156
+ }
157
+ //# sourceMappingURL=harness-serving.js.map