@zackbart/connecta 0.28.1 → 0.29.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 (319) hide show
  1. package/CHANGELOG.md +788 -5
  2. package/README.md +62 -42
  3. package/bin/connecta.mjs +110 -139
  4. package/bin/meta-tool-names.d.mts +2 -0
  5. package/bin/meta-tool-names.mjs +9 -0
  6. package/bin/version.mjs +3 -0
  7. package/dist/access-tokens.js +53 -63
  8. package/dist/activity-request.js +8 -0
  9. package/dist/activity.d.ts +76 -42
  10. package/dist/activity.js +110 -42
  11. package/dist/auth/clerk-sdk/client.d.ts +65 -0
  12. package/dist/auth/clerk-sdk/client.js +5 -0
  13. package/dist/auth/clerk-sdk/generated.js +1845 -0
  14. package/dist/auth/clerk-transport.js +19 -0
  15. package/dist/auth/clerk.d.ts +17 -7
  16. package/dist/auth/clerk.js +189 -107
  17. package/dist/auth/cloudflare-access.js +25 -26
  18. package/dist/auth/downstream-client-metadata.d.ts +29 -0
  19. package/dist/auth/downstream-client-metadata.js +133 -0
  20. package/dist/auth/downstream-oauth.js +1584 -1580
  21. package/dist/auth/downstream-revocation.js +106 -0
  22. package/dist/auth/oauth-token-response.js +231 -0
  23. package/dist/auth/oauth-v2-migration.js +116 -0
  24. package/dist/auth/static-oauth.js +93 -71
  25. package/dist/auth-elicitation.js +283 -0
  26. package/dist/branding.d.ts +8 -16
  27. package/dist/branding.js +26 -59
  28. package/dist/byte-read-response.js +39 -0
  29. package/dist/call-admission.js +12 -16
  30. package/dist/catalog-cache.js +739 -0
  31. package/dist/catalog-drift.d.ts +50 -15
  32. package/dist/catalog-drift.js +365 -128
  33. package/dist/catalog-fingerprint.js +2 -4
  34. package/dist/catalog-freshness.js +13 -0
  35. package/dist/catalog-limits.js +2 -2
  36. package/dist/catalog-service.js +368 -224
  37. package/dist/catalog.js +43 -84
  38. package/dist/concurrency.js +3 -4
  39. package/dist/config-defaults.d.ts +39 -0
  40. package/dist/config-defaults.js +46 -0
  41. package/dist/config-schema.d.ts +181 -0
  42. package/dist/config-schema.js +435 -0
  43. package/dist/config-value-sources.js +102 -0
  44. package/dist/config.d.ts +631 -0
  45. package/dist/config.js +503 -0
  46. package/dist/connector-access.d.ts +1 -0
  47. package/dist/connector-access.js +13 -15
  48. package/dist/connector-caller.d.ts +8 -0
  49. package/dist/connector-caller.js +15 -6
  50. package/dist/connector-scope.js +1 -1
  51. package/dist/connectors/api-connector.d.ts +59 -7
  52. package/dist/connectors/api-connector.js +106 -19
  53. package/dist/connectors/api.js +4 -1
  54. package/dist/connectors/guarded-fetch.d.ts +144 -0
  55. package/dist/connectors/guarded-fetch.js +84 -35
  56. package/dist/connectors/negotiation-cache.js +46 -0
  57. package/dist/connectors/option-shapes.js +27 -0
  58. package/dist/connectors/remote-mcp.d.ts +30 -4
  59. package/dist/connectors/remote-mcp.js +1774 -320
  60. package/dist/connectors/resource-uri.js +335 -0
  61. package/dist/credential-contract.d.ts +10 -0
  62. package/dist/credential-rules.js +1 -3
  63. package/dist/credential-url.js +108 -0
  64. package/dist/credentials.d.ts +6 -1
  65. package/dist/credentials.js +27 -18
  66. package/dist/d1.d.ts +130 -0
  67. package/dist/d1.js +290 -0
  68. package/dist/describe-config.d.ts +165 -0
  69. package/dist/describe-config.js +315 -0
  70. package/dist/described.js +106 -0
  71. package/dist/downstream-input-context.js +119 -0
  72. package/dist/downstream-input.js +323 -0
  73. package/dist/errors.d.ts +97 -20
  74. package/dist/errors.js +158 -80
  75. package/dist/execute.js +453 -305
  76. package/dist/executor-admission.d.ts +1 -0
  77. package/dist/executor-admission.js +11 -15
  78. package/dist/executor-contract.d.ts +20 -0
  79. package/dist/executor-contract.js +48 -0
  80. package/dist/executor-result.js +24 -9
  81. package/dist/executors/quickjs-child.js +3 -4
  82. package/dist/executors/quickjs-runtime.js +147 -59
  83. package/dist/executors/quickjs.js +29 -35
  84. package/dist/favicon.js +1 -2
  85. package/dist/fix-prompt.js +1 -3
  86. package/dist/guest-runtime.js +188 -0
  87. package/dist/guest-types.d.ts +176 -0
  88. package/dist/guest-types.js +1 -0
  89. package/dist/html-security.js +24 -0
  90. package/dist/identity.js +1 -3
  91. package/dist/inbound-credential.js +52 -0
  92. package/dist/index.d.ts +24 -256
  93. package/dist/index.js +65 -478
  94. package/dist/invocation-auth.js +69 -0
  95. package/dist/invocation.js +230 -73
  96. package/dist/json-schema.d.ts +1 -1
  97. package/dist/mcp-client-context.js +35 -0
  98. package/dist/mcp-result.js +11 -7
  99. package/dist/meta-output.js +76 -0
  100. package/dist/meta-tool-names.d.ts +2 -0
  101. package/dist/meta-tool-names.js +3 -0
  102. package/dist/meta-tools.js +285 -209
  103. package/dist/module-contracts.d.ts +8 -23
  104. package/dist/node.d.ts +0 -2
  105. package/dist/node.js +2 -2
  106. package/dist/oauth-callback-outcome.js +1 -3
  107. package/dist/oauth-handoff.js +117 -0
  108. package/dist/oauth-sealing.js +20 -0
  109. package/dist/operator-record.d.ts +137 -0
  110. package/dist/operator-record.js +420 -0
  111. package/dist/operator-ui/assets.js +31 -0
  112. package/dist/operator-ui/contract.d.ts +72 -0
  113. package/dist/operator-ui/contract.js +1 -0
  114. package/dist/operator-ui/fix-prompts.d.ts +18 -0
  115. package/dist/operator-ui/generated.js +5 -4
  116. package/dist/operator-ui/model.d.ts +12 -87
  117. package/dist/operator-ui/model.js +2 -9
  118. package/dist/operator-ui/setup-commands.js +1 -3
  119. package/dist/operator-ui/view.d.ts +323 -0
  120. package/dist/operator-ui/view.js +62 -189
  121. package/dist/page-styles.js +2 -3
  122. package/dist/program-source.js +14 -2
  123. package/dist/{exempt-writes.js → program-writes.js} +55 -18
  124. package/dist/provider.d.ts +142 -0
  125. package/dist/provider.js +187 -0
  126. package/dist/providers/_shared/google/result-size.js +57 -0
  127. package/dist/providers/_shared/google/service-account.d.ts +58 -0
  128. package/dist/providers/_shared/google/service-account.js +500 -0
  129. package/dist/providers/_shared/google/workspace.d.ts +276 -0
  130. package/dist/providers/_shared/google/workspace.js +518 -0
  131. package/dist/providers/{basecamp.d.ts → basecamp/index.d.ts} +6 -28
  132. package/dist/providers/basecamp/index.js +997 -0
  133. package/dist/providers/basecamp/skill.generated.js +9 -0
  134. package/dist/providers/{breeze.d.ts → breeze/index.d.ts} +2 -2
  135. package/dist/providers/{breeze.js → breeze/index.js} +184 -140
  136. package/dist/providers/breeze/skill.generated.js +9 -0
  137. package/dist/providers/{ccb.d.ts → ccb/index.d.ts} +2 -2
  138. package/dist/providers/{ccb.js → ccb/index.js} +271 -116
  139. package/dist/providers/ccb/skill.generated.js +9 -0
  140. package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
  141. package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
  142. package/dist/providers/cloudflare/skill.generated.js +10 -0
  143. package/dist/providers/docs/index.d.ts +54 -0
  144. package/dist/providers/docs/index.js +1237 -0
  145. package/dist/providers/docs/skill.generated.js +9 -0
  146. package/dist/providers/drive/index.d.ts +53 -0
  147. package/dist/providers/drive/index.js +1523 -0
  148. package/dist/providers/drive/skill.generated.js +9 -0
  149. package/dist/providers/forms/index.d.ts +54 -0
  150. package/dist/providers/forms/index.js +1217 -0
  151. package/dist/providers/forms/skill.generated.js +11 -0
  152. package/dist/providers/github/auth.d.ts +32 -0
  153. package/dist/providers/github/auth.js +361 -0
  154. package/dist/providers/github/hosted.js +218 -0
  155. package/dist/providers/github/index.d.ts +13 -0
  156. package/dist/providers/github/index.js +140 -0
  157. package/dist/providers/github/key.js +100 -0
  158. package/dist/providers/github/rest.js +321 -0
  159. package/dist/providers/github/scope.d.ts +29 -0
  160. package/dist/providers/github/scope.js +124 -0
  161. package/dist/providers/github/skill.generated.js +8 -0
  162. package/dist/providers/gmail/index.d.ts +51 -0
  163. package/dist/providers/gmail/index.js +1436 -0
  164. package/dist/providers/gmail/skill.generated.js +9 -0
  165. package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
  166. package/dist/providers/linear/index.js +352 -0
  167. package/dist/providers/linear/skill.generated.js +8 -0
  168. package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
  169. package/dist/providers/mixpanel/index.js +416 -0
  170. package/dist/providers/mixpanel/skill.generated.js +9 -0
  171. package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
  172. package/dist/providers/{notion.js → notion/index.js} +226 -239
  173. package/dist/providers/notion/skill.generated.js +10 -0
  174. package/dist/providers/{overflow.d.ts → overflow/index.d.ts} +2 -2
  175. package/dist/providers/{overflow.js → overflow/index.js} +74 -111
  176. package/dist/providers/overflow/skill.generated.js +8 -0
  177. package/dist/providers/{planning-center.d.ts → planning-center/index.d.ts} +2 -2
  178. package/dist/providers/{planning-center.js → planning-center/index.js} +264 -104
  179. package/dist/providers/planning-center/skill.generated.js +10 -0
  180. package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
  181. package/dist/providers/revenuecat/index.js +557 -0
  182. package/dist/providers/revenuecat/skill.generated.js +11 -0
  183. package/dist/providers/sheets/index.d.ts +54 -0
  184. package/dist/providers/sheets/index.js +1237 -0
  185. package/dist/providers/sheets/skill.generated.js +10 -0
  186. package/dist/providers/slides/index.d.ts +53 -0
  187. package/dist/providers/slides/index.js +2645 -0
  188. package/dist/providers/slides/skill.generated.js +9 -0
  189. package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
  190. package/dist/providers/stripe/index.js +266 -0
  191. package/dist/providers/stripe/skill.generated.js +11 -0
  192. package/dist/providers/{tithely.d.ts → tithely/index.d.ts} +2 -2
  193. package/dist/providers/{tithely.js → tithely/index.js} +60 -91
  194. package/dist/providers/tithely/skill.generated.js +8 -0
  195. package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
  196. package/dist/providers/vercel/index.js +1038 -0
  197. package/dist/providers/vercel/mcp-ownership.js +212 -0
  198. package/dist/providers/vercel/skill.generated.js +11 -0
  199. package/dist/registry.d.ts +108 -171
  200. package/dist/registry.js +513 -925
  201. package/dist/request-state.js +21 -0
  202. package/dist/resource-read.js +100 -0
  203. package/dist/result-shapes.js +17 -49
  204. package/dist/retired-toolkits.js +1 -1
  205. package/dist/routes/access-tokens.js +3 -6
  206. package/dist/routes/activity-context.js +21 -0
  207. package/dist/routes/activity-disclosure.js +40 -0
  208. package/dist/routes/activity.js +59 -21
  209. package/dist/routes/actor-labels.js +3 -50
  210. package/dist/routes/connect.js +221 -0
  211. package/dist/routes/credentials.js +15 -27
  212. package/dist/routes/mcp.js +356 -130
  213. package/dist/routes/oauth-client-metadata.js +15 -0
  214. package/dist/routes/oauth-management.js +45 -107
  215. package/dist/routes/oauth.js +110 -57
  216. package/dist/routes/operator.js +3 -3
  217. package/dist/routes/shared.d.ts +25 -64
  218. package/dist/routes/shared.js +160 -80
  219. package/dist/routes/skills.js +30 -0
  220. package/dist/routes/ui-config.js +225 -0
  221. package/dist/routes/ui-data.js +40 -35
  222. package/dist/routes/ui.js +66 -56
  223. package/dist/runtime/admission.js +4 -2
  224. package/dist/runtime/call-admission.js +3 -1
  225. package/dist/runtime/connector-scope.js +1 -4
  226. package/dist/runtime/run.js +10 -39
  227. package/dist/runtime/services.js +12 -117
  228. package/dist/runtime/shared-read.js +1 -3
  229. package/dist/runtime/storage.js +8 -1
  230. package/dist/sent-secrets.d.ts +52 -0
  231. package/dist/sent-secrets.js +474 -0
  232. package/dist/server.js +28 -71
  233. package/dist/skills.js +406 -174
  234. package/dist/sqlite.d.ts +48 -0
  235. package/dist/sqlite.js +166 -0
  236. package/dist/storage/keys.js +428 -0
  237. package/dist/storage/memory.js +7 -0
  238. package/dist/storage/sql.d.ts +66 -0
  239. package/dist/storage/sql.js +534 -0
  240. package/dist/timeout.js +4 -2
  241. package/dist/tool-name.js +17 -0
  242. package/dist/tool-safety.d.ts +9 -35
  243. package/dist/tool-safety.js +20 -40
  244. package/dist/types.d.ts +320 -54
  245. package/dist/types.js +0 -1
  246. package/dist/ui.d.ts +7 -19
  247. package/dist/ui.js +76 -90
  248. package/dist/url-safety.js +3 -6
  249. package/dist/usage-guide.js +137 -0
  250. package/dist/validate.d.ts +7 -0
  251. package/dist/validate.js +309 -47
  252. package/dist/version.d.ts +1 -7
  253. package/dist/version.js +3 -7
  254. package/dist/worker.d.ts +11 -0
  255. package/dist/worker.js +434 -0
  256. package/documentation/architecture.md +664 -231
  257. package/documentation/auth.md +936 -546
  258. package/documentation/code-mode.md +501 -312
  259. package/documentation/meta-tools.md +449 -200
  260. package/documentation/operator-tests.md +93 -0
  261. package/documentation/provider-migration-0.29.md +60 -0
  262. package/examples/worker/AGENTS.md +34 -12
  263. package/examples/worker/README.md +286 -255
  264. package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
  265. package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
  266. package/examples/worker/src/connecta.config.ts +151 -0
  267. package/examples/worker/src/index.ts +14 -197
  268. package/examples/worker/wrangler.jsonc +15 -35
  269. package/package.json +120 -54
  270. package/templates/node/.dockerignore +1 -2
  271. package/templates/node/.env.example +20 -21
  272. package/templates/node/AGENTS.md +21 -17
  273. package/templates/node/Dockerfile +3 -5
  274. package/templates/node/README.md +133 -58
  275. package/templates/node/docker-compose.yml +11 -12
  276. package/templates/node/package.json +4 -2
  277. package/templates/node/src/connecta.config.ts +119 -0
  278. package/templates/node/src/index.ts +9 -154
  279. package/templates/node/src/provision-token.ts +17 -0
  280. package/AGENTS.md +0 -170
  281. package/dist/artifacts/connector.d.ts +0 -58
  282. package/dist/artifacts/connector.js +0 -730
  283. package/dist/artifacts/document.js +0 -86
  284. package/dist/artifacts/guide.js +0 -140
  285. package/dist/artifacts/html-scan.js +0 -329
  286. package/dist/artifacts/json.js +0 -78
  287. package/dist/artifacts/kv-store.d.ts +0 -20
  288. package/dist/artifacts/kv-store.js +0 -140
  289. package/dist/artifacts/markdown.js +0 -478
  290. package/dist/artifacts/module.d.ts +0 -37
  291. package/dist/artifacts/module.js +0 -66
  292. package/dist/artifacts/operations.d.ts +0 -197
  293. package/dist/artifacts/operations.js +0 -1002
  294. package/dist/artifacts/refresh.d.ts +0 -55
  295. package/dist/artifacts/refresh.js +0 -236
  296. package/dist/artifacts/routes.js +0 -206
  297. package/dist/artifacts/types.d.ts +0 -214
  298. package/dist/artifacts/types.js +0 -22
  299. package/dist/artifacts/validate.d.ts +0 -62
  300. package/dist/artifacts/validate.js +0 -651
  301. package/dist/artifacts.d.ts +0 -6
  302. package/dist/artifacts.js +0 -9
  303. package/dist/auth/bearer.d.ts +0 -11
  304. package/dist/auth/bearer.js +0 -50
  305. package/dist/providers/basecamp.js +0 -445
  306. package/dist/providers/linear.js +0 -217
  307. package/dist/providers/mixpanel.js +0 -247
  308. package/dist/providers/revenuecat.js +0 -317
  309. package/dist/providers/stripe.js +0 -253
  310. package/dist/providers/vercel.js +0 -1253
  311. package/dist/storage/file.d.ts +0 -15
  312. package/dist/storage/file.js +0 -455
  313. package/ethos.md +0 -93
  314. package/examples/worker/src/cloudflare-kv.ts +0 -43
  315. package/examples/worker/src/d1-activity-row.ts +0 -155
  316. package/examples/worker/src/d1-activity.ts +0 -147
  317. package/examples/worker/src/d1-storage.ts +0 -138
  318. package/examples/worker/src/r2-artifact-blobs.ts +0 -29
  319. package/templates/node/src/file-activity.ts +0 -182
