@zackbart/connecta 0.34.1 → 0.35.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 (429) hide show
  1. package/CHANGELOG.md +363 -0
  2. package/README.md +62 -106
  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 +2051 -1160
  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 +663 -271
  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 +12 -7
  53. package/dist/connectors/api-connector.js +142 -56
  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 +228 -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 +383 -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/agents.d.ts +5 -4
  109. package/dist/operator-ui/agents.js +17 -7
  110. package/dist/operator-ui/config-summary.js +5 -4
  111. package/dist/operator-ui/connection-map.js +7 -5
  112. package/dist/operator-ui/contract.d.ts +7 -3
  113. package/dist/operator-ui/endpoints.js +4 -13
  114. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  115. package/dist/operator-ui/fix-prompts.js +0 -8
  116. package/dist/operator-ui/generated.js +3 -3
  117. package/dist/operator-ui/model.d.ts +2 -3
  118. package/dist/operator-ui/overview.js +5 -2
  119. package/dist/operator-ui/setup-commands.js +0 -4
  120. package/dist/operator-ui/view.d.ts +2 -25
  121. package/dist/operator-ui/view.js +2 -76
  122. package/dist/program-writes.js +47 -26
  123. package/dist/provider-call-facts.d.ts +115 -0
  124. package/dist/provider-call-facts.js +182 -0
  125. package/dist/provider-call.d.ts +112 -0
  126. package/dist/provider-call.js +271 -0
  127. package/dist/provider.d.ts +65 -31
  128. package/dist/provider.js +116 -39
  129. package/dist/providers/_shared/google/hatch.js +91 -0
  130. package/dist/providers/_shared/google/kit.js +537 -0
  131. package/dist/providers/_shared/google/result-size.js +15 -2
  132. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  133. package/dist/providers/_shared/google/service-account.js +8 -4
  134. package/dist/providers/_shared/google/workspace.d.ts +6 -210
  135. package/dist/providers/_shared/google/workspace.js +6 -425
  136. package/dist/providers/_shared/rest/compact-index.js +86 -0
  137. package/dist/providers/_shared/rest/dispatch.js +3 -23
  138. package/dist/providers/_shared/rest/kit.js +546 -0
  139. package/dist/providers/_shared/rest/operation-index.js +230 -14
  140. package/dist/providers/_shared/rest/response-media.js +11 -0
  141. package/dist/providers/_shared/rest/tools.js +101 -78
  142. package/dist/providers/_shared/rest/value-safety.js +353 -195
  143. package/dist/providers/_shared/sensitive-fields.js +27 -0
  144. package/dist/providers/breeze/api.js +584 -0
  145. package/dist/providers/breeze/index.d.ts +1 -3
  146. package/dist/providers/breeze/index.js +67 -1420
  147. package/dist/providers/breeze/openapi.generated.js +60 -0
  148. package/dist/providers/breeze/skill.generated.js +2 -6
  149. package/dist/providers/breeze/tools.js +696 -0
  150. package/dist/providers/ccb/api.js +496 -0
  151. package/dist/providers/ccb/index.d.ts +15 -37
  152. package/dist/providers/ccb/index.js +77 -1702
  153. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  154. package/dist/providers/ccb/lib/constants.js +74 -0
  155. package/dist/providers/ccb/lib/guide.js +9 -0
  156. package/dist/providers/ccb/lib/verdicts.js +387 -0
  157. package/dist/providers/ccb/openapi.generated.js +397 -0
  158. package/dist/providers/ccb/safety.js +295 -0
  159. package/dist/providers/ccb/skill.generated.js +2 -6
  160. package/dist/providers/ccb/tools.js +853 -0
  161. package/dist/providers/cloudflare/api.js +1066 -0
  162. package/dist/providers/cloudflare/index.d.ts +5 -22
  163. package/dist/providers/cloudflare/index.js +79 -197
  164. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  165. package/dist/providers/cloudflare/lib/config.js +2 -0
  166. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  167. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  168. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  169. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  170. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  171. package/dist/providers/cloudflare/openapi.generated.js +4 -3
  172. package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
  173. package/dist/providers/cloudflare/skill.generated.js +2 -10
  174. package/dist/providers/cloudflare/tools.js +360 -0
  175. package/dist/providers/docs/api.js +51 -0
  176. package/dist/providers/docs/index.d.ts +1 -12
  177. package/dist/providers/docs/index.js +53 -1165
  178. package/dist/providers/docs/lib/constants.d.ts +18 -0
  179. package/dist/providers/docs/lib/constants.js +18 -0
  180. package/dist/providers/docs/lib/discovery.js +26 -0
  181. package/dist/providers/docs/lib/requests.js +48 -0
  182. package/dist/providers/docs/lib/schemas.js +168 -0
  183. package/dist/providers/docs/openapi.generated.js +16 -0
  184. package/dist/providers/docs/safety.js +54 -0
  185. package/dist/providers/docs/skill.generated.js +2 -6
  186. package/dist/providers/docs/tools.js +802 -0
  187. package/dist/providers/drive/api.js +177 -0
  188. package/dist/providers/drive/index.d.ts +1 -12
  189. package/dist/providers/drive/index.js +38 -1448
  190. package/dist/providers/drive/lib/constants.d.ts +6 -0
  191. package/dist/providers/drive/lib/constants.js +6 -0
  192. package/dist/providers/drive/lib/contracts.js +532 -0
  193. package/dist/providers/drive/lib/hatch.js +197 -0
  194. package/dist/providers/drive/openapi.generated.js +77 -0
  195. package/dist/providers/drive/safety.js +90 -0
  196. package/dist/providers/drive/skill.generated.js +2 -6
  197. package/dist/providers/drive/tools.js +1290 -0
  198. package/dist/providers/forms/api.js +71 -0
  199. package/dist/providers/forms/index.d.ts +1 -12
  200. package/dist/providers/forms/index.js +49 -1145
  201. package/dist/providers/forms/lib/constants.d.ts +14 -0
  202. package/dist/providers/forms/lib/constants.js +19 -0
  203. package/dist/providers/forms/lib/hatch.js +72 -0
  204. package/dist/providers/forms/openapi.generated.js +23 -0
  205. package/dist/providers/forms/safety.js +34 -0
  206. package/dist/providers/forms/skill.generated.js +2 -8
  207. package/dist/providers/forms/tools.js +1024 -0
  208. package/dist/providers/github/api.js +150 -0
  209. package/dist/providers/github/index.d.ts +4 -5
  210. package/dist/providers/github/index.js +30 -87
  211. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  212. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  213. package/dist/providers/github/lib/discovery.js +132 -0
  214. package/dist/providers/github/lib/operations.js +58 -0
  215. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  216. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  217. package/dist/providers/github/openapi.generated.js +1216 -0
  218. package/dist/providers/github/safety.js +216 -0
  219. package/dist/providers/github/skill.generated.js +2 -5
  220. package/dist/providers/github/tools.js +506 -0
  221. package/dist/providers/gmail/api.js +114 -0
  222. package/dist/providers/gmail/index.d.ts +1 -12
  223. package/dist/providers/gmail/index.js +73 -1621
  224. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  225. package/dist/providers/gmail/lib/constants.js +16 -0
  226. package/dist/providers/gmail/lib/index.js +173 -0
  227. package/dist/providers/gmail/lib/schemas.js +176 -0
  228. package/dist/providers/gmail/lib/threading.js +120 -0
  229. package/dist/providers/gmail/openapi.generated.js +92 -0
  230. package/dist/providers/gmail/safety.js +21 -0
  231. package/dist/providers/gmail/skill.generated.js +2 -6
  232. package/dist/providers/gmail/tools.js +1435 -0
  233. package/dist/providers/overflow/api.js +1008 -0
  234. package/dist/providers/overflow/index.d.ts +1 -17
  235. package/dist/providers/overflow/index.js +60 -1488
  236. package/dist/providers/overflow/skill.generated.js +2 -5
  237. package/dist/providers/overflow/tools.js +873 -0
  238. package/dist/providers/planning-center/api.js +467 -0
  239. package/dist/providers/planning-center/index.d.ts +4 -35
  240. package/dist/providers/planning-center/index.js +69 -2445
  241. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  242. package/dist/providers/planning-center/lib/constants.js +83 -0
  243. package/dist/providers/planning-center/lib/discovery.js +40 -0
  244. package/dist/providers/planning-center/lib/guide.js +39 -0
  245. package/dist/providers/planning-center/lib/json-api.js +83 -0
  246. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  247. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  248. package/dist/providers/planning-center/safety.js +188 -0
  249. package/dist/providers/planning-center/skill.generated.js +2 -27
  250. package/dist/providers/planning-center/tools.js +1010 -0
  251. package/dist/providers/sheets/api.js +133 -0
  252. package/dist/providers/sheets/index.d.ts +4 -16
  253. package/dist/providers/sheets/index.js +61 -1172
  254. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  255. package/dist/providers/sheets/lib/constants.js +14 -0
  256. package/dist/providers/sheets/lib/hatch.js +163 -0
  257. package/dist/providers/sheets/lib/requests.js +105 -0
  258. package/dist/providers/sheets/lib/schemas.js +138 -0
  259. package/dist/providers/sheets/openapi.generated.js +30 -0
  260. package/dist/providers/sheets/safety.js +27 -0
  261. package/dist/providers/sheets/skill.generated.js +2 -7
  262. package/dist/providers/sheets/tools.js +734 -0
  263. package/dist/providers/slides/api.js +147 -0
  264. package/dist/providers/slides/index.d.ts +2 -10
  265. package/dist/providers/slides/index.js +48 -2555
  266. package/dist/providers/slides/lib/constants.d.ts +11 -0
  267. package/dist/providers/slides/lib/constants.js +11 -0
  268. package/dist/providers/slides/lib/requests.js +60 -0
  269. package/dist/providers/slides/lib/schemas.js +565 -0
  270. package/dist/providers/slides/openapi.generated.js +18 -0
  271. package/dist/providers/slides/skill.generated.js +2 -6
  272. package/dist/providers/slides/tools.js +1968 -0
  273. package/dist/providers/stripe/api.js +401 -0
  274. package/dist/providers/stripe/index.d.ts +5 -27
  275. package/dist/providers/stripe/index.js +74 -210
  276. package/dist/providers/stripe/lib/config.d.ts +4 -0
  277. package/dist/providers/stripe/lib/config.js +2 -0
  278. package/dist/providers/stripe/openapi.generated.js +4 -3
  279. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  280. package/dist/providers/stripe/skill.generated.js +2 -11
  281. package/dist/providers/stripe/tools.js +77 -0
  282. package/dist/providers/tithely/api.js +531 -0
  283. package/dist/providers/tithely/index.d.ts +17 -0
  284. package/dist/providers/tithely/index.js +86 -965
  285. package/dist/providers/tithely/skill.generated.js +2 -5
  286. package/dist/providers/tithely/tools.js +426 -0
  287. package/dist/providers/vercel/api.js +551 -0
  288. package/dist/providers/vercel/index.d.ts +9 -25
  289. package/dist/providers/vercel/index.js +66 -260
  290. package/dist/providers/vercel/lib/config.d.ts +2 -0
  291. package/dist/providers/vercel/lib/config.js +2 -0
  292. package/dist/providers/vercel/lib/index.js +117 -0
  293. package/dist/providers/vercel/lib/logs.js +100 -0
  294. package/dist/providers/vercel/lib/pin.js +270 -0
  295. package/dist/providers/vercel/openapi.generated.js +10 -5
  296. package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
  297. package/dist/providers/vercel/skill.generated.js +2 -7
  298. package/dist/providers/vercel/tools.js +642 -0
  299. package/dist/redaction-identity.js +47 -0
  300. package/dist/redaction-marker.js +125 -0
  301. package/dist/registry.d.ts +21 -15
  302. package/dist/registry.js +409 -376
  303. package/dist/routes/access-tokens.js +1 -1
  304. package/dist/routes/actor-labels.js +1 -1
  305. package/dist/routes/connect.js +1 -1
  306. package/dist/routes/dispatch.js +103 -0
  307. package/dist/routes/mcp.js +170 -79
  308. package/dist/routes/oauth.js +3 -1
  309. package/dist/routes/operator.js +2 -2
  310. package/dist/routes/shared.d.ts +5 -4
  311. package/dist/routes/shared.js +244 -177
  312. package/dist/routes/skills.js +10 -8
  313. package/dist/routes/ui-config.js +27 -3
  314. package/dist/routes/ui-data.js +21 -20
  315. package/dist/routes/ui.js +1 -1
  316. package/dist/runtime/call-admission.js +0 -26
  317. package/dist/runtime/call-entry.js +30 -0
  318. package/dist/runtime/call.js +556 -0
  319. package/dist/runtime/connector-scope.js +7 -0
  320. package/dist/runtime/credential-probe.js +34 -0
  321. package/dist/runtime/executor.js +40 -0
  322. package/dist/runtime/native-storage.js +63 -0
  323. package/dist/runtime/registry.js +27 -0
  324. package/dist/runtime/request-scope.js +72 -0
  325. package/dist/runtime/run.js +15 -7
  326. package/dist/runtime/shared-read.js +34 -5
  327. package/dist/runtime/storage.js +34 -21
  328. package/dist/sent-secrets.d.ts +194 -37
  329. package/dist/sent-secrets.js +1743 -340
  330. package/dist/server.js +5 -56
  331. package/dist/skills.js +322 -222
  332. package/dist/sqlite.js +15 -14
  333. package/dist/storage/d1-copy.js +255 -0
  334. package/dist/storage/d1-driver.js +15 -0
  335. package/dist/storage/keys.js +28 -0
  336. package/dist/storage/sql-driver.js +88 -0
  337. package/dist/storage/sql-native.js +544 -0
  338. package/dist/storage/sql-schema.d.ts +6 -0
  339. package/dist/storage/sql-schema.js +15 -0
  340. package/dist/storage/sql.d.ts +14 -20
  341. package/dist/storage/sql.js +29 -535
  342. package/dist/timeout.js +0 -26
  343. package/dist/tool-safety.js +20 -10
  344. package/dist/types.d.ts +7 -109
  345. package/dist/upward.js +3 -0
  346. package/dist/usage-guide.js +3 -1
  347. package/dist/validate.d.ts +4 -2
  348. package/dist/validate.js +86 -9
  349. package/dist/version.d.ts +1 -1
  350. package/dist/version.js +1 -1
  351. package/dist/worker.js +312 -292
  352. package/dist/workspace-subject.js +5 -1
  353. package/dist/write-outcome.js +454 -34
  354. package/documentation/README.md +27 -7
  355. package/documentation/architecture.md +2547 -226
  356. package/documentation/auth.md +821 -98
  357. package/documentation/code-mode.md +49 -16
  358. package/documentation/deploying.md +164 -20
  359. package/documentation/hosted-mcp-migration.md +460 -0
  360. package/documentation/integrating.md +129 -144
  361. package/documentation/meta-tools.md +409 -32
  362. package/documentation/operating.md +27 -3
  363. package/documentation/operator-tests.md +3 -0
  364. package/documentation/operator-ui.md +68 -45
  365. package/documentation/provider-auth-migration.md +16 -63
  366. package/documentation/provider-migration-0.29.md +10 -5
  367. package/documentation/provider-migration-0.35.md +975 -0
  368. package/documentation/providers.md +965 -0
  369. package/examples/worker/AGENTS.md +23 -9
  370. package/examples/worker/README.md +254 -135
  371. package/examples/worker/alchemy.run.ts +116 -0
  372. package/examples/worker/gitignore +10 -0
  373. package/examples/worker/src/connecta.config.ts +23 -21
  374. package/examples/worker/wrangler.jsonc +14 -5
  375. package/guides/connecting-agents.md +157 -0
  376. package/guides/how-it-works.md +156 -0
  377. package/guides/safety-and-trust.md +153 -0
  378. package/package.json +27 -46
  379. package/templates/node/.env.example +3 -0
  380. package/templates/node/README.md +22 -2
  381. package/templates/node/docker-compose.yml +1 -0
  382. package/templates/node/package.json +3 -2
  383. package/templates/node/src/connecta.config.ts +8 -0
  384. package/dist/catalog-drift.d.ts +0 -138
  385. package/dist/catalog-drift.js +0 -578
  386. package/dist/providers/_shared/request-token.js +0 -83
  387. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  388. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  389. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  390. package/dist/providers/basecamp/index.d.ts +0 -45
  391. package/dist/providers/basecamp/index.js +0 -997
  392. package/dist/providers/basecamp/skill.generated.js +0 -9
  393. package/dist/providers/cloudflare/rest.d.ts +0 -37
  394. package/dist/providers/cloudflare/rest.js +0 -1097
  395. package/dist/providers/github/hosted.js +0 -218
  396. package/dist/providers/github/rest.js +0 -321
  397. package/dist/providers/infisical/index.d.ts +0 -7
  398. package/dist/providers/infisical/index.js +0 -713
  399. package/dist/providers/infisical/skill.generated.js +0 -8
  400. package/dist/providers/intercom/index.d.ts +0 -24
  401. package/dist/providers/intercom/index.js +0 -121
  402. package/dist/providers/intercom/skill.generated.js +0 -8
  403. package/dist/providers/linear/index.d.ts +0 -55
  404. package/dist/providers/linear/index.js +0 -537
  405. package/dist/providers/linear/skill.generated.js +0 -8
  406. package/dist/providers/mixpanel/index.d.ts +0 -59
  407. package/dist/providers/mixpanel/index.js +0 -472
  408. package/dist/providers/mixpanel/operations.js +0 -20
  409. package/dist/providers/mixpanel/rest.js +0 -603
  410. package/dist/providers/mixpanel/skill.generated.js +0 -10
  411. package/dist/providers/mixpanel/value-safety.js +0 -16
  412. package/dist/providers/notion/index.d.ts +0 -67
  413. package/dist/providers/notion/index.js +0 -368
  414. package/dist/providers/notion/openapi.generated.js +0 -75
  415. package/dist/providers/notion/rest.d.ts +0 -24
  416. package/dist/providers/notion/rest.js +0 -1226
  417. package/dist/providers/notion/skill.generated.js +0 -11
  418. package/dist/providers/notion/value-safety.js +0 -56
  419. package/dist/providers/revenuecat/index.d.ts +0 -51
  420. package/dist/providers/revenuecat/index.js +0 -697
  421. package/dist/providers/revenuecat/skill.generated.js +0 -11
  422. package/dist/providers/stripe/rest.d.ts +0 -14
  423. package/dist/providers/stripe/rest.js +0 -402
  424. package/dist/providers/vercel/rest.d.ts +0 -20
  425. package/dist/providers/vercel/rest.js +0 -1020
  426. package/dist/providers/wispr-flow/index.d.ts +0 -14
  427. package/dist/providers/wispr-flow/index.js +0 -117
  428. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  429. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -0,0 +1,383 @@
