@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
@@ -81,34 +81,61 @@ function projectNode(node, path, runtimeEnforced) {
81
81
  }
82
82
  else if (keyword === 'type' && Array.isArray(value)) {
83
83
  /**
84
- * A union `type` array advertises its CONCRETE member, with the union recorded as
85
- * runtime-enforced.
84
+ * A union `type` array is advertised as `type: 'json'` (unconstrained), NOT
85
+ * narrowed to one member.
86
86
  *
87
- * Three attempts got here. `{ type: ['string', 'null'] }` is valid JSON Schema but
88
- * the DSL rejected the array with "type must be string/number/... or use oneOf",
89
- * and converting it to `oneOf` was rejected too, with "oneOf must be an array of at
90
- * least two value schemas" - `{ type: 'null' }` does not count as one. So the
91
- * non-null member is advertised, which is the case a client actually handles, and
92
- * the nullability is reported in runtimeEnforced rather than dropped silently,
93
- * which is what BASE-04 forbids.
87
+ * An earlier version advertised the concrete non-null member, which made the
88
+ * advertised schema STRICTER than the contract: `{ type: ['string','null'] }`
89
+ * was projected to `type: 'string'`, and the registry VALIDATES success values
90
+ * against the advertised schema, so a legitimate null result was rejected.
91
+ * Dropping the type entirely also fails: the DSL requires every property to
92
+ * have a type or oneOf. `type: 'json'` is the loosest the DSL accepts, it is
93
+ * strictly looser than any union, and the runtime contract check still enforces
94
+ * the union itself.
94
95
  */
95
- const members = value;
96
- const concrete = members.find(member => member !== 'null');
97
- if (concrete === undefined) {
98
- runtimeEnforced.push(`${path}.type`);
99
- }
100
- else {
101
- out.type = concrete;
102
- if (members.length > 1)
103
- runtimeEnforced.push(`${path}.type(non-nullable projection)`);
104
- }
96
+ runtimeEnforced.push(`${path}.type(union -> json)`);
97
+ out.type = 'json';
105
98
  }
106
99
  else {
107
100
  out[keyword] = value;
108
101
  }
109
102
  }
103
+ /**
104
+ * Post-pass the DSL rejects but projectNode would otherwise emit:
105
+ *
106
+ * - `type: 'json'` cannot carry `items`/`enum`/`const` siblings, so a union-typed
107
+ * array whose element schema (or scalar constraints) survived the pass is
108
+ * stripped HERE, with the keyword recorded rather than silently lost.
109
+ * - A NON-SCALAR `enum` is dropped everywhere: the DSL requires "a non-empty array
110
+ * of scalar values", and the confidence contract (DECL-04) enumerates OBJECT
111
+ * members to distinguish vendor-reported from calibrated from unavailable.
112
+ * Membership is still enforced at runtime against the untouched contract.
113
+ * - An annotation-only node (every keyword dropped to runtimeEnforced) has no
114
+ * `type`/`oneOf`, which the DSL rejects; advertising `type: 'json'` keeps it
115
+ * strictly looser than the original instead of crashing registration.
116
+ */
117
+ if (out.type === undefined && out.oneOf === undefined) {
118
+ runtimeEnforced.push(`${path}.type(annotation-only -> json)`);
119
+ out.type = 'json';
120
+ }
121
+ if (out.type === 'json') {
122
+ for (const sibling of ['items', 'enum', 'const']) {
123
+ if (sibling in out) {
124
+ runtimeEnforced.push(`${path}.${sibling}`);
125
+ delete out[sibling];
126
+ }
127
+ }
128
+ }
129
+ if (out.type !== 'json' && Array.isArray(out.enum) && !out.enum.every(member => isScalar(member))) {
130
+ runtimeEnforced.push(`${path}.enum`);
131
+ delete out.enum;
132
+ }
110
133
  return out;
111
134
  }
