@zackbart/connecta 0.34.1 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. package/CHANGELOG.md +418 -0
  2. package/README.md +65 -105
  3. package/SECURITY.md +3 -2
  4. package/bin/connecta.mjs +41 -16
  5. package/bin/version.mjs +1 -1
  6. package/dist/access-tokens.d.ts +2 -1
  7. package/dist/access-tokens.js +66 -30
  8. package/dist/activity.d.ts +1 -1
  9. package/dist/activity.js +2 -0
  10. package/dist/agent-config.d.ts +23 -0
  11. package/dist/agent-config.js +59 -0
  12. package/dist/agent-description.js +16 -0
  13. package/dist/agent-identity.js +4 -4
  14. package/dist/agent-observation.js +39 -0
  15. package/dist/auth/clerk-sdk/client.d.ts +2 -0
  16. package/dist/auth/clerk-sdk/generated.js +554 -563
  17. package/dist/auth/clerk-transport.js +70 -3
  18. package/dist/auth/clerk.d.ts +13 -0
  19. package/dist/auth/clerk.js +653 -246
  20. package/dist/auth/cloudflare-access.js +46 -42
  21. package/dist/auth/downstream-client-metadata.js +2 -2
  22. package/dist/auth/downstream-oauth.js +2044 -1161
  23. package/dist/auth/downstream-revocation.js +88 -88
  24. package/dist/auth/native-call.js +20 -0
  25. package/dist/auth/native.js +184 -0
  26. package/dist/auth/oauth-start-reset.js +11 -5
  27. package/dist/auth/oauth-token-response.js +121 -102
  28. package/dist/auth/oauth-v2-migration.js +97 -78
  29. package/dist/auth/renewable-grant.js +10 -0
  30. package/dist/auth/static-oauth.js +751 -281
  31. package/dist/auth/vercel-agent.js +266 -0
  32. package/dist/auth-admission.js +204 -0
  33. package/dist/auth-elicitation.js +350 -241
  34. package/dist/authorization-handoff.js +164 -90
  35. package/dist/call-admission-context.js +3 -10
  36. package/dist/call-admission.js +2 -0
  37. package/dist/call-classification.js +9 -0
  38. package/dist/call-recovery.js +32 -13
  39. package/dist/canonical-json.js +8 -0
  40. package/dist/catalog-cache.js +369 -213
  41. package/dist/catalog-service.js +659 -530
  42. package/dist/catalog.js +5 -1
  43. package/dist/concurrency.js +0 -25
  44. package/dist/config-defaults.d.ts +1 -0
  45. package/dist/config-defaults.js +1 -0
  46. package/dist/config-schema.d.ts +3 -1
  47. package/dist/config-schema.js +13 -3
  48. package/dist/config.d.ts +40 -6
  49. package/dist/config.js +40 -26
  50. package/dist/connector-caller.d.ts +4 -0
  51. package/dist/connector-caller.js +17 -4
  52. package/dist/connectors/api-connector.d.ts +29 -7
  53. package/dist/connectors/api-connector.js +145 -57
  54. package/dist/connectors/guarded-fetch.d.ts +51 -17
  55. package/dist/connectors/guarded-fetch.js +215 -121
  56. package/dist/connectors/negotiation-cache.js +20 -10
  57. package/dist/connectors/remote-mcp.d.ts +10 -30
  58. package/dist/connectors/remote-mcp.js +955 -563
  59. package/dist/d1.js +10 -243
  60. package/dist/derived-context.js +5 -0
  61. package/dist/describe-config.d.ts +3 -1
  62. package/dist/describe-config.js +2 -0
  63. package/dist/downstream-input.js +347 -260
  64. package/dist/errors.d.ts +87 -6
  65. package/dist/errors.js +114 -4
  66. package/dist/execute.js +87 -50
  67. package/dist/executor-admission.js +3 -0
  68. package/dist/executors/quickjs.js +163 -112
  69. package/dist/guarded-transport.js +50 -0
  70. package/dist/guest-runtime.js +1 -1
  71. package/dist/http/client.js +439 -0
  72. package/dist/http/errors.js +558 -0
  73. package/dist/http/fields.js +49 -0
  74. package/dist/http/hatch-paging.js +318 -0
  75. package/dist/http/hatch.js +1279 -0
  76. package/dist/http/json-schema.js +267 -0
  77. package/dist/http/node-transport.js +241 -0
  78. package/dist/http/oauth.js +162 -0
  79. package/dist/http/paging.js +227 -0
  80. package/dist/http/provider.js +221 -0
  81. package/dist/http/safety.js +82 -0
  82. package/dist/http/services.js +79 -0
  83. package/dist/http/tools.js +379 -0
  84. package/dist/http/vendor-index.js +138 -0
  85. package/dist/http/vendor.js +448 -0
  86. package/dist/http/write-request.js +66 -0
  87. package/dist/http-policy.d.ts +11 -0
  88. package/dist/http-policy.js +45 -0
  89. package/dist/inbound-credential.js +1 -1
  90. package/dist/index.d.ts +2 -2
  91. package/dist/index.js +4 -0
  92. package/dist/invocation-auth.js +30 -19
  93. package/dist/invocation.js +218 -85
  94. package/dist/mcp-result.js +0 -4
  95. package/dist/membership.d.ts +4 -0
  96. package/dist/meta-output.js +1 -1
  97. package/dist/meta-tools.js +531 -406
  98. package/dist/native-recovery.js +52 -0
  99. package/dist/native-tools.js +382 -0
  100. package/dist/node.d.ts +4 -3
  101. package/dist/node.js +45 -8
  102. package/dist/oauth-handoff.js +177 -104
  103. package/dist/oauth-partition.js +6 -20
  104. package/dist/oauth-sealing.js +6 -7
  105. package/dist/operation-vocabulary.js +101 -0
  106. package/dist/operator-record.d.ts +2 -2
  107. package/dist/operator-record.js +17 -4
  108. package/dist/operator-ui/contract.d.ts +8 -3
  109. package/dist/operator-ui/generated.js +4 -4
  110. package/dist/operator-ui/model.d.ts +2 -3
  111. package/dist/program-writes.js +47 -26
  112. package/dist/provider-call-facts.d.ts +115 -0
  113. package/dist/provider-call-facts.js +182 -0
  114. package/dist/provider-call.d.ts +112 -0
  115. package/dist/provider-call.js +271 -0
  116. package/dist/provider.d.ts +65 -31
  117. package/dist/provider.js +116 -39
  118. package/dist/providers/_shared/google/hatch.js +91 -0
  119. package/dist/providers/_shared/google/kit.js +427 -0
  120. package/dist/providers/_shared/google/result-size.js +15 -2
  121. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  122. package/dist/providers/_shared/google/service-account.js +8 -4
  123. package/dist/providers/_shared/google/workspace.d.ts +6 -210
  124. package/dist/providers/_shared/google/workspace.js +6 -425
  125. package/dist/providers/_shared/rest/compact-index.js +86 -0
  126. package/dist/providers/_shared/rest/kit.js +146 -0
  127. package/dist/providers/_shared/rest/operation-index.js +230 -14
  128. package/dist/providers/_shared/rest/response-media.js +11 -0
  129. package/dist/providers/_shared/rest/value-safety.js +353 -195
  130. package/dist/providers/_shared/sensitive-fields.js +27 -0
  131. package/dist/providers/breeze/api.js +584 -0
  132. package/dist/providers/breeze/index.d.ts +1 -3
  133. package/dist/providers/breeze/index.js +67 -1420
  134. package/dist/providers/breeze/openapi.generated.js +60 -0
  135. package/dist/providers/breeze/skill.generated.js +2 -6
  136. package/dist/providers/breeze/tools.js +696 -0
  137. package/dist/providers/ccb/api.js +496 -0
  138. package/dist/providers/ccb/index.d.ts +15 -37
  139. package/dist/providers/ccb/index.js +77 -1702
  140. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  141. package/dist/providers/ccb/lib/constants.js +74 -0
  142. package/dist/providers/ccb/lib/guide.js +9 -0
  143. package/dist/providers/ccb/lib/verdicts.js +387 -0
  144. package/dist/providers/ccb/openapi.generated.js +397 -0
  145. package/dist/providers/ccb/safety.js +295 -0
  146. package/dist/providers/ccb/skill.generated.js +2 -6
  147. package/dist/providers/ccb/tools.js +853 -0
  148. package/dist/providers/cloudflare/api.js +1066 -0
  149. package/dist/providers/cloudflare/index.d.ts +5 -22
  150. package/dist/providers/cloudflare/index.js +79 -197
  151. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  152. package/dist/providers/cloudflare/lib/config.js +2 -0
  153. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  154. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  155. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  156. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  157. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  158. package/dist/providers/cloudflare/openapi.generated.js +4 -3
  159. package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
  160. package/dist/providers/cloudflare/skill.generated.js +2 -10
  161. package/dist/providers/cloudflare/tools.js +360 -0
  162. package/dist/providers/docs/api.js +51 -0
  163. package/dist/providers/docs/index.d.ts +1 -12
  164. package/dist/providers/docs/index.js +53 -1165
  165. package/dist/providers/docs/lib/constants.d.ts +18 -0
  166. package/dist/providers/docs/lib/constants.js +18 -0
  167. package/dist/providers/docs/lib/discovery.js +26 -0
  168. package/dist/providers/docs/lib/requests.js +48 -0
  169. package/dist/providers/docs/lib/schemas.js +168 -0
  170. package/dist/providers/docs/openapi.generated.js +16 -0
  171. package/dist/providers/docs/safety.js +54 -0
  172. package/dist/providers/docs/skill.generated.js +2 -6
  173. package/dist/providers/docs/tools.js +801 -0
  174. package/dist/providers/drive/api.js +177 -0
  175. package/dist/providers/drive/index.d.ts +1 -12
  176. package/dist/providers/drive/index.js +38 -1448
  177. package/dist/providers/drive/lib/constants.d.ts +6 -0
  178. package/dist/providers/drive/lib/constants.js +6 -0
  179. package/dist/providers/drive/lib/contracts.js +532 -0
  180. package/dist/providers/drive/lib/hatch.js +197 -0
  181. package/dist/providers/drive/openapi.generated.js +77 -0
  182. package/dist/providers/drive/safety.js +90 -0
  183. package/dist/providers/drive/skill.generated.js +2 -6
  184. package/dist/providers/drive/tools.js +1290 -0
  185. package/dist/providers/forms/api.js +71 -0
  186. package/dist/providers/forms/index.d.ts +1 -12
  187. package/dist/providers/forms/index.js +49 -1145
  188. package/dist/providers/forms/lib/constants.d.ts +14 -0
  189. package/dist/providers/forms/lib/constants.js +19 -0
  190. package/dist/providers/forms/lib/hatch.js +72 -0
  191. package/dist/providers/forms/openapi.generated.js +23 -0
  192. package/dist/providers/forms/safety.js +34 -0
  193. package/dist/providers/forms/skill.generated.js +2 -8
  194. package/dist/providers/forms/tools.js +1023 -0
  195. package/dist/providers/github/api.js +150 -0
  196. package/dist/providers/github/index.d.ts +4 -5
  197. package/dist/providers/github/index.js +30 -87
  198. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  199. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  200. package/dist/providers/github/lib/discovery.js +132 -0
  201. package/dist/providers/github/lib/operations.js +58 -0
  202. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  203. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  204. package/dist/providers/github/openapi.generated.js +1216 -0
  205. package/dist/providers/github/safety.js +216 -0
  206. package/dist/providers/github/skill.generated.js +2 -5
  207. package/dist/providers/github/tools.js +506 -0
  208. package/dist/providers/gmail/api.js +114 -0
  209. package/dist/providers/gmail/index.d.ts +1 -12
  210. package/dist/providers/gmail/index.js +73 -1621
  211. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  212. package/dist/providers/gmail/lib/constants.js +16 -0
  213. package/dist/providers/gmail/lib/index.js +173 -0
  214. package/dist/providers/gmail/lib/schemas.js +176 -0
  215. package/dist/providers/gmail/lib/threading.js +120 -0
  216. package/dist/providers/gmail/openapi.generated.js +92 -0
  217. package/dist/providers/gmail/safety.js +21 -0
  218. package/dist/providers/gmail/skill.generated.js +2 -6
  219. package/dist/providers/gmail/tools.js +1435 -0
  220. package/dist/providers/overflow/api.js +1008 -0
  221. package/dist/providers/overflow/index.d.ts +1 -17
  222. package/dist/providers/overflow/index.js +60 -1488
  223. package/dist/providers/overflow/skill.generated.js +2 -5
  224. package/dist/providers/overflow/tools.js +873 -0
  225. package/dist/providers/planning-center/api.js +467 -0
  226. package/dist/providers/planning-center/index.d.ts +4 -35
  227. package/dist/providers/planning-center/index.js +69 -2445
  228. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  229. package/dist/providers/planning-center/lib/constants.js +83 -0
  230. package/dist/providers/planning-center/lib/discovery.js +40 -0
  231. package/dist/providers/planning-center/lib/guide.js +39 -0
  232. package/dist/providers/planning-center/lib/json-api.js +83 -0
  233. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  234. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  235. package/dist/providers/planning-center/safety.js +188 -0
  236. package/dist/providers/planning-center/skill.generated.js +2 -27
  237. package/dist/providers/planning-center/tools.js +1010 -0
  238. package/dist/providers/quickbooks/api.js +299 -0
  239. package/dist/providers/quickbooks/index.d.ts +13 -0
  240. package/dist/providers/quickbooks/index.js +93 -0
  241. package/dist/providers/quickbooks/lib/query.js +118 -0
  242. package/dist/providers/quickbooks/lib/writes.js +168 -0
  243. package/dist/providers/quickbooks/safety.js +222 -0
  244. package/dist/providers/quickbooks/skill.generated.js +5 -0
  245. package/dist/providers/quickbooks/tools.js +117 -0
  246. package/dist/providers/sheets/api.js +133 -0
  247. package/dist/providers/sheets/index.d.ts +4 -16
  248. package/dist/providers/sheets/index.js +61 -1172
  249. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  250. package/dist/providers/sheets/lib/constants.js +14 -0
  251. package/dist/providers/sheets/lib/hatch.js +163 -0
  252. package/dist/providers/sheets/lib/requests.js +105 -0
  253. package/dist/providers/sheets/lib/schemas.js +138 -0
  254. package/dist/providers/sheets/openapi.generated.js +30 -0
  255. package/dist/providers/sheets/safety.js +27 -0
  256. package/dist/providers/sheets/skill.generated.js +2 -7
  257. package/dist/providers/sheets/tools.js +733 -0
  258. package/dist/providers/slides/api.js +147 -0
  259. package/dist/providers/slides/index.d.ts +2 -10
  260. package/dist/providers/slides/index.js +48 -2555
  261. package/dist/providers/slides/lib/constants.d.ts +11 -0
  262. package/dist/providers/slides/lib/constants.js +11 -0
  263. package/dist/providers/slides/lib/requests.js +60 -0
  264. package/dist/providers/slides/lib/schemas.js +565 -0
  265. package/dist/providers/slides/openapi.generated.js +18 -0
  266. package/dist/providers/slides/skill.generated.js +2 -6
  267. package/dist/providers/slides/tools.js +1968 -0
  268. package/dist/providers/stripe/api.js +401 -0
  269. package/dist/providers/stripe/index.d.ts +5 -27
  270. package/dist/providers/stripe/index.js +74 -210
  271. package/dist/providers/stripe/lib/config.d.ts +4 -0
  272. package/dist/providers/stripe/lib/config.js +2 -0
  273. package/dist/providers/stripe/openapi.generated.js +4 -3
  274. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  275. package/dist/providers/stripe/skill.generated.js +2 -11
  276. package/dist/providers/stripe/tools.js +77 -0
  277. package/dist/providers/tithely/api.js +531 -0
  278. package/dist/providers/tithely/index.d.ts +17 -0
  279. package/dist/providers/tithely/index.js +86 -965
  280. package/dist/providers/tithely/skill.generated.js +2 -5
  281. package/dist/providers/tithely/tools.js +426 -0
  282. package/dist/providers/vercel/api.js +551 -0
  283. package/dist/providers/vercel/index.d.ts +9 -25
  284. package/dist/providers/vercel/index.js +65 -260
  285. package/dist/providers/vercel/lib/config.d.ts +2 -0
  286. package/dist/providers/vercel/lib/config.js +2 -0
  287. package/dist/providers/vercel/lib/index.js +117 -0
  288. package/dist/providers/vercel/lib/logs.js +100 -0
  289. package/dist/providers/vercel/lib/pin.js +270 -0
  290. package/dist/providers/vercel/openapi.generated.js +10 -5
  291. package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
  292. package/dist/providers/vercel/skill.generated.js +2 -7
  293. package/dist/providers/vercel/tools.js +642 -0
  294. package/dist/redaction-identity.js +47 -0
  295. package/dist/redaction-marker.js +125 -0
  296. package/dist/registry.d.ts +21 -15
  297. package/dist/registry.js +409 -376
  298. package/dist/routes/access-tokens.js +1 -1
  299. package/dist/routes/actor-labels.js +1 -1
  300. package/dist/routes/connect.js +1 -1
  301. package/dist/routes/dispatch.js +103 -0
  302. package/dist/routes/mcp.js +170 -79
  303. package/dist/routes/oauth.js +6 -1
  304. package/dist/routes/operator.js +2 -2
  305. package/dist/routes/shared.d.ts +5 -4
  306. package/dist/routes/shared.js +244 -177
  307. package/dist/routes/skills.js +10 -8
  308. package/dist/routes/ui-config.js +27 -3
  309. package/dist/routes/ui-data.js +21 -20
  310. package/dist/routes/ui.js +1 -1
  311. package/dist/runtime/call-admission.js +0 -26
  312. package/dist/runtime/call-entry.js +30 -0
  313. package/dist/runtime/call.js +552 -0
  314. package/dist/runtime/connector-scope.js +7 -0
  315. package/dist/runtime/credential-probe.js +34 -0
  316. package/dist/runtime/executor.js +40 -0
  317. package/dist/runtime/native-storage.js +63 -0
  318. package/dist/runtime/registry.js +27 -0
  319. package/dist/runtime/request-scope.js +72 -0
  320. package/dist/runtime/run.js +15 -7
  321. package/dist/runtime/shared-read.js +34 -5
  322. package/dist/runtime/storage.js +34 -21
  323. package/dist/sent-secrets.d.ts +194 -37
  324. package/dist/sent-secrets.js +1743 -340
  325. package/dist/server.js +5 -56
  326. package/dist/skills.js +322 -223
  327. package/dist/sqlite.js +15 -14
  328. package/dist/storage/d1-copy.js +255 -0
  329. package/dist/storage/d1-driver.js +15 -0
  330. package/dist/storage/keys.js +28 -0
  331. package/dist/storage/sql-driver.js +88 -0
  332. package/dist/storage/sql-native.js +544 -0
  333. package/dist/storage/sql-schema.d.ts +6 -0
  334. package/dist/storage/sql-schema.js +15 -0
  335. package/dist/storage/sql.d.ts +14 -20
  336. package/dist/storage/sql.js +29 -535
  337. package/dist/timeout.js +0 -26
  338. package/dist/tool-safety.js +20 -10
  339. package/dist/types.d.ts +9 -109
  340. package/dist/ui.d.ts +1 -1
  341. package/dist/ui.js +0 -1
  342. package/dist/upward.js +3 -0
  343. package/dist/usage-guide.js +3 -1
  344. package/dist/validate.d.ts +4 -2
  345. package/dist/validate.js +86 -9
  346. package/dist/version.d.ts +1 -1
  347. package/dist/version.js +1 -1
  348. package/dist/worker.js +312 -292
  349. package/dist/workspace-subject.js +5 -1
  350. package/dist/write-outcome.js +454 -34
  351. package/documentation/README.md +28 -7
  352. package/documentation/architecture.md +2409 -255
  353. package/documentation/auth.md +867 -114
  354. package/documentation/code-mode.md +49 -16
  355. package/documentation/deploying.md +164 -20
  356. package/documentation/hosted-mcp-migration.md +460 -0
  357. package/documentation/integrating.md +129 -144
  358. package/documentation/meta-tools.md +409 -32
  359. package/documentation/operating.md +27 -3
  360. package/documentation/operator-tests.md +3 -0
  361. package/documentation/operator-ui.md +84 -48
  362. package/documentation/provider-auth-migration.md +16 -63
  363. package/documentation/provider-migration-0.29.md +10 -5
  364. package/documentation/provider-migration-0.35.md +975 -0
  365. package/documentation/providers.md +1347 -0
  366. package/examples/worker/AGENTS.md +23 -9
  367. package/examples/worker/README.md +254 -135
  368. package/examples/worker/alchemy.run.ts +116 -0
  369. package/examples/worker/gitignore +10 -0
  370. package/examples/worker/src/connecta.config.ts +23 -21
  371. package/examples/worker/wrangler.jsonc +14 -5
  372. package/guides/connecting-agents.md +157 -0
  373. package/guides/how-it-works.md +156 -0
  374. package/guides/safety-and-trust.md +153 -0
  375. package/package.json +30 -50
  376. package/templates/node/.env.example +3 -0
  377. package/templates/node/README.md +22 -2
  378. package/templates/node/docker-compose.yml +1 -0
  379. package/templates/node/package.json +3 -2
  380. package/templates/node/src/connecta.config.ts +8 -0
  381. package/dist/catalog-drift.d.ts +0 -138
  382. package/dist/catalog-drift.js +0 -578
  383. package/dist/operator-ui/agents.d.ts +0 -74
  384. package/dist/operator-ui/agents.js +0 -104
  385. package/dist/operator-ui/config-summary.js +0 -565
  386. package/dist/operator-ui/connection-map.js +0 -376
  387. package/dist/operator-ui/endpoints.js +0 -221
  388. package/dist/operator-ui/fix-prompts.d.ts +0 -18
  389. package/dist/operator-ui/fix-prompts.js +0 -87
  390. package/dist/operator-ui/health.js +0 -52
  391. package/dist/operator-ui/member-page.js +0 -97
  392. package/dist/operator-ui/overview.js +0 -123
  393. package/dist/operator-ui/setup-commands.js +0 -51
  394. package/dist/operator-ui/view.d.ts +0 -401
  395. package/dist/operator-ui/view.js +0 -705
  396. package/dist/providers/_shared/request-token.js +0 -83
  397. package/dist/providers/_shared/rest/dispatch.js +0 -41
  398. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  399. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  400. package/dist/providers/_shared/rest/tools.js +0 -569
  401. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  402. package/dist/providers/basecamp/index.d.ts +0 -45
  403. package/dist/providers/basecamp/index.js +0 -997
  404. package/dist/providers/basecamp/skill.generated.js +0 -9
  405. package/dist/providers/cloudflare/rest.d.ts +0 -37
  406. package/dist/providers/cloudflare/rest.js +0 -1097
  407. package/dist/providers/github/hosted.js +0 -218
  408. package/dist/providers/github/rest.js +0 -321
  409. package/dist/providers/infisical/index.d.ts +0 -7
  410. package/dist/providers/infisical/index.js +0 -713
  411. package/dist/providers/infisical/skill.generated.js +0 -8
  412. package/dist/providers/intercom/index.d.ts +0 -24
  413. package/dist/providers/intercom/index.js +0 -121
  414. package/dist/providers/intercom/skill.generated.js +0 -8
  415. package/dist/providers/linear/index.d.ts +0 -55
  416. package/dist/providers/linear/index.js +0 -537
  417. package/dist/providers/linear/skill.generated.js +0 -8
  418. package/dist/providers/mixpanel/index.d.ts +0 -59
  419. package/dist/providers/mixpanel/index.js +0 -472
  420. package/dist/providers/mixpanel/operations.js +0 -20
  421. package/dist/providers/mixpanel/rest.js +0 -603
  422. package/dist/providers/mixpanel/skill.generated.js +0 -10
  423. package/dist/providers/mixpanel/value-safety.js +0 -16
  424. package/dist/providers/notion/index.d.ts +0 -67
  425. package/dist/providers/notion/index.js +0 -368
  426. package/dist/providers/notion/openapi.generated.js +0 -75
  427. package/dist/providers/notion/rest.d.ts +0 -24
  428. package/dist/providers/notion/rest.js +0 -1226
  429. package/dist/providers/notion/skill.generated.js +0 -11
  430. package/dist/providers/notion/value-safety.js +0 -56
  431. package/dist/providers/revenuecat/index.d.ts +0 -51
  432. package/dist/providers/revenuecat/index.js +0 -697
  433. package/dist/providers/revenuecat/skill.generated.js +0 -11
  434. package/dist/providers/stripe/rest.d.ts +0 -14
  435. package/dist/providers/stripe/rest.js +0 -402
  436. package/dist/providers/vercel/rest.d.ts +0 -20
  437. package/dist/providers/vercel/rest.js +0 -1020
  438. package/dist/providers/wispr-flow/index.d.ts +0 -14
  439. package/dist/providers/wispr-flow/index.js +0 -117
  440. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  441. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