1
+ // Provider kit (decision 0010, B.4). Unreachable from src/index.ts.
2
+ //
3
+ // Tool builders. A tool is a name, a description, an input Schema, an output
4
+ // Schema, and a program; the builder renders both Schemas as catalog JSON
5
+ // Schema and annotates the tool from which builder was called (never from an
6
+ // HTTP method). At run time the call's served classification decides, so a
7
+ // deployment that reclassifies a tool is obeyed by the transport and the
8
+ // write-outcome rule alike. Failures leave through the one mapping in
9
+ // src/http/errors.ts.
10
+ //
11
+ // The result is an ordinary `ApiTool`, so a kit tool sits in `api()` beside
12
+ // hand-written ones and keeps every guarantee `api()` already gives:
13
+ // argument validation, sent-secret redaction, withheld handler text. Its
14
+ // boundary also decides every write's outcome, from the core ledger the kit's
15
+ // transport records into, so a kit connector declares `tracksEveryRequest`.
16
+ import { Context, Effect, Schema } from "effect";
17
+ import { inLogicalCall } from "../provider-call.js";
18
+ import { registerToolEntry } from "../runtime/call-entry.js";
19
+ import { ConnectorCallError } from "../errors.js";
20
+ import { refuseWithheldValues } from "../providers/_shared/rest/value-safety.js";
21
+ import { causeError, runEdge } from "../runtime/run.js";
22
+ import { recordUnauthorized, Refusal, RequestRefused, toConnectorCallError, withheldDefect, } from "./errors.js";
23
+ import { fieldsInput, fieldsProblem, selectFields } from "./fields.js";
24
+ import { catalogSchema, Integer } from "./json-schema.js";
25
+ import { boundCursor, Cursor, PageInfo, StandardPage } from "./paging.js";
26
+ import { Classification, Dispatches, IdempotencyKey, Recovery, ReadTool, WriteCapacity, writeRequestKey, fromConnectorContext, } from "./services.js";
27
+ const inputs = new WeakMap();
28
+ const keyed = new WeakSet();
29
+ /** Whether a kit write builder declared an idempotency key for this tool. */
30
+ export function takesIdempotencyKey(tool) {
31
+ return keyed.has(tool);
32
+ }
33
+ /** Copy decoded values only; the input supplies key order, never values or admission. */
34
+ function originalOrder(decoded, original) {
35
+ const copies = new WeakMap();
36
+ const copy = (value, source) => {
37
+ if (value === source || value === null || typeof value !== "object")
38
+ return value;
39
+ if (copies.has(value))
40
+ return copies.get(value);
41
+ if (Array.isArray(value)) {
42
+ const out = [];
43
+ copies.set(value, out);
44
+ value.forEach((item, index) => out.push(copy(item, Array.isArray(source) ? source[index] : undefined)));
45
+ return out;
46
+ }
47
+ const values = value;
48
+ const keys = source !== null && typeof source === "object" && !Array.isArray(source) ? Object.keys(source) : [];
49
+ const present = keys.filter((key) => Object.hasOwn(values, key));
50
+ const ordered = new Set(present);
51
+ const out = {};
52
+ copies.set(value, out);
53
+ for (const key of [...present, ...Object.keys(values).filter((key) => !ordered.has(key))]) {
54
+ Object.defineProperty(out, key, {
55
+ value: copy(values[key], source !== null && typeof source === "object" ? source[key] : undefined),
56
+ enumerable: true,
57
+ writable: true,
58
+ configurable: true,
59
+ });
60
+ }
61
+ return out;
62
+ };
63
+ return copy(decoded, original);
64
+ }
65
+ /** The input Schema a kit tool decodes with, for the catalog/decoder agreement check. */
66
+ export function kitInput(tool) {
67
+ return inputs.get(tool);
68
+ }
69
+ /** A Struct's own property names, for `fields`. */
70
+ function propertyNames(schema, what) {
71
+ const fields = schema.fields;
72
+ if (!fields)
73
+ throw new Error(`fields needs ${what} declared as a Schema.Struct.`);
74
+ return new Set(Object.keys(fields));
75
+ }
76
+ /** Refuse a bad `fields` path before anything is sent. */
77
+ function checkFields(fields, names, of) {
78
+ const error = fieldsProblem(fields, names, of);
79
+ return error ? Effect.fail(new Refusal({ error })) : Effect.void;
80
+ }
81
+ const fieldsExample = (names) => {
82
+ const first = [...names][0];
83
+ return first === undefined ? "" : `, e.g. ["${first}"]`;
84
+ };
85
+ /**
86
+ * A read: admitted to call_tool and programs. `fields: true` (decision 0011
87
+ * S5) appends a `fields` argument that narrows the returned record; the input
88
+ * and output must then be Structs, and a path outside the output's properties
89
+ * is refused before anything is sent.
90
+ */
91
+ export function read(connection, spec) {
92
+ if (spec.review !== undefined && !spec.review.trim())
93
+ throw new Error("A read review must be nonempty.");
94
+ if (spec.fields === undefined)
95
+ return build(connection, spec, "read", { readOnlyHint: true }, undefined, spec.review);
96
+ const names = propertyNames(spec.output, "the output");
97
+ propertyNames(spec.input, "the input");
98
+ const input = Schema.Struct({
99
+ ...spec.input.fields,
100
+ fields: Schema.optionalKey(fieldsInput(`Dot paths to keep in the result${fieldsExample(names)}. It only narrows the result.`)),
101
+ });
102
+ return build(connection, {
103
+ ...spec,
104
+ input,
105
+ run: (args) => Effect.gen(function* () {
106
+ yield* checkFields(args.fields, names, "the result");
107
+ const { fields, ...rest } = args;
108
+ return selectFields(yield* spec.run(rest), fields);
109
+ }),
110
+ // A selection may omit any property: the result is typed unknown and rendered sparse.
111
+ output: Schema.Unknown,
112
+ }, "read", { readOnlyHint: true }, undefined, spec.review, sparse(catalogSchema(spec.output, "output")));
113
+ }
114
+ /** Fetch one entity with the same read contract as a list. */
115
+ export function get(connection, spec) {
116
+ return read(connection, spec);
117
+ }
118
+ export function list(connection, spec) {
119
+ if (spec.cursor !== undefined && spec.cursor !== "plain" && spec.cursor !== "bound")
120
+ throw new Error('A list cursor must be "plain" or "bound".');
121
+ if (!("key" in spec))
122
+ return standardList(connection, spec);
123
+ if (!spec.key || spec.key === "page")
124
+ throw new Error("A list needs a row key distinct from page.");
125
+ return read(connection, {
126
+ ...spec,
127
+ output: Schema.Struct({ [spec.key]: Schema.Array(spec.row), page: PageInfo }),
128
+ run: (args) => Effect.gen(function* () {
129
+ const fields = args;
130
+ const supplied = typeof fields.cursor === "string" ? fields.cursor : undefined;
131
+ const cursor = supplied !== undefined && spec.cursor === "bound"
132
+ ? yield* boundCursor.decode(spec.name, fields, supplied)
133
+ : supplied;
134
+ const result = yield* spec.page(args, cursor);
135
+ const nextCursor = result.page.nextCursor !== null && spec.cursor === "bound"
136
+ ? yield* boundCursor.encode(spec.name, fields, result.page.nextCursor)
137
+ : result.page.nextCursor;
138
+ return { [spec.key]: result.rows, page: { ...result.page, nextCursor } };
139
+ }),
140
+ });
141
+ }
142
+ function standardList(connection, spec) {
143
+ const { default: size, max } = spec.limit;
144
+ if (spec.total !== undefined && spec.total !== true)
145
+ throw new Error(`${spec.name} total must opt in with true for a vendor-stated exact count.`);
146
+ if (!Number.isSafeInteger(size) || !Number.isSafeInteger(max) || size < 1 || max < size)
147
+ throw new Error(`${spec.name} limit needs positive whole default and max values, with default <= max.`);
148
+ const values = spec.limit.values === undefined ? undefined : [...spec.limit.values];
149
+ if (values &&
150
+ (!values.length ||
151
+ new Set(values).size !== values.length ||
152
+ !values.includes(size) ||
153
+ values.some((value) => !Number.isSafeInteger(value) || value < 1 || value > max)))
154
+ throw new Error(`${spec.name} limit values must be unique positive whole sizes within max and include the default.`);
155
+ const limit = Integer.check(Schema.isBetween({ minimum: 1, maximum: max }));
156
+ const allowedLimit = values
157
+ ? limit.check(Schema.makeFilter((value) => values.includes(value), {
158
+ expected: `one of ${values.join(", ")}`,
159
+ toJsonSchema: () => ({ enum: [...values] }),
160
+ }))
161
+ : limit;
162
+ for (const name of ["limit", "cursor", "fields"]) {
163
+ if (name in spec.filters)
164
+ throw new Error(`${spec.name} filters cannot declare ${name}; the kit supplies it.`);
165
+ }
166
+ const names = propertyNames(spec.row, "the row");
167
+ const input = Schema.Struct({
168
+ ...spec.filters,
169
+ limit: Schema.optionalKey(allowedLimit.annotate({
170
+ description: spec.limit.description,
171
+ default: size,
172
+ })),
173
+ cursor: Schema.optionalKey(Cursor),
174
+ fields: Schema.optionalKey(fieldsInput(`Dot paths to keep in each item${fieldsExample(names)}. It only narrows the result.`)),
175
+ });
176
+ return build(connection, {
177
+ name: spec.name,
178
+ description: spec.description,
179
+ input,
180
+ // `fields` narrows each item, so items render sparse; the envelope keeps items and page required.
181
+ output: Schema.Unknown,
182
+ run: (args) => Effect.gen(function* () {
183
+ yield* checkFields(args.fields, names, "an item");
184
+ // A cursor stays valid when only the projection changes between pages.
185
+ const { fields, cursor: supplied, ...rest } = args;
186
+ const scope = spec.cursorScope === undefined
187
+ ? rest
188
+ : {
189
+ arguments: Object.fromEntries(Object.entries(rest).filter(([key]) => key !== "limit")),
190
+ deploymentPolicy: spec.cursorScope,
191
+ };
192
+ const bound = spec.cursor === "bound";
193
+ const cursor = typeof supplied === "string" && bound ? yield* boundCursor.decode(spec.name, scope, supplied) : supplied;
194
+ const result = yield* spec.page({ ...rest, limit: typeof rest["limit"] === "number" ? rest["limit"] : size }, cursor);
195
+ const items = selectFields(result.rows, fields);
196
+ const total = spec.total ? result.page.total : undefined;
197
+ if (total !== undefined && (!Number.isSafeInteger(total) || total < 0))
198
+ return yield* Effect.fail(new Refusal({
199
+ error: new ConnectorCallError("connector_call_failed", "The vendor returned an invalid exact total.", {
200
+ retryable: false,
201
+ }),
202
+ }));
203
+ const count = total === undefined ? {} : { total };
204
+ if (!result.page.hasMore)
205
+ return { items, page: { hasMore: false, ...count } };
206
+ if (result.page.nextCursor === null)
207
+ return yield* Effect.fail(new Refusal({
208
+ error: new ConnectorCallError("connector_call_failed", "The vendor reported another page without a next cursor.", { retryable: false }),
209
+ }));
210
+ const nextCursor = bound
211
+ ? yield* boundCursor.encode(spec.name, scope, result.page.nextCursor)
212
+ : result.page.nextCursor;
213
+ return { items, page: { hasMore: true, nextCursor, ...count } };
214
+ }),
215
+ }, "read", { readOnlyHint: true }, undefined, spec.review, sparseItems(catalogSchema(Schema.Struct({
216
+ items: Schema.Array(spec.row),
217
+ page: spec.total
218
+ ? Schema.Struct({
219
+ ...StandardPage.fields,
220
+ total: Schema.optionalKey(Integer.check(Schema.isGreaterThanOrEqualTo(0))),
221
+ })
222
+ : StandardPage,
223
+ }), "output")));
224
+ }
225
+ /** What a `fields` selection may return: the declared shape with no property required, at any depth. */
226
+ function sparse(schema) {
227
+ // Walk schema positions deliberately: drop each `required` keyword, keep property names (a
228
+ // property may be called "required") and literal data (enum, const, default, examples) as is.
229
+ const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
230
+ const map = (value) => object(value) ? Object.fromEntries(Object.entries(value).map(([name, child]) => [name, walk(child)])) : value;
231
+ const walk = (node) => {
232
+ if (!object(node))
233
+ return node;
234
+ return Object.fromEntries(Object.entries(node).flatMap(([key, value]) => {
235
+ if (key === "required")
236
+ return [];
237
+ if (["properties", "patternProperties", "$defs", "definitions", "dependentSchemas"].includes(key))
238
+ return [[key, map(value)]];
239
+ if (["anyOf", "oneOf", "allOf", "prefixItems"].includes(key))
240
+ return [[key, Array.isArray(value) ? value.map(walk) : value]];
241
+ if (["items", "additionalProperties", "not", "if", "then", "else", "contains", "propertyNames"].includes(key))
242
+ return [[key, Array.isArray(value) ? value.map(walk) : walk(value)]];
243
+ return [[key, value]];
244
+ }));
245
+ };
246
+ return walk(schema);
247
+ }
248
+ /** A standard list's output with each item sparse. */
249
+ function sparseItems(schema) {
250
+ const root = schema;
251
+ return {
252
+ ...schema,
253
+ properties: {
254
+ ...root.properties,
255
+ items: { ...root.properties.items, items: sparse(root.properties.items.items) },
256
+ },
257
+ };
258
+ }
259
+ /** A write: approval-gated, dispatched once, and its failures reported by the write-outcome rule. */
260
+ export function write(connection, spec) {
261
+ return build(connection, spec, "write", {
262
+ readOnlyHint: false,
263
+ destructiveHint: spec.destructive,
264
+ ...(spec.idempotent === undefined ? {} : { idempotentHint: spec.idempotent }),
265
+ }, spec.idempotency);
266
+ }
267
+ /** Money, mail, and refunds are always destructive and never idempotent hints. */
268
+ export function action(connection, spec) {
269
+ return build(connection, spec, "write", { readOnlyHint: false, destructiveHint: true, idempotentHint: false });
270
+ }
271
+ /**
272
+ * A key the transport may send: not blank, and only characters an HTTP
273
+ * header carries. The REST layer refuses the same keys before dispatch.
274
+ */
275
+ function unsendableKey(key) {
276
+ return key.trim() === "" || !/^[\t\x20-\x7e\x80-\xff]*$/.test(key);
277
+ }
278
+ function build(connection, spec, verdict, annotations, idempotency, review,
279
+ /** A rendered output schema that replaces the Schema's, for sparse `fields` results. */
280
+ rendered) {
281
+ // One key protects one request: a tool with several write steps cannot share it.
282
+ const declared = Object.entries(spec.writeSteps ?? { write: "once" });
283
+ if (idempotency && (declared.length !== 1 || declared[0]?.[1] !== "once" || !idempotency.header.trim())) {
284
+ throw new Error("An idempotency key needs a header name and a tool with one write step sent once.");
285
+ }
286
+ if (idempotency) {
287
+ try {
288
+ new Headers([[idempotency.header, "key"]]);
289
+ }
290
+ catch {
291
+ throw new Error("An idempotency key needs a valid HTTP header name.");
292
+ }
293
+ }
294
+ // Snapshot the declaration now; mutations and retries cannot add step names or increase bounds.
295
+ const steps = Object.entries(spec.writeSteps ?? { write: "once" }).map(([name, declaration]) => {
296
+ if (!name ||
297
+ (declaration !== "once" &&
298
+ (!Number.isSafeInteger(declaration.maxItems) ||
299
+ declaration.maxItems < 1 ||
300
+ typeof declaration.items !== "function" ||
301
+ typeof declaration.request !== "function"))) {
302
+ throw new Error("Write steps need nonempty names and a positive whole maxItems bound.");
303
+ }
304
+ return [name, declaration === "once" ? declaration : { ...declaration }];
305
+ });
306
+ const capacity = (args) => {
307
+ const identities = new Set();
308
+ return new Map(steps.map(([name, declaration]) => {
309
+ if (declaration === "once")
310
+ return [name, new Map([[undefined, undefined]])];
311
+ const items = [...declaration.items(args)];
312
+ if (items.length > declaration.maxItems ||
313
+ items.some((item) => typeof item !== "string" || item.length === 0) ||
314
+ new Set(items).size !== items.length) {
315
+ throw new Error("Write item identities must be unique nonempty strings within the declared maxItems bound.");
316
+ }
317
+ const requests = items.map((item) => {
318
+ // Copy identifying content: a retained mutable object cannot change its request later.
319
+ const request = structuredClone(declaration.request(item, args));
320
+ const key = writeRequestKey(request);
321
+ if (identities.has(key))
322
+ throw new Error("Write item aliases must not identify identical request content.");
323
+ identities.add(key);
324
+ return [item, request];
325
+ });
326
+ return [name, new Map(requests)];
327
+ }));
328
+ };
329
+ const decode = Schema.decodeUnknownEffect(spec.input, { onExcessProperty: "error" });
330
+ const tool = {
331
+ name: spec.name,
332
+ description: spec.description,
333
+ inputSchema: catalogSchema(spec.input, "input"),
334
+ outputSchema: rendered ?? catalogSchema(spec.output, "output"),
335
+ annotations,
336
+ handler: (args, ctx) => runEdge(program(args, ctx), { signal: ctx.signal }),
337
+ };
338
+ const program = (args, ctx, served = false) => Effect.suspend(() => {
339
+ // The builder's verdict only stands in for a call no invocation dispatched.
340
+ const lease = fromConnectorContext(ctx, verdict);
341
+ const classification = Context.get(lease.services, Classification);
342
+ const dispatches = Context.get(lease.services, Dispatches);
343
+ const map = { classification, dispatches, withholds: connection.safety.withholdsErrors, signal: ctx.signal };
344
+ return Effect.try({
345
+ try: () => {
346
+ if (verdict === "write" || classification === "write")
347
+ refuseWithheldValues(args, spec.name);
348
+ },
349
+ catch: (error) => error,
350
+ }).pipe(Effect.catch((error) => error instanceof ConnectorCallError ? Effect.fail(new Refusal({ error })) : Effect.die(error)),
351
+ // Its message can quote the argument; as a defect, api() withholds it.
352
+ Effect.flatMap(() => decode(args).pipe(Effect.orDie)), Effect.map((decoded) => (spec.inputOrder === "original" ? originalOrder(decoded, args) : decoded)), Effect.flatMap((decoded) => Effect.gen(function* () {
353
+ const key = idempotency?.key(decoded);
354
+ if (key !== undefined && unsendableKey(key)) {
355
+ return yield* Effect.fail(new RequestRefused({
356
+ message: "The idempotency key is blank or holds a character an HTTP header cannot carry.",
357
+ }));
358
+ }
359
+ // Recorded before anything leaves: a deadline that interrupts
360
+ // the call still returns the key for reconciliation.
361
+ if (key !== undefined)
362
+ yield* (yield* Recovery).record({ idempotencyKey: key });
363
+ return yield* Effect.suspend(() => spec.run(decoded)).pipe(Effect.provideService(ReadTool, verdict === "read" ? (review ? { review } : {}) : undefined), Effect.provideService(WriteCapacity, capacity(decoded)), Effect.provideService(IdempotencyKey, key === undefined ? undefined : { header: idempotency.header, key }));
364
+ })),
365
+ // A native served call shares its invocation's cancellation. The
366
+ // invocation settles that interruption from the raw ledger before
367
+ // any completed handler verdict exists, just as at the Promise edge.
368
+ Effect.mapError((failure) => served && ctx.signal?.aborted ? ctx.signal.reason : toConnectorCallError(failure, connection.errors, map)), Effect.catchDefect((defect) => Effect.die(withheldDefect(defect, map))), Effect.provideContext(lease.services),
369
+ // The call's finalizer: every capability kept from it refuses after this.
370
+ Effect.ensuring(Effect.sync(lease.close)), Effect.onError((cause) => Effect.sync(() => {
371
+ if (!served &&
372
+ ctx.signal?.aborted === true &&
373
+ causeError(cause, ctx.signal) === ctx.signal.reason &&
374
+ map.classification === "write")
375
+ recordUnauthorized(connection.errors, map);
376
+ })));
377
+ });
378
+ registerToolEntry(tool, (args, ctx) => program(args, ctx, inLogicalCall(ctx)));
379
+ inputs.set(tool, spec.input);
380
+ if (idempotency)
381
+ keyed.add(tool);
382
+ return tool;
383
+ }
@@ -0,0 +1,138 @@
1
+ // Internal provider kit (decision 0011 S1). Unreachable from src/index.ts.
2
+ //
3
+ // The standard hatch validates every request against an operation index. A
4
+ // vendor with a pinned OpenAPI document compiles one at generation time; a
5
+ // kit vendor without one (its reference is per-page prose, as Tithe.ly's is)
6
+ // derives it here from its own declarations, through `manifest(vendor)`. The
7
+ // vendor stays the one operation list: what the typed client sends, what drift
8
+ // checks compare and what the hatch admits are the same declarations.
9
+ import { OperationIndex, } from "../providers/_shared/rest/operation-index.js";
10
+ import { manifest } from "./vendor.js";
11
+ const METHODS = ["get", "head", "post", "put", "patch", "delete"];
12
+ /** How the manifest renders a number carried in a query or form string. */
13
+ const NUMERIC_STRING = "^[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?$";
14
+ function record(value) {
15
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
16
+ }
17
+ /** Compact one manifest schema into the index's node form, resolving local references. */
18
+ function node(schema, components, seen = new Set()) {
19
+ const source = record(schema);
20
+ const ref = typeof source["$ref"] === "string" ? source["$ref"] : undefined;
21
+ if (ref !== undefined) {
22
+ const name = ref.replace(/^#\/components\/schemas\//, "");
23
+ // A recursive reference stops validating below itself rather than looping.
24
+ return seen.has(name) ? { x: 1 } : node(components[name], components, new Set([...seen, name]));
25
+ }
26
+ const out = {};
27
+ const type = source["type"];
28
+ // A numeric query or form string is a number to the caller; the transport stringifies it.
29
+ if (type === "string" && source["pattern"] === NUMERIC_STRING)
30
+ out.t = "number";
31
+ else if (typeof type === "string" || Array.isArray(type))
32
+ out.t = type;
33
+ if (Array.isArray(source["enum"]))
34
+ out.e = source["enum"];
35
+ if (typeof source["description"] === "string")
36
+ out.d = source["description"];
37
+ // A property's key annotation renders as an `allOf` member beside its encoded type.
38
+ for (const member of Array.isArray(source["allOf"]) ? source["allOf"] : []) {
39
+ if (out.d === undefined && typeof record(member)["description"] === "string")
40
+ out.d = record(member)["description"];
41
+ }
42
+ const branches = source["anyOf"] ?? source["oneOf"];
43
+ if (Array.isArray(branches))
44
+ out.a = branches.map((branch) => node(branch, components, seen));
45
+ const properties = record(source["properties"]);
46
+ if (Object.keys(properties).length > 0) {
47
+ out.p = Object.fromEntries(Object.entries(properties).map(([key, value]) => [key, node(value, components, seen)]));
48
+ }
49
+ if (Array.isArray(source["required"]) && source["required"].length > 0)
50
+ out.r = source["required"];
51
+ if (source["items"] !== undefined)
52
+ out.i = node(source["items"], components, seen);
53
+ if (record(source["additionalProperties"]) === source["additionalProperties"]) {
54
+ out.m = node(source["additionalProperties"], components, seen);
55
+ }
56
+ return out;
57
+ }
58
+ /** Every property path a schema declares, local references resolved once each. */
59
+ function propertyPaths(schema, components, prefix = "", seen = new Set()) {
60
+ const source = record(schema);
61
+ const ref = typeof source["$ref"] === "string" ? source["$ref"].replace(/^#\/components\/schemas\//, "") : undefined;
62
+ if (ref !== undefined)
63
+ return seen.has(ref) ? [] : propertyPaths(components[ref], components, prefix, new Set([...seen, ref]));
64
+ const branches = [source["anyOf"], source["oneOf"], source["allOf"]].flatMap((list) => Array.isArray(list) ? list : []);
65
+ return [
66
+ ...Object.entries(record(source["properties"])).flatMap(([name, child]) => [
67
+ `${prefix}${name}`,
68
+ ...propertyPaths(child, components, `${prefix}${name}.`, seen),
69
+ ]),
70
+ ...(source["items"] === undefined
71
+ ? []
72
+ : propertyPaths(source["items"], components, prefix ? `${prefix.slice(0, -1)}[].` : "[].", seen)),
73
+ ...branches.flatMap((branch) => propertyPaths(branch, components, prefix, seen)),
74
+ ];
75
+ }
76
+ /**
77
+ * An operation index over a kit vendor's own declarations: every operation's
78
+ * method, path, `operationId`, `Summary`, path and query parameters, and
79
+ * request body with its content type, plus the request and response
80
+ * properties `OperationIndex.fields` answers. `prefix` names the hatch tools in
81
+ * refusals; `revision` identifies the declared API version.
82
+ */
83
+ export function vendorIndex(vendor, names) {
84
+ const document = manifest(vendor);
85
+ const components = record(record(document["components"])["schemas"]);
86
+ const ops = [];
87
+ const details = [];
88
+ const fields = [];
89
+ for (const [path, item] of Object.entries(record(document["paths"]))) {
90
+ for (const method of METHODS) {
91
+ const operation = record(record(item)[method]);
92
+ if (Object.keys(operation).length === 0)
93
+ continue;
94
+ const operationId = typeof operation["operationId"] === "string" ? operation["operationId"] : "";
95
+ const summary = typeof operation["summary"] === "string" ? operation["summary"] : "";
96
+ ops.push([method.toUpperCase(), path, operationId, summary, 0]);
97
+ const params = (Array.isArray(operation["parameters"]) ? operation["parameters"] : [])
98
+ .map(record)
99
+ .filter((param) => param["in"] === "path" || param["in"] === "query")
100
+ .map((param) => {
101
+ // The parameter row carries the description once, beside its schema.
102
+ const { d, ...schema } = node(param["schema"], components);
103
+ const description = typeof param["description"] === "string" ? param["description"] : d;
104
+ return [
105
+ String(param["name"]),
106
+ param["in"],
107
+ param["required"] === true ? 1 : 0,
108
+ schema,
109
+ ...(description === undefined ? [] : [description]),
110
+ ];
111
+ });
112
+ const requestBody = record(operation["requestBody"]);
113
+ const [contentType, media] = Object.entries(record(requestBody["content"]))[0] ?? [];
114
+ const body = contentType === undefined
115
+ ? 0
116
+ : [contentType, node(record(media)["schema"], components), ...(requestBody["required"] === true ? [1] : [])];
117
+ details.push(params.length === 0 && body === 0 ? 0 : [params, body]);
118
+ const success = Object.entries(record(operation["responses"])).find(([status]) => status.startsWith("2"))?.[1];
119
+ const paths = (where, schema) => [...new Set(propertyPaths(schema, components))].map((path) => ({ in: where, path }));
120
+ fields.push([
121
+ ...paths("response", record(record(record(success)["content"])["application/json"])["schema"]),
122
+ ...paths("body", record(media)["schema"]),
123
+ ]);
124
+ }
125
+ }
126
+ const data = {
127
+ source: `${names.title} kit vendor declarations`,
128
+ revision: names.revision,
129
+ digest: "",
130
+ version: names.revision,
131
+ servers: [],
132
+ tags: [""],
133
+ ops,
134
+ details: JSON.stringify({ d: [], o: details }),
135
+ fields,
136
+ };
137
+ return new OperationIndex(data, { vendor: names.prefix, title: names.title });
138
+ }