@jami-studio/core 0.92.17 → 0.92.19

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.
@@ -1,5 +1,17 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.92.19
4
+
5
+ ### Patch Changes
6
+
7
+ - 33aeaec: Fix Neon on Cloudflare Workers: workerd forbids reusing I/O objects across requests, so pooled Neon WebSocket clients created by one request and handed to a later one threw "Cannot perform I/O on behalf of a different request", hung the worker, and returned 500s (first seen on auth get-session under wrangler pages dev). Both Neon paths (raw DbExec in client.ts and the Drizzle pool in create-get-db.ts) now route plain queries over Neon's stateless HTTP transport (poolQueryViaFetch) on workerd and cap WebSocket clients (still used for transactions) to a single use so they are never reused across requests.
8
+
9
+ ## 0.92.18
10
+
11
+ ### Patch Changes
12
+
13
+ - 1c340cc: Fix three Cloudflare Pages worker module-init crashes surfaced by serving the unified workspace artifact under wrangler pages dev: stub `sharp` (its native loader threw at require time), expose functional overrides like `os.tmpdir()` through the node-builtin stub default export (a bare throwing proxy killed workers that call overridden members via `import os from "os"`), and patch remaining `import.meta.url` occurrences in worker bundles (wrangler's re-bundle empties inner `import.meta`, so `fileURLToPath(import.meta.url)` threw at module init). Also default `RAYON_NUM_THREADS` to 1 on Windows workspace builds — 2 threads still hit the rolldown rayon access-violation race in full 14-app sequences.
14
+
3
15
  ## 0.92.17
4
16
 
5
17
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.92.17",
3
+ "version": "0.92.19",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/studio-jami/jami-studio#readme",
6
6
  "bugs": {
@@ -10,6 +10,8 @@
10
10
  */
11
11
  import path from "path";
12
12
 
13
+ import { isCloudflareRuntime } from "../shared/runtime.js";
14
+
13
15
  const recyclingPostgresPools = new WeakSet<object>();
14
16
  const loggedNeonPools = new WeakSet<object>();
15
17
 
@@ -1079,12 +1081,25 @@ async function createDbExecInternal(
1079
1081
  // analytics worker stalls right after model resolution and never claims.
1080
1082
  // HTTP-per-query (poolQueryViaFetch) has no persistent socket to die; the
1081
1083
  // foreground keeps the WebSocket pool. See the bg-fn execute branch below.
1082
- const bgHttp = isBackgroundFunctionPoolContext();
1084
+ // Cloudflare Workers (workerd) additionally forbids reusing I/O objects
1085
+ // across requests — a pooled WebSocket created in request A and handed
1086
+ // to request B throws "Cannot perform I/O on behalf of a different
1087
+ // request" and hangs the worker — so workerd always takes the stateless
1088
+ // HTTP path too.
1089
+ const bgHttp =
1090
+ isBackgroundFunctionPoolContext() || isCloudflareRuntime();
1083
1091
  if (bgHttp) {
1084
1092
  (neonConfig as { poolQueryViaFetch?: boolean }).poolQueryViaFetch =
1085
1093
  true;
1086
1094
  }
1087
- const pool = new Pool({ connectionString: url, max: neonPoolMax() });
1095
+ // On workerd, transactions still use pool.connect() WebSocket clients —
1096
+ // cap each client to a single use so a socket created in one request is
1097
+ // destroyed on release instead of being handed to a later request.
1098
+ const pool = new Pool({
1099
+ connectionString: url,
1100
+ max: neonPoolMax(),
1101
+ ...(isCloudflareRuntime() ? { maxUses: 1 } : {}),
1102
+ });
1088
1103
  attachNeonPoolErrorLogger(pool);
1089
1104
  if (trackSingletonResources) _neonPool = pool;
1090
1105
  async function queryNeonClient(
@@ -22,6 +22,7 @@ import {
22
22
  retryOnConnectionError,
23
23
  dbOpTimeoutMs,
24
24
  } from "./client.js";
25
+ import { isCloudflareRuntime } from "../shared/runtime.js";
25
26
 
26
27
  // Lazy driver loaders — cached promises so dynamic import only runs once.
27
28
  let _pgDrizzle: Promise<{ drizzle: any; postgres: any }> | undefined;
@@ -38,7 +39,9 @@ function getPgDrizzle() {
38
39
  return _pgDrizzle;
39
40
  }
40
41
 
41
- let _neonServerlessDrizzle: Promise<{ drizzle: any; Pool: any }> | undefined;
42
+ let _neonServerlessDrizzle:
43
+ | Promise<{ drizzle: any; Pool: any; neonConfig: any }>
44
+ | undefined;
42
45
  function getNeonServerlessDrizzle() {
43
46
  if (!_neonServerlessDrizzle) {
44
47
  _neonServerlessDrizzle = Promise.all([
@@ -47,6 +50,7 @@ function getNeonServerlessDrizzle() {
47
50
  ]).then(([drizzleMod, neonMod]) => ({
48
51
  drizzle: drizzleMod.drizzle,
49
52
  Pool: neonMod.Pool,
53
+ neonConfig: neonMod.neonConfig,
50
54
  }));
51
55
  }
52
56
  return _neonServerlessDrizzle;
@@ -465,19 +469,31 @@ export function createGetDb<T extends Record<string, unknown>>(schema: T) {
465
469
 
466
470
  if (dialect === "postgres") {
467
471
  if (isNeonUrl(url)) {
468
- _dbReady = getNeonServerlessDrizzle().then(({ drizzle, Pool }) => {
469
- const rawPool = new Pool({
470
- connectionString: url,
471
- max: neonPoolMax(),
472
- });
473
- attachNeonPoolErrorLogger(rawPool);
474
- // Wrap the pool with the resilience layer so Drizzle queries get the
475
- // same withDbTimeout + retryOnConnectionError protection as the raw
476
- // DbExec path in client.ts. Reads retry freely; writes only retry on
477
- // acquire-timeout (pre-send) errors to avoid double-execution.
478
- const pool = buildResilientNeonPool(rawPool);
479
- _db = drizzle(pool, { schema });
480
- });
472
+ _dbReady = getNeonServerlessDrizzle().then(
473
+ ({ drizzle, Pool, neonConfig }) => {
474
+ // Cloudflare Workers (workerd) forbids reusing I/O objects across
475
+ // requests — a WebSocket client cached in the pool by request A and
476
+ // handed to request B throws "Cannot perform I/O on behalf of a
477
+ // different request" and hangs the worker. Route plain queries over
478
+ // Neon's stateless HTTP transport (poolQueryViaFetch) and cap each
479
+ // WebSocket client (used for transactions) to a single use so it is
480
+ // never reused across requests.
481
+ const cfWorker = isCloudflareRuntime();
482
+ if (cfWorker) neonConfig.poolQueryViaFetch = true;
483
+ const rawPool = new Pool({
484
+ connectionString: url,
485
+ max: neonPoolMax(),
486
+ ...(cfWorker ? { maxUses: 1 } : {}),
487
+ });
488
+ attachNeonPoolErrorLogger(rawPool);
489
+ // Wrap the pool with the resilience layer so Drizzle queries get the
490
+ // same withDbTimeout + retryOnConnectionError protection as the raw
491
+ // DbExec path in client.ts. Reads retry freely; writes only retry on
492
+ // acquire-timeout (pre-send) errors to avoid double-execution.
493
+ const pool = buildResilientNeonPool(rawPool);
494
+ _db = drizzle(pool, { schema });
495
+ },
496
+ );
481
497
  } else {
482
498
  _dbReady = getPgDrizzle().then(({ drizzle, postgres }) => {
483
499
  // pgPoolOptions caps the pool to a small size on serverless so
@@ -119,6 +119,16 @@ export const CLOUDFLARE_WORKER_STUB_MODULES: Record<string, string> = {
119
119
  ].join("\n"),
120
120
  "better-sqlite3":
121
121
  "export default {}; export const Database = class {}; export const watch = () => ({ close() {} });\n",
122
+ // sharp loads its native binary (@img/sharp-<platform>) at require time and
123
+ // throws "Could not load the sharp module using the linux- runtime" at
124
+ // worker module init. Stub it with a callable that throws at call time —
125
+ // image processing can't run on workerd regardless.
126
+ sharp: [
127
+ "const unavailable = () => { throw new Error('sharp unavailable in Cloudflare Pages worker'); };",
128
+ "const sharp = new Proxy(unavailable, { get: (_t, prop) => (prop === 'default' ? sharp : unavailable), apply: unavailable });",
129
+ "export default sharp;",
130
+ "",
131
+ ].join("\n"),
122
132
  "node-pty":
123
133
  "export default {}; export const watch = () => ({ close() {} });\n",
124
134
  chokidar: "export default {}; export const watch = () => ({ close() {} });\n",
@@ -274,13 +284,20 @@ function cloudflareNodeBuiltinStubSource(
274
284
  const exports = Array.from(new Set(namedExports))
275
285
  .filter((name) => !overridden.has(name))
276
286
  .sort();
287
+ // The default export must expose the SAME members as the named exports —
288
+ // including functional overrides like os.tmpdir() — because most consumers
289
+ // use the default import (`import os from "os"; os.tmpdir()`). A bare
290
+ // throwing proxy here killed workers at module init whenever a dependency
291
+ // called an overridden member through the default export.
292
+ const allNames = Array.from(new Set([...overridden, ...exports])).sort();
277
293
  return [
278
294
  `const unavailable = (name) => (..._args) => { throw new Error(name + " is unavailable in Cloudflare Pages workers"); };`,
279
- `const proxy = new Proxy({}, { get(_target, prop) { return unavailable("${moduleName}." + String(prop)); } });`,
280
295
  ...overrides,
281
296
  ...exports.map(
282
297
  (name) => `export const ${name} = unavailable("${moduleName}.${name}");`,
283
298
  ),
299
+ `const __members = { ${allNames.join(", ")} };`,
300
+ `const proxy = new Proxy(__members, { get(target, prop) { return prop in target ? target[prop] : unavailable("${moduleName}." + String(prop)); } });`,
284
301
  "export default proxy;",
285
302
  "",
286
303
  ].join("\n");
@@ -1882,6 +1899,13 @@ async function buildCloudflarePages() {
1882
1899
  "var $1 = function() { return typeof require !== 'undefined' ? require : function(m) { throw new Error('require not supported: ' + m); }; };",
1883
1900
  );
1884
1901
 
1902
+ // Patch remaining import.meta.url occurrences — when wrangler/Pages
1903
+ // re-bundles the worker, inner modules get an emptied import.meta, so
1904
+ // fileURLToPath(import.meta.url) throws at module init ("path" argument
1905
+ // must be string, received undefined). Same treatment as the Vite
1906
+ // server-build path: replace with a stable synthetic file URL.
1907
+ code = code.replace(/\bimport\.meta\.url\b/g, '"file:///worker.mjs"');
1908
+
1885
1909
  // Patch setInterval/setTimeout at module scope — CF Workers disallows timers in global scope.
1886
1910
  // Some dependencies (e.g. Anthropic SDK rate limiter) call setInterval at module init.
1887
1911
  // With code splitting, chunks evaluate before the entry, so the shim must be in every file.
@@ -228,10 +228,12 @@ function buildOneApp(
228
228
  // intermittently (and for some apps deterministically) kills the build
229
229
  // with an access violation (0xC0000005). Capping the pool avoids the
230
230
  // race entirely; verified: chat's cloudflare_pages build crashed 100%
231
- // in-sequence at default threads and passes at 2. Respect an explicit
232
- // operator override.
231
+ // in-sequence at default threads and STILL crashed at 2 (forms died at
232
+ // 2 in a full 14-app sequence) — only a single rayon thread has proven
233
+ // green across the whole workspace. Respect an explicit operator
234
+ // override.
233
235
  ...(process.platform === "win32"
234
- ? { RAYON_NUM_THREADS: process.env.RAYON_NUM_THREADS ?? "2" }
236
+ ? { RAYON_NUM_THREADS: process.env.RAYON_NUM_THREADS ?? "1" }
235
237
  : {}),
236
238
  AGENT_NATIVE_WORKSPACE: "1",
237
239
  AGENT_NATIVE_WORKSPACE_APP_ID: app,
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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"}
package/dist/db/client.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * Cloudflare Workers, edge) without failing on missing native deps.
10
10
  */
11
11
  import path from "path";
12
+ import { isCloudflareRuntime } from "../shared/runtime.js";
12
13
  const recyclingPostgresPools = new WeakSet();
13
14
  const loggedNeonPools = new WeakSet();
14
15
  /** Read the request-scoped Cloudflare binding without requiring every
@@ -909,12 +910,24 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
909
910
  // analytics worker stalls right after model resolution and never claims.
910
911
  // HTTP-per-query (poolQueryViaFetch) has no persistent socket to die; the
911
912
  // foreground keeps the WebSocket pool. See the bg-fn execute branch below.
912
- const bgHttp = isBackgroundFunctionPoolContext();
913
+ // Cloudflare Workers (workerd) additionally forbids reusing I/O objects
914
+ // across requests — a pooled WebSocket created in request A and handed
915
+ // to request B throws "Cannot perform I/O on behalf of a different
916
+ // request" and hangs the worker — so workerd always takes the stateless
917
+ // HTTP path too.
918
+ const bgHttp = isBackgroundFunctionPoolContext() || isCloudflareRuntime();
913
919
  if (bgHttp) {
914
920
  neonConfig.poolQueryViaFetch =
915
921
  true;
916
922
  }
917
- const pool = new Pool({ connectionString: url, max: neonPoolMax() });
923
+ // On workerd, transactions still use pool.connect() WebSocket clients —
924
+ // cap each client to a single use so a socket created in one request is
925
+ // destroyed on release instead of being handed to a later request.
926
+ const pool = new Pool({
927
+ connectionString: url,
928
+ max: neonPoolMax(),
929
+ ...(isCloudflareRuntime() ? { maxUses: 1 } : {}),
930
+ });
918
931
  attachNeonPoolErrorLogger(pool);
919
932
  if (trackSingletonResources)
920
933
  _neonPool = pool;