@zackbart/connecta 0.34.1 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. package/CHANGELOG.md +418 -0
  2. package/README.md +65 -105
  3. package/SECURITY.md +3 -2
  4. package/bin/connecta.mjs +41 -16
  5. package/bin/version.mjs +1 -1
  6. package/dist/access-tokens.d.ts +2 -1
  7. package/dist/access-tokens.js +66 -30
  8. package/dist/activity.d.ts +1 -1
  9. package/dist/activity.js +2 -0
  10. package/dist/agent-config.d.ts +23 -0
  11. package/dist/agent-config.js +59 -0
  12. package/dist/agent-description.js +16 -0
  13. package/dist/agent-identity.js +4 -4
  14. package/dist/agent-observation.js +39 -0
  15. package/dist/auth/clerk-sdk/client.d.ts +2 -0
  16. package/dist/auth/clerk-sdk/generated.js +554 -563
  17. package/dist/auth/clerk-transport.js +70 -3
  18. package/dist/auth/clerk.d.ts +13 -0
  19. package/dist/auth/clerk.js +653 -246
  20. package/dist/auth/cloudflare-access.js +46 -42
  21. package/dist/auth/downstream-client-metadata.js +2 -2
  22. package/dist/auth/downstream-oauth.js +2044 -1161
  23. package/dist/auth/downstream-revocation.js +88 -88
  24. package/dist/auth/native-call.js +20 -0
  25. package/dist/auth/native.js +184 -0
  26. package/dist/auth/oauth-start-reset.js +11 -5
  27. package/dist/auth/oauth-token-response.js +121 -102
  28. package/dist/auth/oauth-v2-migration.js +97 -78
  29. package/dist/auth/renewable-grant.js +10 -0
  30. package/dist/auth/static-oauth.js +751 -281
  31. package/dist/auth/vercel-agent.js +266 -0
  32. package/dist/auth-admission.js +204 -0
  33. package/dist/auth-elicitation.js +350 -241
  34. package/dist/authorization-handoff.js +164 -90
  35. package/dist/call-admission-context.js +3 -10
  36. package/dist/call-admission.js +2 -0
  37. package/dist/call-classification.js +9 -0
  38. package/dist/call-recovery.js +32 -13
  39. package/dist/canonical-json.js +8 -0
  40. package/dist/catalog-cache.js +369 -213
  41. package/dist/catalog-service.js +659 -530
  42. package/dist/catalog.js +5 -1
  43. package/dist/concurrency.js +0 -25
  44. package/dist/config-defaults.d.ts +1 -0
  45. package/dist/config-defaults.js +1 -0
  46. package/dist/config-schema.d.ts +3 -1
  47. package/dist/config-schema.js +13 -3
  48. package/dist/config.d.ts +40 -6
  49. package/dist/config.js +40 -26
  50. package/dist/connector-caller.d.ts +4 -0
  51. package/dist/connector-caller.js +17 -4
  52. package/dist/connectors/api-connector.d.ts +29 -7
  53. package/dist/connectors/api-connector.js +145 -57
  54. package/dist/connectors/guarded-fetch.d.ts +51 -17
  55. package/dist/connectors/guarded-fetch.js +215 -121
  56. package/dist/connectors/negotiation-cache.js +20 -10
  57. package/dist/connectors/remote-mcp.d.ts +10 -30
  58. package/dist/connectors/remote-mcp.js +955 -563
  59. package/dist/d1.js +10 -243
  60. package/dist/derived-context.js +5 -0
  61. package/dist/describe-config.d.ts +3 -1
  62. package/dist/describe-config.js +2 -0
  63. package/dist/downstream-input.js +347 -260
  64. package/dist/errors.d.ts +87 -6
  65. package/dist/errors.js +114 -4
  66. package/dist/execute.js +87 -50
  67. package/dist/executor-admission.js +3 -0
  68. package/dist/executors/quickjs.js +163 -112
  69. package/dist/guarded-transport.js +50 -0
  70. package/dist/guest-runtime.js +1 -1
  71. package/dist/http/client.js +439 -0
  72. package/dist/http/errors.js +558 -0
  73. package/dist/http/fields.js +49 -0
  74. package/dist/http/hatch-paging.js +318 -0
  75. package/dist/http/hatch.js +1279 -0
  76. package/dist/http/json-schema.js +267 -0
  77. package/dist/http/node-transport.js +241 -0
  78. package/dist/http/oauth.js +162 -0
  79. package/dist/http/paging.js +227 -0
  80. package/dist/http/provider.js +221 -0
  81. package/dist/http/safety.js +82 -0
  82. package/dist/http/services.js +79 -0
  83. package/dist/http/tools.js +379 -0
  84. package/dist/http/vendor-index.js +138 -0
  85. package/dist/http/vendor.js +448 -0
  86. package/dist/http/write-request.js +66 -0
  87. package/dist/http-policy.d.ts +11 -0
  88. package/dist/http-policy.js +45 -0
  89. package/dist/inbound-credential.js +1 -1
  90. package/dist/index.d.ts +2 -2
  91. package/dist/index.js +4 -0
  92. package/dist/invocation-auth.js +30 -19
  93. package/dist/invocation.js +218 -85
  94. package/dist/mcp-result.js +0 -4
  95. package/dist/membership.d.ts +4 -0
  96. package/dist/meta-output.js +1 -1
  97. package/dist/meta-tools.js +531 -406
  98. package/dist/native-recovery.js +52 -0
  99. package/dist/native-tools.js +382 -0
  100. package/dist/node.d.ts +4 -3
  101. package/dist/node.js +45 -8
  102. package/dist/oauth-handoff.js +177 -104
  103. package/dist/oauth-partition.js +6 -20
  104. package/dist/oauth-sealing.js +6 -7
  105. package/dist/operation-vocabulary.js +101 -0
  106. package/dist/operator-record.d.ts +2 -2
  107. package/dist/operator-record.js +17 -4
  108. package/dist/operator-ui/contract.d.ts +8 -3
  109. package/dist/operator-ui/generated.js +4 -4
  110. package/dist/operator-ui/model.d.ts +2 -3
  111. package/dist/program-writes.js +47 -26
  112. package/dist/provider-call-facts.d.ts +115 -0
  113. package/dist/provider-call-facts.js +182 -0
  114. package/dist/provider-call.d.ts +112 -0
  115. package/dist/provider-call.js +271 -0
  116. package/dist/provider.d.ts +65 -31
  117. package/dist/provider.js +116 -39
  118. package/dist/providers/_shared/google/hatch.js +91 -0
  119. package/dist/providers/_shared/google/kit.js +427 -0
  120. package/dist/providers/_shared/google/result-size.js +15 -2
  121. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  122. package/dist/providers/_shared/google/service-account.js +8 -4
  123. package/dist/providers/_shared/google/workspace.d.ts +6 -210
  124. package/dist/providers/_shared/google/workspace.js +6 -425
  125. package/dist/providers/_shared/rest/compact-index.js +86 -0
  126. package/dist/providers/_shared/rest/kit.js +146 -0
  127. package/dist/providers/_shared/rest/operation-index.js +230 -14
  128. package/dist/providers/_shared/rest/response-media.js +11 -0
  129. package/dist/providers/_shared/rest/value-safety.js +353 -195
  130. package/dist/providers/_shared/sensitive-fields.js +27 -0
  131. package/dist/providers/breeze/api.js +584 -0
  132. package/dist/providers/breeze/index.d.ts +1 -3
  133. package/dist/providers/breeze/index.js +67 -1420
  134. package/dist/providers/breeze/openapi.generated.js +60 -0
  135. package/dist/providers/breeze/skill.generated.js +2 -6
  136. package/dist/providers/breeze/tools.js +696 -0
  137. package/dist/providers/ccb/api.js +496 -0
  138. package/dist/providers/ccb/index.d.ts +15 -37
  139. package/dist/providers/ccb/index.js +77 -1702
  140. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  141. package/dist/providers/ccb/lib/constants.js +74 -0
  142. package/dist/providers/ccb/lib/guide.js +9 -0
  143. package/dist/providers/ccb/lib/verdicts.js +387 -0
  144. package/dist/providers/ccb/openapi.generated.js +397 -0
  145. package/dist/providers/ccb/safety.js +295 -0
  146. package/dist/providers/ccb/skill.generated.js +2 -6
  147. package/dist/providers/ccb/tools.js +853 -0
  148. package/dist/providers/cloudflare/api.js +1066 -0
  149. package/dist/providers/cloudflare/index.d.ts +5 -22
  150. package/dist/providers/cloudflare/index.js +79 -197
  151. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  152. package/dist/providers/cloudflare/lib/config.js +2 -0
  153. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  154. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  155. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  156. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  157. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  158. package/dist/providers/cloudflare/openapi.generated.js +4 -3
  159. package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
  160. package/dist/providers/cloudflare/skill.generated.js +2 -10
  161. package/dist/providers/cloudflare/tools.js +360 -0
  162. package/dist/providers/docs/api.js +51 -0
  163. package/dist/providers/docs/index.d.ts +1 -12
  164. package/dist/providers/docs/index.js +53 -1165
  165. package/dist/providers/docs/lib/constants.d.ts +18 -0
  166. package/dist/providers/docs/lib/constants.js +18 -0
  167. package/dist/providers/docs/lib/discovery.js +26 -0
  168. package/dist/providers/docs/lib/requests.js +48 -0
  169. package/dist/providers/docs/lib/schemas.js +168 -0
  170. package/dist/providers/docs/openapi.generated.js +16 -0
  171. package/dist/providers/docs/safety.js +54 -0
  172. package/dist/providers/docs/skill.generated.js +2 -6
  173. package/dist/providers/docs/tools.js +801 -0
  174. package/dist/providers/drive/api.js +177 -0
  175. package/dist/providers/drive/index.d.ts +1 -12
  176. package/dist/providers/drive/index.js +38 -1448
  177. package/dist/providers/drive/lib/constants.d.ts +6 -0
  178. package/dist/providers/drive/lib/constants.js +6 -0
  179. package/dist/providers/drive/lib/contracts.js +532 -0
  180. package/dist/providers/drive/lib/hatch.js +197 -0
  181. package/dist/providers/drive/openapi.generated.js +77 -0
  182. package/dist/providers/drive/safety.js +90 -0
  183. package/dist/providers/drive/skill.generated.js +2 -6
  184. package/dist/providers/drive/tools.js +1290 -0
  185. package/dist/providers/forms/api.js +71 -0
  186. package/dist/providers/forms/index.d.ts +1 -12
  187. package/dist/providers/forms/index.js +49 -1145
  188. package/dist/providers/forms/lib/constants.d.ts +14 -0
  189. package/dist/providers/forms/lib/constants.js +19 -0
  190. package/dist/providers/forms/lib/hatch.js +72 -0
  191. package/dist/providers/forms/openapi.generated.js +23 -0
  192. package/dist/providers/forms/safety.js +34 -0
  193. package/dist/providers/forms/skill.generated.js +2 -8
  194. package/dist/providers/forms/tools.js +1023 -0
  195. package/dist/providers/github/api.js +150 -0
  196. package/dist/providers/github/index.d.ts +4 -5
  197. package/dist/providers/github/index.js +30 -87
  198. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  199. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  200. package/dist/providers/github/lib/discovery.js +132 -0
  201. package/dist/providers/github/lib/operations.js +58 -0
  202. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  203. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  204. package/dist/providers/github/openapi.generated.js +1216 -0
  205. package/dist/providers/github/safety.js +216 -0
  206. package/dist/providers/github/skill.generated.js +2 -5
  207. package/dist/providers/github/tools.js +506 -0
  208. package/dist/providers/gmail/api.js +114 -0
  209. package/dist/providers/gmail/index.d.ts +1 -12
  210. package/dist/providers/gmail/index.js +73 -1621
  211. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  212. package/dist/providers/gmail/lib/constants.js +16 -0
  213. package/dist/providers/gmail/lib/index.js +173 -0
  214. package/dist/providers/gmail/lib/schemas.js +176 -0
  215. package/dist/providers/gmail/lib/threading.js +120 -0
  216. package/dist/providers/gmail/openapi.generated.js +92 -0
  217. package/dist/providers/gmail/safety.js +21 -0
  218. package/dist/providers/gmail/skill.generated.js +2 -6
  219. package/dist/providers/gmail/tools.js +1435 -0
  220. package/dist/providers/overflow/api.js +1008 -0
  221. package/dist/providers/overflow/index.d.ts +1 -17
  222. package/dist/providers/overflow/index.js +60 -1488
  223. package/dist/providers/overflow/skill.generated.js +2 -5
  224. package/dist/providers/overflow/tools.js +873 -0
  225. package/dist/providers/planning-center/api.js +467 -0
  226. package/dist/providers/planning-center/index.d.ts +4 -35
  227. package/dist/providers/planning-center/index.js +69 -2445
  228. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  229. package/dist/providers/planning-center/lib/constants.js +83 -0
  230. package/dist/providers/planning-center/lib/discovery.js +40 -0
  231. package/dist/providers/planning-center/lib/guide.js +39 -0
  232. package/dist/providers/planning-center/lib/json-api.js +83 -0
  233. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  234. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  235. package/dist/providers/planning-center/safety.js +188 -0
  236. package/dist/providers/planning-center/skill.generated.js +2 -27
  237. package/dist/providers/planning-center/tools.js +1010 -0
  238. package/dist/providers/quickbooks/api.js +299 -0
  239. package/dist/providers/quickbooks/index.d.ts +13 -0
  240. package/dist/providers/quickbooks/index.js +93 -0
  241. package/dist/providers/quickbooks/lib/query.js +118 -0
  242. package/dist/providers/quickbooks/lib/writes.js +168 -0
  243. package/dist/providers/quickbooks/safety.js +222 -0
  244. package/dist/providers/quickbooks/skill.generated.js +5 -0
  245. package/dist/providers/quickbooks/tools.js +117 -0
  246. package/dist/providers/sheets/api.js +133 -0
  247. package/dist/providers/sheets/index.d.ts +4 -16
  248. package/dist/providers/sheets/index.js +61 -1172
  249. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  250. package/dist/providers/sheets/lib/constants.js +14 -0
  251. package/dist/providers/sheets/lib/hatch.js +163 -0
  252. package/dist/providers/sheets/lib/requests.js +105 -0
  253. package/dist/providers/sheets/lib/schemas.js +138 -0
  254. package/dist/providers/sheets/openapi.generated.js +30 -0
  255. package/dist/providers/sheets/safety.js +27 -0
  256. package/dist/providers/sheets/skill.generated.js +2 -7
  257. package/dist/providers/sheets/tools.js +733 -0
  258. package/dist/providers/slides/api.js +147 -0
  259. package/dist/providers/slides/index.d.ts +2 -10
  260. package/dist/providers/slides/index.js +48 -2555
  261. package/dist/providers/slides/lib/constants.d.ts +11 -0
  262. package/dist/providers/slides/lib/constants.js +11 -0
  263. package/dist/providers/slides/lib/requests.js +60 -0
  264. package/dist/providers/slides/lib/schemas.js +565 -0
  265. package/dist/providers/slides/openapi.generated.js +18 -0
  266. package/dist/providers/slides/skill.generated.js +2 -6
  267. package/dist/providers/slides/tools.js +1968 -0
  268. package/dist/providers/stripe/api.js +401 -0
  269. package/dist/providers/stripe/index.d.ts +5 -27
  270. package/dist/providers/stripe/index.js +74 -210
  271. package/dist/providers/stripe/lib/config.d.ts +4 -0
  272. package/dist/providers/stripe/lib/config.js +2 -0
  273. package/dist/providers/stripe/openapi.generated.js +4 -3
  274. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  275. package/dist/providers/stripe/skill.generated.js +2 -11
  276. package/dist/providers/stripe/tools.js +77 -0
  277. package/dist/providers/tithely/api.js +531 -0
  278. package/dist/providers/tithely/index.d.ts +17 -0
  279. package/dist/providers/tithely/index.js +86 -965
  280. package/dist/providers/tithely/skill.generated.js +2 -5
  281. package/dist/providers/tithely/tools.js +426 -0
  282. package/dist/providers/vercel/api.js +551 -0
  283. package/dist/providers/vercel/index.d.ts +9 -25
  284. package/dist/providers/vercel/index.js +65 -260
  285. package/dist/providers/vercel/lib/config.d.ts +2 -0
  286. package/dist/providers/vercel/lib/config.js +2 -0
  287. package/dist/providers/vercel/lib/index.js +117 -0
  288. package/dist/providers/vercel/lib/logs.js +100 -0
  289. package/dist/providers/vercel/lib/pin.js +270 -0
  290. package/dist/providers/vercel/openapi.generated.js +10 -5
  291. package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
  292. package/dist/providers/vercel/skill.generated.js +2 -7
  293. package/dist/providers/vercel/tools.js +642 -0
  294. package/dist/redaction-identity.js +47 -0
  295. package/dist/redaction-marker.js +125 -0
  296. package/dist/registry.d.ts +21 -15
  297. package/dist/registry.js +409 -376
  298. package/dist/routes/access-tokens.js +1 -1
  299. package/dist/routes/actor-labels.js +1 -1
  300. package/dist/routes/connect.js +1 -1
  301. package/dist/routes/dispatch.js +103 -0
  302. package/dist/routes/mcp.js +170 -79
  303. package/dist/routes/oauth.js +6 -1
  304. package/dist/routes/operator.js +2 -2
  305. package/dist/routes/shared.d.ts +5 -4
  306. package/dist/routes/shared.js +244 -177
  307. package/dist/routes/skills.js +10 -8
  308. package/dist/routes/ui-config.js +27 -3
  309. package/dist/routes/ui-data.js +21 -20
  310. package/dist/routes/ui.js +1 -1
  311. package/dist/runtime/call-admission.js +0 -26
  312. package/dist/runtime/call-entry.js +30 -0
  313. package/dist/runtime/call.js +552 -0
  314. package/dist/runtime/connector-scope.js +7 -0
  315. package/dist/runtime/credential-probe.js +34 -0
  316. package/dist/runtime/executor.js +40 -0
  317. package/dist/runtime/native-storage.js +63 -0
  318. package/dist/runtime/registry.js +27 -0
  319. package/dist/runtime/request-scope.js +72 -0
  320. package/dist/runtime/run.js +15 -7
  321. package/dist/runtime/shared-read.js +34 -5
  322. package/dist/runtime/storage.js +34 -21
  323. package/dist/sent-secrets.d.ts +194 -37
  324. package/dist/sent-secrets.js +1743 -340
  325. package/dist/server.js +5 -56
  326. package/dist/skills.js +322 -223
  327. package/dist/sqlite.js +15 -14
  328. package/dist/storage/d1-copy.js +255 -0
  329. package/dist/storage/d1-driver.js +15 -0
  330. package/dist/storage/keys.js +28 -0
  331. package/dist/storage/sql-driver.js +88 -0
  332. package/dist/storage/sql-native.js +544 -0
  333. package/dist/storage/sql-schema.d.ts +6 -0
  334. package/dist/storage/sql-schema.js +15 -0
  335. package/dist/storage/sql.d.ts +14 -20
  336. package/dist/storage/sql.js +29 -535
  337. package/dist/timeout.js +0 -26
  338. package/dist/tool-safety.js +20 -10
  339. package/dist/types.d.ts +9 -109
  340. package/dist/ui.d.ts +1 -1
  341. package/dist/ui.js +0 -1
  342. package/dist/upward.js +3 -0
  343. package/dist/usage-guide.js +3 -1
  344. package/dist/validate.d.ts +4 -2
  345. package/dist/validate.js +86 -9
  346. package/dist/version.d.ts +1 -1
  347. package/dist/version.js +1 -1
  348. package/dist/worker.js +312 -292
  349. package/dist/workspace-subject.js +5 -1
  350. package/dist/write-outcome.js +454 -34
  351. package/documentation/README.md +28 -7
  352. package/documentation/architecture.md +2409 -255
  353. package/documentation/auth.md +867 -114
  354. package/documentation/code-mode.md +49 -16
  355. package/documentation/deploying.md +164 -20
  356. package/documentation/hosted-mcp-migration.md +460 -0
  357. package/documentation/integrating.md +129 -144
  358. package/documentation/meta-tools.md +409 -32
  359. package/documentation/operating.md +27 -3
  360. package/documentation/operator-tests.md +3 -0
  361. package/documentation/operator-ui.md +84 -48
  362. package/documentation/provider-auth-migration.md +16 -63
  363. package/documentation/provider-migration-0.29.md +10 -5
  364. package/documentation/provider-migration-0.35.md +975 -0
  365. package/documentation/providers.md +1347 -0
  366. package/examples/worker/AGENTS.md +23 -9
  367. package/examples/worker/README.md +254 -135
  368. package/examples/worker/alchemy.run.ts +116 -0
  369. package/examples/worker/gitignore +10 -0
  370. package/examples/worker/src/connecta.config.ts +23 -21
  371. package/examples/worker/wrangler.jsonc +14 -5
  372. package/guides/connecting-agents.md +157 -0
  373. package/guides/how-it-works.md +156 -0
  374. package/guides/safety-and-trust.md +153 -0
  375. package/package.json +30 -50
  376. package/templates/node/.env.example +3 -0
  377. package/templates/node/README.md +22 -2
  378. package/templates/node/docker-compose.yml +1 -0
  379. package/templates/node/package.json +3 -2
  380. package/templates/node/src/connecta.config.ts +8 -0
  381. package/dist/catalog-drift.d.ts +0 -138
  382. package/dist/catalog-drift.js +0 -578
  383. package/dist/operator-ui/agents.d.ts +0 -74
  384. package/dist/operator-ui/agents.js +0 -104
  385. package/dist/operator-ui/config-summary.js +0 -565
  386. package/dist/operator-ui/connection-map.js +0 -376
  387. package/dist/operator-ui/endpoints.js +0 -221
  388. package/dist/operator-ui/fix-prompts.d.ts +0 -18
  389. package/dist/operator-ui/fix-prompts.js +0 -87
  390. package/dist/operator-ui/health.js +0 -52
  391. package/dist/operator-ui/member-page.js +0 -97
  392. package/dist/operator-ui/overview.js +0 -123
  393. package/dist/operator-ui/setup-commands.js +0 -51
  394. package/dist/operator-ui/view.d.ts +0 -401
  395. package/dist/operator-ui/view.js +0 -705
  396. package/dist/providers/_shared/request-token.js +0 -83
  397. package/dist/providers/_shared/rest/dispatch.js +0 -41
  398. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  399. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  400. package/dist/providers/_shared/rest/tools.js +0 -569
  401. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  402. package/dist/providers/basecamp/index.d.ts +0 -45
  403. package/dist/providers/basecamp/index.js +0 -997
  404. package/dist/providers/basecamp/skill.generated.js +0 -9
  405. package/dist/providers/cloudflare/rest.d.ts +0 -37
  406. package/dist/providers/cloudflare/rest.js +0 -1097
  407. package/dist/providers/github/hosted.js +0 -218
  408. package/dist/providers/github/rest.js +0 -321
  409. package/dist/providers/infisical/index.d.ts +0 -7
  410. package/dist/providers/infisical/index.js +0 -713
  411. package/dist/providers/infisical/skill.generated.js +0 -8
  412. package/dist/providers/intercom/index.d.ts +0 -24
  413. package/dist/providers/intercom/index.js +0 -121
  414. package/dist/providers/intercom/skill.generated.js +0 -8
  415. package/dist/providers/linear/index.d.ts +0 -55
  416. package/dist/providers/linear/index.js +0 -537
  417. package/dist/providers/linear/skill.generated.js +0 -8
  418. package/dist/providers/mixpanel/index.d.ts +0 -59
  419. package/dist/providers/mixpanel/index.js +0 -472
  420. package/dist/providers/mixpanel/operations.js +0 -20
  421. package/dist/providers/mixpanel/rest.js +0 -603
  422. package/dist/providers/mixpanel/skill.generated.js +0 -10
  423. package/dist/providers/mixpanel/value-safety.js +0 -16
  424. package/dist/providers/notion/index.d.ts +0 -67
  425. package/dist/providers/notion/index.js +0 -368
  426. package/dist/providers/notion/openapi.generated.js +0 -75
  427. package/dist/providers/notion/rest.d.ts +0 -24
  428. package/dist/providers/notion/rest.js +0 -1226
  429. package/dist/providers/notion/skill.generated.js +0 -11
  430. package/dist/providers/notion/value-safety.js +0 -56
  431. package/dist/providers/revenuecat/index.d.ts +0 -51
  432. package/dist/providers/revenuecat/index.js +0 -697
  433. package/dist/providers/revenuecat/skill.generated.js +0 -11
  434. package/dist/providers/stripe/rest.d.ts +0 -14
  435. package/dist/providers/stripe/rest.js +0 -402
  436. package/dist/providers/vercel/rest.d.ts +0 -20
  437. package/dist/providers/vercel/rest.js +0 -1020
  438. package/dist/providers/wispr-flow/index.d.ts +0 -14
  439. package/dist/providers/wispr-flow/index.js +0 -117
  440. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  441. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -0,0 +1,146 @@
