@zackbart/connecta 0.34.0 → 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 (428) hide show
  1. package/CHANGELOG.md +393 -0
  2. package/README.md +62 -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 +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 +15 -7
  53. package/dist/connectors/api-connector.js +147 -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/option-shapes.js +1 -1
  58. package/dist/connectors/remote-mcp.d.ts +12 -30
  59. package/dist/connectors/remote-mcp.js +960 -564
  60. package/dist/d1.js +10 -243
  61. package/dist/derived-context.js +5 -0
  62. package/dist/describe-config.d.ts +5 -1
  63. package/dist/describe-config.js +3 -0
  64. package/dist/downstream-input.js +347 -260
  65. package/dist/errors.d.ts +87 -6
  66. package/dist/errors.js +114 -4
  67. package/dist/execute.js +87 -50
  68. package/dist/executor-admission.js +3 -0
  69. package/dist/executors/quickjs.js +163 -112
  70. package/dist/guarded-transport.js +50 -0
  71. package/dist/guest-runtime.js +1 -1
  72. package/dist/http/client.js +439 -0
  73. package/dist/http/errors.js +558 -0
  74. package/dist/http/fields.js +49 -0
  75. package/dist/http/hatch-paging.js +318 -0
  76. package/dist/http/hatch.js +1279 -0
  77. package/dist/http/json-schema.js +267 -0
  78. package/dist/http/node-transport.js +241 -0
  79. package/dist/http/oauth.js +162 -0
  80. package/dist/http/paging.js +228 -0
  81. package/dist/http/provider.js +221 -0
  82. package/dist/http/safety.js +82 -0
  83. package/dist/http/services.js +79 -0
  84. package/dist/http/tools.js +383 -0
  85. package/dist/http/vendor-index.js +138 -0
  86. package/dist/http/vendor.js +448 -0
  87. package/dist/http/write-request.js +66 -0
  88. package/dist/http-policy.d.ts +11 -0
  89. package/dist/http-policy.js +45 -0
  90. package/dist/inbound-credential.js +1 -1
  91. package/dist/index.d.ts +2 -2
  92. package/dist/index.js +4 -0
  93. package/dist/invocation-auth.js +30 -19
  94. package/dist/invocation.js +221 -87
  95. package/dist/mcp-result.js +0 -4
  96. package/dist/membership.d.ts +4 -0
  97. package/dist/meta-output.js +1 -1
  98. package/dist/meta-tools.js +534 -408
  99. package/dist/native-recovery.js +52 -0
  100. package/dist/native-tools.js +382 -0
  101. package/dist/node.d.ts +4 -3
  102. package/dist/node.js +45 -8
  103. package/dist/oauth-handoff.js +177 -104
  104. package/dist/oauth-partition.js +6 -20
  105. package/dist/oauth-sealing.js +6 -7
  106. package/dist/operation-vocabulary.js +101 -0
  107. package/dist/operator-record.d.ts +2 -2
  108. package/dist/operator-record.js +17 -4
  109. package/dist/operator-ui/agents.d.ts +5 -4
  110. package/dist/operator-ui/agents.js +17 -7
  111. package/dist/operator-ui/config-summary.js +8 -4
  112. package/dist/operator-ui/connection-map.js +9 -6
  113. package/dist/operator-ui/contract.d.ts +7 -3
  114. package/dist/operator-ui/endpoints.js +5 -14
  115. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  116. package/dist/operator-ui/fix-prompts.js +0 -8
  117. package/dist/operator-ui/generated.js +3 -3
  118. package/dist/operator-ui/health.js +52 -0
  119. package/dist/operator-ui/model.d.ts +2 -3
  120. package/dist/operator-ui/overview.js +11 -19
  121. package/dist/operator-ui/setup-commands.js +0 -4
  122. package/dist/operator-ui/view.d.ts +5 -29
  123. package/dist/operator-ui/view.js +3 -59
  124. package/dist/program-writes.js +47 -26
  125. package/dist/provider-call-facts.d.ts +115 -0
  126. package/dist/provider-call-facts.js +182 -0
  127. package/dist/provider-call.d.ts +112 -0
  128. package/dist/provider-call.js +271 -0
  129. package/dist/provider.d.ts +71 -32
  130. package/dist/provider.js +134 -40
  131. package/dist/providers/_shared/google/hatch.js +91 -0
  132. package/dist/providers/_shared/google/kit.js +537 -0
  133. package/dist/providers/_shared/google/result-size.js +15 -2
  134. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  135. package/dist/providers/_shared/google/service-account.js +8 -4
  136. package/dist/providers/_shared/google/workspace.d.ts +8 -209
  137. package/dist/providers/_shared/google/workspace.js +7 -426
  138. package/dist/providers/_shared/rest/compact-index.js +86 -0
  139. package/dist/providers/_shared/rest/dispatch.js +3 -23
  140. package/dist/providers/_shared/rest/kit.js +546 -0
  141. package/dist/providers/_shared/rest/operation-index.js +230 -14
  142. package/dist/providers/_shared/rest/response-media.js +11 -0
  143. package/dist/providers/_shared/rest/tools.js +101 -78
  144. package/dist/providers/_shared/rest/value-safety.js +353 -195
  145. package/dist/providers/_shared/sensitive-fields.js +27 -0
  146. package/dist/providers/breeze/api.js +584 -0
  147. package/dist/providers/breeze/index.d.ts +3 -3
  148. package/dist/providers/breeze/index.js +67 -1420
  149. package/dist/providers/breeze/openapi.generated.js +60 -0
  150. package/dist/providers/breeze/skill.generated.js +2 -6
  151. package/dist/providers/breeze/tools.js +696 -0
  152. package/dist/providers/ccb/api.js +496 -0
  153. package/dist/providers/ccb/index.d.ts +17 -37
  154. package/dist/providers/ccb/index.js +77 -1702
  155. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  156. package/dist/providers/ccb/lib/constants.js +74 -0
  157. package/dist/providers/ccb/lib/guide.js +9 -0
  158. package/dist/providers/ccb/lib/verdicts.js +387 -0
  159. package/dist/providers/ccb/openapi.generated.js +397 -0
  160. package/dist/providers/ccb/safety.js +295 -0
  161. package/dist/providers/ccb/skill.generated.js +2 -6
  162. package/dist/providers/ccb/tools.js +853 -0
  163. package/dist/providers/cloudflare/api.js +1066 -0
  164. package/dist/providers/cloudflare/index.d.ts +7 -22
  165. package/dist/providers/cloudflare/index.js +80 -194
  166. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  167. package/dist/providers/cloudflare/lib/config.js +2 -0
  168. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  169. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  170. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  171. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  172. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  173. package/dist/providers/cloudflare/openapi.generated.js +3299 -3208
  174. package/dist/providers/cloudflare/{value-safety.js → safety.js} +538 -18
  175. package/dist/providers/cloudflare/skill.generated.js +2 -10
  176. package/dist/providers/cloudflare/tools.js +360 -0
  177. package/dist/providers/docs/api.js +51 -0
  178. package/dist/providers/docs/index.d.ts +1 -12
  179. package/dist/providers/docs/index.js +53 -1165
  180. package/dist/providers/docs/lib/constants.d.ts +18 -0
  181. package/dist/providers/docs/lib/constants.js +18 -0
  182. package/dist/providers/docs/lib/discovery.js +26 -0
  183. package/dist/providers/docs/lib/requests.js +48 -0
  184. package/dist/providers/docs/lib/schemas.js +168 -0
  185. package/dist/providers/docs/openapi.generated.js +16 -0
  186. package/dist/providers/docs/safety.js +54 -0
  187. package/dist/providers/docs/skill.generated.js +2 -6
  188. package/dist/providers/docs/tools.js +802 -0
  189. package/dist/providers/drive/api.js +177 -0
  190. package/dist/providers/drive/index.d.ts +1 -12
  191. package/dist/providers/drive/index.js +38 -1448
  192. package/dist/providers/drive/lib/constants.d.ts +6 -0
  193. package/dist/providers/drive/lib/constants.js +6 -0
  194. package/dist/providers/drive/lib/contracts.js +532 -0
  195. package/dist/providers/drive/lib/hatch.js +197 -0
  196. package/dist/providers/drive/openapi.generated.js +77 -0
  197. package/dist/providers/drive/safety.js +90 -0
  198. package/dist/providers/drive/skill.generated.js +2 -6
  199. package/dist/providers/drive/tools.js +1290 -0
  200. package/dist/providers/forms/api.js +71 -0
  201. package/dist/providers/forms/index.d.ts +1 -12
  202. package/dist/providers/forms/index.js +49 -1145
  203. package/dist/providers/forms/lib/constants.d.ts +14 -0
  204. package/dist/providers/forms/lib/constants.js +19 -0
  205. package/dist/providers/forms/lib/hatch.js +72 -0
  206. package/dist/providers/forms/openapi.generated.js +23 -0
  207. package/dist/providers/forms/safety.js +34 -0
  208. package/dist/providers/forms/skill.generated.js +2 -8
  209. package/dist/providers/forms/tools.js +1024 -0
  210. package/dist/providers/github/api.js +150 -0
  211. package/dist/providers/github/index.d.ts +4 -5
  212. package/dist/providers/github/index.js +30 -87
  213. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  214. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  215. package/dist/providers/github/lib/discovery.js +132 -0
  216. package/dist/providers/github/lib/operations.js +58 -0
  217. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  218. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  219. package/dist/providers/github/openapi.generated.js +1216 -0
  220. package/dist/providers/github/safety.js +216 -0
  221. package/dist/providers/github/skill.generated.js +2 -5
  222. package/dist/providers/github/tools.js +506 -0
  223. package/dist/providers/gmail/api.js +114 -0
  224. package/dist/providers/gmail/index.d.ts +1 -12
  225. package/dist/providers/gmail/index.js +73 -1621
  226. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  227. package/dist/providers/gmail/lib/constants.js +16 -0
  228. package/dist/providers/gmail/lib/index.js +173 -0
  229. package/dist/providers/gmail/lib/schemas.js +176 -0
  230. package/dist/providers/gmail/lib/threading.js +120 -0
  231. package/dist/providers/gmail/openapi.generated.js +92 -0
  232. package/dist/providers/gmail/safety.js +21 -0
  233. package/dist/providers/gmail/skill.generated.js +2 -6
  234. package/dist/providers/gmail/tools.js +1435 -0
  235. package/dist/providers/overflow/api.js +1008 -0
  236. package/dist/providers/overflow/index.d.ts +3 -17
  237. package/dist/providers/overflow/index.js +60 -1488
  238. package/dist/providers/overflow/skill.generated.js +2 -5
  239. package/dist/providers/overflow/tools.js +873 -0
  240. package/dist/providers/planning-center/api.js +467 -0
  241. package/dist/providers/planning-center/index.d.ts +6 -35
  242. package/dist/providers/planning-center/index.js +69 -2445
  243. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  244. package/dist/providers/planning-center/lib/constants.js +83 -0
  245. package/dist/providers/planning-center/lib/discovery.js +40 -0
  246. package/dist/providers/planning-center/lib/guide.js +39 -0
  247. package/dist/providers/planning-center/lib/json-api.js +83 -0
  248. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  249. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  250. package/dist/providers/planning-center/safety.js +188 -0
  251. package/dist/providers/planning-center/skill.generated.js +2 -27
  252. package/dist/providers/planning-center/tools.js +1010 -0
  253. package/dist/providers/sheets/api.js +133 -0
  254. package/dist/providers/sheets/index.d.ts +4 -16
  255. package/dist/providers/sheets/index.js +61 -1172
  256. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  257. package/dist/providers/sheets/lib/constants.js +14 -0
  258. package/dist/providers/sheets/lib/hatch.js +163 -0
  259. package/dist/providers/sheets/lib/requests.js +105 -0
  260. package/dist/providers/sheets/lib/schemas.js +138 -0
  261. package/dist/providers/sheets/openapi.generated.js +30 -0
  262. package/dist/providers/sheets/safety.js +27 -0
  263. package/dist/providers/sheets/skill.generated.js +2 -7
  264. package/dist/providers/sheets/tools.js +734 -0
  265. package/dist/providers/slides/api.js +147 -0
  266. package/dist/providers/slides/index.d.ts +2 -10
  267. package/dist/providers/slides/index.js +48 -2555
  268. package/dist/providers/slides/lib/constants.d.ts +11 -0
  269. package/dist/providers/slides/lib/constants.js +11 -0
  270. package/dist/providers/slides/lib/requests.js +60 -0
  271. package/dist/providers/slides/lib/schemas.js +565 -0
  272. package/dist/providers/slides/openapi.generated.js +18 -0
  273. package/dist/providers/slides/skill.generated.js +2 -6
  274. package/dist/providers/slides/tools.js +1968 -0
  275. package/dist/providers/stripe/api.js +401 -0
  276. package/dist/providers/stripe/index.d.ts +7 -27
  277. package/dist/providers/stripe/index.js +75 -191
  278. package/dist/providers/stripe/lib/config.d.ts +4 -0
  279. package/dist/providers/stripe/lib/config.js +2 -0
  280. package/dist/providers/stripe/openapi.generated.js +4 -3
  281. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  282. package/dist/providers/stripe/skill.generated.js +2 -10
  283. package/dist/providers/stripe/tools.js +77 -0
  284. package/dist/providers/tithely/api.js +531 -0
  285. package/dist/providers/tithely/index.d.ts +19 -0
  286. package/dist/providers/tithely/index.js +86 -965
  287. package/dist/providers/tithely/skill.generated.js +2 -5
  288. package/dist/providers/tithely/tools.js +426 -0
  289. package/dist/providers/vercel/api.js +551 -0
  290. package/dist/providers/vercel/index.d.ts +11 -25
  291. package/dist/providers/vercel/index.js +67 -261
  292. package/dist/providers/vercel/lib/config.d.ts +2 -0
  293. package/dist/providers/vercel/lib/config.js +2 -0
  294. package/dist/providers/vercel/lib/index.js +117 -0
  295. package/dist/providers/vercel/lib/logs.js +100 -0
  296. package/dist/providers/vercel/lib/pin.js +270 -0
  297. package/dist/providers/vercel/openapi.generated.js +398 -376
  298. package/dist/providers/vercel/{value-safety.js → safety.js} +261 -42
  299. package/dist/providers/vercel/skill.generated.js +2 -7
  300. package/dist/providers/vercel/tools.js +642 -0
  301. package/dist/redaction-identity.js +47 -0
  302. package/dist/redaction-marker.js +125 -0
  303. package/dist/registry.d.ts +30 -28
  304. package/dist/registry.js +446 -413
  305. package/dist/routes/access-tokens.js +1 -1
  306. package/dist/routes/actor-labels.js +1 -1
  307. package/dist/routes/connect.js +1 -1
  308. package/dist/routes/dispatch.js +103 -0
  309. package/dist/routes/mcp.js +170 -79
  310. package/dist/routes/oauth.js +3 -1
  311. package/dist/routes/operator.js +2 -2
  312. package/dist/routes/shared.d.ts +5 -4
  313. package/dist/routes/shared.js +244 -177
  314. package/dist/routes/skills.js +10 -8
  315. package/dist/routes/ui-config.js +27 -3
  316. package/dist/routes/ui-data.js +29 -22
  317. package/dist/routes/ui.js +1 -1
  318. package/dist/runtime/call-admission.js +0 -26
  319. package/dist/runtime/call-entry.js +30 -0
  320. package/dist/runtime/call.js +556 -0
  321. package/dist/runtime/connector-scope.js +7 -0
  322. package/dist/runtime/credential-probe.js +34 -0
  323. package/dist/runtime/executor.js +40 -0
  324. package/dist/runtime/native-storage.js +63 -0
  325. package/dist/runtime/registry.js +27 -0
  326. package/dist/runtime/request-scope.js +72 -0
  327. package/dist/runtime/run.js +15 -7
  328. package/dist/runtime/shared-read.js +34 -5
  329. package/dist/runtime/storage.js +34 -21
  330. package/dist/sent-secrets.d.ts +194 -37
  331. package/dist/sent-secrets.js +1743 -340
  332. package/dist/server.js +5 -56
  333. package/dist/skills.js +330 -224
  334. package/dist/sqlite.js +15 -14
  335. package/dist/storage/d1-copy.js +255 -0
  336. package/dist/storage/d1-driver.js +15 -0
  337. package/dist/storage/keys.js +28 -0
  338. package/dist/storage/sql-driver.js +88 -0
  339. package/dist/storage/sql-native.js +544 -0
  340. package/dist/storage/sql-schema.d.ts +6 -0
  341. package/dist/storage/sql-schema.js +15 -0
  342. package/dist/storage/sql.d.ts +14 -20
  343. package/dist/storage/sql.js +29 -535
  344. package/dist/timeout.js +0 -26
  345. package/dist/tool-safety.js +20 -10
  346. package/dist/types.d.ts +11 -99
  347. package/dist/upward.js +3 -0
  348. package/dist/usage-guide.js +3 -1
  349. package/dist/validate.d.ts +4 -2
  350. package/dist/validate.js +86 -9
  351. package/dist/version.d.ts +1 -1
  352. package/dist/version.js +1 -1
  353. package/dist/worker.js +312 -292
  354. package/dist/workspace-subject.js +5 -1
  355. package/dist/write-outcome.js +454 -34
  356. package/documentation/README.md +27 -7
  357. package/documentation/architecture.md +2550 -186
  358. package/documentation/auth.md +821 -98
  359. package/documentation/code-mode.md +56 -21
  360. package/documentation/deploying.md +164 -20
  361. package/documentation/hosted-mcp-migration.md +460 -0
  362. package/documentation/integrating.md +144 -105
  363. package/documentation/meta-tools.md +411 -34
  364. package/documentation/operating.md +28 -4
  365. package/documentation/operator-tests.md +11 -2
  366. package/documentation/operator-ui.md +103 -33
  367. package/documentation/provider-auth-migration.md +38 -63
  368. package/documentation/provider-migration-0.29.md +10 -5
  369. package/documentation/provider-migration-0.35.md +975 -0
  370. package/documentation/providers.md +965 -0
  371. package/examples/worker/AGENTS.md +23 -9
  372. package/examples/worker/README.md +254 -135
  373. package/examples/worker/alchemy.run.ts +116 -0
  374. package/examples/worker/gitignore +10 -0
  375. package/examples/worker/src/connecta.config.ts +23 -21
  376. package/examples/worker/wrangler.jsonc +14 -5
  377. package/guides/connecting-agents.md +157 -0
  378. package/guides/how-it-works.md +156 -0
  379. package/guides/safety-and-trust.md +153 -0
  380. package/package.json +27 -42
  381. package/templates/node/.env.example +3 -0
  382. package/templates/node/README.md +22 -2
  383. package/templates/node/docker-compose.yml +1 -0
  384. package/templates/node/package.json +3 -2
  385. package/templates/node/src/connecta.config.ts +8 -0
  386. package/dist/catalog-drift.d.ts +0 -134
  387. package/dist/catalog-drift.js +0 -493
  388. package/dist/providers/_shared/request-token.js +0 -83
  389. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  390. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  391. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  392. package/dist/providers/basecamp/index.d.ts +0 -43
  393. package/dist/providers/basecamp/index.js +0 -997
  394. package/dist/providers/basecamp/skill.generated.js +0 -9
  395. package/dist/providers/cloudflare/rest.d.ts +0 -37
  396. package/dist/providers/cloudflare/rest.js +0 -1078
  397. package/dist/providers/github/hosted.js +0 -218
  398. package/dist/providers/github/rest.js +0 -321
  399. package/dist/providers/infisical/index.d.ts +0 -7
  400. package/dist/providers/infisical/index.js +0 -713
  401. package/dist/providers/infisical/skill.generated.js +0 -8
  402. package/dist/providers/linear/index.d.ts +0 -55
  403. package/dist/providers/linear/index.js +0 -352
  404. package/dist/providers/linear/skill.generated.js +0 -8
  405. package/dist/providers/mixpanel/index.d.ts +0 -57
  406. package/dist/providers/mixpanel/index.js +0 -468
  407. package/dist/providers/mixpanel/operations.js +0 -20
  408. package/dist/providers/mixpanel/rest.js +0 -603
  409. package/dist/providers/mixpanel/skill.generated.js +0 -10
  410. package/dist/providers/mixpanel/value-safety.js +0 -16
  411. package/dist/providers/notion/index.d.ts +0 -65
  412. package/dist/providers/notion/index.js +0 -368
  413. package/dist/providers/notion/openapi.generated.js +0 -75
  414. package/dist/providers/notion/rest.d.ts +0 -24
  415. package/dist/providers/notion/rest.js +0 -1226
  416. package/dist/providers/notion/skill.generated.js +0 -11
  417. package/dist/providers/notion/value-safety.js +0 -56
  418. package/dist/providers/revenuecat/index.d.ts +0 -49
  419. package/dist/providers/revenuecat/index.js +0 -557
  420. package/dist/providers/revenuecat/skill.generated.js +0 -11
  421. package/dist/providers/stripe/rest.d.ts +0 -14
  422. package/dist/providers/stripe/rest.js +0 -402
  423. package/dist/providers/vercel/rest.d.ts +0 -20
  424. package/dist/providers/vercel/rest.js +0 -1020
  425. package/dist/providers/wispr-flow/index.d.ts +0 -14
  426. package/dist/providers/wispr-flow/index.js +0 -117
  427. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  428. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -0,0 +1,556 @@
