@zackbart/connecta 0.34.1 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/CHANGELOG.md +363 -0
  2. package/README.md +62 -106
  3. package/SECURITY.md +3 -2
  4. package/bin/connecta.mjs +41 -16
  5. package/bin/version.mjs +1 -1
  6. package/dist/access-tokens.d.ts +2 -1
  7. package/dist/access-tokens.js +66 -30
  8. package/dist/activity.d.ts +1 -1
  9. package/dist/activity.js +2 -0
  10. package/dist/agent-config.d.ts +23 -0
  11. package/dist/agent-config.js +59 -0
  12. package/dist/agent-description.js +16 -0
  13. package/dist/agent-identity.js +4 -4
  14. package/dist/agent-observation.js +39 -0
  15. package/dist/auth/clerk-sdk/client.d.ts +2 -0
  16. package/dist/auth/clerk-sdk/generated.js +554 -563
  17. package/dist/auth/clerk-transport.js +70 -3
  18. package/dist/auth/clerk.d.ts +13 -0
  19. package/dist/auth/clerk.js +653 -246
  20. package/dist/auth/cloudflare-access.js +46 -42
  21. package/dist/auth/downstream-client-metadata.js +2 -2
  22. package/dist/auth/downstream-oauth.js +2051 -1160
  23. package/dist/auth/downstream-revocation.js +88 -88
  24. package/dist/auth/native-call.js +20 -0
  25. package/dist/auth/native.js +184 -0
  26. package/dist/auth/oauth-start-reset.js +11 -5
  27. package/dist/auth/oauth-token-response.js +121 -102
  28. package/dist/auth/oauth-v2-migration.js +97 -78
  29. package/dist/auth/renewable-grant.js +10 -0
  30. package/dist/auth/static-oauth.js +663 -271
  31. package/dist/auth/vercel-agent.js +266 -0
  32. package/dist/auth-admission.js +204 -0
  33. package/dist/auth-elicitation.js +350 -241
  34. package/dist/authorization-handoff.js +164 -90
  35. package/dist/call-admission-context.js +3 -10
  36. package/dist/call-admission.js +2 -0
  37. package/dist/call-classification.js +9 -0
  38. package/dist/call-recovery.js +32 -13
  39. package/dist/canonical-json.js +8 -0
  40. package/dist/catalog-cache.js +369 -213
  41. package/dist/catalog-service.js +659 -530
  42. package/dist/catalog.js +5 -1
  43. package/dist/concurrency.js +0 -25
  44. package/dist/config-defaults.d.ts +1 -0
  45. package/dist/config-defaults.js +1 -0
  46. package/dist/config-schema.d.ts +3 -1
  47. package/dist/config-schema.js +13 -3
  48. package/dist/config.d.ts +40 -6
  49. package/dist/config.js +40 -26
  50. package/dist/connector-caller.d.ts +4 -0
  51. package/dist/connector-caller.js +17 -4
  52. package/dist/connectors/api-connector.d.ts +12 -7
  53. package/dist/connectors/api-connector.js +142 -56
  54. package/dist/connectors/guarded-fetch.d.ts +51 -17
  55. package/dist/connectors/guarded-fetch.js +215 -121
  56. package/dist/connectors/negotiation-cache.js +20 -10
  57. package/dist/connectors/remote-mcp.d.ts +10 -30
  58. package/dist/connectors/remote-mcp.js +955 -563
  59. package/dist/d1.js +10 -243
  60. package/dist/derived-context.js +5 -0
  61. package/dist/describe-config.d.ts +3 -1
  62. package/dist/describe-config.js +2 -0
  63. package/dist/downstream-input.js +347 -260
  64. package/dist/errors.d.ts +87 -6
  65. package/dist/errors.js +114 -4
  66. package/dist/execute.js +87 -50
  67. package/dist/executor-admission.js +3 -0
  68. package/dist/executors/quickjs.js +163 -112
  69. package/dist/guarded-transport.js +50 -0
  70. package/dist/guest-runtime.js +1 -1
  71. package/dist/http/client.js +439 -0
  72. package/dist/http/errors.js +558 -0
  73. package/dist/http/fields.js +49 -0
  74. package/dist/http/hatch-paging.js +318 -0
  75. package/dist/http/hatch.js +1279 -0
  76. package/dist/http/json-schema.js +267 -0
  77. package/dist/http/node-transport.js +241 -0
  78. package/dist/http/oauth.js +162 -0
  79. package/dist/http/paging.js +228 -0
  80. package/dist/http/provider.js +221 -0
  81. package/dist/http/safety.js +82 -0
  82. package/dist/http/services.js +79 -0
  83. package/dist/http/tools.js +383 -0
  84. package/dist/http/vendor-index.js +138 -0
  85. package/dist/http/vendor.js +448 -0
  86. package/dist/http/write-request.js +66 -0
  87. package/dist/http-policy.d.ts +11 -0
  88. package/dist/http-policy.js +45 -0
  89. package/dist/inbound-credential.js +1 -1
  90. package/dist/index.d.ts +2 -2
  91. package/dist/index.js +4 -0
  92. package/dist/invocation-auth.js +30 -19
  93. package/dist/invocation.js +218 -85
  94. package/dist/mcp-result.js +0 -4
  95. package/dist/membership.d.ts +4 -0
  96. package/dist/meta-output.js +1 -1
  97. package/dist/meta-tools.js +531 -406
  98. package/dist/native-recovery.js +52 -0
  99. package/dist/native-tools.js +382 -0
  100. package/dist/node.d.ts +4 -3
  101. package/dist/node.js +45 -8
  102. package/dist/oauth-handoff.js +177 -104
  103. package/dist/oauth-partition.js +6 -20
  104. package/dist/oauth-sealing.js +6 -7
  105. package/dist/operation-vocabulary.js +101 -0
  106. package/dist/operator-record.d.ts +2 -2
  107. package/dist/operator-record.js +17 -4
  108. package/dist/operator-ui/agents.d.ts +5 -4
  109. package/dist/operator-ui/agents.js +17 -7
  110. package/dist/operator-ui/config-summary.js +5 -4
  111. package/dist/operator-ui/connection-map.js +7 -5
  112. package/dist/operator-ui/contract.d.ts +7 -3
  113. package/dist/operator-ui/endpoints.js +4 -13
  114. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  115. package/dist/operator-ui/fix-prompts.js +0 -8
  116. package/dist/operator-ui/generated.js +3 -3
  117. package/dist/operator-ui/model.d.ts +2 -3
  118. package/dist/operator-ui/overview.js +5 -2
  119. package/dist/operator-ui/setup-commands.js +0 -4
  120. package/dist/operator-ui/view.d.ts +2 -25
  121. package/dist/operator-ui/view.js +2 -76
  122. package/dist/program-writes.js +47 -26
  123. package/dist/provider-call-facts.d.ts +115 -0
  124. package/dist/provider-call-facts.js +182 -0
  125. package/dist/provider-call.d.ts +112 -0
  126. package/dist/provider-call.js +271 -0
  127. package/dist/provider.d.ts +65 -31
  128. package/dist/provider.js +116 -39
  129. package/dist/providers/_shared/google/hatch.js +91 -0
  130. package/dist/providers/_shared/google/kit.js +537 -0
  131. package/dist/providers/_shared/google/result-size.js +15 -2
  132. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  133. package/dist/providers/_shared/google/service-account.js +8 -4
  134. package/dist/providers/_shared/google/workspace.d.ts +6 -210
  135. package/dist/providers/_shared/google/workspace.js +6 -425
  136. package/dist/providers/_shared/rest/compact-index.js +86 -0
  137. package/dist/providers/_shared/rest/dispatch.js +3 -23
  138. package/dist/providers/_shared/rest/kit.js +546 -0
  139. package/dist/providers/_shared/rest/operation-index.js +230 -14
  140. package/dist/providers/_shared/rest/response-media.js +11 -0
  141. package/dist/providers/_shared/rest/tools.js +101 -78
  142. package/dist/providers/_shared/rest/value-safety.js +353 -195
  143. package/dist/providers/_shared/sensitive-fields.js +27 -0
  144. package/dist/providers/breeze/api.js +584 -0
  145. package/dist/providers/breeze/index.d.ts +1 -3
  146. package/dist/providers/breeze/index.js +67 -1420
  147. package/dist/providers/breeze/openapi.generated.js +60 -0
  148. package/dist/providers/breeze/skill.generated.js +2 -6
  149. package/dist/providers/breeze/tools.js +696 -0
  150. package/dist/providers/ccb/api.js +496 -0
  151. package/dist/providers/ccb/index.d.ts +15 -37
  152. package/dist/providers/ccb/index.js +77 -1702
  153. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  154. package/dist/providers/ccb/lib/constants.js +74 -0
  155. package/dist/providers/ccb/lib/guide.js +9 -0
  156. package/dist/providers/ccb/lib/verdicts.js +387 -0
  157. package/dist/providers/ccb/openapi.generated.js +397 -0
  158. package/dist/providers/ccb/safety.js +295 -0
  159. package/dist/providers/ccb/skill.generated.js +2 -6
  160. package/dist/providers/ccb/tools.js +853 -0
  161. package/dist/providers/cloudflare/api.js +1066 -0
  162. package/dist/providers/cloudflare/index.d.ts +5 -22
  163. package/dist/providers/cloudflare/index.js +79 -197
  164. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  165. package/dist/providers/cloudflare/lib/config.js +2 -0
  166. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  167. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  168. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  169. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  170. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  171. package/dist/providers/cloudflare/openapi.generated.js +4 -3
  172. package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
  173. package/dist/providers/cloudflare/skill.generated.js +2 -10
  174. package/dist/providers/cloudflare/tools.js +360 -0
  175. package/dist/providers/docs/api.js +51 -0
  176. package/dist/providers/docs/index.d.ts +1 -12
  177. package/dist/providers/docs/index.js +53 -1165
  178. package/dist/providers/docs/lib/constants.d.ts +18 -0
  179. package/dist/providers/docs/lib/constants.js +18 -0
  180. package/dist/providers/docs/lib/discovery.js +26 -0
  181. package/dist/providers/docs/lib/requests.js +48 -0
  182. package/dist/providers/docs/lib/schemas.js +168 -0
  183. package/dist/providers/docs/openapi.generated.js +16 -0
  184. package/dist/providers/docs/safety.js +54 -0
  185. package/dist/providers/docs/skill.generated.js +2 -6
  186. package/dist/providers/docs/tools.js +802 -0
  187. package/dist/providers/drive/api.js +177 -0
  188. package/dist/providers/drive/index.d.ts +1 -12
  189. package/dist/providers/drive/index.js +38 -1448
  190. package/dist/providers/drive/lib/constants.d.ts +6 -0
  191. package/dist/providers/drive/lib/constants.js +6 -0
  192. package/dist/providers/drive/lib/contracts.js +532 -0
  193. package/dist/providers/drive/lib/hatch.js +197 -0
  194. package/dist/providers/drive/openapi.generated.js +77 -0
  195. package/dist/providers/drive/safety.js +90 -0
  196. package/dist/providers/drive/skill.generated.js +2 -6
  197. package/dist/providers/drive/tools.js +1290 -0
  198. package/dist/providers/forms/api.js +71 -0
  199. package/dist/providers/forms/index.d.ts +1 -12
  200. package/dist/providers/forms/index.js +49 -1145
  201. package/dist/providers/forms/lib/constants.d.ts +14 -0
  202. package/dist/providers/forms/lib/constants.js +19 -0
  203. package/dist/providers/forms/lib/hatch.js +72 -0
  204. package/dist/providers/forms/openapi.generated.js +23 -0
  205. package/dist/providers/forms/safety.js +34 -0
  206. package/dist/providers/forms/skill.generated.js +2 -8
  207. package/dist/providers/forms/tools.js +1024 -0
  208. package/dist/providers/github/api.js +150 -0
  209. package/dist/providers/github/index.d.ts +4 -5
  210. package/dist/providers/github/index.js +30 -87
  211. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  212. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  213. package/dist/providers/github/lib/discovery.js +132 -0
  214. package/dist/providers/github/lib/operations.js +58 -0
  215. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  216. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  217. package/dist/providers/github/openapi.generated.js +1216 -0
  218. package/dist/providers/github/safety.js +216 -0
  219. package/dist/providers/github/skill.generated.js +2 -5
  220. package/dist/providers/github/tools.js +506 -0
  221. package/dist/providers/gmail/api.js +114 -0
  222. package/dist/providers/gmail/index.d.ts +1 -12
  223. package/dist/providers/gmail/index.js +73 -1621
  224. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  225. package/dist/providers/gmail/lib/constants.js +16 -0
  226. package/dist/providers/gmail/lib/index.js +173 -0
  227. package/dist/providers/gmail/lib/schemas.js +176 -0
  228. package/dist/providers/gmail/lib/threading.js +120 -0
  229. package/dist/providers/gmail/openapi.generated.js +92 -0
  230. package/dist/providers/gmail/safety.js +21 -0
  231. package/dist/providers/gmail/skill.generated.js +2 -6
  232. package/dist/providers/gmail/tools.js +1435 -0
  233. package/dist/providers/overflow/api.js +1008 -0
  234. package/dist/providers/overflow/index.d.ts +1 -17
  235. package/dist/providers/overflow/index.js +60 -1488
  236. package/dist/providers/overflow/skill.generated.js +2 -5
  237. package/dist/providers/overflow/tools.js +873 -0
  238. package/dist/providers/planning-center/api.js +467 -0
  239. package/dist/providers/planning-center/index.d.ts +4 -35
  240. package/dist/providers/planning-center/index.js +69 -2445
  241. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  242. package/dist/providers/planning-center/lib/constants.js +83 -0
  243. package/dist/providers/planning-center/lib/discovery.js +40 -0
  244. package/dist/providers/planning-center/lib/guide.js +39 -0
  245. package/dist/providers/planning-center/lib/json-api.js +83 -0
  246. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  247. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  248. package/dist/providers/planning-center/safety.js +188 -0
  249. package/dist/providers/planning-center/skill.generated.js +2 -27
  250. package/dist/providers/planning-center/tools.js +1010 -0
  251. package/dist/providers/sheets/api.js +133 -0
  252. package/dist/providers/sheets/index.d.ts +4 -16
  253. package/dist/providers/sheets/index.js +61 -1172
  254. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  255. package/dist/providers/sheets/lib/constants.js +14 -0
  256. package/dist/providers/sheets/lib/hatch.js +163 -0
  257. package/dist/providers/sheets/lib/requests.js +105 -0
  258. package/dist/providers/sheets/lib/schemas.js +138 -0
  259. package/dist/providers/sheets/openapi.generated.js +30 -0
  260. package/dist/providers/sheets/safety.js +27 -0
  261. package/dist/providers/sheets/skill.generated.js +2 -7
  262. package/dist/providers/sheets/tools.js +734 -0
  263. package/dist/providers/slides/api.js +147 -0
  264. package/dist/providers/slides/index.d.ts +2 -10
  265. package/dist/providers/slides/index.js +48 -2555
  266. package/dist/providers/slides/lib/constants.d.ts +11 -0
  267. package/dist/providers/slides/lib/constants.js +11 -0
  268. package/dist/providers/slides/lib/requests.js +60 -0
  269. package/dist/providers/slides/lib/schemas.js +565 -0
  270. package/dist/providers/slides/openapi.generated.js +18 -0
  271. package/dist/providers/slides/skill.generated.js +2 -6
  272. package/dist/providers/slides/tools.js +1968 -0
  273. package/dist/providers/stripe/api.js +401 -0
  274. package/dist/providers/stripe/index.d.ts +5 -27
  275. package/dist/providers/stripe/index.js +74 -210
  276. package/dist/providers/stripe/lib/config.d.ts +4 -0
  277. package/dist/providers/stripe/lib/config.js +2 -0
  278. package/dist/providers/stripe/openapi.generated.js +4 -3
  279. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  280. package/dist/providers/stripe/skill.generated.js +2 -11
  281. package/dist/providers/stripe/tools.js +77 -0
  282. package/dist/providers/tithely/api.js +531 -0
  283. package/dist/providers/tithely/index.d.ts +17 -0
  284. package/dist/providers/tithely/index.js +86 -965
  285. package/dist/providers/tithely/skill.generated.js +2 -5
  286. package/dist/providers/tithely/tools.js +426 -0
  287. package/dist/providers/vercel/api.js +551 -0
  288. package/dist/providers/vercel/index.d.ts +9 -25
  289. package/dist/providers/vercel/index.js +66 -260
  290. package/dist/providers/vercel/lib/config.d.ts +2 -0
  291. package/dist/providers/vercel/lib/config.js +2 -0
  292. package/dist/providers/vercel/lib/index.js +117 -0
  293. package/dist/providers/vercel/lib/logs.js +100 -0
  294. package/dist/providers/vercel/lib/pin.js +270 -0
  295. package/dist/providers/vercel/openapi.generated.js +10 -5
  296. package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
  297. package/dist/providers/vercel/skill.generated.js +2 -7
  298. package/dist/providers/vercel/tools.js +642 -0
  299. package/dist/redaction-identity.js +47 -0
  300. package/dist/redaction-marker.js +125 -0
  301. package/dist/registry.d.ts +21 -15
  302. package/dist/registry.js +409 -376
  303. package/dist/routes/access-tokens.js +1 -1
  304. package/dist/routes/actor-labels.js +1 -1
  305. package/dist/routes/connect.js +1 -1
  306. package/dist/routes/dispatch.js +103 -0
  307. package/dist/routes/mcp.js +170 -79
  308. package/dist/routes/oauth.js +3 -1
  309. package/dist/routes/operator.js +2 -2
  310. package/dist/routes/shared.d.ts +5 -4
  311. package/dist/routes/shared.js +244 -177
  312. package/dist/routes/skills.js +10 -8
  313. package/dist/routes/ui-config.js +27 -3
  314. package/dist/routes/ui-data.js +21 -20
  315. package/dist/routes/ui.js +1 -1
  316. package/dist/runtime/call-admission.js +0 -26
  317. package/dist/runtime/call-entry.js +30 -0
  318. package/dist/runtime/call.js +556 -0
  319. package/dist/runtime/connector-scope.js +7 -0
  320. package/dist/runtime/credential-probe.js +34 -0
  321. package/dist/runtime/executor.js +40 -0
  322. package/dist/runtime/native-storage.js +63 -0
  323. package/dist/runtime/registry.js +27 -0
  324. package/dist/runtime/request-scope.js +72 -0
  325. package/dist/runtime/run.js +15 -7
  326. package/dist/runtime/shared-read.js +34 -5
  327. package/dist/runtime/storage.js +34 -21
  328. package/dist/sent-secrets.d.ts +194 -37
  329. package/dist/sent-secrets.js +1743 -340
  330. package/dist/server.js +5 -56
  331. package/dist/skills.js +322 -222
  332. package/dist/sqlite.js +15 -14
  333. package/dist/storage/d1-copy.js +255 -0
  334. package/dist/storage/d1-driver.js +15 -0
  335. package/dist/storage/keys.js +28 -0
  336. package/dist/storage/sql-driver.js +88 -0
  337. package/dist/storage/sql-native.js +544 -0
  338. package/dist/storage/sql-schema.d.ts +6 -0
  339. package/dist/storage/sql-schema.js +15 -0
  340. package/dist/storage/sql.d.ts +14 -20
  341. package/dist/storage/sql.js +29 -535
  342. package/dist/timeout.js +0 -26
  343. package/dist/tool-safety.js +20 -10
  344. package/dist/types.d.ts +7 -109
  345. package/dist/upward.js +3 -0
  346. package/dist/usage-guide.js +3 -1
  347. package/dist/validate.d.ts +4 -2
  348. package/dist/validate.js +86 -9
  349. package/dist/version.d.ts +1 -1
  350. package/dist/version.js +1 -1
  351. package/dist/worker.js +312 -292
  352. package/dist/workspace-subject.js +5 -1
  353. package/dist/write-outcome.js +454 -34
  354. package/documentation/README.md +27 -7
  355. package/documentation/architecture.md +2547 -226
  356. package/documentation/auth.md +821 -98
  357. package/documentation/code-mode.md +49 -16
  358. package/documentation/deploying.md +164 -20
  359. package/documentation/hosted-mcp-migration.md +460 -0
  360. package/documentation/integrating.md +129 -144
  361. package/documentation/meta-tools.md +409 -32
  362. package/documentation/operating.md +27 -3
  363. package/documentation/operator-tests.md +3 -0
  364. package/documentation/operator-ui.md +68 -45
  365. package/documentation/provider-auth-migration.md +16 -63
  366. package/documentation/provider-migration-0.29.md +10 -5
  367. package/documentation/provider-migration-0.35.md +975 -0
  368. package/documentation/providers.md +965 -0
  369. package/examples/worker/AGENTS.md +23 -9
  370. package/examples/worker/README.md +254 -135
  371. package/examples/worker/alchemy.run.ts +116 -0
  372. package/examples/worker/gitignore +10 -0
  373. package/examples/worker/src/connecta.config.ts +23 -21
  374. package/examples/worker/wrangler.jsonc +14 -5
  375. package/guides/connecting-agents.md +157 -0
  376. package/guides/how-it-works.md +156 -0
  377. package/guides/safety-and-trust.md +153 -0
  378. package/package.json +27 -46
  379. package/templates/node/.env.example +3 -0
  380. package/templates/node/README.md +22 -2
  381. package/templates/node/docker-compose.yml +1 -0
  382. package/templates/node/package.json +3 -2
  383. package/templates/node/src/connecta.config.ts +8 -0
  384. package/dist/catalog-drift.d.ts +0 -138
  385. package/dist/catalog-drift.js +0 -578
  386. package/dist/providers/_shared/request-token.js +0 -83
  387. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  388. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  389. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  390. package/dist/providers/basecamp/index.d.ts +0 -45
  391. package/dist/providers/basecamp/index.js +0 -997
  392. package/dist/providers/basecamp/skill.generated.js +0 -9
  393. package/dist/providers/cloudflare/rest.d.ts +0 -37
  394. package/dist/providers/cloudflare/rest.js +0 -1097
  395. package/dist/providers/github/hosted.js +0 -218
  396. package/dist/providers/github/rest.js +0 -321
  397. package/dist/providers/infisical/index.d.ts +0 -7
  398. package/dist/providers/infisical/index.js +0 -713
  399. package/dist/providers/infisical/skill.generated.js +0 -8
  400. package/dist/providers/intercom/index.d.ts +0 -24
  401. package/dist/providers/intercom/index.js +0 -121
  402. package/dist/providers/intercom/skill.generated.js +0 -8
  403. package/dist/providers/linear/index.d.ts +0 -55
  404. package/dist/providers/linear/index.js +0 -537
  405. package/dist/providers/linear/skill.generated.js +0 -8
  406. package/dist/providers/mixpanel/index.d.ts +0 -59
  407. package/dist/providers/mixpanel/index.js +0 -472
  408. package/dist/providers/mixpanel/operations.js +0 -20
  409. package/dist/providers/mixpanel/rest.js +0 -603
  410. package/dist/providers/mixpanel/skill.generated.js +0 -10
  411. package/dist/providers/mixpanel/value-safety.js +0 -16
  412. package/dist/providers/notion/index.d.ts +0 -67
  413. package/dist/providers/notion/index.js +0 -368
  414. package/dist/providers/notion/openapi.generated.js +0 -75
  415. package/dist/providers/notion/rest.d.ts +0 -24
  416. package/dist/providers/notion/rest.js +0 -1226
  417. package/dist/providers/notion/skill.generated.js +0 -11
  418. package/dist/providers/notion/value-safety.js +0 -56
  419. package/dist/providers/revenuecat/index.d.ts +0 -51
  420. package/dist/providers/revenuecat/index.js +0 -697
  421. package/dist/providers/revenuecat/skill.generated.js +0 -11
  422. package/dist/providers/stripe/rest.d.ts +0 -14
  423. package/dist/providers/stripe/rest.js +0 -402
  424. package/dist/providers/vercel/rest.d.ts +0 -20
  425. package/dist/providers/vercel/rest.js +0 -1020
  426. package/dist/providers/wispr-flow/index.d.ts +0 -14
  427. package/dist/providers/wispr-flow/index.js +0 -117
  428. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  429. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