package/dist/skills.js CHANGED
@@ -1,3 +1,7 @@
1
+ import { duringViewEffect } from "./runtime/call.js";
2
+ import { RequestScope, requestOwner } from "./runtime/request-scope.js";
3
+ import { upwardStep } from "./upward.js";
4
+ import { authCall, authInvoke, authFlow, authMethod, registerAuth, registerAuthMethod, authOwnMethod, } from "./auth/native.js";
1
5
  import { USAGE_SKILL } from "./usage-guide.js";
2
6
  import { boundedEchoText, ConnectorCallError } from "./errors.js";
3
7
  import { Effect } from "effect";
@@ -20,10 +24,14 @@ export const CONNECTA_INSTRUCTIONS = `${ROUTE} On a writable endpoint, programs
20
24
  * comes from deployment config for the pool the request was admitted through;
21
25
  * nothing a request sends reaches it.
22
26
  */
23
- export function endpointInstructions(description) {
24
- return description === undefined ? CONNECTA_INSTRUCTIONS : `${CONNECTA_INSTRUCTIONS} This endpoint: ${description}`;
27
+ export function endpointInstructions(description, native) {
28
+ const instructions = native ? nativeInstructions(native.executeCode) : CONNECTA_INSTRUCTIONS;
29
+ return description === undefined ? instructions : `${instructions} This endpoint: ${description}`;
30
+ }
31
+ /** Instructions for pools whose host searches the listed native tools. */
32
+ export function nativeInstructions(executeCode) {
33
+ return `Each tool here is one operation; annotations classify reads/writes. Call known tools directly; ${executeCode ? "combine work in execute_code using the program addresses in tool descriptions." : "find tools with your host's search."} Read-only endpoints omit and refuse writes. Never repeat a write for output. Give auth handoffs to the user/operator. Follow nextAction to page with ${executeCode ? "connecta.result in execute_code" : "read_result"}. skills lists guidance.`;
25
34
  }
26
- export { USAGE_SKILL } from "./usage-guide.js";
27
35
  /** True when at least one of `connectors` carries a usage guide. */
28
36
  export function hasConnectorGuides(connectors) {
29
37
  return connectors.some((connector) => connectorGuide(connector) !== undefined);
@@ -346,38 +354,44 @@ function localRecord(name, uri, description, content, aliases) {
346
354
  function validSkillName(name) {
347
355
  return name.length <= 64 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
348
356
  }
349
- async function localRecords(connectors) {
350
- const builtIns = AVAILABLE_SKILLS.map((skill) => localRecord(skill.name, `skill://connecta/${skill.name}/SKILL.md`, skill.description, skill.content(), [
351
- skill.name,
352
- `skill://connecta/${skill.name}`,
353
- ]));
354
- const guides = await Promise.all(connectors
355
- .filter((connector) => connectorGuide(connector) !== undefined)
356
- .sort((a, b) => Number(connectorGuideRequired(b)) - Number(connectorGuideRequired(a)) ||
357
- (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
358
- .map(async (connector) => {
359
- const name = validSkillName(connector.id)
360
- ? connector.id
361
- : `connector-${[...new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(connector.id)))]
362
- .map((byte) => byte.toString(16).padStart(2, "0"))
363
- .join("")
364
- .slice(0, 48)}`;
365
- const description = connectorGuideSummary(connector);
366
- const root = `skill://connecta/connectors/${encodeURIComponent(name)}`;
367
- const content = `---\n${JSON.stringify({ name, description }, null, 2)}\n---\n\n${connectorGuide(connector)}`;
368
- return {
369
- ...localRecord(name, `${root}/SKILL.md`, description, content, [
370
- connectorSkillName(connector.id),
371
- `skill://connecta/connectors/${encodeURIComponent(connector.id)}`,
372
- root,
373
- ]),
374
- connector,
375
- };
376
- }));
377
- if (new Set(guides.map((guide) => guide.entry.uri)).size !== guides.length)
378
- throw new ConnectorCallError("unavailable", "Connector skill slugs collide.");
379
- return [builtIns[0], ...guides, ...builtIns.slice(1)];
357
+ function localRecords(connectors) {
358
+ return runEdge(localRecordsNative(connectors));
380
359
  }
360
+ const localRecordsNative = /* @__PURE__ */ registerAuth(localRecords, function (connectors) {
361
+ return authFlow(function* () {
362
+ const builtIns = AVAILABLE_SKILLS.map((skill) => localRecord(skill.name, `skill://connecta/${skill.name}/SKILL.md`, skill.description, skill.content(), [
363
+ skill.name,
364
+ `skill://connecta/${skill.name}`,
365
+ ]));
366
+ const guides = yield* upwardStep(Effect.forEach(connectors
367
+ .filter((connector) => connectorGuide(connector) !== undefined)
368
+ .sort((a, b) => Number(connectorGuideRequired(b)) - Number(connectorGuideRequired(a)) ||
369
+ (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)), (connector) => authFlow(function* () {
370
+ const name = validSkillName(connector.id)
371
+ ? connector.id
372
+ : `connector-${[
373
+ ...new Uint8Array(yield* upwardStep(authInvoke(crypto.subtle, "digest", ["SHA-256", encoder.encode(connector.id)]))),
374
+ ]
375
+ .map((byte) => byte.toString(16).padStart(2, "0"))
376
+ .join("")
377
+ .slice(0, 48)}`;
378
+ const description = connectorGuideSummary(connector);
379
+ const root = `skill://connecta/connectors/${encodeURIComponent(name)}`;
380
+ const content = `---\n${JSON.stringify({ name, description }, null, 2)}\n---\n\n${connectorGuide(connector)}`;
381
+ return {
382
+ ...localRecord(name, `${root}/SKILL.md`, description, content, [
383
+ connectorSkillName(connector.id),
384
+ `skill://connecta/connectors/${encodeURIComponent(connector.id)}`,
385
+ root,
386
+ ]),
387
+ connector,
388
+ };
389
+ }), { concurrency: "unbounded" }));
390
+ if (new Set(guides.map((guide) => guide.entry.uri)).size !== guides.length)
391
+ throw new ConnectorCallError("unavailable", "Connector skill slugs collide.");
392
+ return [builtIns[0], ...guides, ...builtIns.slice(1)];
393
+ });
394
+ });
381
395
  /** Keep the downstream path tree, so relative supporting-file references still resolve. */
382
396
  export function downstreamSkillUri(connectorId, uri) {
383
397
  if (uri.length > 32_768)
@@ -452,18 +466,28 @@ function validateEntry(entry) {
452
466
  if (!files.has(entry.uri) || bytes > MAX_SKILL_BYTES)
453
467
  throw new ConnectorCallError("unavailable", "Downstream skill manifest is incomplete or oversized.");
454
468
  }
455
- async function withManifest(record) {
456
- const bytes = encoder.encode(record.content);
457
- if (bytes.length > MAX_SKILL_BYTES)
458
- throw new ConnectorCallError("unavailable", "Local skill exceeds the byte bound.");
459
- const digest = [...new Uint8Array(await crypto.subtle.digest("SHA-256", bytes))]
460
- .map((byte) => byte.toString(16).padStart(2, "0"))
461
- .join("");
462
- return {
463
- ...record,
464
- entry: { ...record.entry, resources: [{ uri: record.entry.uri, digest: `sha256:${digest}`, size: bytes.length }] },
465
- };
469
+ function withManifest(record) {
470
+ return runEdge(withManifestNative(record));
466
471
  }
472
+ const withManifestNative = /* @__PURE__ */ registerAuth(withManifest, function (record) {
473
+ return authFlow(function* () {
474
+ const bytes = encoder.encode(record.content);
475
+ if (bytes.length > MAX_SKILL_BYTES)
476
+ throw new ConnectorCallError("unavailable", "Local skill exceeds the byte bound.");
477
+ const digest = [
478
+ ...new Uint8Array(yield* upwardStep(authInvoke(crypto.subtle, "digest", ["SHA-256", bytes]))),
479
+ ]
480
+ .map((byte) => byte.toString(16).padStart(2, "0"))
481
+ .join("");
482
+ return {
483
+ ...record,
484
+ entry: {
485
+ ...record.entry,
486
+ resources: [{ uri: record.entry.uri, digest: `sha256:${digest}`, size: bytes.length }],
487
+ },
488
+ };
489
+ });
490
+ });
467
491
  /**
468
492
  * One caller-view registry for native methods, the meta-tool and the guest API.
469
493
  * No content reaches storage or operator sinks. Downstream skills use uncached
@@ -481,42 +505,15 @@ export class SkillsRegistry {
481
505
  this.registry = registry;
482
506
  this.baseUrl = baseUrl;
483
507
  this.options = options;
508
+ void SkillsRegistry.nativePrograms;
484
509
  this.scope = options.requestScope ?? {};
485
- this.local = localRecords(registry.listConnectors());
510
+ this.local = authCall(localRecords, [registry.listConnectors()]);
486
511
  }
487
512
  operation(connector, read) {
488
- const timeoutMs = this.options.probeTimeoutMs ?? 20_000;
489
- const operationScope = {};
490
- sentSecretsForRequest(this.scope).include(sentSecretsForRequest(operationScope));
491
- return runEdge(withDeadlineEffect((signal) => Effect.scoped(Effect.gen({ self: this }, function* () {
492
- const ctx = this.registry.contextFor(connector.id, this.baseUrl, operationScope, {
493
- signal,
494
- timeoutMs,
495
- ...(this.options.defer ? { defer: this.options.defer } : {}),
496
- });
497
- yield* closeScopeOnExit(connector, ctx, this.options.defer);
498
- return yield* Effect.tryPromise({
499
- try: () => read(ctx),
500
- catch: (error) => error instanceof ConnectorCallError && error.code === "auth_required"
501
- ? new ConnectorCallError("auth_required", "Downstream skills require authorization.")
502
- : new ConnectorCallError("unavailable", "Downstream skills are unavailable."),
503
- });
504
- })), {
505
- timeoutMs,
506
- ...(this.options.requestSignal ? { signal: this.options.requestSignal } : {}),
507
- timeoutError: new ConnectorCallError("unavailable", "Downstream skills timed out."),
508
- }), { signal: this.options.requestSignal });
513
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "operation", [connector, read]));
509
514
  }
510
- async records() {
511
- if (!this.snapshot) {
512
- this.snapshot = this.build();
513
- this.snapshot.catch(() => {
514
- this.snapshot = undefined;
515
- });
516
- }
517
- const records = await this.snapshot;
518
- this.assertSafe(records);
519
- return records;
515
+ records() {
516
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "records", []));
520
517
  }
521
518
  /** Later catalog/read operations can add credentials to this request. */
522
519
  assertSafe(records) {
@@ -536,71 +533,11 @@ export class SkillsRegistry {
536
533
  }
537
534
  }
538
535
  }
539
- async build() {
540
- const records = await Promise.all((await this.local).map(withManifest));
541
- let catalogBytes = jsonBytes(records.map((record) => record.entry));
542
- // Bounded sequential connector reads avoid unbounded fan-out and finish
543
- // cleanup before a later connector's failure can end the whole listing.
544
- for (const connector of this.registry.listConnectors()) {
545
- if (!connector.downstreamSkills || !this.registry.canReadConnectorSkills(connector.id))
546
- continue;
547
- const entries = await this.operation(connector, (ctx) => connector.downstreamSkills.list(ctx));
548
- if (!Array.isArray(entries) || records.length + entries.length > MAX_SKILLS)
549
- throw new ConnectorCallError("unavailable", "Downstream skills listing exceeds its bound.");
550
- for (const original of entries) {
551
- if (catalogBytes + jsonBytes(original) + 1 > MAX_SKILL_CATALOG_BYTES)
552
- throw new ConnectorCallError("unavailable", "Skills listing exceeds its byte bound.");
553
- const entry = structuredClone(original);
554
- validateEntry(entry);
555
- const files = new Map();
556
- const uri = downstreamSkillUri(connector.id, entry.uri);
557
- const secrets = sentSecretsForRequest(this.scope);
558
- if (secrets.containsUrl(entry.uri))
559
- throw new ConnectorCallError("unavailable", "Downstream skill URI contains sent credentials.");
560
- files.set(uri, entry.uri);
561
- const resources = entry.resources === "dynamic"
562
- ? "dynamic"
563
- : entry.resources.map((file) => {
564
- const uri = downstreamSkillUri(connector.id, file.uri);
565
- if (secrets.containsUrl(file.uri))
566
- throw new ConnectorCallError("unavailable", "Downstream skill URI contains sent credentials.");
567
- files.set(uri, file.uri);
568
- return { ...file, uri };
569
- });
570
- if (records.some((record) => record.entry.uri === uri))
571
- throw new ConnectorCallError("unavailable", "Downstream skills listing contains duplicate entries.");
572
- const mapped = { ...entry, uri, resources };
573
- catalogBytes += jsonBytes(mapped) + 1;
574
- if (catalogBytes > MAX_SKILL_CATALOG_BYTES)
575
- throw new ConnectorCallError("unavailable", "Skills listing exceeds its byte bound.");
576
- records.push({ entry: mapped, aliases: [], connector, files });
577
- }
578
- }
579
- if (records.length > MAX_SKILLS || jsonBytes(records.map((record) => record.entry)) > MAX_SKILL_CATALOG_BYTES) {
580
- throw new ConnectorCallError("unavailable", "Skills listing exceeds its byte or entry bound.");
581
- }
582
- // Keep the old investigation guide behind every connector and downstream
583
- // guide, where it cannot consume one of the first five import slots.
584
- const investigate = records.findIndex((record) => record.aliases.includes("investigate"));
585
- if (investigate >= 0)
586
- records.push(records.splice(investigate, 1)[0]);
587
- this.assertSafe(records);
588
- return records;
536
+ build() {
537
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "build", []));
589
538
  }
590
- async lookup(uri) {
591
- const local = (await this.local).find((record) => record.entry.uri === uri || record.aliases.includes(uri));
592
- if (local) {
593
- const record = await withManifest(local);
594
- this.assertSafe([record]);
595
- return record;
596
- }
597
- // A non-skill URI never starts a downstream resource request or listing.
598
- if (!uri.startsWith("skill://downstream/"))
599
- throw this.missing(uri);
600
- const record = (await this.records()).find((record) => record.entry.uri === uri);
601
- if (!record)
602
- throw this.missing(uri);
603
- return record;
539
+ lookup(uri) {
540
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "lookup", [uri]));
604
541
  }
605
542
  missing(name) {
606
543
  const guides = this.registry.listConnectors().filter((connector) => connectorGuide(connector) !== undefined);
@@ -624,92 +561,254 @@ export class SkillsRegistry {
624
561
  : `Unknown skill "${boundedEchoText(name)}".`;
625
562
  return new ConnectorCallError("not_found", `${message} Available skills: ${available}.`);
626
563
  }
627
- async list(cursor) {
628
- const records = await this.records();
629
- const offset = cursor === undefined ? 0 : /^skills:[1-9][0-9]*$/.test(cursor) ? Number(cursor.slice(7)) : NaN;
630
- if (!Number.isSafeInteger(offset) || offset % SKILL_PAGE_SIZE !== 0 || offset >= records.length)
631
- throw new ConnectorCallError("invalid_args", "Invalid skills cursor.");
632
- return {
633
- ...PRIVATE,
634
- skills: records.slice(offset, offset + SKILL_PAGE_SIZE).map((record) => record.entry),
635
- ...(offset + SKILL_PAGE_SIZE < records.length ? { nextCursor: `skills:${offset + SKILL_PAGE_SIZE}` } : {}),
636
- };
564
+ list(cursor) {
565
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "list", [cursor]));
637
566
  }
638
- async get(uri) {
639
- return { ...PRIVATE, skill: (await this.lookup(uri)).entry };
567
+ get(uri) {
568
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "get", [uri]));
640
569
  }