1
+ // Operation and call services. Only the Promise view bridge is keyed on a
2
+ // context object; authority lives in Context values, shared by derived views.
3
+ import { Context, Effect } from "effect";
4
+ import { ConnectorCallError } from "../errors.js";
5
+ import { dispatchProviderRequest, } from "../provider-call.js";
6
+ import { SentSecrets, sentSecretsForRequest, registerCredentialValues } from "../sent-secrets.js";
7
+ import { recordRecovery } from "../call-recovery.js";
8
+ import { fromSignal, runEdge } from "./run.js";
9
+ import { RequestScope, requestOwner as requestOf } from "./request-scope.js";
10
+ /** Who admitted the operation; absent for a probe or a callback no request admitted. */
11
+ export class Caller extends Context.Service()("connecta/call/Caller") {
12
+ }
13
+ /** The deployment's root store, used only for its durable continuation-signing key. */
14
+ export const ContinuationStorage = Context.Reference("connecta/call/ContinuationStorage", {
15
+ defaultValue: () => undefined,
16
+ });
17
+ /** Admitted connection and credential owner or per-call identity; never derived from tool arguments. */
18
+ export const ContinuationBinding = Context.Reference("connecta/call/ContinuationBinding", { defaultValue: () => ({ connection: "", principal: null }) });
19
+ /** The credentials this call may send, already registered as sent secrets when read. */
20
+ export class Credentials extends Context.Service()("connecta/call/Credentials") {
21
+ }
22
+ /** Native operation credential access; custom contexts retain their Promise leaf. */
23
+ export const OperationCredentials = Context.Reference("connecta/operation/Credentials", { defaultValue: () => undefined });
24
+ /** The call's sent-secret set; every credential header and query value is registered here. */
25
+ export class Secrets extends Context.Service()("connecta/call/Secrets") {
26
+ }
27
+ /**
28
+ * Everything the request sent, every connector's credentials included: the
29
+ * set that redacts downstream text whole before anything cuts, trims, or
30
+ * extracts from it (#911's `redactBeforeCut`).
31
+ */
32
+ export class RequestSecrets extends Context.Service()("connecta/call/RequestSecrets") {
33
+ }
34
+ /**
35
+ * The enclosing invocation's admission permit, as the one thing a provider
36
+ * may do with it: charge an auxiliary request to the same budget.
37
+ */
38
+ export class Budget extends Context.Service()("connecta/call/Budget") {
39
+ }
40
+ /** Facts that let an agent reconcile a write whose outcome is unknown. */
41
+ export class Recovery extends Context.Service()("connecta/call/Recovery") {
42
+ }
43
+ /** The call's cancellation, handed to `fetch` as guarded-fetch handed `ctx.signal`. */
44
+ class SourceSignal extends Context.Service()("connecta/call/SourceSignal") {
45
+ }
46
+ export class Signal extends Context.Service()("connecta/call/Signal") {
47
+ }
48
+ /**
49
+ * The call's served classification: deployment config's verdict when it
50
+ * gives one, else the tool's. The OAuth middleware and the write-outcome rule
51
+ * read it; neither the builder nor the HTTP method decides.
52
+ */
53
+ export class ServedClassification extends Context.Service()("connecta/call/ServedClassification") {
54
+ }
55
+ export class Classification extends Context.Service()("connecta/call/Classification") {
56
+ }
57
+ /**
58
+ * The core's request ledger for this call (src/provider-call.ts), which the
59
+ * `api()` boundary reads to decide every write verdict (INV-9). The transport
60
+ * opens an entry for each resource request with its method and any genuine
61
+ * idempotency key it carries, dispatches it synchronously before `fetch`
62
+ * (which refuses a request whose call has ended), and records its status
63
+ * when answered. A dispatch also joins the request to the invocation's
64
+ * logical call, so identities are captured when the request leaves.
65
+ */
66
+ export class Ledger extends Context.Service()("connecta/call/Ledger") {
67
+ }
68
+ /**
69
+ * A ledger no `api()` boundary reads: what a lease built without a context
70
+ * (a unit test) records into. It still marks each request dispatched.
71
+ */
72
+ const detachedLedger = {
73
+ open: ({ auxiliary, provider, method, key }) => ({
74
+ dispatched: false,
75
+ auxiliary,
76
+ provider,
77
+ method,
78
+ ...(key === undefined ? {} : { key }),
79
+ }),
80
+ dispatch: (request, headers, method) => dispatchProviderRequest(undefined, request, headers, method),
81
+ };
82
+ export class ProviderLedger extends Context.Service()("connecta/call/ProviderLedger") {
83
+ }
84
+ export class LogicalLedger extends Context.Service()("connecta/call/LogicalLedger") {
85
+ }
86
+ class CallMemo extends Context.Service()("connecta/call/Memo") {
87
+ }
88
+ /** Construction-owned keys keep provider memoization on the call, including derived views. */
89
+ export function callMemo(view, key, create) {
90
+ if (viewClosed(view))
91
+ throw ended();
92
+ let memo = serviceFor(view, CallMemo);
93
+ if (!memo) {
94
+ memo = new Map();
95
+ setViewService(view, CallMemo, memo);
96
+ }
97
+ if (!memo.has(key))
98
+ memo.set(key, create());
99
+ return memo.get(key);
100
+ }
101
+ export class Operation extends Context.Service()("connecta/call/Operation") {
102
+ }
103
+ export class ActiveCall extends Context.Service()("connecta/call/ActiveCall") {
104
+ }
105
+ function ended() {
106
+ return new ConnectorCallError("connector_call_failed", "This call has ended; a capability kept from it can no longer be used.", { retryable: false });
107
+ }
108
+ /** Build one call's services. Invocation calls this in the scoped attempt that owns the permit (B.1). */
109
+ export function openCall(inputs) {
110
+ let open = true;
111
+ const parentSignal = inputs.parent ? Context.get(inputs.parent.services, Signal) : undefined;
112
+ const parents = [inputs.signal, parentSignal, inputs.requestSignal].filter((signal) => signal !== undefined);
113
+ const controller = new AbortController();
114
+ const detachParents = [];
115
+ const failures = [];
116
+ const attempt = (step) => {
117
+ try {
118
+ step();
119
+ }
120
+ catch (failure) {
121
+ failures.push(failure);
122
+ }
123
+ };
124
+ // Revocation never throws, including when reached by a parent's abort
125
+ // listener. Report detach failures at the next explicit close, once every
126
+ // capability and listener is revoked. Abort before touching any facade.
127
+ const revoke = (reason) => {
128
+ if (!open)
129
+ return;
130
+ open = false;
131
+ attempt(() => controller.abort(reason));
132
+ for (const detach of detachParents.splice(0))
133
+ attempt(detach);
134
+ };
135
+ // Forward structurally rather than passing a caller's signal to a native
136
+ // brand check: adapters can supply a signal facade owned by their request.
137
+ for (const signal of parents) {
138
+ if (!open)
139
+ break;
140
+ const abort = () => revoke(signal.reason);
141
+ if (signal.aborted)
142
+ abort();
143
+ else {
144
+ detachParents.push(() => signal.removeEventListener("abort", abort));
145
+ signal.addEventListener("abort", abort, { once: true });
146
+ }
147
+ }
148
+ // Closure settles the Effect immediately and interrupts its Promise bridge.
149
+ // Inputs receive that cancellation too, so their owned I/O can be aborted.
150
+ const live = (work, fail, closed = ended) => Effect.suspend(() => open && !controller.signal.aborted
151
+ ? Effect.raceFirst(Effect.suspend(() => work(controller.signal)).pipe(Effect.mapError(fail), Effect.catchDefect((error) => Effect.fail(fail(error)))), fromSignal(controller.signal).pipe(Effect.mapError(closed))).pipe(Effect.flatMap((value) => open && !controller.signal.aborted ? Effect.succeed(value) : Effect.fail(closed())))
152
+ : Effect.fail(closed()));
153
+ const owner = requestOf(inputs.operation
154
+ ? (views.get(inputs.operation)?.request ?? inputs.operation.requestScope ?? inputs.operation)
155
+ : inputs);
156
+ sentSecretsForRequest(owner.identity, inputs.requestSecrets ?? inputs.secrets);
157
+ const services = Context.make(RequestScope, owner).pipe(Context.add(Caller, inputs.caller), Context.add(Credentials, {
158
+ values: live((signal) => (inputs.credentialsEffect ??
159
+ Effect.tryPromise({
160
+ try: (interrupted) => inputs.credentials(AbortSignal.any([signal, interrupted])),
161
+ catch: (error) => error,
162
+ })).pipe(Effect.tap((values) => Effect.sync(() => registerCredentialValues(inputs.secrets, values)))), (error) => open
163
+ ? error instanceof ConnectorCallError
164
+ ? error
165
+ : new ConnectorCallError("auth_required", "The connector's stored credential could not be read.", {
166
+ retryable: false,
167
+ })
168
+ : ended()),
169
+ }), Context.add(Secrets, inputs.secrets), Context.add(RequestSecrets, inputs.requestSecrets ?? inputs.secrets), Context.add(Budget, {
170
+ charge: live((signal) => inputs.chargeEffect?.(signal) ??
171
+ Effect.tryPromise({
172
+ try: (interrupted) => inputs.charge(AbortSignal.any([signal, interrupted])),
173
+ catch: (error) => error,
174
+ }), (error) => error, inputs.chargeClosed),
175
+ }), Context.add(Recovery, {
176
+ // Late facts are dropped: invocation has already read the record.
177
+ record: (facts) => Effect.sync(() => (open && !controller.signal.aborted ? inputs.record(facts) : undefined)),
178
+ recordNow: (facts) => {
179
+ if (open && !controller.signal.aborted)
180
+ inputs.record(facts);
181
+ },
182
+ }), Context.add(Signal, controller.signal), Context.add(SourceSignal, {
183
+ signal: inputs.operation ? callerSignal(inputs.operation) : inputs.signal,
184
+ requestSignal: Object.hasOwn(inputs, "requestSourceSignal")
185
+ ? inputs.requestSourceSignal
186
+ : inputs.operation
187
+ ? requestCallerSignal(inputs.operation)
188
+ : inputs.signal,
189
+ }), Context.add(Classification, inputs.classification), Context.add(ServedClassification, inputs.served), Context.add(Ledger, {
190
+ open: (facts) => {
191
+ if (!open || controller.signal.aborted)
192
+ throw ended();
193
+ return (inputs.ledger ?? detachedLedger).open(facts);
194
+ },
195
+ dispatch: (request, headers, method) => {
196
+ if (!open || controller.signal.aborted)
197
+ throw ended();
198
+ (inputs.ledger ?? detachedLedger).dispatch(request, headers, method);
199
+ },
200
+ }), Context.add(CallMemo, new Map()), Context.add(ProviderLedger, inputs.providerLedger), Context.add(LogicalLedger, inputs.operation ? serviceFor(inputs.operation, LogicalLedger) : undefined));
201
+ const lease = {
202
+ get services() {
203
+ return Context.add(Context.add(services, ActiveCall, lease), Operation, inputs.operation);
204
+ },
205
+ closed: () => !open || controller.signal.aborted,
206
+ close: () => {
207
+ revoke(ended());
208
+ if (failures.length)
209
+ throw new AggregateError(failures.splice(0), "Closing the call: signal cleanup failed.");
210
+ },
211
+ };
212
+ return lease;
213
+ }
214
+ const views = new WeakMap();
215
+ function entryOf(view) {
216
+ const entry = views.get(view);
217
+ return entry && requestOf(entry.request).open ? entry : undefined;
218
+ }
219
+ export function serviceFor(view, key) {
220
+ const entry = entryOf(view);
221
+ return entry ? Context.getOrUndefined(entry.services, key) : undefined;
222
+ }
223
+ /** Settlement retains facts after revocation; it never acquires a live capability. */
224
+ export function recordedService(view, key) {
225
+ const entry = views.get(view);
226
+ return entry ? Context.getOrUndefined(entry.services, key) : undefined;
227
+ }
228
+ export function viewClosed(view) {
229
+ const entry = views.get(view);
230
+ return entry !== undefined && (!requestOf(entry.request).open || entry.call?.closed() === true);
231
+ }
232
+ /** Request revocation is independent of call authority, including on an unregistered copy. */
233
+ export function requestClosed(view) {
234
+ const scope = views.get(view)?.request ?? view.requestScope ?? view;
235
+ return !requestOf(scope).open;
236
+ }
237
+ export function setViewService(view, key, value) {
238
+ const entry = ensureOperation(view);
239
+ if (requestOf(entry.request).open)
240
+ entry.services = Context.add(entry.services, key, value);
241
+ }
242
+ function ensureOperation(base, explicitOperation = false) {
243
+ const existing = views.get(base);
244
+ if (existing) {
245
+ // Custom contexts can acquire an explicit requestScope after their caller
246
+ // was attached. Bind that initial scope before deriving any call view;
247
+ // call views and contexts already bound to an explicit scope never move.
248
+ if (!existing.call &&
249
+ !existing.scopeBound &&
250
+ existing.request === base &&
251
+ requestOf(existing.request).open &&
252
+ base.requestScope &&
253
+ base.requestScope !== base) {
254
+ requestOf(existing.request).entries.delete(existing);
255
+ existing.request = base.requestScope;
256
+ const all = sentSecretsForRequest(existing.request);
257
+ all.include(Context.get(existing.services, Secrets));
258
+ existing.services = Context.add(Context.add(existing.services, RequestSecrets, all), RequestScope, requestOf(existing.request));
259
+ requestOf(existing.request).entries.add(existing);
260
+ }
261
+ return existing;
262
+ }
263
+ // A copied view has no authority. Request membership is evidence only that
264
+ // authority is required, never a way to recover the original call's state.
265
+ // Registry operations and anonymous probes are constructed explicitly.
266
+ if (!explicitOperation && callScopeKnown(base))
267
+ throw ended();
268
+ const request = base.requestScope ?? base;
269
+ const secrets = new SentSecrets();
270
+ const all = sentSecretsForRequest(request);
271
+ all.include(secrets);
272
+ const entry = {
273
+ services: Context.make(Caller, undefined).pipe(Context.add(Secrets, secrets), Context.add(RequestSecrets, all), Context.add(RequestScope, requestOf(request))),
274
+ request,
275
+ base,
276
+ };
277
+ views.set(base, entry);
278
+ requestOf(request).entries.add(entry);
279
+ return entry;
280
+ }
281
+ export function operationView(base, caller) {
282
+ const view = { ...base, requestScope: base.requestScope ?? {} };
283
+ const entry = ensureOperation(view, true);
284
+ if (requestOf(entry.request).open)
285
+ entry.services = Context.add(entry.services, Caller, caller);
286
+ return view;
287
+ }
288
+ export function deriveView(view, overrides) {
289
+ const entry = ensureOperation(view);
290
+ entry.scopeBound = true;
291
+ const derived = { ...view, ...overrides, requestScope: entry.request };
292
+ views.set(derived, entry);
293
+ return derived;
294
+ }
295
+ export function viewCaller(view) {
296
+ return serviceFor(view, Caller);
297
+ }
298
+ export function viewLease(view) {
299
+ return views.get(view)?.call;
300
+ }
301
+ export function viewServices(view) {
302
+ return ensureOperation(view).services;
303
+ }
304
+ export function contextView(lease, operation) {
305
+ const origin = ensureOperation(operation);
306
+ origin.scopeBound = true;
307
+ const values = Context.get(lease.services, Credentials).values;
308
+ const signal = Context.get(lease.services, Signal);
309
+ const view = {
310
+ ...operation,
311
+ requestScope: origin.request,
312
+ ...(signal ? { signal } : {}),
313
+ ...(operation.credential
314
+ ? {
315
+ credential: {
316
+ getAll: () => settleOnClose(view, () => runEdge(values)),
317
+ get: (field = "value") => settleOnClose(view, async () => {
318
+ const all = await runEdge(values);
319
+ return all && Object.hasOwn(all, field) ? all[field] : null;
320
+ }),
321
+ },
322
+ }
323
+ : {}),
324
+ };
325
+ const entry = {
326
+ services: Context.add(Context.merge(origin.services, lease.services), Caller, serviceFor(operation, Caller)),
327
+ request: origin.request,
328
+ base: origin.base,
329
+ call: lease,
330
+ credentialWrapped: true,
331
+ };
332
+ views.set(view, entry);
333
+ const request = requestOf(origin.request);
334
+ request.entries.add(entry);
335
+ request.calls.add(lease);
336
+ if (!request.open)
337
+ lease.close();
338
+ return view;
339
+ }
340
+ export const callView = (operation, lease) => contextView(lease, operation);
341
+ export function chargeView(view) {
342
+ const budget = recordedService(view, Budget);
343
+ return budget ? runEdge(budget.charge) : Promise.reject(ended());
344
+ }
345
+ /** Admission is sticky until request close; ending a call never makes its copies standalone. */
346
+ export function callScopeKnown(view) {
347
+ const scope = requestOf(views.get(view)?.request ?? view.requestScope ?? view);
348
+ return scope !== undefined && (!scope.open || scope.admitted);
349
+ }
350
+ export function viewSecrets(view) {
351
+ const entry = ensureOperation(view);
352
+ return Context.get(entry.services, Secrets);
353
+ }
354
+ /** Register operation credentials once; call credentials are supplied by the lease. */
355
+ export function wrapViewCredentials(view) {
356
+ const entry = ensureOperation(view);
357
+ if (!view.credential || entry.credentialWrapped)
358
+ return;
359
+ entry.credentialWrapped = true;
360
+ const access = view.credential;
361
+ view.credential = {
362
+ get: (field) => settleOnClose(view, async () => {
363
+ const value = await access.get(field);
364
+ registerCredentialValues(viewSecrets(view), value === null ? null : { [field ?? "value"]: value });
365
+ return value;
366
+ }, true),
367
+ getAll: () => settleOnClose(view, async () => {
368
+ const values = await access.getAll();
369
+ registerCredentialValues(viewSecrets(view), values);
370
+ return values;
371
+ }, true),
372
+ };
373
+ }
374
+ /** Credentials for request-owned transports use the operation, never a closed call. */
375
+ export function operationContext(view) {
376
+ return views.get(view)?.base ?? view;
377
+ }
378
+ export function openRequest(scope) {
379
+ const state = requestOf(scope);
380
+ return { signal: state.controller.signal, own: (finalizer) => state.own(finalizer), close: () => state.close() };
381
+ }
382
+ /** Open a child lease from operation services, never read security side tables. */
383
+ export function callFromContext(ctx, classification, overrides = {}) {
384
+ const { admitted, anonymous, ...callOverrides } = overrides;
385
+ const entry = ensureOperation(ctx);
386
+ const scope = requestOf(entry.request);
387
+ // Direct api() calls on an unadmitted scope and explicit anonymous probes
388
+ // have no served invocation to charge. Once a permit has existed, however,
389
+ // no missing Budget may become a standalone call, even if an anonymous
390
+ // entry was registered before admission or the admitted call already ended.
391
+ if (scope.admitted && !recordedService(ctx, Budget) && !admitted && !anonymous)
392
+ throw ended();
393
+ if (admitted)
394
+ scope.admitted = true;
395
+ if (Object.hasOwn(callOverrides, "requestSourceSignal")) {
396
+ // The operation's credentials also serve request-owned transports. Keep
397
+ // their request source separate from the attempt's expiring deadline.
398
+ entry.services = Context.add(entry.services, SourceSignal, {
399
+ signal: callerSignal(ctx),
400
+ requestSignal: callOverrides.requestSourceSignal,
401
+ });
402
+ }
403
+ const request = openRequest(entry.request);
404
+ const credential = ctx.credential;
405
+ const secrets = new SentSecrets();
406
+ secrets.include(Context.get(entry.services, Secrets));
407
+ Context.get(entry.services, RequestSecrets).include(secrets);
408
+ const lease = openCall({
409
+ caller: serviceFor(ctx, Caller),
410
+ classification,
411
+ served: serviceFor(ctx, ServedClassification),
412
+ credentials: async () => (credential ? credential.getAll() : null),
413
+ credentialsEffect: Object.hasOwn(callOverrides, "credentials")
414
+ ? undefined
415
+ : entry.call
416
+ ? recordedService(ctx, Credentials)?.values
417
+ : serviceFor(ctx, OperationCredentials),
418
+ charge: () => (serviceFor(ctx, Budget) ? chargeView(ctx) : Promise.resolve()),
419
+ chargeEffect: Object.hasOwn(callOverrides, "charge")
420
+ ? undefined
421
+ : () => serviceFor(ctx, Budget)?.charge ?? Effect.void,
422
+ record: (facts) => recordRecovery(ctx, facts),
423
+ secrets,
424
+ requestSecrets: serviceFor(ctx, RequestSecrets),
425
+ signal: ctx.signal,
426
+ requestSignal: request.signal,
427
+ ...(entry.call ? { parent: entry.call } : {}),
428
+ operation: ctx,
429
+ ...callOverrides,
430
+ });
431
+ requestOf(entry.request).calls.add(lease);
432
+ if (!requestOf(entry.request).open)
433
+ lease.close();
434
+ return lease;
435
+ }
436
+ /** Cancellation is request-owned for operations and auxiliaries, call-owned otherwise. */
437
+ export function viewSignal(ctx, requestOwned = false) {
438
+ const state = requestOf(views.get(ctx)?.request ?? ctx.requestScope ?? ctx);
439
+ const request = state.controller.signal;
440
+ // The original caller signal is distinct from the revocable call signal:
441
+ // ending a call must not stop its request's session or auxiliary work.
442
+ const source = requestOwned ? requestCallerSignal(ctx) : ctx.signal;
443
+ const leaseSignal = requestOwned ? undefined : recordedService(ctx, Signal);
444
+ // A derived transport signal can add cancellation, never replace the lease
445
+ // that owns this wait. Both inputs here are native, even for source facades.
446
+ const owned = (signal) => leaseSignal && leaseSignal !== source ? AbortSignal.any([signal, leaseSignal]) : signal;
447
+ if (!source || source === request)
448
+ return owned(request);
449
+ let binding = state.signals.get(source);
450
+ if (!binding) {
451
+ const controller = new AbortController();
452
+ const failures = [];
453
+ let attached = false;
454
+ const detach = () => {
455
+ if (!attached)
456
+ return;
457
+ attached = false;
458
+ for (const remove of [
459
+ () => source.removeEventListener("abort", fromSource),
460
+ () => request.removeEventListener("abort", fromRequest),
461
+ ]) {
462
+ try {
463
+ remove();
464
+ }
465
+ catch (error) {
466
+ failures.push(error);
467
+ }
468
+ }
469
+ };
470
+ const revoke = (reason) => {
471
+ controller.abort(reason);
472
+ detach();
473
+ };
474
+ const fromSource = () => revoke(source.reason);
475
+ const fromRequest = () => revoke(request.reason);
476
+ // Read structurally, as openCall does: a request-owned facade need not
477
+ // pass AbortSignal.any's native brand check. Never share it across scopes.
478
+ const refresh = () => {
479
+ if (controller.signal.aborted)
480
+ return;
481
+ if (request.aborted)
482
+ fromRequest();
483
+ else if (source.aborted)
484
+ fromSource();
485
+ };
486
+ refresh();
487
+ if (!controller.signal.aborted) {
488
+ attached = true;
489
+ source.addEventListener("abort", fromSource, { once: true });
490
+ if (!controller.signal.aborted)
491
+ request.addEventListener("abort", fromRequest, { once: true });
492
+ state.finalizers.push(() => {
493
+ detach();
494
+ if (failures.length)
495
+ throw new AggregateError(failures.splice(0), "Closing the operation signal failed.");
496
+ });
497
+ }
498
+ binding = { signal: controller.signal, refresh };
499
+ state.signals.set(source, binding);
500
+ }
501
+ // Some adapters expose cancellation through a live getter without an abort
502
+ // event. Poll it at each boundary, including after an awaited operation.
503
+ binding.refresh();
504
+ return owned(binding.signal);
505
+ }
506
+ /** Compose native work under the same revocation guards as the Promise view. */
507
+ export function duringViewEffect(ctx, work, requestOwned = false) {
508
+ return Effect.suspend(() => {
509
+ const lease = views.get(ctx)?.call;
510
+ if (!requestOwned && lease?.closed())
511
+ return Effect.fail(Context.get(lease.services, Signal)?.reason ?? ended());
512
+ const signal = viewSignal(ctx, requestOwned);
513
+ if (signal.aborted)
514
+ return Effect.fail(signal.reason);
515
+ return Effect.raceFirst(Effect.suspend(() => work(signal)), fromSignal(signal)).pipe(Effect.flatMap((value) => {
516
+ const current = viewSignal(ctx, requestOwned);
517
+ return current.aborted ? Effect.fail(current.reason) : Effect.succeed(value);
518
+ }));
519
+ });
520
+ }
521
+ /**
522
+ * Settle an entire Promise boundary when its owner closes, regardless of the
523
+ * internal seam currently awaiting. Interruption observes late rejections;
524
+ * detached work still has to pass the transport and lease guards before any
525
+ * dispatch or call-owned commit. Refresh coordinator ownership is independent
526
+ * of this caller's wait once its claim has been submitted.
527
+ */
528
+ export async function settleOnClose(ctx, work, requestOwned = false) {
529
+ const lease = views.get(ctx)?.call;
530
+ if (!requestOwned && lease?.closed())
531
+ throw Context.get(lease.services, Signal)?.reason ?? ended();
532
+ const signal = viewSignal(ctx, requestOwned);
533
+ if (signal.aborted)
534
+ throw signal.reason;
535
+ // Enter synchronously after the guard, as the original Promise method did:
536
+ // shared-session waiter accounting and claim ownership precede cancellation.
537
+ const pending = work(signal);
538
+ void pending.catch(() => { });
539
+ const value = await runEdge(Effect.tryPromise({ try: () => pending, catch: (error) => error }), { signal });
540
+ const current = viewSignal(ctx, requestOwned);
541
+ if (current.aborted)
542
+ throw current.reason;
543
+ return value;
544
+ }
545
+ /** Also pass the resolved owner to I/O that can release resources on abort. */
546
+ export function duringViewCall(ctx, work, requestOwned = false) {
547
+ return settleOnClose(ctx, work, requestOwned);
548
+ }
549
+ export function callerSignal(view) {
550
+ const source = recordedService(view, SourceSignal);
551
+ return source ? source.signal : view.signal;
552
+ }
553
+ function requestCallerSignal(view) {
554
+ const source = recordedService(view, SourceSignal);
555
+ return source ? source.requestSignal : view.signal;
556
+ }
@@ -4,6 +4,7 @@
4
4
  // Effect caller that owns a Scope registers the close as that scope's