135
+ /** A scalar the DSL's `enum` admits. */
136
+ function isScalar(member) {
137
+ return typeof member === 'string' || typeof member === 'number' || typeof member === 'boolean';
138
+ }
112
139
  /**
113
140
  * Project a contract's input schema into DSH parameters.
114
141
  *
@@ -204,55 +231,42 @@ export function projectSchemaToDsh(schema) {
204
231
  const runtimeEnforced = [];
205
232
  const projected = projectNode(schema, '', runtimeEnforced);
206
233
  /**
207
- * `items` is stripped from an OUTPUT projection, and this is a real DSL limit found
208
- * the hard way rather than a precaution.
209
- *
210
- * `items` is in the supported set and works for a top-level input parameter, but the
211
- * registry rejected `schema.properties.words.items` with "items is not supported by
212
- * the value schema DSL" - so its support does not extend to an array nested inside an
213
- * object, which is exactly what an output schema contains. Keeping it would make the
214
- * tool fail to register at all.
234
+ * Nested array `items` are RETAINED, not stripped.
215
235
  *
216
- * The result is still a genuine declaration: property names, types and requiredness
217
- * are advertised, and `words` is declared an array. Only the ELEMENT schema is left to
218
- * runtime enforcement, which the contract's assertValidOutput performs against the
219
- * untouched schema. That is a long way from the
220
- * `{type: "object", additionalProperties: true}` this replaced, which declared nothing
221
- * about any field.
236
+ * An earlier version stripped every `items` at depth, on evidence that the registry
237
+ * rejected `schema.properties.words.items`. That evidence is stale against the pinned
238
+ * `dsh-tools@0.2.0-rc.2`, which compiles nested array items (probed: a `words` schema
239
+ * with a full item schema registers and validates). Stripping by key name was also a
240
+ * stricter-than-contract bug in waiting: a payload field legitimately NAMED `items`
241
+ * would lose its advertisement. Union-typed arrays (`type: ['array','null']`) become
242
+ * `type: 'json'` in projectNode, which already removes the `items` sibling with the
243
+ * keyword recorded, so nothing here needs to strip it again.
222
244
  */
223
245
  const parameters = stripItems(projected.properties ?? {}, '', runtimeEnforced);
224
246
  return { parameters: parameters, runtimeEnforced };
225
247
  }
226
248
  /**
227
- * Remove `items` at every depth in an output projection, recording each removal
228
- * (DECL-02).
249
+ * Deep-clone a projected schema while preserving ARRAYS as arrays (DECL-02).
250
+ *
251
+ * The post-pass in projectNode removed every keyword the DSL rejects, so this
252
+ * function no longer edits keywords — it exists so no recursion turns a scalar
253
+ * `enum` array like ['host','device'] into a record {0:'host',1:'device'}, which
254
+ * is an invalid schema the registry rejects.
229
255
  * @param node - the projected node.
230
- * @param path - the path, for the runtime-enforced list.
231
- * @param runtimeEnforced - collected keyword paths.
232
- * @returns the node without `items`.
256
+ * @param path - the path, for diagnostics.
257
+ * @param runtimeEnforced - collected keyword paths (unused; kept for the signature).
258
+ * @returns the node, arrays intact.
233
259
  */