package/dist/worker.js ADDED
@@ -0,0 +1,434 @@
1
+ // The upstream sandbox, with request-owned loader/RPC handles. A guest's
2
+ // deadline cannot clean up after the parent response has already ended.
3
+ import { DynamicWorkerExecutor, normalizeCode } from "@cloudflare/codemode";
4
+ import { AdmissionController, ExecutorExecutionError } from "./executor-admission.js";
5
+ import { brandExecutor } from "./executor-contract.js";
6
+ import { InvocationFailure } from "./invocation.js";
7
+ import { parse } from "acorn";
8
+ import { guestInitializer, guestPrelude, guestPromiseInitializer, isolateGuestProgram } from "./guest-runtime.js";
9
+ /** Parse guest syntax before rewriting imports; strings and regexes are data. */
10
+ function routeGuestImports(source) {
11
+ const offsets = [];
12
+ const visit = (node) => {
13
+ if (node.type === "ImportExpression")
14
+ offsets.push(node.start - "export default (".length);
15
+ for (const value of Object.values(node)) {
16
+ if (Array.isArray(value)) {
17
+ for (const child of value)
18
+ if (child && typeof child === "object" && "type" in child)
19
+ visit(child);
20
+ }
21
+ else if (value && typeof value === "object" && "type" in value)
22
+ visit(value);
23
+ }
24
+ };
25
+ const module = parse(`export default (${source}\n);`, {
26
+ ecmaVersion: "latest",
27
+ sourceType: "module",
28
+ locations: true,
29
+ });
30
+ // Closing the parentheses and adding statements must never create module
31
+ // code outside this one expression. Check the assembled splice, including
32
+ // comments and all grouping parentheses, before the loader sees any source.
33
+ if (module.body.length !== 1 || module.body[0]?.type !== "ExportDefaultDeclaration") {
34
+ throw new SyntaxError("A Worker program must contain exactly one expression.");
35
+ }
36
+ visit(module);
37
+ for (const offset of offsets.sort((a, b) => b - a)) {
38
+ source = source.slice(0, offset) + "__connecta_import" + source.slice(offset + 6);
39
+ }
40
+ return source;
41
+ }
42
+ /** Loader-only upstream sandbox whose lease disposes handles at run end. */
43
+ export function workerExecutor(options) {
44
+ const admission = new AdmissionController(options.admission ?? {
45
+ concurrency: 2,
46
+ maxQueueSize: 8,
47
+ queueTimeoutMs: 5_000,
48
+ retryAfterMs: 1_000,
49
+ });
50
+ const active = new Set();
51
+ return brandExecutor({
52
+ name: "DynamicWorkerExecutor",
53
+ async acquire(request = {}) {
54
+ const permit = await admission.acquire(request);
55
+ const disposers = [];
56
+ let released = false;
57
+ let executed = false;
58
+ let runEnded = false;
59
+ let cancel;
60
+ let hostProviders;
61
+ const hostFailures = new Map();
62
+ // An upstream evaluation can remain pending after disposal. Its
63
+ // dispatchers retain only these forwarders, detached on lease release.
64
+ const forward = (index, name) => async (...args) => {
65
+ const fn = hostProviders?.[index]?.fns[name];
66
+ try {
67
+ if (!fn)
68
+ throw new Error("The Worker run ended.");
69
+ return { ok: true, value: await fn(...args) };
70
+ }
71
+ catch (error) {
72
+ const message = error instanceof Error ? error.message : "Host call failed.";
73
+ if (error instanceof InvocationFailure && !released && !runEnded) {
74
+ const failureId = crypto.randomUUID();
75
+ hostFailures.set(failureId, error.details);
76
+ // The codec may expose the copy to guest hooks. The authoritative
77
+ // record never leaves this host-side map.
78
+ return {
79
+ ok: false,
80
+ error: {
81
+ message,
82
+ code: error.details.code,
83
+ retryable: error.details.retryable,
84
+ details: structuredClone(error.details),
85
+ },
86
+ failureId,
87
+ };
88
+ }
89
+ return { ok: false, error: { message } };
90
+ }
91
+ };
92
+ let rpcOutcome;
93
+ // Keep each native method's receiver and make upstream's later finally
94
+ // harmless. Release RPC stubs before the Worker Loader handle.
95
+ const track = (resource, entrypoint = false) => {
96
+ let disposed = false;
97
+ const dispose = () => {
98
+ if (disposed)
99
+ return;
100
+ disposed = true;
101
+ const method = Reflect.get(resource, Symbol.dispose);
102
+ if (typeof method === "function")
103
+ method.call(resource);
104
+ };
105
+ disposers.push(dispose);
106
+ return new Proxy(resource, {
107
+ get(target, key) {
108
+ if (key === Symbol.dispose)
109
+ return dispose;
110
+ if (key === "getEntrypoint" && !entrypoint) {
111
+ return (...args) => track(Reflect.apply(Reflect.get(target, key), target, args), true);
112
+ }
113
+ if (key === "evaluate" && entrypoint)
114
+ return async (...args) => {
115
+ const result = (await Reflect.apply(Reflect.get(target, key), target, args));
116
+ // Only the native RPC return channel supplies executor facts.
117
+ rpcOutcome = result;
118
+ return result;
119
+ };
120
+ const value = Reflect.get(target, key);
121
+ return typeof value === "function" ? (...args) => Reflect.apply(value, target, args) : value;
122
+ },
123
+ });
124
+ };
125
+ let executableCode;
126
+ let guestProgram;
127
+ let normalizationLines = 0;
128
+ const loader = new Proxy(options.loader, {
129
+ get(target, key) {
130
+ if (key === "load")
131
+ return (...args) => {
132
+ if (released)
133
+ throw new Error("Executor lease was already released.");
134
+ const definition = args[0];
135
+ const source = definition?.modules?.["executor.js"];
136
+ // Keep guest source in its own module, outside the lexical scope of
137
+ // RPC dispatchers and retained host-failure identities.
138
+ if (typeof source !== "string" || !executableCode || !hostProviders)
139
+ throw new Error("Worker executable module was unavailable.");
140
+ const index = source.indexOf(executableCode);
141
+ if (index < 0)
142
+ throw new Error("Worker executable module did not contain the program.");
143
+ const guest = guestProgram;
144
+ if (guest)
145
+ normalizationLines = 0;
146
+ const names = hostProviders.map((provider) => provider.name).join(", ");
147
+ const globals = hostProviders
148
+ .map((provider) => `globalThis[${JSON.stringify(provider.name)}] = ${provider.name};`)
149
+ .join("\n");
150
+ let isolated = source.slice(0, index) + "__connecta_program" + source.slice(index + executableCode.length);
151
+ const bridge = `if (data.error) throw new Error(data.error);\n return data.result;`;
152
+ if (hostProviders.length > 0 && !isolated.includes(bridge))
153
+ throw new Error("Worker bridge contract changed.");
154
+ isolated = isolated.replaceAll(bridge, `if (data.error) throw new NativeError(data.error);
155
+ const reply = data.result;
156
+ if (!reply.ok) {
157
+ const error = new NativeError(reply.error.message);
158
+ if (typeof reply.failureId === "string") {
159
+ retain(failures, error, reply.failureId);
160
+ defineProperties(error, {
161
+ code: { value: reply.error.code, enumerable: true },
162
+ retryable: { value: reply.error.retryable, enumerable: true },
163
+ details: { value: freeze(clone(reply.error.details)), enumerable: true }
164
+ });
165
+ }
166
+ throw error;
167
+ }
168
+ return reply.value;`);
169
+ isolated = isolated.replace(" const __logs = [];", ` if (initialized) throw new NativeError("Worker initialization is single-use.");
170
+ initialized = true;
171
+ const failures = new NativeWeakMap();
172
+ const timeoutError = new NativeError("Execution timed out");
173
+ const __logs = [];`);
174
+ isolated = isolated.replace('new Error("Execution timed out")', "timeoutError");
175
+ isolated = isolated.replace("setTimeout(() => reject(timeoutError)", "nativeSetTimeout(() => reject(timeoutError)");
176
+ isolated = isolated.replace("return { result: undefined, error: err.message, logs: __logs };", `
177
+ const failureId = lookup(failures, err);
178
+ let name = "Error", message = "Program threw a value.", stack = "";
179
+ try {
180
+ if (typeof err === "string") message = slice(err, 0, 1000);
181
+ else if (err) {
182
+ if (typeof err.name === "string") name = slice(err.name, 0, 64);
183
+ if (typeof err.message === "string") message = slice(err.message, 0, 1000);
184
+ if (typeof err.stack === "string") stack = slice(err.stack, 0, 1000);
185
+ }
186
+ } catch {}
187
+ const location = exec(/connecta-guest\\.js:(\\d+):\\d+/, stack);
188
+ return { result: undefined, error: message, logs: __logs, failure: {
189
+ name, ...(failureId ? { failureId } : {}), ...(location ? { line: toNumber(location[1]) - 1 } : {}),
190
+ ...(err === timeoutError ? { timeout: { elapsedMs: ${options.timeout ?? 60_000}, deadlineMs: ${options.timeout ?? 60_000} } } : {})
191
+ } };`);
192
+ const preludes = [];
193
+ let firstInitializer;
194
+ for (const provider of hostProviders) {
195
+ if (!provider.prelude)
196
+ continue;
197
+ if (!isolated.includes(provider.prelude))
198
+ throw new Error("Worker provider setup was unavailable.");
199
+ preludes.push(provider.prelude);
200
+ const call = firstInitializer ? "" : `__connecta_initialize(${names});`;
201
+ isolated = isolated.replace(provider.prelude, call);
202
+ firstInitializer ||= call;
203
+ }
204
+ // Successive preludes share lexical bindings in both executors.
205
+ const captureGuest = preludes.includes(guestPrelude());
206
+ const initializer = preludes.length
207
+ ? `const __connecta_initialize = (${names}) => {\n${preludes.map((prelude) => (prelude === guestPrelude() ? "__connecta_guest_initialize(connecta);" : prelude)).join("\n")}\n};\n`
208
+ : "";
209
+ // Runner modules are inaccessible to guest imports. The callback has
210
+ // no lexical access to initialization or RPC dispatchers.
211
+ const programName = guest ? "__connecta_user_program" : "__connecta_program";
212
+ const imports = 'import Runner from "./connecta-runner.js";\n' + `import program from "./connecta-guest.js";\n`;
213
+ const wrapper = guest ? ` const __connecta_program = (${guest.wrapper});\n` : "";
214
+ const hardening = `
215
+ const builtinAllowed = name => typeof name === "string" && name !== "module" && name !== "node:module" && name !== "process" && name !== "node:process";
216
+ if (typeof process !== "undefined" && typeof process.getBuiltinModule === "function") {
217
+ const getBuiltin = process.getBuiltinModule.bind(process);
218
+ Object.defineProperty(process, "getBuiltinModule", { configurable: false, writable: false,
219
+ value: name => builtinAllowed(name) ? getBuiltin(name) : undefined });
220
+ }
221
+ `;
222
+ // ESM evaluates the first dependency completely before the next.
223
+ // This module has no guest dependency; its references and retained
224
+ // failures stay private, and guest imports cannot reach its export.
225
+ const captures = `
226
+ const {
227
+ NativeError, NativeWeakMap, NativeProxy, NativePromise, NativeUint8Array, NativeArrayBuffer,
228
+ defineProperties, freeze, clone, retain, lookup, slice, nativeSetTimeout, toNumber, exec,
229
+ hasOwn, push, map, join, toString, fromCharCode, min, subarray, charCodeAt, bufferSlice,
230
+ isView, nativeBtoa, nativeAtob, race, jsonParse, jsonStringify, nativeConsole
231
+ } = Object.freeze({
232
+ NativeError: Error, NativeWeakMap: WeakMap, NativeProxy: Proxy, NativePromise: Promise,
233
+ NativeUint8Array: Uint8Array, NativeArrayBuffer: ArrayBuffer,
234
+ defineProperties: Object.defineProperties, freeze: Object.freeze, clone: structuredClone,
235
+ retain: Function.prototype.call.bind(WeakMap.prototype.set),
236
+ lookup: Function.prototype.call.bind(WeakMap.prototype.get),
237
+ slice: Function.prototype.call.bind(String.prototype.slice),
238
+ nativeSetTimeout: setTimeout, toNumber: Number,
239
+ exec: Function.prototype.call.bind(RegExp.prototype.exec),
240
+ hasOwn: Function.prototype.call.bind(Object.prototype.hasOwnProperty),
241
+ push: Function.prototype.call.bind(Array.prototype.push),
242
+ map: Function.prototype.call.bind(Array.prototype.map),
243
+ join: Function.prototype.call.bind(Array.prototype.join), toString: String,
244
+ fromCharCode: String.fromCharCode, min: Math.min,
245
+ subarray: Function.prototype.call.bind(Uint8Array.prototype.subarray),
246
+ charCodeAt: Function.prototype.call.bind(String.prototype.charCodeAt),
247
+ bufferSlice: Function.prototype.call.bind(ArrayBuffer.prototype.slice),
248
+ isView: ArrayBuffer.isView, nativeBtoa: btoa, nativeAtob: atob,
249
+ race: Promise.race.bind(Promise), jsonParse: JSON.parse, jsonStringify: JSON.stringify,
250
+ nativeConsole: console
251
+ });
252
+ `;
253
+ const binaryTagCheck = "(__CODEMODE_BINARY_TAG in value)";
254
+ const binaryDataCheck = 'typeof value.data !== "string"';
255
+ if (!isolated.includes(binaryTagCheck) || !isolated.includes(binaryDataCheck)) {
256
+ throw new Error("Worker binary codec contract changed.");
257
+ }
258
+ isolated = isolated
259
+ .replace("async evaluate(__dispatchers = {}, __connectors = {}) {", `async evaluate(__dispatchers = {}, __connectors = {}, ${programName}) {\n${wrapper}`)
260
+ .replaceAll("JSON.parse(", "jsonParse(")
261
+ .replaceAll("JSON.stringify(", "jsonStringify(")
262
+ .replaceAll(binaryTagCheck, "hasOwn(value, __CODEMODE_BINARY_TAG)")
263
+ .replaceAll(binaryDataCheck, '!hasOwn(value, "data") || typeof value.data !== "string"')
264
+ .replaceAll("console.", "nativeConsole.")
265
+ .replaceAll("new Proxy(", "new NativeProxy(")
266
+ .replaceAll("Object.prototype.hasOwnProperty.call(target, toolName)", "hasOwn(target, toolName)")
267
+ .replaceAll("String(toolName)", "toString(toolName)")
268
+ .replaceAll('a.map(String).join(" ")', 'join(map(a, toString), " ")')
269
+ .replaceAll("__logs.push(", "push(__logs, ")
270
+ .replaceAll("String.fromCharCode(", "fromCharCode(")
271
+ .replaceAll("bytes.subarray(i, Math.min(i + chunkSize, bytes.byteLength))", "subarray(bytes, i, min(i + chunkSize, bytes.byteLength))")
272
+ .replaceAll("btoa(binary)", "nativeBtoa(binary)")
273
+ .replaceAll("atob(b64)", "nativeAtob(b64)")
274
+ .replaceAll("new Uint8Array(", "new NativeUint8Array(")
275
+ .replaceAll("instanceof Uint8Array", "instanceof NativeUint8Array")
276
+ .replaceAll("instanceof ArrayBuffer", "instanceof NativeArrayBuffer")
277
+ .replaceAll("ArrayBuffer.isView(", "isView(")
278
+ .replaceAll("binary.charCodeAt(i)", "charCodeAt(binary, i)")
279
+ .replaceAll("bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)", "bufferSlice(bytes.buffer, bytes.byteOffset, bytes.byteOffset + bytes.byteLength)")
280
+ .replaceAll("Promise.race(", "race(")
281
+ .replaceAll("new Promise(", "new NativePromise(");
282
+ // Recompute the insertion point after changing the generated runner.
283
+ const setup = firstInitializer
284
+ ? isolated.indexOf(firstInitializer)
285
+ : isolated.indexOf(" try {\n const result = await race");
286
+ if (setup < 0)
287
+ throw new Error("Worker provider setup was unavailable.");
288
+ const runner = hardening +
289
+ (captureGuest
290
+ ? `const __connecta_guest_initialize = ${guestInitializer()};\n`
291
+ : `${guestPromiseInitializer()};\n`) +
292
+ captures +
293
+ "let initialized = false;\n" +
294
+ initializer +
295
+ isolated.slice(0, setup) +
296
+ globals +
297
+ "\n" +
298
+ isolated.slice(setup);
299
+ const main = imports +
300
+ `export default class CodeExecutor extends Runner {
301
+ evaluate(dispatchers, connectors) { return super.evaluate(dispatchers, connectors, program); }
302
+ }`;
303
+ const routed = routeGuestImports(guest?.program ?? executableCode);
304
+ return track(Reflect.apply(Reflect.get(target, key), target, [
305
+ {
306
+ ...definition,
307
+ modules: {
308
+ ...definition.modules,
309
+ "executor.js": main,
310
+ "connecta-runner.js": runner,
311
+ "connecta-guest.js": `const startsWith = Function.prototype.call.bind(String.prototype.startsWith); const reject = Promise.reject.bind(Promise); const NativeError = Error; const __connecta_import = specifier => typeof specifier === "string" && ((startsWith(specifier, "node:") && specifier !== "node:module" && specifier !== "node:process") || specifier === "cloudflare:workers") ? import(specifier) : reject(new NativeError("Imports of runner modules are outside the guest API."));\nexport default (${routed}\n);`,
312
+ },
313
+ },
314
+ ...args.slice(1),
315
+ ]));
316
+ };
317
+ const value = Reflect.get(target, key);
318
+ return typeof value === "function" ? (...args) => Reflect.apply(value, target, args) : value;
319
+ },
320
+ });
321
+ const lease = {
322
+ waitMs: permit.waitMs,
323
+ async execute(code, providers) {
324
+ if (released)
325
+ throw new Error("Executor lease was already released.");
326
+ if (executed)
327
+ throw new Error("Executor lease may execute only once.");
328
+ executed = true;
329
+ hostProviders = providers;
330
+ // Extract the fixed wrapper from the original source. Upstream may
331
+ // wrap invalid syntax as a bare body; that must not turn an attempted
332
+ // module escape into runnable statements or shift guest locations.
333
+ guestProgram = isolateGuestProgram(code.trim());
334
+ executableCode = normalizeCode(code);
335
+ const original = executableCode.indexOf(code.trim());
336
+ if (original >= 0)
337
+ normalizationLines = executableCode.slice(0, original).split("\n").length - 1;
338
+ const detached = providers.map((provider, index) => ({
339
+ name: provider.name,
340
+ ...(provider.prelude ? { prelude: provider.prelude } : {}),
341
+ fns: Object.fromEntries(Object.keys(provider.fns).map((name) => [name, forward(index, name)])),
342
+ }));
343
+ const stopped = new Promise((_resolve, reject) => {
344
+ cancel = () => reject(new ExecutorExecutionError("executor_cancelled", "Worker executor lease was released during execution."));
345
+ });
346
+ const started = Date.now();
347
+ try {
348
+ const result = await Promise.race([
349
+ new DynamicWorkerExecutor({
350
+ loader,
351
+ ...(options.timeout !== undefined ? { timeout: options.timeout } : {}),
352
+ }).execute(code, detached),
353
+ stopped,
354
+ ]);
355
+ const outcome = rpcOutcome ?? result;
356
+ if (outcome.failure) {
357
+ const failure = { ...outcome.failure };
358
+ const call = typeof failure.failureId === "string" ? hostFailures.get(failure.failureId) : undefined;
359
+ // Neither an unknown id nor a guest/RPC-supplied call record
360
+ // supplies typed host details. Strip the private id at the edge.
361
+ delete failure.call;
362
+ delete failure.failureId;
363
+ outcome.failure = { ...failure, ...(call ? { call } : {}) };
364
+ }
365
+ if (outcome.failure?.timeout)
366
+ outcome.failure.timeout.elapsedMs = Date.now() - started;
367
+ return outcome;
368
+ }
369
+ catch (error) {
370
+ const message = error instanceof Error ? error.message : "";
371
+ // Worker Loader erases the native SyntaxError type at its RPC edge.
372
+ // Match its startup diagnostic only; guest/downstream failures return normally.
373
+ const syntax = /^Failed to start Worker:\nUncaught SyntaxError: ([^\n]*)\n\s+at connecta-guest\.js:(\d+):\d+$/.exec(message);
374
+ if (error instanceof SyntaxError || syntax) {
375
+ const location = error instanceof SyntaxError && "loc" in error ? error.loc : undefined;
376
+ const line = syntax
377
+ ? Math.max(1, Number(syntax[2]) - normalizationLines - 1)
378
+ : location?.line !== undefined
379
+ ? Math.max(1, location.line)
380
+ : undefined;
381
+ return {
382
+ result: undefined,
383
+ error: (syntax?.[1] ?? message) || "Invalid JavaScript program.",
384
+ failure: { name: "SyntaxError", ...(line !== undefined ? { line } : {}) },
385
+ };
386
+ }
387
+ throw error;
388
+ }
389
+ finally {
390
+ runEnded = true;
391
+ cancel = undefined;
392
+ hostFailures.clear();
393
+ }
394
+ },
395
+ release() {
396
+ if (released)
397
+ return;
398
+ released = true;
399
+ hostProviders = undefined;
400
+ hostFailures.clear();
401
+ cancel?.();
402
+ for (const dispose of disposers.reverse()) {
403
+ try {
404
+ dispose();
405
+ }
406
+ catch {
407
+ /* Release every handle and the permit. */
408
+ }
409
+ }
410
+ disposers.length = 0;
411
+ active.delete(lease);
412
+ permit.release();
413
+ },
414
+ };
415
+ active.add(lease);
416
+ return lease;
417
+ },
418
+ async execute(code, providers) {
419
+ const lease = await this.acquire();
420
+ try {
421
+ return await lease.execute(code, providers);
422
+ }
423
+ finally {
424
+ lease.release();
425
+ }
426
+ },
427
+ admissionSnapshot: () => admission.snapshot(),
428
+ close() {
429
+ admission.close();
430
+ for (const lease of active)
431
+ lease.release();
432
+ },
433
+ }, "leased");
434
+ }