5
5
  // finalizer instead, so teardown runs however the work inside it ends.
6
6
  import { Duration, Effect } from "effect";
7
+ import { openRequest } from "./call.js";
7
8
  import { detach } from "./run.js";
8
9
  /** Enough for local transport abort/close without letting cleanup own latency. */
9
10
  const CONNECTOR_SCOPE_CLOSE_BUDGET_MS = 100;
@@ -33,6 +34,12 @@ function waitAtMost(work, budgetMs) {
33
34
  */
34
35
  export function closeScope(connector, ctx, defer) {
35
36
  return Effect.suspend(() => {
37
+ try {
38
+ openRequest(ctx.requestScope ?? ctx).close();
39
+ }
40
+ catch {
41
+ /* Every cleanup step already ran. */
42
+ }
36
43
  let settled;
37
44
  try {
38
45
  const closing = connector.closeScope?.(ctx);
@@ -0,0 +1,34 @@
1
+ // Candidate credential tests are anonymous read calls, never context copies
2
+ // that borrow an admitted caller, budget, or served write classification.
3
+ import { callFromContext, contextView, operationView, viewLease } from "./call.js";
4
+ function credentialProbeContext(ctx, values) {
5
+ const operation = operationView({
6
+ storage: ctx.storage,
7
+ logger: ctx.logger,
8
+ baseUrl: ctx.baseUrl,
9
+ ...(ctx.publicUrl !== undefined ? { publicUrl: ctx.publicUrl } : {}),
10
+ ...(ctx.oauthClientName !== undefined ? { oauthClientName: ctx.oauthClientName } : {}),
11
+ ...(ctx.requestScope ? { requestScope: ctx.requestScope } : {}),
12
+ ...(ctx.signal ? { signal: ctx.signal } : {}),
13
+ ...(ctx.timeoutMs !== undefined ? { timeoutMs: ctx.timeoutMs } : {}),
14
+ ...(ctx.defer ? { defer: ctx.defer } : {}),
15
+ credential: { getAll: async () => values, get: async (field = "value") => values[field] ?? null },
16
+ }, undefined);
17
+ const parent = viewLease(ctx);
18
+ const lease = callFromContext(operation, "read", {
19
+ anonymous: true,
20
+ charge: async () => { },
21
+ record: () => { },
22
+ ...(parent ? { parent } : {}),
23
+ });
24
+ return contextView(lease, operation);
25
+ }
26
+ export async function credentialProbe(ctx, values, work) {
27
+ const view = credentialProbeContext(ctx, values);
28
+ try {
29
+ return await work(view);
30
+ }
31
+ finally {
32
+ viewLease(view).close();
33
+ }
34
+ }
@@ -0,0 +1,40 @@
1
+ // Private execution dispatch. Public shells call their own program directly;
2
+ // only consumers select by method identity, so wrappers may call saved shells.
3
+ import { Effect } from "effect";
4
+ const programs = new WeakMap();
5
+ export function provideExecutorProgram(target, run, logs) {
6
+ programs.set(target, { method: target.execute, run, ...(logs ? { logs } : {}) });
7
+ }
8
+ /** Queued ownership crosses a Promise so workerd resumes in the waiting request. */
9
+ export function awaitExecutorLease(acquire) {
10
+ return Effect.suspend(() => {
11
+ let pending;
12
+ return Effect.tryPromise({ try: (signal) => (pending = acquire(signal)), catch: (error) => error }).pipe(Effect.onInterrupt(() => Effect.sync(() => {
13
+ pending
14
+ ?.then((lease) => lease.release(), () => { })
15
+ .catch(() => { });
16
+ })));
17
+ });
18
+ }
19
+ export function executorProgram(target, code, providers, observe) {
20
+ return Effect.suspend(() => {
21
+ const native = programs.get(target);
22
+ return native?.method === target.execute
23
+ ? native.run(code, providers).pipe(Effect.tap((outcome) => Effect.sync(() => observe?.result(outcome))), Effect.tapError((error) => Effect.sync(() => observe?.error(error))), Effect.onInterrupt(() => Effect.sync(() => {
24
+ if (native.logs)
25
+ observe?.interrupted(native.logs());
26
+ })))
27
+ : Effect.tryPromise({
28
+ // Observe a real Promise leaf even if its waiting fiber has lost a
29
+ // terminal race. Its synchronous log prefix still belongs to the run.
30
+ try: () => target.execute(code, providers).then((outcome) => {
31
+ observe?.result(outcome);
32
+ return outcome;
33
+ }, (error) => {
34
+ observe?.error(error);
35
+ throw error;
36
+ }),
37
+ catch: (error) => error,
38
+ });
39
+ }).pipe(Effect.catchDefect((error) => Effect.fail(error)));
40
+ }