1
+ // Shared REST call shapes, pinned-schema conversion and indexed vendor declarations.
2
+ import { Effect, Schema } from "effect";
3
+ import { ConnectorCallError } from "../../../errors.js";
4
+ import { Refusal } from "../../../http/errors.js";
5
+ import { Integer, isMinChars, isMaxChars } from "../../../http/json-schema.js";
6
+ import { vendor as declareVendor, get, head, post, put, patch, del, } from "../../../http/vendor.js";
7
+ function isRecord(value) {
8
+ return !!value && typeof value === "object" && !Array.isArray(value);
9
+ }
10
+ function invalid(message) {
11
+ throw new ConnectorCallError("invalid_args", message);
12
+ }
13
+ export function checked(run) {
14
+ return Effect.try({ try: run, catch: (error) => error }).pipe(Effect.catch((error) => error instanceof ConnectorCallError ? Effect.fail(new Refusal({ error })) : Effect.die(error)));
15
+ }
16
+ /** Index matches retain encoded segments; HttpApiClient uses encodeURIComponent. */
17
+ export function typedParams(params) {
18
+ return Object.fromEntries(Object.entries(params).map(([name, encoded]) => {
19
+ let value;
20
+ try {
21
+ value = decodeURIComponent(encoded);
22
+ }
23
+ catch {
24
+ return invalid(`Indexed path parameter ${name} is not valid URI encoding.`);
25
+ }
26
+ if (encodeURIComponent(value) !== encoded)
27
+ invalid(`Indexed path parameter ${name} does not round-trip through the typed path encoder.`);
28
+ return [name, value];
29
+ }));
30
+ }
31
+ /** Convert the JSON forms published by pinned indexes. No vendor encoders run here. */
32
+ export function schema(node) {
33
+ const n = node;
34
+ let out;
35
+ const types = n["type"];
36
+ if (n["truncated"] === true)
37
+ out = Schema.Unknown;
38
+ else if (Array.isArray(n["enum"]))
39
+ out = n["enum"].length === 1 ? Schema.Literal(n["enum"][0]) : Schema.Literals(n["enum"]);
40
+ else if (Array.isArray(n["anyOf"]))
41
+ out = Schema.Union(n["anyOf"].map((v) => schema(v)));
42
+ else if (Array.isArray(types))
43
+ out = Schema.Union(types.map((type) => schema({ ...n, type, description: undefined })));
44
+ else if (types === "object" || isRecord(n["properties"])) {
45
+ const required = n["required"];
46
+ const fields = Object.fromEntries(Object.entries((n["properties"] ?? {})).map(([key, value]) => {
47
+ const part = schema(value);
48
+ const annotated = part.ast._tag === "Unknown" && isRecord(value) && typeof value["description"] === "string"
49
+ ? part.pipe(Schema.annotateKey({ description: value["description"] }))
50
+ : part;
51
+ return [key, required?.includes(key) ? annotated : Schema.optionalKey(annotated)];
52
+ }));
53
+ out =
54
+ n["properties"] && n["additionalProperties"] !== true
55
+ ? Schema.Struct(fields)
56
+ : Schema.StructWithRest(Schema.Struct(fields), [
57
+ Schema.Record(Schema.String, isRecord(n["additionalProperties"]) ? schema(n["additionalProperties"]) : Schema.Unknown),
58
+ ]);
59
+ }
60
+ else if (types === "array") {
61
+ let array = Schema.Array(schema((n["items"] ?? {})));
62
+ if (typeof n["minItems"] === "number")
63
+ array = array.check(Schema.isMinLength(n["minItems"]));
64
+ if (typeof n["maxItems"] === "number")
65
+ array = array.check(Schema.isMaxLength(n["maxItems"]));
66
+ if (n["uniqueItems"] === true)
67
+ array = array.check(Schema.isUnique());
68
+ out = array;
69
+ }
70
+ else if (types === "string") {
71
+ let string = Schema.String;
72
+ if (typeof n["minLength"] === "number")
73
+ string = string.check(isMinChars(n["minLength"]));
74
+ if (typeof n["maxLength"] === "number")
75
+ string = string.check(isMaxChars(n["maxLength"]));
76
+ out = string;
77
+ }
78
+ else if (types === "integer" || types === "number") {
79
+ let number = types === "integer" ? Integer : Schema.Finite;
80
+ if (typeof n["minimum"] === "number")
81
+ number = number.check(Schema.isGreaterThanOrEqualTo(n["minimum"]));
82
+ if (typeof n["maximum"] === "number")
83
+ number = number.check(Schema.isLessThanOrEqualTo(n["maximum"]));
84
+ out = number;
85
+ }
86
+ else
87
+ out = types === "boolean" ? Schema.Boolean : types === "null" ? Schema.Null : Schema.Unknown;
88
+ if (n["nullable"] === true)
89
+ out = Schema.Union([out, Schema.Null]);
90
+ if (n["writeOnly"] === true)
91
+ out = out.annotate({ writeOnly: true });
92
+ return typeof n["description"] === "string" ? out.annotate({ description: n["description"] }) : out;
93
+ }
94
+ /** Declare each indexed operation once; request schema subtrees stay suspended until manifest/client use. */
95
+ export function indexedVendor(name, index, named = []) {
96
+ for (const op of index.ops) {
97
+ if ([...op.path.matchAll(/\{([^}]*)\}/g)].some((match) => !/^[A-Za-z0-9_-]+$/.test(match[1])) ||
98
+ /[{}]/.test(op.path.replace(/\{[^}]*\}/g, "")))
99
+ throw new Error(`Indexed operation ${op.method} ${op.path} has an unsupported path parameter name.`);
100
+ }
101
+ const constructors = { GET: get, HEAD: head, POST: post, PUT: put, PATCH: patch, DELETE: del };
102
+ const overrides = new Map(named.map((op) => {
103
+ const declared = op;
104
+ return [`${declared.method} ${declared.path.replace(/:([^/]+)/g, "{$1}")}`, op];
105
+ }));
106
+ for (const key of overrides.keys())
107
+ if (!index.ops.some((op) => `${op.method} ${op.path}` === key))
108
+ throw new Error(`Named operation ${key} is absent from the pinned index.`);
109
+ const cache = new Map();
110
+ const cached = (node) => {
111
+ const key = JSON.stringify(node);
112
+ let found = cache.get(key);
113
+ if (!found) {
114
+ found = schema(node);
115
+ cache.set(key, found);
116
+ }
117
+ return found;
118
+ };
119
+ const build = () => {
120
+ const endpoints = index.ops.map((op) => overrides.get(`${op.method} ${op.path}`) ??
121
+ constructors[op.method]("indexed" + op.row,
122
+ // These declarations feed only the manifest. The live client uses `named` below.
123
+ op.path, {
124
+ // Parameter names come directly from the vendor template; hatch validation still uses index.check.
125
+ params: Schema.Struct(Object.fromEntries([...op.path.matchAll(/\{([^}]+)\}/g)].map((match) => [match[1], Schema.String]))),
126
+ query: Schema.suspend(() => {
127
+ const parameters = index.contract(op).parameters.filter((p) => p.in === "query");
128
+ return Schema.Struct(Object.fromEntries(parameters.map((p) => [p.name, p.required ? cached(p.schema) : Schema.optionalKey(cached(p.schema))])));
129
+ }),
130
+ ...(op.method === "GET" || op.method === "HEAD"
131
+ ? {}
132
+ : { payload: Schema.suspend(() => cached(index.contract(op).body?.schema ?? {})) }),
133
+ success: Schema.Unknown,
134
+ }));
135
+ if (!endpoints.length)
136
+ throw new Error("An indexed vendor needs operations.");
137
+ return declareVendor(name, endpoints[0], ...endpoints.slice(1)).api;
138
+ };
139
+ if (!named.length)
140
+ throw new Error("An indexed vendor declares at least its typed credential probe.");
141
+ let built;
142
+ return {
143
+ ...declareVendor(name, named[0], ...named.slice(1)),
144
+ indexed: { operations: index.ops.map((op) => `${op.method} ${op.path}`).sort(), api: () => (built ??= build()) },
145
+ };
146
+ }
@@ -1,3 +1,5 @@
1
+ import { canonicalJson } from "../../../canonical-json.js";
2
+ import { parseIndexDetails } from "./compact-index.js";
1
3
  // The pinned operation index a REST connector validates against before it