package/dist/errors.d.ts CHANGED
@@ -13,7 +13,7 @@ export type ConnectorCallErrorCode = "timeout" | "auth_required" | "downstream_o
13
13
  * re-authorizing, or repairing arguments, and a program looping over ids can
14
14
  * continue past it where `connector_call_failed` would abort. Map a status
15
15
  * here only where the provider distinguishes absence from a permission gap —
16
- * where it does not (Notion's `object_not_found` covers both), the honest
16
+ * where one status covers both, the honest
17
17
  * code stays `connector_call_failed` or `auth_required` with a message that
18
18
  * states the ambiguity (H11).
19
19
  */
@@ -89,7 +89,11 @@ export declare function echoedCallArgs(args: unknown, schema?: JsonSchema): {
89
89
  };
90
90
  /** Optional transport diagnostics; never a URL path or raw runtime message. */
91
91
  interface UnavailableDetails {
92
- /** Guest program diagnostics; returned to the agent, never operator records. */
92
+ /**
93
+ * An error class label: a guest program's, or the class of the caller's own
94
+ * abort reason behind a direct write whose outcome is unknown. Returned to
95
+ * the agent, never operator records.
96
+ */
93
97
  name?: string;
94
98
  line?: number | null;
95
99
  hint?: string;
@@ -139,6 +143,8 @@ export declare class WithheldTextError extends Error {
139
143
  }
140
144
  /** Agent-visible recovery class for downstream credential failures. */
141
145
  export type AuthRecoveryMode = "oauth" | "operator_config" | "unavailable";
146
+ /** Runtime membership in the closed connector taxonomy, checked against its exhaustive table. */
147
+ export declare function isConnectorCallErrorCode(value: unknown): value is ConnectorCallErrorCode;
142
148
  /**
143
149
  * Throw from `Connector.callTool` (or anything beneath it) to classify a
144
150
  * failure exactly. Untyped errors are non-retryable unless a runtime errno
@@ -166,13 +172,24 @@ export declare class ConnectorCallError extends Error {
166
172
  /** Bounded schema findings for `invalid_args`; never submitted values. */
167
173
  readonly validation: ArgumentValidationDetails | undefined;
168
174
  readonly repair: ArgumentRepairDetails | undefined;
169
- /** Sanitized transport diagnostics for `unavailable` only. */
175
+ /**
176
+ * Sanitized transport diagnostics, for `unavailable` and for a write whose
177
+ * outcome is unknown (a timeout's errno, an abort's class).
178
+ */
170
179
  readonly details: UnavailableDetails | undefined;
171
180
  /**
172
181
  * For `conflict` only: where each thing the write touched stands now, e.g.
173
182
  * `{ revision: 12, view: 7 }`. Bounded to 20 whole-number entries.
174
183
  */
175
184
  readonly current: Readonly<Record<string, number>> | undefined;
185
+ /**
186
+ * `"unknown"` when the write this call sent may have taken effect, whatever
187
+ * `code` says: an authorization verdict reached after the downstream already
188
+ * had the write (a 401, unless the vendor's reviewed evidence says it
189
+ * authenticates first, or a renewal that failed after one) is still an
190
+ * unknown outcome (INV-9). Undefined when the code alone tells the outcome.
191
+ */
192
+ readonly writeOutcome: "unknown" | undefined;
176
193
  constructor(code: ConnectorCallErrorCode, message: string, opts?: {
177
194
  retryable?: boolean;
178
195
  retryAfterMs?: number;
@@ -181,6 +198,7 @@ export declare class ConnectorCallError extends Error {
181
198
  repair?: ArgumentRepairDetails;
182
199
  details?: UnavailableDetails;
183
200
  current?: Readonly<Record<string, number>>;
201
+ writeOutcome?: "unknown";
184
202
  });
185
203
  }
186
204
  /** Secret-free payload returned by authorize_connector and auth failures. */
@@ -218,10 +236,15 @@ export interface CallErrorDetails extends Partial<AuthorizationHandoff> {
218
236
  connector?: string;
219
237
  /** Canonical downstream address the agent may retry after recovery. */
220
238
  operation?: string;
221
- /** Which safe recovery path `authorize_connector` will return. */
239
+ /** Safe recovery path for this authentication failure. */
222
240
  recovery?: AuthRecoveryMode;
223
241
  /** An auth failure followed a write's downstream send. Reconcile before retry. */
224
242
  reconciliationRequired?: true;
243
+ /**
244
+ * The write this call sent may have taken effect, whatever `code` says (see
245
+ * {@link ConnectorCallError.writeOutcome}). Check its target before repeating it.
246
+ */
247
+ writeOutcome?: "unknown";
225
248
  /** The single model-facing entry point for every credential class. */
226
249
  nextAction?: {
227
250
  tool: "authorize_connector";
@@ -282,7 +305,10 @@ export interface CallErrorDetails extends Partial<AuthorizationHandoff> {
282
305
  args?: unknown;
283
306
  argsOmitted?: true;
284
307
  argsRedacted?: true;
285
- /** Facts the connector recorded before dispatch, such as a generated `idempotencyKey`. */
308
+ /**
309
+ * Facts the connector recorded before dispatch, such as a generated
310
+ * `idempotencyKey`: diagnostics. `retry` says when reusing the key is safe.
311
+ */
286
312
  recovery?: Readonly<Record<string, string>>;
287
313
  };
288
314
  /** Explicit retry guidance; recovery never retries or mutates by itself. */
@@ -290,7 +316,62 @@ export interface CallErrorDetails extends Partial<AuthorizationHandoff> {
290
316
  }
291
317
  /** Retryability of connecta framing depends only on its code. */
292
318
  export declare function framingError(code: ClassificationCode, message: string): CallErrorDetails;
293
- /** Typed connector verdicts and runtime facts only. Prose never changes a verdict. */
319
+ /**
320
+ * Attach advice to send the call again (a rate limit's " Back off before
321
+ * retrying.", a token error's ", then retry authorization") to `error` as a
322
+ * segment of its own: `error.message` never contains it. It holds for a read
323
+ * and a known refusal, so output composes it ({@link withResendAdvice}) only
324
+ * there, after the outcome is decided. No redaction or rewording of the
325
+ * message can then hide it from removal on a write whose outcome is unknown
326
+ * (INV-9). A segment that opens a sentence (" Wait…") follows the message;
327
+ * any other is a clause, placed before the message's closing period.
328
+ */
329
+ export declare function resendAdvice<T extends object>(error: T, advice: string): T;
330
+ /** The resend advice attached to `from`, if any. */
331
+ export declare function resendAdviceOf(from: unknown): string | undefined;
332
+ export interface KeyResendAdvice {
333
+ /** The key the advice names, as it was sent. */
334
+ key: string;
335
+ advice: string;
336
+ }
337
+ /**
338
+ * Attach advice that reusing `key` with the same arguments cannot repeat the
339
+ * write, a segment of its own like {@link resendAdvice}. It holds only where
340
+ * that key protects the whole logical call (`keyProtectsCall`): one
341
+ * boundary entered, one write sent, carrying `key`. Attach it only once the
342
+ * call's ledger shows a dispatched request carrying `key`: a key generated
343
+ * but never sent protects nothing. Two places compose it. The invocation
344
+ * sees the whole call and composes it for a served call once
345
+ * `keyProtectsCall` holds. {@link classifyCallError} composes it for a
346
+ * dispatched direct call, which has no invocation: only the one boundary that
347
+ * sent the keyed request attaches it, and any boundary above that one
348
+ * finalizes the write as unknown, which drops it. Either way the key stays in
349
+ * the message as a diagnostic.
350
+ */
351
+ export declare function keyResendAdvice<T extends object>(error: T, key: string, advice: string): T;
352
+ /** The key-reuse advice attached to `from`, if any. */
353
+ export declare function keyResendAdviceOf(from: unknown): KeyResendAdvice | undefined;
354
+ /**
355
+ * Keep `from`'s resend advice, key-reuse advice included, on `to`, a copy or
356
+ * rewording of it (redaction, a provider's recovery words). A write already
357
+ * marked unknown never takes it.
358
+ */
359
+ export declare function carryResendAdvice(from: unknown, to: unknown): void;
360
+ /** `message` with resend `advice` composed in. Only output calls this. */
361
+ export declare function withResendAdvice(message: string, advice: string | undefined): string;
362
+ /**
363
+ * Typed connector verdicts and runtime facts only. Prose never changes a
364
+ * verdict. The message carries the error's resend advice unless its write's
365
+ * outcome is unknown. This is a direct caller's view, outside any logical
366
+ * call: key-reuse advice is here only because the one boundary that sent the
367
+ * keyed request attached it to its own failure, and any boundary above it
368
+ * finalizes the write as unknown. An invocation composes advice itself.
369
+ */
294
370
  export declare function classifyCallError(err: unknown, fallbackCode?: ClassificationCode): CallErrorDetails;
371
+ /**
372
+ * {@link classifyCallError} without the resend advice, for a caller that
373
+ * decides the outcome first and composes the advice only where it holds.
374
+ */
375
+ export declare function classifyWithoutAdvice(err: unknown, fallbackCode?: ClassificationCode): CallErrorDetails;
295
376
  export declare function msg(err: unknown): string;
296
377
  export {};
package/dist/errors.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // Typed failure contract for connector tool calls. Web-API only — no node:
2
2
  // imports here.
3
3
  import { redactCallArguments } from "./argument-redaction.js";
4
+ import { followRedactedCopies } from "./redaction-identity.js";
4
5
  const CLASSIFICATION_CODE_TABLE = {
5
6
  timeout: true,
6
7
  auth_required: true,
@@ -192,6 +193,8 @@ export const NETWORK_ERROR_CODES = new Set([
192
193
  function networkCode(value) {
193
194
  return typeof value === "string" && value.length <= 32 && NETWORK_ERROR_CODES.has(value) ? value : undefined;
194
195
  }
196
+ /** An error class label, as `errorLabel` reports one. */
197
+ const ERROR_CLASS = /^[A-Z][A-Za-z]{0,63}$/;
195
198
  function sanitizedUnavailableDetails(details) {
196
199
  if (!details)
197
200
  return undefined;
@@ -207,7 +210,10 @@ function sanitizedUnavailableDetails(details) {
207
210
  }
208
211
  }
209
212
  const code = networkCode(details.code);
210
- return host || code ? { ...(host ? { host } : {}), ...(code ? { code } : {}) } : undefined;
213
+ const name = typeof details.name === "string" && ERROR_CLASS.test(details.name) ? details.name : undefined;
214
+ return host || code || name
215
+ ? { ...(name ? { name } : {}), ...(host ? { host } : {}), ...(code ? { code } : {}) }
216
+ : undefined;
211
217
  }
212
218
  /** Runtime fields only: provider prose cannot supply an errno or a deadline. */
213
219
  export function networkErrorCode(error) {
@@ -282,6 +288,10 @@ const RETRYABLE_BY_CODE = {
282
288
  input_required_limit: false,
283
289
  connector_call_failed: false,
284
290
  };
291
+ /** Runtime membership in the closed connector taxonomy, checked against its exhaustive table. */
292
+ export function isConnectorCallErrorCode(value) {
293
+ return typeof value === "string" && Object.hasOwn(RETRYABLE_BY_CODE, value);
294
+ }
285
295
  /** Entries a conflict's `current` map may carry. */
286
296
  const MAX_CURRENT_ENTRIES = 20;
287
297
  const MAX_CURRENT_KEY_CHARS = 128;
@@ -337,23 +347,36 @@ export class ConnectorCallError extends Error {
337
347
  /** Bounded schema findings for `invalid_args`; never submitted values. */
338
348
  validation;
339
349
  repair;
340
- /** Sanitized transport diagnostics for `unavailable` only. */
350
+ /**
351
+ * Sanitized transport diagnostics, for `unavailable` and for a write whose
352
+ * outcome is unknown (a timeout's errno, an abort's class).
353
+ */
341
354
  details;
342
355
  /**
343
356
  * For `conflict` only: where each thing the write touched stands now, e.g.
344
357
  * `{ revision: 12, view: 7 }`. Bounded to 20 whole-number entries.
345
358
  */
346
359
  current;
360
+ /**
361
+ * `"unknown"` when the write this call sent may have taken effect, whatever
362
+ * `code` says: an authorization verdict reached after the downstream already
363
+ * had the write (a 401, unless the vendor's reviewed evidence says it
364
+ * authenticates first, or a renewal that failed after one) is still an
365
+ * unknown outcome (INV-9). Undefined when the code alone tells the outcome.
366
+ */
367
+ writeOutcome;
347
368
  constructor(code, message, opts = {}) {
348
369
  super(message, opts.cause !== undefined ? { cause: opts.cause } : undefined);
349
370
  this.name = "ConnectorCallError";
350
371
  this.code = code;
351
372
  this.retryable = opts.retryable ?? RETRYABLE_BY_CODE[code];
352
373
  this.retryAfterMs = normalizeRetryAfterMs(opts.retryAfterMs);
353
- this.details = code === "unavailable" ? sanitizedUnavailableDetails(opts.details) : undefined;
374
+ this.details =
375
+ code === "unavailable" || opts.writeOutcome === "unknown" ? sanitizedUnavailableDetails(opts.details) : undefined;
354
376
  this.validation = code === "invalid_args" ? boundedValidation(opts.validation) : undefined;
355
377
  this.repair = code === "invalid_args" ? boundedRepair(opts.repair) : undefined;
356
378
  this.current = code === "conflict" ? boundedCurrent(opts.current) : undefined;
379
+ this.writeOutcome = opts.writeOutcome === "unknown" ? "unknown" : undefined;
357
380
  }
358
381
  }
359
382
  /** Retryability of connecta framing depends only on its code. */
@@ -364,8 +387,94 @@ export function framingError(code, message) {
364
387
  retryable: code === "timeout" || code === "unavailable" || code === "rate_limited",
365
388
  };
366
389
  }
367
- /** Typed connector verdicts and runtime facts only. Prose never changes a verdict. */
390
+ // Advice to send a call again, kept beside its failure and never inside the
391
+ // failure's message. See resendAdvice.
392
+ const resendAdvices = followRedactedCopies(new WeakMap());
393
+ /**
394
+ * Attach advice to send the call again (a rate limit's " Back off before
395
+ * retrying.", a token error's ", then retry authorization") to `error` as a
396
+ * segment of its own: `error.message` never contains it. It holds for a read
397
+ * and a known refusal, so output composes it ({@link withResendAdvice}) only
398
+ * there, after the outcome is decided. No redaction or rewording of the
399
+ * message can then hide it from removal on a write whose outcome is unknown
400
+ * (INV-9). A segment that opens a sentence (" Wait…") follows the message;
401
+ * any other is a clause, placed before the message's closing period.
402
+ */
403
+ export function resendAdvice(error, advice) {
404
+ resendAdvices.set(error, advice);
405
+ return error;
406
+ }
407
+ /** The resend advice attached to `from`, if any. */
408
+ export function resendAdviceOf(from) {
409
+ return from !== null && typeof from === "object" ? resendAdvices.get(from) : undefined;
410
+ }
411
+ // Advice that reusing an idempotency key cannot repeat the write, kept apart
412
+ // from the failure's message and its other resend advice. See keyResendAdvice.
413
+ const keyAdvices = followRedactedCopies(new WeakMap());
414
+ /**
415
+ * Attach advice that reusing `key` with the same arguments cannot repeat the
416
+ * write, a segment of its own like {@link resendAdvice}. It holds only where
417
+ * that key protects the whole logical call (`keyProtectsCall`): one
418
+ * boundary entered, one write sent, carrying `key`. Attach it only once the
419
+ * call's ledger shows a dispatched request carrying `key`: a key generated
420
+ * but never sent protects nothing. Two places compose it. The invocation
421
+ * sees the whole call and composes it for a served call once
422
+ * `keyProtectsCall` holds. {@link classifyCallError} composes it for a
423
+ * dispatched direct call, which has no invocation: only the one boundary that
424
+ * sent the keyed request attaches it, and any boundary above that one
425
+ * finalizes the write as unknown, which drops it. Either way the key stays in
426
+ * the message as a diagnostic.
427
+ */
428
+ export function keyResendAdvice(error, key, advice) {
429
+ keyAdvices.set(error, { key, advice });
430
+ return error;
431
+ }
432
+ /** The key-reuse advice attached to `from`, if any. */
433
+ export function keyResendAdviceOf(from) {
434
+ return from !== null && typeof from === "object" ? keyAdvices.get(from) : undefined;
435
+ }
436
+ /**
437
+ * Keep `from`'s resend advice, key-reuse advice included, on `to`, a copy or
438
+ * rewording of it (redaction, a provider's recovery words). A write already
439
+ * marked unknown never takes it.
440
+ */
441
+ export function carryResendAdvice(from, to) {
442
+ if (!(to instanceof Error) || to.writeOutcome === "unknown")
443
+ return;
444
+ const advice = resendAdviceOf(from);
445
+ const keyed = keyResendAdviceOf(from);
446
+ if (advice !== undefined && !resendAdvices.has(to))
447
+ resendAdvices.set(to, advice);
448
+ if (keyed !== undefined && !keyAdvices.has(to))
449
+ keyAdvices.set(to, keyed);
450
+ }
451
+ /** `message` with resend `advice` composed in. Only output calls this. */
452
+ export function withResendAdvice(message, advice) {
453
+ if (advice === undefined)
454
+ return message;
455
+ return /^ [A-Z]/.test(advice) || !message.endsWith(".") ? message + advice : `${message.slice(0, -1)}${advice}.`;
456
+ }
457
+ /**
458
+ * Typed connector verdicts and runtime facts only. Prose never changes a
459
+ * verdict. The message carries the error's resend advice unless its write's
460
+ * outcome is unknown. This is a direct caller's view, outside any logical
461
+ * call: key-reuse advice is here only because the one boundary that sent the
462
+ * keyed request attached it to its own failure, and any boundary above it
463
+ * finalizes the write as unknown. An invocation composes advice itself.
464
+ */
368
465
  export function classifyCallError(err, fallbackCode = "connector_call_failed") {
466
+ const details = classifyWithoutAdvice(err, fallbackCode);
467
+ if (details.writeOutcome !== "unknown") {
468
+ details.message = withResendAdvice(details.message, keyResendAdviceOf(err)?.advice);
469
+ details.message = withResendAdvice(details.message, resendAdviceOf(err));
470
+ }
471
+ return details;
472
+ }
473
+ /**
474
+ * {@link classifyCallError} without the resend advice, for a caller that
475
+ * decides the outcome first and composes the advice only where it holds.
476
+ */
477
+ export function classifyWithoutAdvice(err, fallbackCode = "connector_call_failed") {
369
478
  if (err instanceof ConnectorCallError) {
370
479
  return {
371
480
  code: err.code,
@@ -376,6 +485,7 @@ export function classifyCallError(err, fallbackCode = "connector_call_failed") {
376
485
  ...(err.repair ? { repair: err.repair } : {}),
377
486
  ...(err.details ? { details: err.details } : {}),
378
487
  ...(err.current ? { current: err.current } : {}),
488
+ ...(err.writeOutcome ? { writeOutcome: err.writeOutcome } : {}),
379
489
  };
380
490
  }
381
491
  if (err instanceof WithheldTextError) {
package/dist/execute.js CHANGED
@@ -1,8 +1,10 @@
1
+ import { authCall, authInvoke, authMethod } from "./auth/native.js";
2
+ import { nativeRecovery } from "./native-recovery.js";
1
3
  import { GUEST_API_DECLARATION } from "./usage-guide.js";
2
4
  import { bindMcpClient } from "./mcp-client-context.js";
3
5
  import { CONFIG_DEFAULTS } from "./config-defaults.js";
4
6
  import { Cause, Deferred, Duration, Effect, Exit } from "effect";
5
- import { z } from "zod";
7
+ import * as z from "zod";
6
8
  import { advertisedSchema } from "./advertised-schema.js";
7
9
  import { boundedDiscoveryText, CatalogService, DiscoveryPolicyError, flatSearchResult, } from "./catalog-service.js";
8
10
  import { createMetaTools, guardProgramReturn, jsonResult, pageProgramResult, } from "./meta-tools.js";
@@ -17,9 +19,10 @@ import { EXECUTE_OUTPUT } from "./meta-output.js";
17
19
  import { normalizeProgramSource } from "./program-source.js";
18
20
  import { readResource } from "./resource-read.js";
19
21
  import { agentOutputOperations, redactAgentOutput, sentSecretsForRequest } from "./sent-secrets.js";
20
- import { normalizeTimeoutMs, underAnySignal } from "./timeout.js";
22
+ import { normalizeTimeoutMs } from "./timeout.js";
21
23
  import { fromSignal, runEdge, withDeadlineEffect } from "./runtime/run.js";
22
24
  import { closeScope } from "./runtime/connector-scope.js";
25
+ import { executorProgram } from "./runtime/executor.js";
23
26
  import { connectorGuide, connectorGuideRequired, connectorSkillName, hasConnectorGuides, SkillsRegistry, } from "./skills.js";
24
27
  /** Keep one model-written program from amplifying into an unbounded fan-out. */
25
28
  const EXECUTE_MAX_HOST_CALLS = CONFIG_DEFAULTS.execute.maxHostCalls;
@@ -558,7 +561,8 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
558
561
  unrecorded: true,
559
562
  };
560
563
  }
561
- if (writes >= maxWrites) {
564
+ const budgeted = target.definition.classification !== "read";
565
+ if (budgeted && writes >= maxWrites) {
562
566
  return {
563
567
  kind: "refuse",
564
568
  error: {
@@ -568,7 +572,8 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
568
572
  },
569
573
  };
570
574
  }
571
- writes++;
575
+ if (budgeted)
576
+ writes++;
572
577
  if (programWrites)
573
578
  sending.settle = programWrites.begin();
574
579
  return { kind: "dispatch" };
@@ -678,7 +683,7 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
678
683
  };
679
684
  const operations = {
680
685
  call,
681
- result: (id, options, signal) => Effect.tryPromise({
686
+ result: (id, options, signal, onStage) => Effect.tryPromise({
682
687
  try: async () => {
683
688
  const transfer = typeof id === "string" ? transfers.get(id) : undefined;
684
689
  const transferId = id;
@@ -709,7 +714,10 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
709
714
  }
710
715
  // A page must fit every shipped bridge even when the connector cap is raised.
711
716
  args.maxBytes = Math.min(args.maxBytes ?? PROGRAM_RESULT_PAGE_BYTES, PROGRAM_RESULT_PAGE_BYTES);
712
- const page = await meta.readResult({ id, ...args }, { signal: signal });
717
+ const page = await meta.readResult({ id, ...args }, {
718
+ signal: signal,
719
+ onStage: onStage,
720
+ });
713
721
  if (page.isError)
714
722
  throw new InvocationFailure((page.structuredContent?.error ?? {
715
723
  code: "not_found",
@@ -864,9 +872,12 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
864
872
  hostCalls.admitted++;
865
873
  const started = Date.now();
866
874
  const utility = name === "result" || name === "skill";
875
+ let stage = name === "result" ? "result storage" : "skill lookup";
867
876
  const invoke = Effect.suspend(() => operation(...args));
868
877
  const guarded = utility
869
- ? withDeadlineEffect((utilitySignal) => Effect.suspend(() => operation(args[0], args[1], utilitySignal)), {
878
+ ? withDeadlineEffect((utilitySignal) => Effect.suspend(() => operation(args[0], args[1], utilitySignal, (current) => {
879
+ stage = current;
880
+ })), {
870
881
  timeoutMs: hostCallTimeoutMs,
871
882
  ...(hostAccessSignal ? { signal: hostAccessSignal } : {}),
872
883
  timeoutError: guestFailure("timeout", `connecta.${name} timed out.`),
@@ -877,14 +888,14 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
877
888
  return typedFailure(guestFailure("cancelled", `connecta.${name} was cancelled because the run ended.`));
878
889
  if (utility && error instanceof InvocationFailure && error.code === "timeout") {
879
890
  const elapsedMs = Date.now() - started;
880
- const message = `Operation "connecta.${name}" timed out during ${name === "result" ? "result storage" : "skill lookup"} after ${elapsedMs}ms (effective deadline ${hostCallTimeoutMs}ms).`;
891
+ const message = `Operation "connecta.${name}" timed out during ${stage} after ${elapsedMs}ms (effective deadline ${hostCallTimeoutMs}ms).`;
881
892
  return typedFailure(new InvocationFailure({
882
893
  code: "timeout",
883
894
  message,
884
895
  retryable: true,
885
896
  details: {
886
897
  operation: `connecta.${name}`,
887
- stage: name === "result" ? "result storage" : "skill lookup",
898
+ stage,
888
899
  elapsedMs,
889
900
  deadlineMs: hostCallTimeoutMs,
890
901
  },
@@ -914,7 +925,7 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
914
925
  };
915
926
  }
916
927
  /**
917
- * Await an executor's promise without trusting it to settle.
928
+ * Await executor work without trusting it to settle.
918
929
  *
919
930
  * An executor's deadline is its own business, and the Dynamic Worker's lives
920
931
  * inside the sandbox: a wedged isolate never fires it, so the call never
@@ -927,28 +938,33 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
927
938
  * a ceiling of its own. Cancellation settles as the same `executor_cancelled`
928
939
  * the QuickJS pool reports, unless the executor reports its own first; the
929
940
  * ceiling as an untyped executor failure naming the key that sets it. Either
930
- * way the handler returns and releases the lease, and the abandoned call
931
- * keeps whatever it was doing: the QuickJS lease release recycles its child,
932
- * the Worker adapter disposes its handles without waiting for the guest. A
933
- * lease granted after its request gave up goes to `late`. The result contract is untouched
934
- * — this only decides when to stop waiting for one.
941
+ * way the handler releases the lease. Losing native programs are interrupted
942
+ * and their finalizers awaited, so native interruption cleanup must remain
943
+ * synchronous or bounded to avoid delaying the watchdog or terminal response.
944
+ * Custom Promise leaves may continue, with late settlements still observed;
945
+ * lease release recycles the QuickJS child or disposes Worker handles without
946
+ * waiting for the guest. A lease granted after its request gave up goes to
947
+ * `late`. The result contract is untouched — this only decides when to stop
948
+ * waiting for one.
935
949
  */
936
950
  function awaitExecutor(start, signal, options = {}) {
937
951
  const started = Date.now();
938
952
  const contenders = [
939
- Effect.suspend(() => {
940
- let pending;
941
- const settling = Effect.tryPromise({
942
- try: () => (pending = Promise.resolve(start())),
943
- catch: (err) => err,
944
- });
945
- const { late } = options;
946
- return late
947
- ? settling.pipe(Effect.onInterrupt(() => Effect.sync(() => {
948
- pending?.then(late, () => { });
949
- })))
950
- : settling;
951
- }),
953
+ typeof start !== "function"
954
+ ? start
955
+ : Effect.suspend(() => {
956
+ let pending;
957
+ const settling = Effect.tryPromise({
958
+ try: () => (pending = Promise.resolve(start())),
959
+ catch: (err) => err,
960
+ });
961
+ const { late } = options;
962
+ return late
963
+ ? settling.pipe(Effect.onInterrupt(() => Effect.sync(() => {
964
+ pending?.then(late, () => { });
965
+ })))
966
+ : settling;
967
+ }),
952
968
  // An executor that honors the signal rejects in the abort event itself,
953
969
  // with the logs it captured attached, and that report beats ours by one
954
970
  // timer turn. (A 1ms sleep, not 0: Effect.sleep(0) waits a microtask,
@@ -1086,17 +1102,18 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
1086
1102
  return yield* timed((elapsed) => {
1087
1103
  if (diagnostics)
1088
1104
  diagnostics.executorWallMs = elapsed;
1089
- }, awaitExecutor(() => (admitted
1090
- ? admitted.execute(wrapGuestProgram(program), [provider])
1091
- : executor.execute(wrapGuestProgram(program), [provider])).then((outcome) => {
1092
- executorLogs = sentSecrets.redact(outcome?.logs, "prose");
1093
- return sentSecrets.redact(outcome);
1094
- }, (err) => {
1095
- if (err !== null && typeof err === "object" && "logs" in err) {
1096
- executorLogs = sentSecrets.redact(err.logs, "prose");
1097
- }
1098
- throw sentSecrets.redact(err);
1099
- }), signal, { watchdog, terminal: Deferred.await(terminal) }).pipe(Effect.ensuring(Effect.suspend(() => {
1105
+ }, awaitExecutor(executorProgram(admitted ?? executor, wrapGuestProgram(program), [provider], {
1106
+ result: (outcome) => {
1107
+ executorLogs = sentSecrets.redact(outcome?.logs);
1108
+ },
1109
+ error: (err) => {
1110
+ if (err !== null && typeof err === "object" && "logs" in err)
1111
+ executorLogs = sentSecrets.redact(err.logs);
1112
+ },
1113
+ interrupted: (logs) => {
1114
+ executorLogs = sentSecrets.redact(logs);
1115
+ },
1116
+ }).pipe(Effect.map((outcome) => sentSecrets.redact(outcome)), Effect.mapError((error) => sentSecrets.redact(error))), signal, { watchdog, terminal: Deferred.await(terminal) }).pipe(Effect.ensuring(Effect.suspend(() => {
1100
1117
  programWrites.close();
1101
1118
  dispatchController.abort();
1102
1119
  return programWrites.drain();
@@ -1141,7 +1158,7 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
1141
1158
  }).pipe(Effect.map((result) => redactAgentOutput(sentSecrets, result)));
1142
1159
  });
1143
1160
  return agentOutputOperations((requestScope) => ({
1144
- execute: ({ code, diagnostics }, options = {}) => {
1161
+ execute: authMethod(({ code, diagnostics }, options = {}) => {
1145
1162
  // A code-unit count above the cap is already too large in UTF-8. Check
1146
1163
  // that first so a huge direct-call string is never encoded in full.
1147
1164
  if (code.length > EXECUTE_MAX_CODE_BYTES ||
@@ -1153,10 +1170,10 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
1153
1170
  hostCalls: { attempted: 0, admitted: 0, succeeded: 0, failed: 0 },
1154
1171
  };
1155
1172
  response.content[0].text = JSON.stringify(response.structuredContent);
1156
- return Promise.resolve(response);
1173
+ return Effect.succeed(response);
1157
1174
  }
1158
- return runEdge(Effect.suspend(() => play(normalizeProgramSource(code), diagnostics, options.signal, requestScope)));
1159
- },
1175
+ return Effect.suspend(() => play(normalizeProgramSource(code), diagnostics, options.signal, requestScope));
1176
+ }),
1160
1177
  }), config.requestScope).execute;
1161
1178
  }
1162
1179
  /** An execution that never produced an ExecuteResult, as the model sees it. */
@@ -1328,7 +1345,7 @@ function connectorInventory(connectors) {
1328
1345
  return `${prefix}${shown.join(", ")}.`;
1329
1346
  return `${prefix}${shown.join(", ")}${shown.length > 0 ? "; " : ""}+${omitted} more.`;
1330
1347
  }
1331
- const executeDescription = (emitBudgets, hostLimits, connectorGuides, connectors, maxWrites, readOnly) => `${readOnly ? "One known read: call_tool. Everything else: execute_code. Read-only endpoint: search and describe omit write tools, and every write call is refused." : "One known read: call_tool. One known write: call_destructive_tool. Everything else: execute_code. Writable endpoint: programs may read and write; the client approves."} Limits: ${hostLimits.maxHostCalls} host calls, ${readOnly ? "" : `${maxWrites} writes, `}${hostLimits.hostCallTimeoutMs / 1_000}s/host call.
1348
+ const executeDescription = (emitBudgets, hostLimits, connectorGuides, connectors, maxWrites, readOnly, native = false) => `${native ? `Call tools directly; combine work here using their program addresses. ${readOnly ? "Read-only endpoint: writes are omitted and refused." : "Writable endpoint: programs may read and write; the client approves."}` : readOnly ? "One known read: call_tool. Everything else: execute_code. Read-only endpoint: search and describe omit write tools, and every write call is refused." : "One known read: call_tool. One known write: call_destructive_tool. Everything else: execute_code. Writable endpoint: programs may read and write; the client approves."} Limits: ${hostLimits.maxHostCalls} host calls, ${readOnly ? "" : `${maxWrites} writes, `}${hostLimits.hostCallTimeoutMs / 1_000}s/host call.
1332
1349
  ${connectorInventory(connectors)}
1333
1350
 
1334
1351
  Use async () => { ... }, no arguments. No portable ambient capabilities. API:
@@ -1383,7 +1400,7 @@ export function registerExecuteTool(server, registry, ctx) {
1383
1400
  description: executeDescription(emitBudgets, {
1384
1401
  ...hostLimits,
1385
1402
  hostCallTimeoutMs: normalizeTimeoutMs(ctx.defaultToolTimeoutMs) ?? hostLimits.hostCallTimeoutMs,
1386
- }, hasConnectorGuides(connectors), connectors, maxWrites, ctx.readOnly === true),
1403
+ }, hasConnectorGuides(connectors), connectors, maxWrites, ctx.readOnly === true, ctx.native === true),
1387
1404
  inputSchema: EXECUTE_INPUT,
1388
1405
  outputSchema: EXECUTE_OUTPUT,
1389
1406
  // The client sees execute_code as a write exactly when the endpoint writes.
@@ -1392,12 +1409,32 @@ export function registerExecuteTool(server, registry, ctx) {
1392
1409
  destructiveHint: ctx.readOnly !== true,
1393
1410
  openWorldHint: true,
1394
1411
  },
1395
- }, (args, extra) => {
1412
+ }, authMethod((args, extra) => Effect.gen(function* () {
1396
1413
  if (ctx.client)
1397
1414
  bindMcpClient(extra, ctx.client, ctx.activity);
1398
- const run = () => underAnySignal([extra.mcpReq.signal, ctx.requestSignal], (signal) => execute(args, {
1399
- signal,
1415
+ const run = authMethod(() => Effect.suspend(() => {
1416
+ const controller = new AbortController();
1417
+ const forwarders = [extra.mcpReq.signal, ctx.requestSignal]
1418
+ .filter((signal) => signal !== undefined)
1419
+ .map((signal) => {
1420
+ const forward = () => controller.abort(signal.reason);
1421
+ if (signal.aborted)
1422
+ forward();
1423
+ else
1424
+ signal.addEventListener("abort", forward, { once: true });
1425
+ return { signal, forward };
1426
+ });
1427
+ return authCall(execute, [
1428
+ args,
1429
+ { signal: controller.signal },
1430
+ ]).pipe(Effect.ensuring(Effect.sync(() => {
1431
+ for (const { signal, forward } of forwarders)
1432
+ signal.removeEventListener("abort", forward);
1433
+ })));
1400
1434
  }));
1401
- return ctx.authElicitation ? ctx.authElicitation.run("execute_code", args, extra, run) : run();
1402
- });
1435
+ const result = yield* ctx.authElicitation
1436
+ ? authInvoke(ctx.authElicitation, "run", ["execute_code", args, extra, run])
1437
+ : authCall(run, []);
1438
+ return ctx.native ? nativeRecovery(result, true) : result;
1439
+ })));
1403
1440
  }
@@ -1,6 +1,7 @@
1
1
  import { Deferred, Duration, Effect } from "effect";
2
2
  import { admit, provideAdmissionProgram } from "./runtime/admission.js";
3
3
  import { fromSignal, runEdge } from "./runtime/run.js";
4
+ import { keepErrorName } from "./redaction-identity.js";
4
5
  /**
5
6
  * A stable, machine-readable admission failure. Overload is retryable; caller
6
7
  * cancellation and shutdown are terminal for this invocation.
@@ -19,6 +20,7 @@ export class ExecutorAdmissionError extends Error {
19
20
  }
20
21
  }
21
22
  }
23
+ keepErrorName(ExecutorAdmissionError, "ExecutorAdmissionError");
22
24
  /**
23
25
  * A lifecycle failure after the sandbox started running. It keeps the stable
24
26
  * admission-error envelope while letting response assembly distinguish work
@@ -30,6 +32,7 @@ export class ExecutorExecutionError extends ExecutorAdmissionError {
30
32
  this.name = "ExecutorExecutionError";
31
33
  }
32
34
  }
35
+ keepErrorName(ExecutorExecutionError, "ExecutorExecutionError");
33
36
  function positiveWhole(value, name) {
34
37
  if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {
35
38
  throw new TypeError(`${name} must be a positive whole number.`);