@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,227 @@
1
+ // Provider kit (decision 0010, B.4). Unreachable from src/index.ts.
2
+ //
3
+ // Paging is a strategy plus one cursor codec. A strategy turns "the next page
4
+ // after this cursor" into a vendor request and reads back rows and the next
5
+ // vendor cursor; tools take one page, and `allRows` walks every page as a
6
+ // Stream for programs and the hatch. The codec is the only place a cursor is
7
+ // minted: `plain` hands the vendor's cursor through; `bound` ties it to the tool and its
8
+ // arguments so a cursor from another call is refused instead of silently
9
+ // reading the wrong list.
10
+ import { Effect, Option, Schema, Stream } from "effect";
11
+ import { ConnectorCallError } from "../errors.js";
12
+ import { Refusal } from "./errors.js";
13
+ import { confinementBase } from "../http-policy.js";
14
+ import { canonicalJson } from "../canonical-json.js";
15
+ import { ContinuationBinding, ContinuationStorage } from "../runtime/call.js";
16
+ import { continuationKeys } from "../storage/keys.js";
17
+ /** The `page` object every list tool returns. */
18
+ export const PageInfo = Schema.Struct({
19
+ hasMore: Schema.Boolean,
20
+ nextCursor: Schema.NullOr(Schema.String),
21
+ });
22
+ /**
23
+ * The standard `page` (decision 0011 S2): `nextCursor` is present exactly
24
+ * when `hasMore` is true and continuation is safe. A hatch adapter can report
25
+ * more data without a cursor when its continuation cannot be confined.
26
+ * Step-1 lists keep `PageInfo` until their step 2.
27
+ */
28
+ export const StandardPage = Schema.Struct({
29
+ hasMore: Schema.Boolean,
30
+ nextCursor: Schema.optionalKey(Schema.String),
31
+ });
32
+ /** The input field that carries a cursor back. */
33
+ export const Cursor = Schema.String.check(Schema.isMinLength(1)).annotate({
34
+ description: "Opaque nextCursor from the previous page. Pass it back unchanged.",
35
+ });
36
+ /**
37
+ * Lookahead paging, for a vendor that returns no `has_more`: ask for one row
38
+ * more than wanted, keep `limit`, and address the next page by the last kept
39
+ * row's id. A full page proves nothing; the extra row does.
40
+ */
41
+ export function lookahead(options) {
42
+ return Effect.gen(function* () {
43
+ const all = yield* options.fetch(options.limit + 1);
44
+ const rows = all.slice(0, options.limit);
45
+ const hasMore = all.length > options.limit;
46
+ if (!hasMore)
47
+ return { rows, page: { hasMore, nextCursor: null } };
48
+ const last = rows[rows.length - 1];
49
+ const id = last?.[options.idKey];
50
+ if (typeof id !== "string" || id === "") {
51
+ return yield* Effect.fail(new Refusal({
52
+ error: new ConnectorCallError("connector_call_failed", `${options.provider} returned a page whose last row has no ${options.idKey}, so the next page cannot be addressed.`, { retryable: false }),
53
+ }));
54
+ }
55
+ return { rows, page: { hasMore, nextCursor: id } };
56
+ });
57
+ }
58
+ /** Vendor-supplied continuation, read only after the connection made its data safe. */
59
+ export function token(options) {
60
+ return Effect.flatMap(Effect.suspend(options.fetch), ({ rows, hasMore, nextCursor }) => {
61
+ if (hasMore && !nextCursor)
62
+ return badPage("The vendor reported another page without a next cursor.");
63
+ return Effect.succeed({ rows, page: { hasMore, nextCursor: hasMore ? nextCursor : null } });
64
+ });
65
+ }
66
+ /** Offset paging advances by the rows actually returned, with a total when supplied. */
67
+ export function offset(options) {
68
+ return Effect.gen(function* () {
69
+ yield* position(options.offset, 0);
70
+ yield* position(options.limit, 1);
71
+ return yield* Effect.map(options.fetch(options.offset, options.limit), ({ rows, total }) => {
72
+ const next = options.offset + rows.length;
73
+ const hasMore = rows.length > 0 && (total === undefined ? rows.length >= options.limit : next < total);
74
+ return { rows, page: { hasMore, nextCursor: hasMore ? String(next) : null } };
75
+ });
76
+ });
77
+ }
78
+ /** Page numbers from a vendor's safe body or headers, with full-page fallback. */
79
+ export function page(options) {
80
+ return Effect.gen(function* () {
81
+ yield* position(options.page, 1);
82
+ yield* position(options.limit, 1);
83
+ return yield* Effect.map(options.fetch(options.page, options.limit), ({ rows, hasMore, totalPages }) => {
84
+ const more = hasMore ?? (totalPages === undefined ? rows.length >= options.limit : options.page < totalPages);
85
+ return { rows, page: { hasMore: more, nextCursor: more ? String(options.page + 1) : null } };
86
+ });
87
+ });
88
+ }
89
+ /** Extract only a cursor from a next URL confined to this connection's origin and path. */
90
+ export function link(options) {
91
+ const base = confinementBase("Paging", options.baseUrl);
92
+ const prefix = base.pathname.replace(/\/+$/, "");
93
+ if (!options.param)
94
+ throw new Error("Link paging needs a cursor parameter.");
95
+ return Effect.flatMap(Effect.suspend(options.fetch), ({ rows, next }) => {
96
+ if (!next)
97
+ return Effect.succeed({ rows, page: { hasMore: false, nextCursor: null } });
98
+ let url;
99
+ try {
100
+ url = new URL(next, base);
101
+ }
102
+ catch {
103
+ return badPage("The vendor returned an invalid next-page URL.");
104
+ }
105
+ if (url.origin !== base.origin ||
106
+ !`${url.pathname}/`.startsWith(`${prefix}/`) ||
107
+ url.username ||
108
+ url.password ||
109
+ url.hash)
110
+ return badPage("The vendor returned a next-page URL outside this connection.");
111
+ const cursors = url.searchParams.getAll(options.param);
112
+ if (cursors.length !== 1 || !cursors[0])
113
+ return badPage("The vendor returned no unique next-page cursor.");
114
+ return Effect.succeed({ rows, page: { hasMore: true, nextCursor: cursors[0] } });
115
+ });
116
+ }
117
+ function position(value, minimum) {
118
+ return Number.isSafeInteger(value) && value >= minimum
119
+ ? Effect.void
120
+ : Effect.fail(new Refusal({
121
+ error: new ConnectorCallError("invalid_args", "Paging positions and limits must be whole numbers within their bounds."),
122
+ }));
123
+ }
124
+ function badPage(message) {
125
+ return Effect.fail(new Refusal({ error: new ConnectorCallError("connector_call_failed", message, { retryable: false }) }));
126
+ }
127
+ /** Every row of every page, fetched as the stream is pulled. */
128
+ export function allRows(fetchPage) {
129
+ return Stream.paginate(undefined, (cursor) => Effect.map(fetchPage(cursor), ({ rows, page }) => [rows, Option.fromNullishOr(page.hasMore ? page.nextCursor : null)]));
130
+ }
131
+ const STRAY_CURSOR = "This cursor belongs to a different call. Pass back the nextCursor from the previous page of this same call, with the same arguments.";
132
+ /** Resolved, nonextractable keys only: no request promise is retained between calls. */
133
+ const signingKeys = new WeakMap();
134
+ async function signingKey(storage) {
135
+ const cached = signingKeys.get(storage);
136
+ if (cached)
137
+ return cached;
138
+ let raw = await storage.get(continuationKeys.signingKey);
139
+ if (raw === null) {
140
+ const candidate = Array.from(crypto.getRandomValues(new Uint8Array(32)), (byte) => byte.toString(16).padStart(2, "0")).join("");
141
+ raw = (await storage.compareAndSet(continuationKeys.signingKey, null, candidate))
142
+ ? candidate
143
+ : await storage.get(continuationKeys.signingKey);
144
+ }
145
+ if (raw === null || !/^[a-f0-9]{64}$/.test(raw))
146
+ throw new Error("The continuation signing key is unavailable.");
147
+ const key = await crypto.subtle.importKey("raw", Uint8Array.from(raw.match(/../g), (byte) => Number.parseInt(byte, 16)), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
148
+ signingKeys.set(storage, key);
149
+ return key;
150
+ }
151
+ const keyUnavailable = () => new Refusal({
152
+ error: new ConnectorCallError("unavailable", "The cursor signing key is unavailable. Retry after storage recovers; a corrupt key requires operator recovery.", { retryable: true }),
153
+ });
154
+ const keyForCall = ContinuationStorage.use((storage) => storage
155
+ ? Effect.tryPromise({ try: () => signingKey(storage), catch: keyUnavailable })
156
+ : Effect.fail(keyUnavailable()));
157
+ /**
158
+ * Authenticated base64url JSON `{v, d, c, m}`: the MAC covers the version,
159
+ * connection/owner/caller binding, tool/argument digest and continuation
160
+ * payload in a canonical tuple and envelope. The deployment store owns
161
+ * the key across isolates/restarts; limit and cursor are excluded from args.
162
+ */
163
+ export const boundCursor = {
164
+ encode(tool, args, cursor, encode = base64url) {
165
+ return Effect.gen(function* () {
166
+ const d = yield* digest(tool, args);
167
+ const key = yield* keyForCall;
168
+ const binding = yield* ContinuationBinding;
169
+ const claims = new TextEncoder().encode(canonicalJson([2, binding.connection, binding.principal, d, cursor]));
170
+ const mac = yield* Effect.promise(() => crypto.subtle.sign("HMAC", key, claims));
171
+ const m = base64urlBytes(new Uint8Array(mac));
172
+ return encode(JSON.stringify({ v: 2, d, c: cursor, m }));
173
+ });
174
+ },
175
+ decode(tool, args, token) {
176
+ return Effect.gen(function* () {
177
+ const expected = yield* digest(tool, args);
178
+ let parsed;
179
+ try {
180
+ parsed = JSON.parse(new TextDecoder().decode(fromBase64url(token)));
181
+ }
182
+ catch {
183
+ parsed = undefined;
184
+ }
185
+ const record = parsed;
186
+ if (record?.v !== 2 ||
187
+ record.d !== expected ||
188
+ typeof record.c !== "string" ||
189
+ typeof record.m !== "string" ||
190
+ !/^[A-Za-z0-9_-]{43}$/.test(record.m)) {
191
+ return yield* Effect.fail(new Refusal({ error: new ConnectorCallError("invalid_args", STRAY_CURSOR) }));
192
+ }
193
+ if (token !== base64url(JSON.stringify({ v: record.v, d: record.d, c: record.c, m: record.m })))
194
+ return yield* Effect.fail(new Refusal({ error: new ConnectorCallError("invalid_args", STRAY_CURSOR) }));
195
+ const key = yield* keyForCall;
196
+ const mac = fromBase64url(record.m);
197
+ const binding = yield* ContinuationBinding;
198
+ const claims = new TextEncoder().encode(canonicalJson([record.v, binding.connection, binding.principal, record.d, record.c]));
199
+ const valid = yield* Effect.promise(() => crypto.subtle.verify("HMAC", key, mac, claims));
200
+ if (!valid || base64urlBytes(mac) !== record.m) {
201
+ return yield* Effect.fail(new Refusal({ error: new ConnectorCallError("invalid_args", STRAY_CURSOR) }));
202
+ }
203
+ return record.c;
204
+ });
205
+ },
206
+ };
207
+ function digest(tool, args) {
208
+ const shape = Object.keys(args)
209
+ .filter((key) => key !== "cursor" && key !== "limit" && args[key] !== undefined)
210
+ .sort()
211
+ .map((key) => [key, args[key]]);
212
+ const bytes = new TextEncoder().encode(canonicalJson([tool, shape]));
213
+ return Effect.promise(() => crypto.subtle.digest("SHA-256", bytes)).pipe(Effect.map((hash) => Array.from(new Uint8Array(hash).slice(0, 16), (byte) => byte.toString(16).padStart(2, "0")).join("")));
214
+ }
215
+ function base64url(text) {
216
+ return base64urlBytes(new TextEncoder().encode(text));
217
+ }
218
+ function base64urlBytes(bytes) {
219
+ let binary = "";
220
+ for (const byte of bytes)
221
+ binary += String.fromCharCode(byte);
222
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
223
+ }
224
+ function fromBase64url(token) {
225
+ const binary = atob(token.replace(/-/g, "+").replace(/_/g, "/"));
226
+ return Uint8Array.from(binary, (char) => char.charCodeAt(0));
227
+ }
@@ -0,0 +1,221 @@
1
+ // Internal provider kit (decision 0010, B.4). Unreachable from src/index.ts.
2
+ import { Context, Effect, Option } from "effect";
3
+ import { api } from "../connectors/api.js";
4
+ import { OAUTH_CHALLENGE_MAX_BYTES } from "../auth/renewable-grant.js";
5
+ import { ConnectorCallError } from "../errors.js";
6
+ import { defineProvider, } from "../provider.js";
7
+ import { tracksEveryRequest } from "../provider-call.js";
8
+ import { unsentAfterUnauthorized } from "../write-outcome.js";
9
+ import { Operation } from "../runtime/call.js";
10
+ import { runEdge } from "../runtime/run.js";
11
+ import { guardedClient } from "./client.js";
12
+ import { errorMeanings, Refusal, toConnectorCallError, withheldDefect, } from "./errors.js";
13
+ import { hatch } from "./hatch.js";
14
+ import { takesIdempotencyKey } from "./tools.js";
15
+ import { Grant, grantFromOAuth, refreshOnce } from "./oauth.js";
16
+ import { resultSafety } from "./safety.js";
17
+ import { Classification, Dispatches, Signal, WriteCapacity, fromConnectorContext, } from "./services.js";
18
+ import { connect, operations } from "./vendor.js";
19
+ /** A declared hatch for one connection: its notes resolved from that connection's options. */
20
+ function hatchDeclaration(declared, options, connection) {
21
+ const { notes, binding, writeEnabled, ...rest } = declared;
22
+ return {
23
+ ...rest,
24
+ ...(notes ? { notes: notes(options) } : {}),
25
+ ...(writeEnabled ? { writeEnabled: writeEnabled(options) } : {}),
26
+ ...(binding ? { binding: binding({ connection, options }) } : {}),
27
+ };
28
+ }
29
+ /** Bind the Promise OAuth facade belonging to this call, never a connection-wide grant. */
30
+ const callGrant = Effect.gen(function* () {
31
+ // Operation is bridge metadata, not a service a provider program supplies.
32
+ const operation = yield* Effect.serviceOption(Operation);
33
+ const oauth = Option.isSome(operation) ? operation.value?.oauth : undefined;
34
+ return oauth ? grantFromOAuth(oauth) : missingGrant;
35
+ });
36
+ const noGrant = Effect.fail(new Refusal({
37
+ error: new ConnectorCallError("auth_required", "This connection has no OAuth grant."),
38
+ }));
39
+ const missingGrant = {
40
+ token: noGrant,
41
+ refresh: () => noGrant,
42
+ rejected: noGrant,
43
+ };
44
+ /** An ordinary Promise connector factory; Effect remains inside the kit. */
45
+ export function defineApiProvider(definition) {
46
+ const { displayTitle, description, authScope, vendor, baseUrl, maxResponseBytes, timeoutMs, headers, admit, transport, defaultCallAdmission, pageSize: declaredPageSize, idempotencyKey, credential, oauth, oauthWrite401, grant, grantRenewal, authenticate, errors, safety, result, inBandRefusals, probe, guide, transformGuide, hatch: declaredHatch, tools, tagConnector, ...metadata } = definition;
47
+ if (credential !== undefined && oauth !== undefined) {
48
+ throw new Error(`${metadata.title} declares both credential and oauth; declare one authentication method.`);
49
+ }
50
+ if (oauthWrite401 && !oauth)
51
+ throw new Error("oauthWrite401 requires a static OAuth declaration.");
52
+ if (grant && oauth)
53
+ throw new Error("A provider declares either a machine grant or static OAuth, never both.");
54
+ if (grantRenewal && !grant)
55
+ throw new Error("grantRenewal requires a machine grant declaration.");
56
+ const renewalModes = grantRenewal ? { ...grantRenewal } : undefined;
57
+ if (!Number.isInteger(maxResponseBytes) || maxResponseBytes < 1) {
58
+ throw new Error(`${metadata.title} maxResponseBytes must be a whole number of bytes >= 1.`);
59
+ }
60
+ const pageSize = declaredPageSize === undefined ? undefined : { ...declaredPageSize };
61
+ if (pageSize &&
62
+ (!Number.isSafeInteger(pageSize.default) ||
63
+ !Number.isSafeInteger(pageSize.max) ||
64
+ pageSize.default < 1 ||
65
+ pageSize.max < pageSize.default)) {
66
+ throw new Error(`${metadata.title} pageSize needs positive whole default and max values, with default <= max.`);
67
+ }
68
+ const meanings = errorMeanings(errors);
69
+ if (idempotencyKey !== undefined && typeof idempotencyKey !== "boolean")
70
+ throw new Error(`${metadata.title} idempotencyKey must be true or false when declared.`);
71
+ const hatchOptions = declaredHatch
72
+ ? {
73
+ ...declaredHatch,
74
+ verdicts: { ...declaredHatch.verdicts },
75
+ ...(declaredHatch.named ? { named: { ...declaredHatch.named } } : {}),
76
+ }
77
+ : undefined;
78
+ return defineProvider({
79
+ ...metadata,
80
+ kind: "api",
81
+ kit: {
82
+ operations: operations(vendor),
83
+ ...(pageSize ? { pageSize } : {}),
84
+ ...(hatchOptions
85
+ ? {
86
+ hatch: {
87
+ name: hatchOptions.name,
88
+ verdicts: hatchOptions.verdicts,
89
+ ...(hatchOptions.fieldsRoot ? { fieldsRoot: hatchOptions.fieldsRoot } : {}),
90
+ ...(hatchOptions.pageCursor && Object.keys(hatchOptions.pages ?? {}).length
91
+ ? { paging: hatchOptions.pageCursor }
92
+ : {}),
93
+ },
94
+ refusesWithheld: true,
95
+ }
96
+ : {}),
97
+ ...(meanings ? { errors: meanings } : {}),
98
+ ...(idempotencyKey === undefined ? {} : { idempotencyKey }),
99
+ },
100
+ create(id, options, provider) {
101
+ const connectionCredential = typeof credential === "function" ? credential(options) : credential;
102
+ const override = "defaultPageSize" in options ? options.defaultPageSize : undefined;
103
+ if (override !== undefined &&
104
+ (!pageSize ||
105
+ typeof override !== "number" ||
106
+ !Number.isSafeInteger(override) ||
107
+ override < 1 ||
108
+ override > pageSize.max)) {
109
+ throw new Error(`defaultPageSize must be a whole number from 1 to ${pageSize?.max ?? "a declared pageSize maximum"}.`);
110
+ }
111
+ const configured = transport?.(options);
112
+ const machineGrant = grant?.(options);
113
+ const guarded = guardedClient({
114
+ provider: errors.provider,
115
+ baseUrl: baseUrl(options),
116
+ maxResponseBytes,
117
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
118
+ ...(oauthWrite401 ? { maxUnauthorizedResponseBytes: OAUTH_CHALLENGE_MAX_BYTES } : {}),
119
+ ...(headers === undefined ? {} : { headers }),
120
+ ...(admit === undefined ? {} : { admit }),
121
+ authenticate: typeof authenticate === "function" ? authenticate(options) : authenticate,
122
+ ...configured,
123
+ });
124
+ const connected = connect(vendor, oauth || machineGrant
125
+ ? refreshOnce(guarded, oauthWrite401
126
+ ? {
127
+ challengeMaxBytes: OAUTH_CHALLENGE_MAX_BYTES,
128
+ writeUnauthorized: (renewal) => unsentAfterUnauthorized(`Connector "${id}"'s API`, renewal._tag === "Renewed"
129
+ ? undefined
130
+ : renewal._tag === "Failed"
131
+ ? renewal.failure
132
+ : new ConnectorCallError("downstream_oauth_required", `Connector "${id}" requires authorization — call authorize_connector({ connector: "${id}" }) and open the returned URL.`), "downstream_oauth_required"),
133
+ }
134
+ : renewalModes)
135
+ : guarded, {
136
+ errors,
137
+ safety: resultSafety(safety(options)),
138
+ ...(inBandRefusals ? { inBandRefusals } : {}),
139
+ ...(result ? { result } : {}),
140
+ });
141
+ const authorize = (work) => work.pipe(Effect.provideServiceEffect(Grant, machineGrant ?? (oauth ? callGrant : Effect.succeed(missingGrant))));
142
+ const connection = {
143
+ ...connected,
144
+ send: (...args) => authorize(connected.send(...args)),
145
+ sendPath: (...args) => authorize(connected.sendPath(...args)),
146
+ sendItem: (...args) => authorize(connected.sendItem(...args)),
147
+ };
148
+ // Construct programs outside every caller context; only execution receives candidate services.
149
+ const probeProgram = probe.run
150
+ ? probe.run(connection, options)
151
+ : connection
152
+ .send(probe.operation, (typeof probe.request === "function" ? probe.request(options) : probe.request))
153
+ .pipe(Effect.map(({ data }) => data));
154
+ const test = (values, ctx) => {
155
+ const problem = probe.check?.(values, options);
156
+ if (problem !== undefined)
157
+ return Promise.resolve({ ok: false, message: problem });
158
+ // api() has already installed anonymous, uncharged candidate services.
159
+ // Bridge those services directly; never copy the supplied context.
160
+ const lease = fromConnectorContext(ctx, "read");
161
+ const signal = Context.get(lease.services, Signal);
162
+ const map = {
163
+ classification: Context.get(lease.services, Classification),
164
+ dispatches: Context.get(lease.services, Dispatches),
165
+ withholds: connection.safety.withholdsErrors,
166
+ signal,
167
+ };
168
+ return runEdge(probeProgram.pipe(Effect.provideService(WriteCapacity, new Map()), Effect.flatMap((data) => Effect.try({
169
+ try: () => {
170
+ const described = probe.describe(data, options);
171
+ return typeof described === "string" ? { ok: true, message: described } : described;
172
+ },
173
+ catch: (error) => error,
174
+ }).pipe(Effect.catch((error) => error instanceof ConnectorCallError ? Effect.fail(new Refusal({ error })) : Effect.die(error)))), Effect.catch((failure) => Effect.sync(() => {
175
+ const error = toConnectorCallError(failure, errors, map);
176
+ return probe.failure?.(error, options) ?? { ok: false, message: error.message };
177
+ })), Effect.catchDefect((defect) => Effect.die(withheldDefect(defect, map, !!probe.run))), Effect.provideContext(lease.services), Effect.ensuring(Effect.sync(lease.close))), { signal: ctx.signal });
178
+ };
179
+ const builtTools = tools({
180
+ connection,
181
+ options,
182
+ get pageSize() {
183
+ if (!pageSize)
184
+ throw new Error("Declare pageSize before using the kit's pageSize.");
185
+ return typeof override === "number" ? override : pageSize.default;
186
+ },
187
+ });
188
+ const hatchTools = hatchOptions
189
+ ? hatch({ ...hatchDeclaration(hatchOptions, options, connection), connection })
190
+ : [];
191
+ // The declared fact the Writes convention states must match what the write builders send.
192
+ if (idempotencyKey !== undefined && [...builtTools, ...hatchTools].some(takesIdempotencyKey) !== idempotencyKey)
193
+ throw new Error(`${metadata.title} declares idempotencyKey: ${idempotencyKey}, but its write tools ${idempotencyKey ? "send no" : "send an"} idempotency key.`);
194
+ const usageGuide = guide(options);
195
+ const renderedGuide = "content" in usageGuide ? usageGuide : provider.usageGuide(usageGuide);
196
+ const connector = tracksEveryRequest(api(id, {
197
+ ...(defaultCallAdmission
198
+ ? {
199
+ callAdmission: typeof defaultCallAdmission === "function" ? defaultCallAdmission(options) : defaultCallAdmission,
200
+ }
201
+ : {}),
202
+ ...provider.connectorOptions,
203
+ ...(authScope ? { authScope: authScope(options) } : {}),
204
+ title: options.title ?? displayTitle?.(options) ?? metadata.title,
205
+ ...(description ? { description: description(options) } : {}),
206
+ usageGuide: transformGuide ? transformGuide(renderedGuide, options) : renderedGuide,
207
+ ...(connectionCredential
208
+ ? {
209
+ credential: connectionCredential,
210
+ testCredential: (value, ctx) => test({ value }, ctx),
211
+ testCredentials: (values, ctx) => test(values, ctx),
212
+ }
213
+ : {}),
214
+ ...(oauth ? { oauth: oauth(options) } : {}),
215
+ tools: [...builtTools, ...hatchTools],
216
+ }));
217
+ tagConnector?.(connector, options);
218
+ return connector;
219
+ },
220
+ });
221
+ }
@@ -0,0 +1,82 @@
1
+ // Provider kit (decision 0010, B.4). Unreachable from src/index.ts.
2
+ //
3
+ // The one value-safety boundary of a kit connection. `connect` requires it,
4
+ // and `Send` hands a provider nothing it has not passed: a named tool, a
5
+ // hatch, a paging strategy, and a projection all read an answer only after
6
+ // the vendor's reviewed redaction and the deployment's sensitive-field
7
+ // choice ran on it. Nothing upstream of it reaches a cursor or a result.
8
+ //
9
+ // The same boundary answers, per operation and before any detail is
10
+ // extracted, whether a failure may quote the vendor's text. A stored secret
11
+ // a request never sent can still sit in a vendor's error prose, so
12
+ // sent-secret redaction cannot stand in for it.
13
+ import { Effect } from "effect";
14
+ import { ConnectorCallError } from "../errors.js";
15
+ import { Refusal } from "./errors.js";
16
+ /** Refuses at construction a connection with neither a reviewed table nor a reason (INV-11). */
17
+ export function resultSafety(options) {
18
+ const review = options.review?.trim();
19
+ if (!options.reviewed && !review) {
20
+ throw new Error("A kit connection needs a reviewed value-safety table, or a review saying why it has none.");
21
+ }
22
+ const { choice, names } = options.sensitiveFields;
23
+ if (choice !== "drop" && choice !== "return")
24
+ throw new Error('sensitiveFields must be "drop" or "return".');
25
+ const dropped = new Set(choice === "drop" ? names : []);
26
+ const strip = (value) => {
27
+ if (Array.isArray(value))
28
+ return value.map(strip);
29
+ if (!value || typeof value !== "object")
30
+ return value;
31
+ return Object.fromEntries(Object.entries(value)
32
+ .filter(([name]) => !dropped.has(name))
33
+ .map(([name, entry]) => [name, strip(entry)]));
34
+ };
35
+ const reviewed = options.reviewed;
36
+ return {
37
+ refusal: (operation) => reviewed?.refusal?.(operation),
38
+ resolve: (method, path) => Effect.try({
39
+ try: () => {
40
+ if (reviewed?.resolve)
41
+ return reviewed.resolve(method, path);
42
+ if (!reviewed && review)
43
+ return { method, template: path };
44
+ throw new ConnectorCallError("invalid_args", "A reviewed path request needs a canonical operation index.");
45
+ },
46
+ catch: (error) => error,
47
+ }).pipe(Effect.catch((error) => error instanceof ConnectorCallError ? Effect.fail(new Refusal({ error })) : Effect.die(error))),
48
+ redact: (data, operation) => {
49
+ const safe = reviewed ? reviewed.redact(data, operation) : data;
50
+ return dropped.size > 0 ? strip(safe) : safe;
51
+ },
52
+ withholdsErrors: (operation) => reviewed?.withholdsErrors(operation) === true,
53
+ };
54
+ }
55
+ /** Bind the REST value-safety table to its pinned index; unknown operations never bypass its review. */
56
+ export function restSafety(reviewed, index) {
57
+ const indexed = (operation) => index.operation(operation.method, operation.template) ??
58
+ index.operation(operation.method, operation.template.replace(/\/:([^/]+)/g, "/{$1}"));
59
+ return {
60
+ refusal: (operation) => {
61
+ const op = indexed(operation);
62
+ return op ? reviewed.refusal(op.method, op.path) : undefined;
63
+ },
64
+ resolve: (method, path) => {
65
+ const { op } = index.resolve(method, path);
66
+ const refusal = reviewed.refusal(op.method, op.path);
67
+ if (refusal)
68
+ throw new ConnectorCallError("invalid_args", refusal);
69
+ return { method: op.method, template: op.path };
70
+ },
71
+ redact: (data, operation) => {
72
+ const op = indexed(operation);
73
+ if (!op)
74
+ throw new Error("A reviewed answer has no canonical operation in its index.");
75
+ return reviewed.redact(data, op.method, op.path);
76
+ },
77
+ withholdsErrors: (operation) => {
78
+ const op = indexed(operation);
79
+ return op ? reviewed.withholdsErrors(op) : true;
80
+ },
81
+ };
82
+ }
@@ -0,0 +1,79 @@
1
+ // HTTP request facts and fixed write reservations (B.2/B.4).
2
+ import { Context, Effect } from "effect";
3
+ import { dispatchProviderRequest, providerRequest } from "../provider-call.js";
4
+ import { callClassification } from "../call-classification.js";
5
+ import { fromSignal } from "../runtime/run.js";
6
+ import { callFromContext, ContinuationBinding, ContinuationStorage, openCall as openCoreCall, serviceFor, Signal, } from "../runtime/call.js";
7
+ import { RequestRefused, ResendRefused } from "./errors.js";
8
+ export { writeRequestKey } from "./write-request.js";
9
+ export { Caller, Credentials, Secrets, RequestSecrets, Budget, Recovery, Signal, Classification, Ledger, } from "../runtime/call.js";
10
+ /** Permanent write reservations plus resource dispatches, in reservation order. */
11
+ export class Dispatches extends Context.Service()("connecta/http/Dispatches") {
12
+ }
13
+ /** A genuine idempotency key the vendor honors, and the header that carries it, for the call's one write. */
14
+ export const IdempotencyKey = Context.Reference("connecta/http/IdempotencyKey", { defaultValue: () => undefined });
15
+ /** The authored read's review; served classification remains the call's own. */
16
+ export const ReadTool = Context.Reference("connecta/http/ReadTool", {
17
+ defaultValue: () => undefined,
18
+ });
19
+ /** Closed capacity and the requests bound to bulk items, snapshotted before the program runs. */
20
+ export class WriteCapacity extends Context.Service()("connecta/http/WriteCapacity") {
21
+ }
22
+ /** No await or fiber yield between the check and insertion. Reservations are never released. */
23
+ export function reserveWrite(ledger, capacity, facts) {
24
+ const step = facts.step ?? "write";
25
+ if (!capacity.get(step)?.has(facts.item)) {
26
+ return new RequestRefused({ message: "This write step/item was not declared by the tool for this call." });
27
+ }
28
+ const first = ledger.find((entry) => entry.write && entry.step === step && entry.item === facts.item);
29
+ if (first)
30
+ return new ResendRefused({ first });
31
+ const slot = {
32
+ write: true,
33
+ step,
34
+ ...(facts.item === undefined ? {} : { item: facts.item }),
35
+ ...(facts.operation ? { operation: facts.operation } : {}),
36
+ state: "reserved",
37
+ };
38
+ ledger.push(slot);
39
+ return slot;
40
+ }
41
+ /**
42
+ * What one request inside a call is: the call's own effect, or an auxiliary
43
+ * request inside a write tool, and which logical write. Auxiliary ownership
44
+ * does not itself prove a physical read. Set by `Send`, read by
45
+ * the transport and the OAuth middleware. `sent` is filled by the transport
46
+ * with the request it handed to `fetch`, so `Send` can record that request's
47
+ * own failure in the ledger.
48
+ */
49
+ export const RequestFacts = Context.Reference("connecta/http/RequestFacts", { defaultValue: () => ({ effect: "call" }) });
50
+ /** A call's use of renewal ends on close; a submitted claim remains coordinator-owned. */
51
+ export function duringCall(work) {
52
+ return Signal.use((signal) => {
53
+ const closed = () => new RequestRefused({ message: "This call has ended; no renewal work may continue." });
54
+ if (!signal)
55
+ return work;
56
+ if (signal.aborted)
57
+ return Effect.fail(closed());
58
+ return Effect.raceFirst(work, fromSignal(signal).pipe(Effect.mapError(closed)));
59
+ });
60
+ }
61
+ export function fromConnectorContext(ctx, fallback) {
62
+ const lease = callFromContext(ctx, callClassification(ctx) ?? fallback, {
63
+ ledger: {
64
+ open: ({ auxiliary, provider, method, key }) => providerRequest(ctx, auxiliary, provider, { method, ...(key === undefined ? {} : { key }) }),
65
+ dispatch: (entry, headers, method) => dispatchProviderRequest(ctx, entry, headers, method),
66
+ },
67
+ });
68
+ return {
69
+ ...lease,
70
+ services: lease.services.pipe(Context.add(ContinuationStorage, serviceFor(ctx, ContinuationStorage) ?? ctx.storage), Context.add(ContinuationBinding, serviceFor(ctx, ContinuationBinding) ?? { connection: "", principal: null }), Context.add(Dispatches, []), Context.add(WriteCapacity, new Map([["write", new Map([[undefined, undefined]])]]))),
71
+ };
72
+ }
73
+ export function openCall(inputs) {
74
+ const lease = openCoreCall(inputs);
75
+ return {
76
+ ...lease,
77
+ services: lease.services.pipe(Context.add(Dispatches, []), Context.add(WriteCapacity, new Map([["write", new Map([[undefined, undefined]])]]))),
78
+ };
79
+ }