641
- async resources(cursor) {
642
- const page = await this.list(cursor);
643
- return {
644
- ...PRIVATE,
645
- resources: page.skills.flatMap((skill) => (skill.resources === "dynamic" ? [{ uri: skill.uri }] : skill.resources).map((file) => ({
646
- uri: file.uri,
647
- name: file.uri === skill.uri ? String(skill.frontmatter.name) : file.uri.slice(file.uri.lastIndexOf("/") + 1),
648
- ...(file.uri === skill.uri
649
- ? { description: String(skill.frontmatter.description), mimeType: "text/markdown" }
650
- : {}),
651
- ...("size" in file ? { size: file.size } : {}),
652
- }))),
653
- ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),
654
- };
570
+ resources(cursor) {
571
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "resources", [cursor]));
655
572
  }
656
- async read(uri) {
657
- const local = (await this.local).find((record) => record.entry.uri === uri || record.aliases.includes(uri));
658
- if (local) {
659
- const record = await withManifest(local);
660
- this.assertSafe([record]);
661
- if (record.connector)
662
- this.options.onRead?.(record.connector, "local");
663
- // A connector guide is operator-authored payload, like a downstream file; built-in guides are Connecta's own.
664
- const text = record.connector ? sentSecretsForRequest(this.scope).redact(record.content) : record.content;
665
- return { ...PRIVATE, contents: [{ uri: record.entry.uri, mimeType: "text/markdown", text }] };
666
- }
667
- if (!uri.startsWith("skill://downstream/"))
668
- throw this.missing(uri);
669
- const record = (await this.records()).find((record) => record.files?.has(uri));
670
- if (!record?.connector || !record.files || !this.registry.canReadConnectorSkills(record.connector.id))
671
- throw this.missing(uri);
672
- const originalUri = record.files.get(uri);
673
- const contents = await this.operation(record.connector, (ctx) => record.connector.downstreamSkills.read(originalUri, ctx));
674
- // Structural fields and preserved digests cannot be repaired by the
675
- // output boundary after this read has sent another credential.
676
- await this.records();
677
- if (!Array.isArray(contents) || contents.length !== 1 || contents[0]?.uri !== originalUri)
678
- throw new ConnectorCallError("unavailable", "Downstream skill read returned unexpected files.");
679
- const content = contents[0];
680
- if (!content || (typeof content.text === "string") === (typeof content.blob === "string"))
681
- throw new ConnectorCallError("unavailable", "Downstream skill read did not return one file.");
682
- let bytes;
683
- try {
684
- bytes = typeof content.text === "string" ? encoder.encode(content.text).length : atob(content.blob).length;
685
- }
686
- catch {
687
- throw new ConnectorCallError("unavailable", "Downstream skill file is not valid base64.");
688
- }
689
- if (bytes > MAX_SKILL_BYTES)
690
- throw new ConnectorCallError("unavailable", "Downstream skill file exceeds the byte bound.");
691
- this.options.onRead?.(record.connector, "downstream");
692
- // Downstream file contents take the request's full payload rules before any reader sees them.
693
- const clean = sentSecretsForRequest(this.scope).redact(content);
694
- return { ...PRIVATE, contents: [{ ...clean, uri }] };
573
+ read(uri) {
574
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "read", [uri]));
695
575
  }