2
4
  // sends anything. `scripts/generate-openapi.mjs` compiles a vendor's OpenAPI
3
5
  // document into `OpenApiData` (search rows plus request-side details as one
@@ -114,16 +116,26 @@ export class OperationIndex {
114
116
  #vendor;
115
117
  #segments;
116
118
  #slashParams;
119
+ #uriTemplates;
120
+ get pathMatching() {
121
+ return this.#uriTemplates ? "uri-template" : "segments";
122
+ }
117
123
  #details;
124
+ #fields;
125
+ #requestSchemas;
118
126
  #words;
119
127
  /**
120
128
  * `vendor` is the tool-name prefix; `title` the display name in refusals.
121
129
  * `slashParams` names path parameters whose values may carry an encoded
122
130
  * "/" (`%2F`), such as an object key, and only as the path's last segment.
131
+ * `pathMatching: "uri-template"` opts into decoded literals and parameters
132
+ * embedded in a segment, such as Google's `{id}:batchUpdate`. The default
133
+ * retains exact literal segments and whole-segment parameters.
123
134
  */
124
135
  constructor(data, names) {
125
136
  const { title } = names;
126
137
  this.#slashParams = new Set(names.slashParams ?? []);
138
+ this.#uriTemplates = names.pathMatching === "uri-template";
127
139
  this.#data = data;
128
140
  this.#title = title;
129
141
  this.#vendor = names.vendor;
@@ -145,6 +157,46 @@ export class OperationIndex {
145
157
  this.#segments = this.ops.map((op) => op.path.slice(1).split("/"));
146
158
  this.methods = [...METHODS].filter((method) => this.ops.some((op) => op.method === method));
147
159
  }
160
+ /** Content binding for discovery continuations; labels alone never identify an index. */
161
+ async cursorRevision() {
162
+ const bytes = new TextEncoder().encode(canonicalJson([
163
+ this.#data,
164
+ this.revision,
165
+ [...this.#slashParams].sort(),
166
+ ...(this.#uriTemplates ? ["uri-template"] : []),
167
+ ]));
168
+ return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)), (byte) => byte.toString(16).padStart(2, "0")).join("");
169
+ }
170
+ /** The request and response properties this operation declares; none when the index carries no fields. */
171
+ fields(op) {
172
+ if (!this.#fields) {
173
+ const data = this.#data.fields;
174
+ if (typeof data === "string") {
175
+ // Generated REST indexes share response paths and complete rows. Kit
176
+ // vendor indexes retain their directly declared body/response fields.
177
+ const { p, d, o } = JSON.parse(data);
178
+ const rows = d.map((ids) => ids.map((id) => ({ in: "response", path: p[id] })));
179
+ this.#fields = o.map((id) => rows[id]);
180
+ }
181
+ else
182
+ this.#fields = data ?? [];
183
+ }
184
+ return this.#fields[op.row] ?? [];
185
+ }
186
+ /**
187
+ * The names a result's first dot-path segment may take: the success
188
+ * response's own properties, or its items' properties when it is an array.
189
+ * Undefined when the operation declares no response contract.
190
+ */
191
+ responseRoots(op) {
192
+ const paths = this.fields(op).filter((field) => field.in === "response");
193
+ if (paths.length === 0)
194
+ return undefined;
195
+ return new Set(paths.map((field) => field.path
196
+ .replace(/^\[\]\./, "")
197
+ .split(".")[0]
198
+ .replace(/\[\]$/, "")));
199
+ }
148
200
  /** The operation with this exact method and path template, if any. */
149
201
  operation(method, template) {
150
202
  return this.ops.find((op) => op.method === method && op.path === template);
@@ -165,11 +217,29 @@ export class OperationIndex {
165
217
  return;
166
218
  let score = 0;
167
219
  for (const [index, part] of template.entries()) {
168
- if (part.startsWith("{"))
220
+ if (!this.#uriTemplates) {
221
+ if (part.startsWith("{"))
222
+ continue;
223
+ if (part !== segments[index])
224
+ return;
225
+ score += 1;
169
226
  continue;
170
- if (part !== segments[index])
171
- return;
172
- score += 1;
227
+ }
228
+ const parameter = /^(.*)\{([^{}]+)\}(.*)$/.exec(part);
229
+ const value = decodeURIComponent(segments[index]);
230
+ if (parameter) {
231
+ if (!value.startsWith(parameter[1]) ||
232
+ !value.endsWith(parameter[3]) ||
233
+ value.length <= parameter[1].length + parameter[3].length)
234
+ return;
235
+ if (parameter[1] || parameter[3])
236
+ score += 0.5;
237
+ }
238
+ else {
239
+ if (part !== value)
240
+ return;
241
+ score += 1;
242
+ }
173
243
  }
174
244
  if (score > best.score)
175
245
  best = { score, rows: [row] };
@@ -195,9 +265,34 @@ export class OperationIndex {
195
265
  }
196
266
  const params = {};
197
267
  template.forEach((part, index) => {
198
- if (part.startsWith("{"))
199
- params[part.slice(1, -1)] = segments[index];
268
+ if (!this.#uriTemplates) {
269
+ if (part.startsWith("{"))
270
+ params[part.slice(1, -1)] = segments[index];
271
+ return;
272
+ }
273
+ const parameter = /^(.*)\{([^{}]+)\}(.*)$/.exec(part);
274
+ if (parameter) {
275
+ const raw = segments[index];
276
+ const prefix = parameter[1], suffix = parameter[3];
277
+ params[parameter[2]] =
278
+ raw.startsWith(prefix) && raw.endsWith(suffix)
279
+ ? raw.slice(prefix.length, suffix ? -suffix.length : undefined)
280
+ : encodeURIComponent(decodeURIComponent(raw).slice(prefix.length, suffix ? -suffix.length : undefined));
281
+ }
200
282
  });
283
+ const issues = [];
284
+ const repair = [];
285
+ for (const [name, at, , schema] of this.#row(op)?.[0] ?? []) {
286
+ if (at === "path" && params[name] !== undefined)
287
+ this.#check(schema, decodeURIComponent(params[name]), `/path/${name}`, issues, repair);
288
+ }
289
+ if (issues.length) {
290
+ const shown = issues
291
+ .slice(0, 5)
292
+ .map((issue) => `${issue.path} (${issue.code}: ${issue.expected})`)
293
+ .join("; ");
294
+ invalid(`Not sent: the path does not match ${op.method} ${op.path} in the pinned API index: ${shown}. Substitute real ids matching ${this.#vendorTool("details")}.${issues.some((issue) => issue.expected?.includes("safe integer")) ? " Integer ids use canonical ASCII decimal notation within the safe-integer range." : ""}`, issues.slice(0, MAX_ISSUES));
295
+ }
201
296
  return { op, params };
202
297
  }
203
298
  /** Up to five operations whose paths most resemble a missed one. */
@@ -231,6 +326,9 @@ export class OperationIndex {
231
326
  * the path, summary, operationId, or tag (plural-insensitive, prefixes of
232
327
  * three letters count), and path matches weigh most. A query that starts
233
328
  * with "/" also matches the templates that fit it.
329
+ * Standard hatches opt into partial matches, ordered by matched term count
330
+ * before relevance, including the person/people alias. Legacy callers keep
331
+ * the all-term contract.
234
332
  */
235
333
  search(query, options) {
236
334
  this.#words ??= this.ops.map((op) => ({
@@ -261,6 +359,12 @@ export class OperationIndex {
261
359
  if (set.has(term))
262
360
  return 2;
263
361
  for (const word of set) {
362
+ if (options.partial && ((term === "person" && word === "people") || (term === "people" && word === "person")))
363
+ return 2;
364
+ if (options.partial &&
365
+ ((term.endsWith("y") && word === `${term.slice(0, -1)}ies`) ||
366
+ (word.endsWith("y") && term === `${word.slice(0, -1)}ies`)))
367
+ return 2;
264
368
  if (word === `${term}s` || term === `${word}s` || word === `${term}es` || term === `${word}es`)
265
369
  return 2;
266
370
  if (term.length >= 3 && word.startsWith(term))
@@ -280,12 +384,13 @@ export class OperationIndex {
280
384
  matched += 1;
281
385
  score += path * 3 + summary * 1.5 + id;
282
386
  }
283
- if (!fits.has(op.row) && (terms.length === 0 || matched < terms.length))
387
+ if (!fits.has(op.row) && (terms.length === 0 || matched < (options.partial ? 1 : terms.length)))
284
388
  return [];
285
- return [{ op, score }];
389
+ return [{ op, score, matched }];
286
390
  });
287
391
  return ranked
288
- .sort((a, b) => b.score - a.score ||
392
+ .sort((a, b) => (options.partial ? b.matched - a.matched : 0) ||
393
+ b.score - a.score ||
289
394
  a.op.path.split("/").length - b.op.path.split("/").length ||
290
395
  a.op.path.localeCompare(b.op.path))
291
396
  .slice(0, options.limit)
@@ -302,8 +407,16 @@ export class OperationIndex {
302
407
  const declared = row ? row[0] : [];
303
408
  // A generator may omit plain-string path parameters (`pathParams:
304
409
  // "typed"`); the template still names them, so the contract does too.
305
- const implied = this.#segments[op.row].filter((part) => part.startsWith("{") && !declared.some(([name, at]) => at === "path" && name === part.slice(1, -1)))
306
- .map((part) => [part.slice(1, -1), "path", 1, { t: "string" }]);
410
+ const implied = this.#segments[op.row].flatMap((part) => {
411
+ const name = this.#uriTemplates
412
+ ? /\{([^{}]+)\}/.exec(part)?.[1]
413
+ : part.startsWith("{")
414
+ ? part.slice(1, -1)
415
+ : undefined;
416
+ return name !== undefined && !declared.some(([key, at]) => at === "path" && key === name)
417
+ ? [[name, "path", 1, { t: "string" }]]
418
+ : [];
419
+ });
307
420
  const parameters = [...implied, ...declared]
308
421
  .filter(([name]) => only === undefined || name === only)
309
422
  .map(([name, at, required, schema, description]) => ({
@@ -317,7 +430,22 @@ export class OperationIndex {
317
430
  if (row && row[1] !== 0) {
318
431
  const [contentType, schema] = row[1];
319
432
  const node = this.#deref(schema);
320
- if (only !== undefined && node.p?.[only] !== undefined) {
433
+ const full = this.#requestSchema(op);
434
+ if (full && only === undefined) {
435
+ body = { contentType, ...(row[1][2] === 1 ? { required: true } : {}), schema: full };
436
+ }
437
+ else if (full && only !== undefined && full["properties"]?.[only]) {
438
+ body = {
439
+ contentType,
440
+ schema: {
441
+ type: "object",
442
+ properties: { [only]: full["properties"][only] },
443
+ ...(Array.isArray(full["required"]) && full["required"].includes(only) ? { required: [only] } : {}),
444
+ ...(full["$defs"] ? { $defs: full["$defs"] } : {}),
445
+ },
446
+ };
447
+ }
448
+ else if (only !== undefined && node.p?.[only] !== undefined) {
321
449
  body = {
322
450
  contentType,
323
451
  schema: {
@@ -402,8 +530,40 @@ export class OperationIndex {
402
530
  #vendorTool(kind) {
403
531
  return `${this.#vendor}_api_${kind}`;
404
532
  }
533
+ #requestSchema(op) {
534
+ if (!this.#data.requestSchemas)
535
+ return undefined;
536
+ this.#requestSchemas ??= JSON.parse(this.#data.requestSchemas);
537
+ const graph = this.#requestSchemas;
538
+ const root = graph.roots[op.row];
539
+ if (!root)
540
+ return undefined;
541
+ const definitions = {};
542
+ const visit = (value) => {
543
+ if (!value || typeof value !== "object")
544
+ return;
545
+ if (Array.isArray(value)) {
546
+ for (const child of value)
547
+ visit(child);
548
+ return;
549
+ }
550
+ const object = value;
551
+ if (typeof object["$ref"] === "string" && object["$ref"].startsWith("#/$defs/")) {
552
+ const name = object["$ref"].slice(8);
553
+ if (!Object.hasOwn(definitions, name)) {
554
+ definitions[name] = graph.definitions[name] ?? {};
555
+ visit(definitions[name]);
556
+ }
557
+ }
558
+ for (const child of Object.values(object))
559
+ visit(child);
560
+ };
561
+ visit(root);
562
+ const resolved = typeof root["$ref"] === "string" ? graph.definitions[root["$ref"].slice(8)] : root;
563
+ return { ...resolved, ...(Object.keys(definitions).length ? { $defs: definitions } : {}) };
564
+ }
405
565
  #row(op) {
406
- this.#details ??= JSON.parse(this.#data.details);
566
+ this.#details ??= parseIndexDetails(this.#data);
407
567
  const row = this.#details.o[op.row];
408
568
  return row === 0 ? undefined : row;
409
569
  }
@@ -427,6 +587,12 @@ export class OperationIndex {
427
587
  out["format"] = resolved.f;
428
588
  if (resolved.n === 1)
429
589
  out["nullable"] = true;
590
+ if (resolved.l !== undefined)
591
+ out["minimum"] = resolved.l;
592
+ if (resolved.u !== undefined)
593
+ out["maximum"] = resolved.u;
594
+ if (resolved.deprecated === true)
595
+ out["deprecated"] = true;
430
596
  if (resolved.a)
431
597
  out["anyOf"] = resolved.a.map((branch) => this.#schema(branch));
432
598
  if (resolved.p) {
@@ -446,6 +612,35 @@ export class OperationIndex {
446
612
  if (issues.length >= MAX_ISSUES)
447
613
  return;
448
614
  const schema = this.#deref(node);
615
+ const path = at.startsWith("/path/");
616
+ const types = typesOf(schema);
617
+ if (path && !schema.a && !types.includes("string") && (types.includes("integer") || types.includes("number"))) {
618
+ const integer = types.includes("integer") && !types.includes("number");
619
+ const numeric = typeof value === "string" ? Number(value) : NaN;
620
+ const syntax = integer ? /^(?:0|-?[1-9][0-9]*)$/ : /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/;
621
+ if (typeof value !== "string" ||
622
+ !syntax.test(value) ||
623
+ Object.is(numeric, -0) ||
624
+ !Number.isFinite(numeric) ||
625
+ Math.abs(numeric) > Number.MAX_SAFE_INTEGER ||
626
+ (integer && !Number.isSafeInteger(numeric))) {
627
+ issues.push({
628
+ path: at,
629
+ code: "type",
630
+ expected: integer ? "a canonical ASCII decimal safe integer" : "a canonical ASCII decimal number",
631
+ });
632
+ return;
633
+ }
634
+ value = numeric;
635
+ }
636
+ else if (path && types.length && !types.includes("string") && !schema.a) {
637
+ if (types.includes("boolean") && (value === "true" || value === "false"))
638
+ value = value === "true";
639
+ else {
640
+ issues.push({ path: at, code: "type", expected: types.join(" or ") });
641
+ return;
642
+ }
643
+ }
449
644
  if (schema.x === 1)
450
645
  return;
451
646
  // Conflicting composed constraints (disjoint enums or types) admit nothing,
@@ -454,6 +649,28 @@ export class OperationIndex {
454
649
  issues.push({ path: at, code: "enum", expected: "no value: this field's combined constraints admit none" });
455
650
  return;
456
651
  }
652
+ // Only newly opted-in bounded schemas enforce scalar numeric values;
653
+ // existing indexes retain their previous validation behavior. HTTP query
654
+ // strings may represent numbers, but must match the declared numeric type.
655
+ if (schema.l !== undefined || schema.u !== undefined) {
656
+ if (value === null && schema.n === 1)
657
+ return;
658
+ const integer = typesOf(schema).includes("integer");
659
+ const syntax = integer ? /^-?\d+$/ : /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
660
+ const numeric = typeof value === "number"
661
+ ? value
662
+ : at.startsWith("/query/") && typeof value === "string" && syntax.test(value)
663
+ ? Number(value)
664
+ : NaN;
665
+ if (!Number.isFinite(numeric) || (integer && !Number.isSafeInteger(numeric))) {
666
+ issues.push({ path: at, code: "type", expected: integer ? "integer" : "finite number" });
667
+ return;
668
+ }
669
+ if (schema.l !== undefined && numeric < schema.l)
670
+ issues.push({ path: at, code: "minimum", expected: `at least ${schema.l}` });
671
+ if (schema.u !== undefined && numeric > schema.u)
672
+ issues.push({ path: at, code: "maximum", expected: `at most ${schema.u}` });
673
+ }
457
674
  if (value === null || value === "")
458
675
  return;
459
676
  if (schema.a) {
@@ -472,7 +689,6 @@ export class OperationIndex {
472
689
  }
473
690
  return;
474
691
  }
475
- const types = typesOf(schema);
476
692
  if (schema.e && (typeof value === "string" || typeof value === "number" || typeof value === "boolean")) {
477
693
  if (!schema.e.some((option) => option === value || String(option) === String(value))) {
478
694
  issues.push({ path: at, code: "enum", expected: oneOf(schema.e.map(String)) });
@@ -0,0 +1,11 @@
1
+ /** Match a reviewed non-JSON success media type only on its pinned operation. */
2
+ export function responseMedia(media, status, operation, contentType = "") {
3
+ if (status < 200 || status > 299)
4
+ return undefined;
5
+ const type = contentType.split(";", 1)[0].trim().toLowerCase();
6
+ const path = operation.template.replace(/:([^/]+)/g, "{$1}");
7
+ if (!type ||
8
+ !media[`${operation.method} ${path}`]?.some((declared) => declared === type || (declared.endsWith("/*") && type.startsWith(declared.slice(0, -1)))))
9
+ return undefined;
10
+ return /^text\/|\bxml\b|\bcsv\b|\b(?:x-ndjson|jsonl|stream\+json)\b/.test(type) ? "text" : "binary";
11
+ }