234
260
  function stripItems(node, path, runtimeEnforced) {
261
+ void path;
262
+ void runtimeEnforced;
235
263
  if (typeof node !== 'object' || node === null)
236
264
  return node;
265
+ if (Array.isArray(node)) {
266
+ return node.map((child, index) => stripItems(child, `${path}[${index}]`, runtimeEnforced));
267
+ }
237
268
  const out = {};
238
269
  for (const [key, value] of Object.entries(node)) {
239
- if (key === 'items') {
240
- runtimeEnforced.push(`${path}.items`);
241
- continue;
242
- }
243
- /**
244
- * A non-scalar `enum` is dropped, for the same reason `items` is.
245
- *
246
- * The DSL requires "a non-empty array of scalar values", and the confidence contract
247
- * (DECL-04) enumerates OBJECT members to distinguish vendor-reported from calibrated
248
- * from unavailable. Membership is still enforced at runtime against the untouched
249
- * contract.
250
- */
251
- const scalar = (member) => typeof member === 'string' || typeof member === 'number' || typeof member === 'boolean';
252
- if (key === 'enum' && Array.isArray(value) && (value.length === 0 || !value.every(scalar))) {
253
- runtimeEnforced.push(`${path}.enum`);
254
- continue;
255
- }
256
270
  out[key] = stripItems(value, `${path}.${key}`, runtimeEnforced);
257
271
  }
258
272
  return out;
@@ -7,11 +7,14 @@
7
7
  *
8
8
  * @module @try-works/tool-mode-contracts
9
9
  */
10
- export { assertValidContract, assertValidInput, assertValidOutput, ContractError, ContractViolationError, TOOL_META_SCHEMA, type ToolContract, } from './registry.ts';
10
+ export { assertValidContract, assertValidInput, assertValidOutput, assertAgainstSchema, compileSchema, ContractError, ContractViolationError, TOOL_META_SCHEMA, type ToolContract, } from './registry.ts';
11
11
  export { withMeta, type ExecutionLocation, type ToolMeta } from './meta.ts';
12
12
  export { crossFieldRules, ProjectionError, projectSchemaToDsh, projectToDsh, toDshParameters, type CrossFieldRule, type DshParameters, type DshProjection, } from './dsh.ts';
13
13
  export { sttTranscribe, STT_ADMITTED_FORMATS } from './contracts/stt-transcribe.ts';
14
14
  export { langDetect } from './contracts/lang-detect.ts';
15
+ export { textEmbed } from './contracts/text-embed.ts';
16
+ export { textRerank } from './contracts/text-rerank.ts';
17
+ export { textTitle, imageDescribe, multimodalEmbed, semanticSimilarity, semanticRank, semanticClassify, semanticDeduplicate, mediaFindMoments, decisionChoose, decisionTest, decisionScore, structuredExtract, toolsPlan, } from './contracts/standard.ts';
15
18
  import type { ToolContract } from './registry.ts';
16
19
  /**
17
20
  * The standard contracts every Tool Mode host knows how to register.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,QAAQ,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAA;AAE3E,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAIvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,YAAY,EAAgC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,QAAQ,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAA;AAE3E,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EACL,SAAS,EACT,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,SAAS,GACV,MAAM,yBAAyB,CAAA;AAqBhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,YAAY,EAkBrD,CAAA"}
@@ -7,18 +7,42 @@
7
7
  *
8
8
  * @module @try-works/tool-mode-contracts
9
9
  */
10
- export { assertValidContract, assertValidInput, assertValidOutput, ContractError, ContractViolationError, TOOL_META_SCHEMA, } from "./registry.js";
10
+ export { assertValidContract, assertValidInput, assertValidOutput, assertAgainstSchema, compileSchema, ContractError, ContractViolationError, TOOL_META_SCHEMA, } from "./registry.js";
11
11
  export { withMeta } from "./meta.js";
12
12
  export { crossFieldRules, ProjectionError, projectSchemaToDsh, projectToDsh, toDshParameters, } from "./dsh.js";
13
13
  export { sttTranscribe, STT_ADMITTED_FORMATS } from "./contracts/stt-transcribe.js";
14
14
  export { langDetect } from "./contracts/lang-detect.js";
15
+ export { textEmbed } from "./contracts/text-embed.js";
16
+ export { textRerank } from "./contracts/text-rerank.js";
17
+ export { textTitle, imageDescribe, multimodalEmbed, semanticSimilarity, semanticRank, semanticClassify, semanticDeduplicate, mediaFindMoments, decisionChoose, decisionTest, decisionScore, structuredExtract, toolsPlan, } from "./contracts/standard.js";
15
18
  import { sttTranscribe } from "./contracts/stt-transcribe.js";
16
19
  import { langDetect } from "./contracts/lang-detect.js";
20
+ import { textEmbed } from "./contracts/text-embed.js";
21
+ import { textRerank } from "./contracts/text-rerank.js";
22
+ import { textTitle, imageDescribe, multimodalEmbed, semanticSimilarity, semanticRank, semanticClassify, semanticDeduplicate, mediaFindMoments, decisionChoose, decisionTest, decisionScore, structuredExtract, toolsPlan, } from "./contracts/standard.js";
17
23
  /**
18
24
  * The standard contracts every Tool Mode host knows how to register.
19
25
  *
20
26
  * A host iterates this list; it does not switch on model names, which is what
21
27
  * ARCH-02 and EXT-01 require of model-independent code.
22
28
  */
23
- export const STANDARD_CONTRACTS = [sttTranscribe, langDetect];
29
+ export const STANDARD_CONTRACTS = [
30
+ sttTranscribe,
31
+ langDetect,
32
+ textEmbed,
33
+ textRerank,
34
+ textTitle,
35
+ imageDescribe,
36
+ multimodalEmbed,
37
+ semanticSimilarity,
38
+ semanticRank,
39
+ semanticClassify,
40
+ semanticDeduplicate,
41
+ mediaFindMoments,
42
+ decisionChoose,
43
+ decisionTest,
44
+ decisionScore,
45
+ structuredExtract,
46
+ toolsPlan,
47
+ ];
24
48
  //# sourceMappingURL=index.js.map
@@ -43,11 +43,11 @@ export declare class ContractError extends Error {
43
43
  readonly violations: readonly string[];
44
44
  constructor(subject: string, violations: readonly string[]);
45
45
  }
46
- /** A result that did not satisfy its contract's output schema. */
46
+ /** A value that did not satisfy a declared schema. */
47
47
  export declare class ContractViolationError extends Error {
48
48
  readonly name = "ContractViolationError";
49
49
  readonly violations: readonly string[];
50
- constructor(contract: string, violations: readonly string[]);
50
+ constructor(subject: string, violations: readonly string[]);
51
51
  }
52
52
  /**
53
53
  * Validate a contract definition.
@@ -78,4 +78,30 @@ export declare function assertValidInput(contract: ToolContract, args: unknown):
78
78
  export declare function assertValidOutput(contract: ToolContract, value: unknown): void;
79
79
  /** The meta envelope's own schema, exported for contract authors. */
80
80
  export { TOOL_META_SCHEMA };
81
+ /**
82
+ * Compile an arbitrary JSON Schema once, for a host that serves manifest-declared
83
+ * tool schemas rather than registered contracts.
84
+ *
85
+ * Compiling at REGISTRATION (in the host's try/catch) means a malformed schema
86
+ * fails when the tool is registered, not on the first caller's event-loop tick —
87
+ * and it is never re-compiled per call, which a per-call text-keyed cache could
88
+ * not guarantee.
89
+ * @param schema - the JSON Schema to compile.
90
+ * @throws ContractError when the schema does not compile.
91
+ * @returns a validator whose violations are rendered by {@link assertAgainstSchema}.
92
+ */
93
+ export declare function compileSchema(schema: Readonly<Record<string, unknown>>): (value: unknown) => readonly string[];
94
+ /**
95
+ * Validate an arbitrary value against a compiled declared schema.
96
+ *
97
+ * The full-schema counterpart of {@link assertValidInput}/{@link assertValidOutput}:
98
+ * the projected advertisement the DSH registry validates is deliberately LOOSER
99
+ * (union members become `json`, unsupported keywords are dropped), so without this
100
+ * the dropped keywords are enforced nowhere for manifest-declared tools.
101
+ * @param subject - the tool or schema name used in the violation message.
102
+ * @param validate - the compiled validator, from {@link compileSchema}.
103
+ * @param value - the candidate value.
104
+ * @throws ContractViolationError listing every violation.
105
+ */
106
+ export declare function assertAgainstSchema(subject: string, validate: (value: unknown) => readonly string[], value: unknown): void;
81
107
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9C,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAA;IACvE,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CACxC;AAED,4DAA4D;AAC5D,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAkB,IAAI,mBAAkB;IACxC,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;gBAC1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE;CAI3D;AAED,kEAAkE;AAClE,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,SAAkB,IAAI,4BAA2B;IACjD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;gBAC1B,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE;CAI5D;AA8BD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAmDhE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAM5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAM9E;AAED,qEAAqE;AACrE,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9C,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAA;IACvE,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CACxC;AAED,4DAA4D;AAC5D,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAkB,IAAI,mBAAkB;IACxC,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;gBAC1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE;CAI3D;AAED,sDAAsD;AACtD,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,SAAkB,IAAI,4BAA2B;IACjD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;gBAC1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE;CAI3D;AA0ED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAmDhE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAM5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAM9E;AAED,qEAAqE;AACrE,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAE3B;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,MAAM,EAAE,CAQ9G;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,MAAM,EAAE,EAC/C,KAAK,EAAE,OAAO,GACb,IAAI,CAGN"}
@@ -14,7 +14,11 @@
14
14
  *
15
15
  * @module @try-works/tool-mode-contracts/registry
16
16
  */
17
- import { Ajv } from 'ajv';
17
+ // The explicit `.js` suffix is REQUIRED for packed installs: plain Node ESM does
18
+ // not apply extension resolution to package subpaths, and the workspace's tsx
19
+ // loader masks that (the round-67 packed-orchestration run caught exactly this
20
+ // failure). extension-needle's validation.ts uses the same spelling.
21
+ import Ajv2020 from 'ajv/dist/2020.js';
18
22
  import { TOOL_META_SCHEMA } from "./meta.js";
19
23
  /** A contract that failed validation, with every reason. */
20
24
  export class ContractError extends Error {
@@ -26,26 +30,66 @@ export class ContractError extends Error {
26
30
  this.violations = violations;
27
31
  }
28
32
  }
29
- /** A result that did not satisfy its contract's output schema. */
33
+ /** A value that did not satisfy a declared schema. */
30
34
  export class ContractViolationError extends Error {
31
35
  name = 'ContractViolationError';
32
36
  violations;
33
- constructor(contract, violations) {
34
- super(`result violates the ${contract} contract: ${violations.join('; ')}`);
37
+ constructor(subject, violations) {
38
+ super(`value violates the ${subject} schema: ${violations.join('; ')}`);
35
39
  this.violations = violations;
36
40
  }
37
41
  }
38
42
  /**
39
- * The validator. `strict: false` because contract schemas use JSON Schema
40
- * keywords that Ajv's strict mode rejects when they are merely annotated, and
41
- * `allErrors` so a violation report lists every problem rather than the first.
43
+ * The validator, on the 2020-12 dialect.
44
+ *
45
+ * 2020-12 rather than draft-07 because extension-declared schemas ship as
46
+ * 2020-12 documents (`$schema`, `$id`, `$defs` — the extension-needle package's
47
+ * tools-plan/structured-extract schemas are the concrete case): a draft-07
48
+ * compiler cannot resolve `#/$defs/...` references, so those real packages
49
+ * could not be activated in the host. `strict: false` for the same reason as
50
+ * before — contract schemas annotate keywords Ajv's strict mode rejects when
51
+ * they are merely descriptive, and a strict-mode THROW on an annotation would
52
+ * refuse a schema that validates fine. A schema that does not COMPILE (an
53
+ * unresolvable `$ref`, a structurally broken keyword) still throws at
54
+ * registration, so a bad schema refuses loudly rather than being accepted.
55
+ * `allowUnionTypes` admits `type: ["number", "null"]`-style unions, which the
56
+ * shipped needle schemas use for nullable fields. `allErrors` keeps the
57
+ * violation report listing every problem rather than the first.
42
58
  */
43
59
  function createAjv() {
44
- return new Ajv({ allErrors: true, strict: false, allowUnionTypes: true });
60
+ return new Ajv2020({ allErrors: true, strict: false, allowUnionTypes: true });
45
61
  }
46
62
  const ajv = createAjv();
47
63
  const outputValidators = new Map();
48
64
  const inputValidators = new Map();
65
+ /**
66
+ * Validators for $id-bearing schemas, keyed by the id itself.
67
+ *
68
+ * Ajv registers a compiled schema under its `$id`, and compiling the same id a
69
+ * second time THROWS "already exists" — which would make re-activating an
70
+ * extension (or two tools sharing one declared schema file) fail on the second
71
+ * compile. Identical content re-compiles to the same validator; DIFFERENT
72
+ * content under one id is a refusal, because two schemas sharing an id is
73
+ * exactly the drift a caller must never silently inherit.
74
+ */
75
+ const compiledById = new Map();
76
+ /** Compile a schema, tolerating a repeat compile of identical $id content. */
77
+ function compileTracked(schema) {
78
+ const id = typeof schema.$id === 'string' ? schema.$id : undefined;
79
+ if (id === undefined)
80
+ return ajv.compile(schema);
81
+ const serialized = JSON.stringify(schema);
82
+ const cached = compiledById.get(id);
83
+ if (cached !== undefined) {
84
+ if (cached.serialized !== serialized) {
85
+ throw new ContractError('declared-schema', [`a schema with $id ${JSON.stringify(id)} was already compiled from different content; two different schemas must not share an id`]);
86
+ }
87
+ return cached.validate;
88
+ }
89
+ const validate = ajv.compile(schema);
90
+ compiledById.set(id, { serialized, validate });
91
+ return validate;
92
+ }
49
93
  /** Render Ajv errors as stable, deduplicated strings. */
50
94
  function renderErrors(errors) {
51
95
  const seen = new Set();
@@ -106,13 +150,13 @@ export function assertValidContract(contract) {
106
150
  throw new ContractError(contract.contract, violations);
107
151
  // Schemas must be compilable, or the contract is unenforceable.
108
152
  try {
109
- inputValidators.set(contract.contract, ajv.compile(contract.inputSchema));
153
+ inputValidators.set(contract.contract, compileTracked(contract.inputSchema));
110
154
  }
111
155
  catch (error) {
112
156
  throw new ContractError(contract.contract, [`inputSchema does not compile: ${message(error)}`]);
113
157
  }
114
158
  try {
115
- outputValidators.set(contract.contract, ajv.compile(contract.outputSchema));
159
+ outputValidators.set(contract.contract, compileTracked(contract.outputSchema));
116
160
  }
117
161
  catch (error) {
118
162
  throw new ContractError(contract.contract, [`outputSchema does not compile: ${message(error)}`]);
@@ -151,6 +195,45 @@ export function assertValidOutput(contract, value) {
151
195
  }
152
196
  /** The meta envelope's own schema, exported for contract authors. */
153
197
  export { TOOL_META_SCHEMA };
198
+ /**
199
+ * Compile an arbitrary JSON Schema once, for a host that serves manifest-declared
200
+ * tool schemas rather than registered contracts.
201
+ *
202
+ * Compiling at REGISTRATION (in the host's try/catch) means a malformed schema
203
+ * fails when the tool is registered, not on the first caller's event-loop tick —
204
+ * and it is never re-compiled per call, which a per-call text-keyed cache could
205
+ * not guarantee.
206
+ * @param schema - the JSON Schema to compile.
207
+ * @throws ContractError when the schema does not compile.
208
+ * @returns a validator whose violations are rendered by {@link assertAgainstSchema}.
209
+ */
210
+ export function compileSchema(schema) {
211
+ let validate;
212
+ try {
213
+ validate = compileTracked(schema);
214
+ }
215
+ catch (error) {
216
+ throw new ContractError('declared-schema', [`schema does not compile: ${message(error)}`]);
217
+ }
218
+ return value => (validate(value) ? [] : renderErrors(validate.errors));
219
+ }
220
+ /**
221
+ * Validate an arbitrary value against a compiled declared schema.
222
+ *
223
+ * The full-schema counterpart of {@link assertValidInput}/{@link assertValidOutput}:
224
+ * the projected advertisement the DSH registry validates is deliberately LOOSER
225
+ * (union members become `json`, unsupported keywords are dropped), so without this
226
+ * the dropped keywords are enforced nowhere for manifest-declared tools.
227
+ * @param subject - the tool or schema name used in the violation message.
228
+ * @param validate - the compiled validator, from {@link compileSchema}.
229
+ * @param value - the candidate value.
230
+ * @throws ContractViolationError listing every violation.
231
+ */
232
+ export function assertAgainstSchema(subject, validate, value) {
233
+ const violations = validate(value);
234
+ if (violations.length > 0)
235
+ throw new ContractViolationError(subject, violations);
236
+ }
154
237
  /** Best-effort message from an arbitrary thrown value. */
155
238
  function message(error) {
156
239
  try {
@@ -14,7 +14,6 @@
14
14
  "types": "lib/index.d.ts",
15
15
  "exports": {
16
16
  ".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
17
- "./src/*": "./src/*",
18
17
  "./package.json": "./package.json"
19
18
  },
20
19
  "files": ["lib/**/*.js", "lib/**/*.d.ts", "lib/**/*.d.ts.map", "README.md"],
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The `dsh-tool-mode` executable (EXT-31).
4
+ *
5
+ * A thin shim: it wires real process streams into the tested CLI and translates
6
+ * the returned code into an exit status. All the logic lives in the library, so
7
+ * every path — including the refusals — is exercised by tests rather than only by
8
+ * running the binary by hand.
9
+ */
10
+
11
+ import { runToolModeCli } from '../lib/cli.js'
12
+
13
+ const code = await runToolModeCli(
14
+ process.argv.slice(2),
15
+ {
16
+ out: line => process.stdout.write(`${line}\n`),
17
+ err: line => process.stderr.write(`${line}\n`),
18
+ },
19
+ )
20
+ process.exitCode = code
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The operator command family (EXT-31).
3
+ *
4
+ * EXT-31 is explicit that these are REQUIRED NEW FUNCTIONALITY, not existing npm
5
+ * or DSH commands, and that offline edits must hold exclusive store ownership. So
6
+ * every mutating command takes the store lock, and the CLI refuses rather than
7
+ * racing a running host.
8
+ *
9
+ * The entry point takes argv and an output sink instead of reading `process`
10
+ * directly. A CLI that can only be exercised by spawning a child process is a CLI
11
+ * whose failure paths are tested by hand or not at all, and the failure paths here
12
+ * are the security-relevant ones.
13
+ *
14
+ * The management surface is deliberately NOT the inference surface: EXT-31 forbids
15
+ * exposing the management channel on the MCP tool surface by default, and nothing
16
+ * in this module registers a tool.
17
+ *
18
+ * @module @try-works/tool-mode-extension-sdk/cli
19
+ */
20
+ import { type ContributionRegistrar } from './install/lifecycle.ts';
21
+ /** Where the CLI writes. Injected so a test can capture output. */
22
+ export interface CliIo {
23
+ /** Write one line of normal output. */
24
+ out(line: string): void;
25
+ /** Write one line of error output. */
26
+ err(line: string): void;
27
+ }
28
+ /** Options resolved from argv. */
29
+ export interface CliOptions {
30
+ /** The extension store root. */
31
+ readonly store: string;
32
+ /** The profile to act on. */
33
+ readonly profile: string;
34
+ /** Positional arguments after the command. */
35
+ readonly positional: readonly string[];
36
+ /** `--flag` names and their values. */
37
+ readonly flags: Readonly<Record<string, string | true>>;
38
+ }
39
+ /** What the CLI needs from the environment to act. */
40
+ export interface CliDependencies {
41
+ /** A registrar for activation. Without one, activation is refused rather than faked. */
42
+ readonly registrar?: ContributionRegistrar;
43
+ /** Parse and install from a specifier; injected so the CLI owns no network stack. */
44
+ readonly install?: (spec: string, integrity: string | undefined, store: string) => Promise<string>;
45
+ /**
46
+ * The recipes authoring runner, forwarded to by the `recipes` namespace
47
+ * (RCP-08). When absent, the SDK resolves `@try-works/tool-mode-recipes/cli`
48
+ * lazily at invocation time; when that also fails, the command answers a
49
+ * PRECISE refusal — the SDK never duplicates recipe semantics and never
50
+ * depends on the recipes package at import time.
51
+ */
52
+ readonly recipeCliRunner?: {
53
+ runRecipeCli(argv: readonly string[], io: CliIo): Promise<number>;
54
+ };
55
+ /** Override the lazy resolver (tests); returns the runner or undefined. */
56
+ readonly resolveRecipeCli?: () => Promise<{
57
+ runRecipeCli(argv: readonly string[], io: CliIo): Promise<number>;
58
+ } | undefined>;
59
+ }
60
+ /**
61
+ * Parse argv into options.
62
+ *
63
+ * Anything unrecognised is REFUSED rather than ignored: a mistyped flag that is
64
+ * silently dropped turns `--deactivate` into a command the operator did not ask
65
+ * for, which on `uninstall` is the difference between previewing and removing.
66
+ * @param argv - arguments after the executable name.
67
+ * @returns the parsed options.
68
+ * @throws ManagementError when a flag is unknown or a value is missing.
69
+ */
70
+ export declare function parseArgs(argv: readonly string[]): CliOptions;
71
+ /**
72
+ * Run one command.
73
+ *
74
+ * @param argv - arguments after the executable name.
75
+ * @param io - output sinks.
76
+ * @param dependencies - the registrar and installer to act with.
77
+ * @returns the process exit code.
78
+ */
79
+ export declare function runToolModeCli(argv: readonly string[], io: CliIo, dependencies?: CliDependencies): Promise<number>;
80
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAIvF,mEAAmE;AACnE,MAAM,WAAW,KAAK;IACpB,uCAAuC;IACvC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,sCAAsC;IACtC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,kCAAkC;AAClC,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;CACxD;AAED,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;IAC1C,qFAAqF;IACrF,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClG;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE;QAAE,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAChG,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,SAAS,CAAC,CAAA;CAC7H;AA4ED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CA4C7D;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,KAAK,EACT,YAAY,GAAE,eAAoB,GACjC,OAAO,CAAC,MAAM,CAAC,CA8DjB"}