696
- async text(name) {
697
- const record = await this.lookup(name);
698
- const content = (await this.read(record.entry.uri)).contents[0];
699
- if (typeof content.text === "string")
700
- return content.text;
701
- try {
702
- return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(Uint8Array.from(atob(content.blob), (char) => char.charCodeAt(0)));
703
- }
704
- catch {
705
- throw new ConnectorCallError("unavailable", "Skill instructions are not UTF-8 text.");
706
- }
576
+ text(name) {
577
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "text", [name]));
707
578
  }
708
- async summaries() {
709
- return (await this.records()).map((record) => ({
710
- name: record.aliases[0] ?? record.entry.uri,
711
- uri: record.entry.uri,
712
- description: String(record.entry.frontmatter.description),
713
- }));
579
+ summaries() {
580
+ return runEdge(authOwnMethod(SkillsRegistry.prototype, this, "summaries", []));
714
581
  }
582
+ static nativePrograms = /* @__PURE__ */ (() => {
583
+ registerAuthMethod(SkillsRegistry.prototype, "summaries", function () {
584
+ const self = this;
585
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
586
+ return (yield* upwardStep(authInvoke(self, "records", []))).map((record) => ({
587
+ name: record.aliases[0] ?? record.entry.uri,
588
+ uri: record.entry.uri,
589
+ description: String(record.entry.frontmatter.description),
590
+ }));
591
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
592
+ }, SkillsRegistry.prototype.summaries);
593
+ registerAuthMethod(SkillsRegistry.prototype, "text", function (name) {
594
+ const self = this;
595
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
596
+ const record = yield* upwardStep(authInvoke(self, "lookup", [name]));
597
+ const content = (yield* upwardStep(authInvoke(self, "read", [record.entry.uri]))).contents[0];
598
+ if (typeof content.text === "string")
599
+ return content.text;
600
+ try {
601
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(Uint8Array.from(atob(content.blob), (char) => char.charCodeAt(0)));
602
+ }
603
+ catch {
604
+ throw new ConnectorCallError("unavailable", "Skill instructions are not UTF-8 text.");
605
+ }
606
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
607
+ }, SkillsRegistry.prototype.text);
608
+ registerAuthMethod(SkillsRegistry.prototype, "read", function (uri) {
609
+ const self = this;
610
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
611
+ const local = (yield* upwardStep(self.local)).find((record) => record.entry.uri === uri || record.aliases.includes(uri));
612
+ if (local) {
613
+ const record = yield* upwardStep(authCall(withManifest, [local]));
614
+ self.assertSafe([record]);
615
+ if (record.connector)
616
+ self.options.onRead?.(record.connector, "local");
617
+ // A connector guide is operator-authored payload, like a downstream file; built-in guides are Connecta's own.
618
+ const text = record.connector
619
+ ? sentSecretsForRequest(self.scope).redact(record.content)
620
+ : record.content;
621
+ return { ...PRIVATE, contents: [{ uri: record.entry.uri, mimeType: "text/markdown", text }] };
622
+ }
623
+ if (!uri.startsWith("skill://downstream/"))
624
+ throw self.missing(uri);
625
+ const record = (yield* upwardStep(authInvoke(self, "records", []))).find((record) => record.files?.has(uri));
626
+ if (!record?.connector || !record.files || !self.registry.canReadConnectorSkills(record.connector.id))
627
+ throw self.missing(uri);
628
+ const originalUri = record.files.get(uri);
629
+ const contents = yield* upwardStep(authInvoke(self, "operation", [
630
+ record.connector,
631
+ authMethod((ctx) => authInvoke(record.connector.downstreamSkills, "read", [
632
+ originalUri,
633
+ ctx,
634
+ ])),
635
+ ]));
636
+ // Structural fields and preserved digests cannot be repaired by the
637
+ // output boundary after this read has sent another credential.
638
+ yield* upwardStep(authInvoke(self, "records", []));
639
+ if (!Array.isArray(contents) || contents.length !== 1 || contents[0]?.uri !== originalUri)
640
+ throw new ConnectorCallError("unavailable", "Downstream skill read returned unexpected files.");
641
+ const content = contents[0];
642
+ if (!content || (typeof content.text === "string") === (typeof content.blob === "string"))
643
+ throw new ConnectorCallError("unavailable", "Downstream skill read did not return one file.");
644
+ let bytes;
645
+ try {
646
+ bytes =
647
+ typeof content.text === "string" ? encoder.encode(content.text).length : atob(content.blob).length;
648
+ }
649
+ catch {
650
+ throw new ConnectorCallError("unavailable", "Downstream skill file is not valid base64.");
651
+ }
652
+ if (bytes > MAX_SKILL_BYTES)
653
+ throw new ConnectorCallError("unavailable", "Downstream skill file exceeds the byte bound.");
654
+ self.options.onRead?.(record.connector, "downstream");
655
+ // Downstream file contents take the request's full payload rules before any reader sees them.
656
+ const clean = sentSecretsForRequest(self.scope).redact(content);
657
+ return { ...PRIVATE, contents: [{ ...clean, uri }] };
658
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
659
+ }, SkillsRegistry.prototype.read);
660
+ registerAuthMethod(SkillsRegistry.prototype, "resources", function (cursor) {
661
+ const self = this;
662
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
663
+ const page = yield* upwardStep(authInvoke(self, "list", [cursor]));
664
+ return {
665
+ ...PRIVATE,
666
+ resources: page.skills.flatMap((skill) => (skill.resources === "dynamic" ? [{ uri: skill.uri }] : skill.resources).map((file) => ({
667
+ uri: file.uri,
668
+ name: file.uri === skill.uri
669
+ ? String(skill.frontmatter.name)
670
+ : file.uri.slice(file.uri.lastIndexOf("/") + 1),
671
+ ...(file.uri === skill.uri
672
+ ? { description: String(skill.frontmatter.description), mimeType: "text/markdown" }
673
+ : {}),
674
+ ...("size" in file ? { size: file.size } : {}),
675
+ }))),
676
+ ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),
677
+ };
678
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
679
+ }, SkillsRegistry.prototype.resources);
680
+ registerAuthMethod(SkillsRegistry.prototype, "get", function (uri) {
681
+ const self = this;
682
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
683
+ return { ...PRIVATE, skill: (yield* upwardStep(authInvoke(self, "lookup", [uri]))).entry };
684
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
685
+ }, SkillsRegistry.prototype.get);
686
+ registerAuthMethod(SkillsRegistry.prototype, "list", function (cursor) {
687
+ const self = this;
688
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
689
+ const records = yield* upwardStep(authInvoke(self, "records", []));
690
+ const offset = cursor === undefined ? 0 : /^skills:[1-9][0-9]*$/.test(cursor) ? Number(cursor.slice(7)) : NaN;
691
+ if (!Number.isSafeInteger(offset) || offset % SKILL_PAGE_SIZE !== 0 || offset >= records.length)
692
+ throw new ConnectorCallError("invalid_args", "Invalid skills cursor.");
693
+ return {
694
+ ...PRIVATE,
695
+ skills: records.slice(offset, offset + SKILL_PAGE_SIZE).map((record) => record.entry),
696
+ ...(offset + SKILL_PAGE_SIZE < records.length
697
+ ? { nextCursor: `skills:${offset + SKILL_PAGE_SIZE}` }
698
+ : {}),
699
+ };
700
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
701
+ }, SkillsRegistry.prototype.list);
702
+ registerAuthMethod(SkillsRegistry.prototype, "lookup", function (uri) {
703
+ const self = this;
704
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
705
+ const local = (yield* upwardStep(self.local)).find((record) => record.entry.uri === uri || record.aliases.includes(uri));
706
+ if (local) {
707
+ const record = yield* upwardStep(authCall(withManifest, [local]));
708
+ self.assertSafe([record]);
709
+ return record;
710
+ }
711
+ // A non-skill URI never starts a downstream resource request or listing.
712
+ if (!uri.startsWith("skill://downstream/"))
713
+ throw self.missing(uri);
714
+ const record = (yield* upwardStep(authInvoke(self, "records", []))).find((record) => record.entry.uri === uri);
715
+ if (!record)
716
+ throw self.missing(uri);
717
+ return record;
718
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
719
+ }, SkillsRegistry.prototype.lookup);
720
+ registerAuthMethod(SkillsRegistry.prototype, "build", function () {
721
+ const self = this;
722
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => authFlow(function* () {
723
+ const records = yield* upwardStep(Effect.forEach(yield* upwardStep(self.local), (record) => authCall(withManifest, [record]), {
724
+ concurrency: "unbounded",
725
+ }));
726
+ let catalogBytes = jsonBytes(records.map((record) => record.entry));
727
+ // Bounded sequential connector reads avoid unbounded fan-out and finish
728
+ // cleanup before a later connector's failure can end the whole listing.
729
+ for (const connector of self.registry.listConnectors()) {
730
+ if (!connector.downstreamSkills || !self.registry.canReadConnectorSkills(connector.id))
731
+ continue;
732
+ const entries = yield* upwardStep(authInvoke(self, "operation", [
733
+ connector,
734
+ authMethod((ctx) => authInvoke(connector.downstreamSkills, "list", [ctx])),
735
+ ]));
736
+ if (!Array.isArray(entries) || records.length + entries.length > MAX_SKILLS)
737
+ throw new ConnectorCallError("unavailable", "Downstream skills listing exceeds its bound.");
738
+ for (const original of entries) {
739
+ if (catalogBytes + jsonBytes(original) + 1 > MAX_SKILL_CATALOG_BYTES)
740
+ throw new ConnectorCallError("unavailable", "Skills listing exceeds its byte bound.");
741
+ const entry = structuredClone(original);
742
+ validateEntry(entry);
743
+ const files = new Map();
744
+ const uri = downstreamSkillUri(connector.id, entry.uri);
745
+ const secrets = sentSecretsForRequest(self.scope);
746
+ if (secrets.containsUrl(entry.uri))
747
+ throw new ConnectorCallError("unavailable", "Downstream skill URI contains sent credentials.");
748
+ files.set(uri, entry.uri);
749
+ const resources = entry.resources === "dynamic"
750
+ ? "dynamic"
751
+ : entry.resources.map((file) => {
752
+ const uri = downstreamSkillUri(connector.id, file.uri);
753
+ if (secrets.containsUrl(file.uri))
754
+ throw new ConnectorCallError("unavailable", "Downstream skill URI contains sent credentials.");
755
+ files.set(uri, file.uri);
756
+ return { ...file, uri };
757
+ });
758
+ if (records.some((record) => record.entry.uri === uri))
759
+ throw new ConnectorCallError("unavailable", "Downstream skills listing contains duplicate entries.");
760
+ const mapped = { ...entry, uri, resources };
761
+ catalogBytes += jsonBytes(mapped) + 1;
762
+ if (catalogBytes > MAX_SKILL_CATALOG_BYTES)
763
+ throw new ConnectorCallError("unavailable", "Skills listing exceeds its byte bound.");
764
+ records.push({ entry: mapped, aliases: [], connector, files });
765
+ }
766
+ }
767
+ if (records.length > MAX_SKILLS ||
768
+ jsonBytes(records.map((record) => record.entry)) > MAX_SKILL_CATALOG_BYTES) {
769
+ throw new ConnectorCallError("unavailable", "Skills listing exceeds its byte or entry bound.");
770
+ }
771
+ // Keep the old investigation guide behind every connector and downstream
772
+ // guide, where it cannot consume one of the first five import slots.
773
+ const investigate = records.findIndex((record) => record.aliases.includes("investigate"));
774
+ if (investigate >= 0)
775
+ records.push(records.splice(investigate, 1)[0]);
776
+ self.assertSafe(records);
777
+ return records;
778
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
779
+ }, SkillsRegistry.prototype.build);
780
+ registerAuthMethod(SkillsRegistry.prototype, "records", function () {
781
+ const instance = this;
782
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => Effect.gen(function* () {
783
+ if (!instance.snapshot)
784
+ instance.snapshot = yield* Effect.cached(authInvoke(instance, "build", []).pipe(Effect.onError(() => Effect.sync(() => {
785
+ instance.snapshot = undefined;
786
+ }))));
787
+ const records = yield* instance.snapshot;
788
+ instance.assertSafe(records);
789
+ return records;
790
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
791
+ }, SkillsRegistry.prototype.records);
792
+ registerAuthMethod(SkillsRegistry.prototype, "operation", function (connector, read) {
793
+ const self = this;
794
+ const timeoutMs = self.options.probeTimeoutMs ?? 20_000;
795
+ const operationScope = {};
796
+ sentSecretsForRequest(self.scope).include(sentSecretsForRequest(operationScope));
797
+ return duringViewEffect({ requestScope: this.scope, signal: this.options.requestSignal }, () => withDeadlineEffect((signal) => Effect.scoped(Effect.gen(function* () {
798
+ const ctx = self.registry.contextFor(connector.id, self.baseUrl, operationScope, {
799
+ signal,
800
+ timeoutMs,
801
+ ...(self.options.defer ? { defer: self.options.defer } : {}),
802
+ });
803
+ yield* closeScopeOnExit(connector, ctx, self.options.defer);
804
+ return yield* authCall(read, [ctx]).pipe(Effect.mapError((error) => error instanceof ConnectorCallError && error.code === "auth_required"
805
+ ? new ConnectorCallError("auth_required", "Downstream skills require authorization.")
806
+ : new ConnectorCallError("unavailable", "Downstream skills are unavailable.")));
807
+ })), {
808
+ timeoutMs,
809
+ ...(self.options.requestSignal ? { signal: self.options.requestSignal } : {}),
810
+ timeoutError: new ConnectorCallError("unavailable", "Downstream skills timed out."),
811
+ })).pipe(Effect.provideService(RequestScope, requestOwner(this.scope)));
812
+ }, SkillsRegistry.prototype.operation);
813
+ })();
715
814
  }
package/dist/sqlite.js CHANGED
@@ -7,6 +7,7 @@
7
7
  import { chmodSync, closeSync, mkdirSync, openSync, readFileSync } from "node:fs";
8
8
  import { dirname, resolve } from "node:path";
9
9
  import { DatabaseSync } from "node:sqlite";
10
+ import { effectSqlDriver, sqlDriverEdge, sqlSync } from "./storage/sql-driver.js";
10
11
  import { validateStorageKey } from "./storage/keys.js";
11
12
  import { KV_SCHEMA, sqlActivityStore, sqlStorage, } from "./storage/sql.js";
12
13
  /** Milliseconds a write waits for another process's write lock. */
@@ -58,17 +59,12 @@ function sqliteDriver(database) {
58
59
  const run = (statement) => {
59
60
  return Number(prepare(statement).run(...statement.params).changes);
60
61
  };
61
- const driver = {
62
- async all(statement) {
63
- return prepare(statement).all(...statement.params);
64
- },
65
- async run(statement) {
66
- return run(statement);
67
- },
68
- async batch(batch) {
69
- // Synchronous from BEGIN to COMMIT: no other call on this connection
70
- // can interleave, and IMMEDIATE takes the write lock up front so
71
- // another process cannot either.
62
+ const driver = sqlDriverEdge(effectSqlDriver({
63
+ all: (statement) => sqlSync(() => prepare(statement).all(...statement.params)),
64
+ run: (statement) => sqlSync(() => run(statement)),
65
+ batch: (batch) => sqlSync(() => {
66
+ // One synchronous native leaf: no fiber can yield between BEGIN and
67
+ // COMMIT and let another caller interleave on this DatabaseSync.
72
68
  db.exec("BEGIN IMMEDIATE");
73
69
  try {
74
70
  const changes = batch.map(run);
@@ -76,11 +72,16 @@ function sqliteDriver(database) {
76
72
  return changes;
77
73
  }
78
74
  catch (error) {
79
- db.exec("ROLLBACK");
75
+ try {
76
+ db.exec("ROLLBACK");
77
+ }
78
+ catch {
79
+ /* Preserve the original failure. */
80
+ }
80
81
  throw error;
81
82
  }
82
- },
83
- };
83
+ }),
84
+ }));
84
85
  drivers.set(db, driver);
85
86
  return driver;
86
87
  }