weifuwu 0.24.1 → 0.24.3

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 (58) hide show
  1. package/README.md +818 -712
  2. package/cli/template/app.ts +5 -1
  3. package/cli/template/index.ts +4 -1
  4. package/cli/template/locales/en.json +6 -1
  5. package/cli/template/locales/zh-CN.json +6 -1
  6. package/cli/template/locales/zh-TW.json +6 -1
  7. package/cli/template/locales/zh.json +6 -1
  8. package/cli/template/ui/app/globals.css +1 -1
  9. package/cli/template/ui/app/page.tsx +55 -16
  10. package/cli.ts +148 -104
  11. package/dist/agent/rest.d.ts +1 -1
  12. package/dist/agent/run.d.ts +2 -2
  13. package/dist/ai/workflow.d.ts +1 -1
  14. package/dist/ai-sdk.d.ts +1 -1
  15. package/dist/cli.js +135 -97
  16. package/dist/compile.d.ts +7 -12
  17. package/dist/cookie.d.ts +24 -0
  18. package/dist/fts.d.ts +5 -5
  19. package/dist/iii/index.d.ts +1 -1
  20. package/dist/index.d.ts +5 -5
  21. package/dist/index.js +1233 -639
  22. package/dist/live.d.ts +2 -3
  23. package/dist/logdb/rest.d.ts +1 -1
  24. package/dist/mailer.d.ts +1 -1
  25. package/dist/messager/agent.d.ts +2 -2
  26. package/dist/messager/rest.d.ts +3 -3
  27. package/dist/messager/ws.d.ts +3 -3
  28. package/dist/module-server.d.ts +10 -0
  29. package/dist/opencode/index.d.ts +1 -1
  30. package/dist/opencode/permissions.d.ts +1 -1
  31. package/dist/opencode/run.d.ts +1 -1
  32. package/dist/opencode/session.d.ts +9 -9
  33. package/dist/opencode/tools/web.d.ts +1 -1
  34. package/dist/opencode/ws.d.ts +1 -2
  35. package/dist/permissions.d.ts +2 -2
  36. package/dist/postgres/module.d.ts +3 -3
  37. package/dist/postgres/schema/index.d.ts +1 -1
  38. package/dist/postgres/schema/table.d.ts +22 -20
  39. package/dist/postgres/types.d.ts +4 -4
  40. package/dist/queue/types.d.ts +1 -1
  41. package/dist/react.d.ts +1 -1
  42. package/dist/react.js +135 -90
  43. package/dist/router.d.ts +10 -10
  44. package/dist/server-registry.d.ts +12 -0
  45. package/dist/session.d.ts +1 -2
  46. package/dist/stream.d.ts +0 -5
  47. package/dist/tenant/graphql.d.ts +2 -2
  48. package/dist/tenant/index.d.ts +1 -1
  49. package/dist/tenant/rest.d.ts +2 -2
  50. package/dist/test-utils.d.ts +3 -3
  51. package/dist/user/index.d.ts +1 -1
  52. package/dist/user/oauth-login.d.ts +2 -2
  53. package/dist/vendor.d.ts +4 -0
  54. package/opencode/ui/app/globals.css +1 -1
  55. package/opencode/ui/app/layout.tsx +2 -3
  56. package/opencode/ui/app/page.tsx +302 -73
  57. package/package.json +27 -4
  58. package/cli/template/.weifuwu/ssr/2e3a7e60.js +0 -112
package/dist/index.js CHANGED
@@ -65,7 +65,8 @@ function isBundled() {
65
65
  return true ? true : false;
66
66
  }
67
67
  function isDev() {
68
- return process.env.NODE_ENV === "development";
68
+ const env2 = process.env.NODE_ENV;
69
+ return env2 !== "production" && env2 !== "test";
69
70
  }
70
71
  function isProd() {
71
72
  return process.env.NODE_ENV === "production";
@@ -262,9 +263,13 @@ function serve(handler, options) {
262
263
  }
263
264
  };
264
265
  }
265
- options.signal.addEventListener("abort", () => {
266
- server.close();
267
- }, { once: true });
266
+ options.signal.addEventListener(
267
+ "abort",
268
+ () => {
269
+ server.close();
270
+ },
271
+ { once: true }
272
+ );
268
273
  }
269
274
  server.on("error", (err) => {
270
275
  console.error("Failed to start server:", err.message);
@@ -289,20 +294,20 @@ function serve(handler, options) {
289
294
  process.off("SIGINT", shutdownHandler);
290
295
  shutdownHandler = null;
291
296
  }
292
- return new Promise((resolve14) => {
297
+ return new Promise((resolve16) => {
293
298
  if (!server.listening) {
294
- resolve14();
299
+ resolve16();
295
300
  return;
296
301
  }
297
302
  server.close();
298
303
  server.closeIdleConnections();
299
304
  const timer = setTimeout(() => {
300
305
  server.closeAllConnections();
301
- resolve14();
306
+ resolve16();
302
307
  }, timeoutMs);
303
308
  server.on("close", () => {
304
309
  clearTimeout(timer);
305
- resolve14();
310
+ resolve16();
306
311
  });
307
312
  });
308
313
  },
@@ -488,7 +493,8 @@ var Router = class _Router {
488
493
  }
489
494
  } else if (typeof arg1 === "function") {
490
495
  this.globalMws.push(arg1);
491
- } else if (typeof arg1 === "object" && arg1 !== null && "middleware" in arg1 && typeof arg1.middleware === "function" && arg1 instanceof _Router) {
496
+ } else if (typeof arg1 === "object" && arg1 !== null && "middleware" in arg1 && // eslint-disable-next-line @typescript-eslint/no-explicit-any
497
+ typeof arg1.middleware === "function" && arg1 instanceof _Router) {
492
498
  const mod = arg1;
493
499
  this.globalMws.push(mod.middleware());
494
500
  this._mountRouter("/", mod);
@@ -529,6 +535,7 @@ var Router = class _Router {
529
535
  return this._routeImpl(method, path2, args);
530
536
  }
531
537
  /** Internal route registration — no type constraints (used by _mountRouter). */
538
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
532
539
  _routeImpl(method, path2, args) {
533
540
  const last = args[args.length - 1];
534
541
  if (last instanceof _Router) {
@@ -554,9 +561,7 @@ var Router = class _Router {
554
561
  node = getOrCreateChild(node, segment, createTrieNode, false);
555
562
  }
556
563
  if (!isProd() && node.handlers.has(method)) {
557
- console.warn(
558
- `[router] route conflict: ${method} ${path2} overwrites existing handler`
559
- );
564
+ console.warn(`[router] route conflict: ${method} ${path2} overwrites existing handler`);
560
565
  }
561
566
  node.handlers.set(method, handler);
562
567
  if (middlewares.length > 0) node.middlewares.set(method, middlewares);
@@ -591,7 +596,7 @@ var Router = class _Router {
591
596
  return result;
592
597
  }
593
598
  _collectRoutes(node, prefix, result) {
594
- for (const [method, handler] of node.handlers) {
599
+ for (const [method] of node.handlers) {
595
600
  const m = method === "*" ? "ANY" : method;
596
601
  const path2 = (prefix || "/") + (node.wildcard ? "/*" : "");
597
602
  const middlewares = node.middlewares.get(method);
@@ -669,7 +674,12 @@ var Router = class _Router {
669
674
  const wsRoutes = [];
670
675
  this._collectWs(sub.wsRoot, "", wsRoutes);
671
676
  for (const { path: path2, handler, middlewares } of wsRoutes) {
672
- this.ws(base + path2, ...allExtra, ...middlewares, handler);
677
+ this.ws(
678
+ base + path2,
679
+ ...allExtra,
680
+ ...middlewares,
681
+ handler
682
+ );
673
683
  }
674
684
  }
675
685
  mergeMws(base, extra) {
@@ -682,7 +692,12 @@ var Router = class _Router {
682
692
  for (const [method, handler] of node.handlers) {
683
693
  const rmws = node.middlewares.get(method) || [];
684
694
  const suffix = node.wildcard ? "/*" : "";
685
- result.push({ method, path: (prefix || "/") + suffix, handler, middlewares: this.mergeMws(mws, rmws) });
695
+ result.push({
696
+ method,
697
+ path: (prefix || "/") + suffix,
698
+ handler,
699
+ middlewares: this.mergeMws(mws, rmws)
700
+ });
686
701
  }
687
702
  for (const [seg, child] of node.children) {
688
703
  const next = seg === ":" ? `/:${child.param}` : `/${seg}`;
@@ -744,7 +759,12 @@ var Router = class _Router {
744
759
  return { handler: wildcardHandler, middlewares: wildcardMws, pathMws, params };
745
760
  }
746
761
  if (node.handlers.size > 0) {
747
- return { middlewares: [], pathMws, params, allowedMethods: [...node.handlers.keys()].filter((k) => k !== "*") };
762
+ return {
763
+ middlewares: [],
764
+ pathMws,
765
+ params,
766
+ allowedMethods: [...node.handlers.keys()].filter((k) => k !== "*")
767
+ };
748
768
  }
749
769
  return null;
750
770
  }
@@ -779,38 +799,54 @@ var Router = class _Router {
779
799
  if (match.allowedMethods && match.allowedMethods.length > 0) {
780
800
  if (this.globalMws.length > 0) {
781
801
  try {
782
- return await this.runChain(this.globalMws, () => new Response("Method Not Allowed", {
783
- status: 405,
784
- headers: { "Allow": match.allowedMethods.join(", ") }
785
- }), req, ctx);
802
+ return await this.runChain(
803
+ this.globalMws,
804
+ () => new Response("Method Not Allowed", {
805
+ status: 405,
806
+ headers: { Allow: match.allowedMethods.join(", ") }
807
+ }),
808
+ req,
809
+ ctx
810
+ );
786
811
  } catch (e) {
787
812
  return this.handleError(e, req, ctx);
788
813
  }
789
814
  }
790
815
  return new Response("Method Not Allowed", {
791
816
  status: 405,
792
- headers: { "Allow": match.allowedMethods.join(", ") }
817
+ headers: { Allow: match.allowedMethods.join(", ") }
793
818
  });
794
819
  }
795
820
  }
796
821
  if (this.globalMws.length > 0) {
797
822
  try {
798
- return await this.runChain(this.globalMws, () => {
799
- if (!isProd()) {
800
- return Response.json({ error: "Not Found", path: "/" + segments.join("/"), method: req.method }, { status: 404 });
801
- }
802
- return new Response("Not Found", { status: 404 });
803
- }, req, ctx);
823
+ return await this.runChain(
824
+ this.globalMws,
825
+ () => {
826
+ if (!isProd()) {
827
+ return Response.json(
828
+ { error: "Not Found", path: "/" + segments.join("/"), method: req.method },
829
+ { status: 404 }
830
+ );
831
+ }
832
+ return new Response("Not Found", { status: 404 });
833
+ },
834
+ req,
835
+ ctx
836
+ );
804
837
  } catch (e) {
805
838
  return this.handleError(e, req, ctx);
806
839
  }
807
840
  }
808
841
  if (!isProd()) {
809
- return Response.json({
810
- error: "Not Found",
811
- path: "/" + segments.join("/"),
812
- method: req.method
813
- }, { status: 404 });
842
+ return Response.json(
843
+ {
844
+ error: "Not Found",
845
+ path: "/" + segments.join("/"),
846
+ method: req.method
847
+ },
848
+ { status: 404 }
849
+ );
814
850
  }
815
851
  return new Response("Not Found", { status: 404 });
816
852
  }
@@ -825,7 +861,9 @@ function runChainLoop(middlewares, index, finalHandler, req, ctx) {
825
861
  let called = false;
826
862
  const dispatch = (r, c) => {
827
863
  if (called) {
828
- console.warn("[router] next() called more than once in middleware \u2014 ignoring duplicate call");
864
+ console.warn(
865
+ "[router] next() called more than once in middleware \u2014 ignoring duplicate call"
866
+ );
829
867
  return Promise.resolve(new Response("Internal Server Error", { status: 500 }));
830
868
  }
831
869
  called = true;
@@ -849,7 +887,7 @@ function upgradeSocket(wss, req, socket, head, handler, ctx, hub) {
849
887
  join(room) {
850
888
  hub.join(room, ws);
851
889
  },
852
- leave(room) {
890
+ leave(_room) {
853
891
  hub.leave(ws);
854
892
  },
855
893
  sendRoom(room, data) {
@@ -899,7 +937,15 @@ function sendHttpResponseOnSocket(socket, response) {
899
937
 
900
938
  // tsx-context.ts
901
939
  import { useSyncExternalStore, createContext } from "react";
902
- var DEFAULT_CTX = { params: {}, query: {}, parsed: {}, loaderData: {}, env: {}, user: {}, flash: {} };
940
+ var DEFAULT_CTX = {
941
+ params: {},
942
+ query: {},
943
+ parsed: {},
944
+ loaderData: {},
945
+ env: {},
946
+ user: {},
947
+ flash: {}
948
+ };
903
949
  var KEY = "__WEIFUWU_CTX_STORE";
904
950
  function getStore() {
905
951
  if (typeof globalThis !== "undefined" && globalThis[KEY]) {
@@ -907,12 +953,22 @@ function getStore() {
907
953
  }
908
954
  const s = {
909
955
  _ctx: DEFAULT_CTX,
910
- _snapshot: { params: DEFAULT_CTX.params, query: DEFAULT_CTX.query, user: DEFAULT_CTX.user, parsed: DEFAULT_CTX.parsed, theme: DEFAULT_CTX.theme, i18n: DEFAULT_CTX.i18n, loaderData: DEFAULT_CTX.loaderData, env: DEFAULT_CTX.env },
956
+ _snapshot: {
957
+ params: DEFAULT_CTX.params,
958
+ query: DEFAULT_CTX.query,
959
+ user: DEFAULT_CTX.user,
960
+ parsed: DEFAULT_CTX.parsed,
961
+ theme: DEFAULT_CTX.theme,
962
+ i18n: DEFAULT_CTX.i18n,
963
+ loaderData: DEFAULT_CTX.loaderData,
964
+ env: DEFAULT_CTX.env
965
+ },
911
966
  _listeners: /* @__PURE__ */ new Set(),
912
967
  _rebuilders: [],
913
968
  _alsGetStore: null
914
969
  };
915
970
  if (typeof globalThis !== "undefined") {
971
+ ;
916
972
  globalThis[KEY] = s;
917
973
  }
918
974
  return s;
@@ -929,7 +985,16 @@ function setCtx(value) {
929
985
  }
930
986
  }
931
987
  store._ctx = { ...store._ctx, ...value };
932
- store._snapshot = { params: store._ctx.params, query: store._ctx.query, user: store._ctx.user, parsed: store._ctx.parsed, theme: store._ctx.theme, i18n: store._ctx.i18n, loaderData: store._ctx.loaderData, env: store._ctx.env };
988
+ store._snapshot = {
989
+ params: store._ctx.params,
990
+ query: store._ctx.query,
991
+ user: store._ctx.user,
992
+ parsed: store._ctx.parsed,
993
+ theme: store._ctx.theme,
994
+ i18n: store._ctx.i18n,
995
+ loaderData: store._ctx.loaderData,
996
+ env: store._ctx.env
997
+ };
933
998
  if (typeof window !== "undefined") {
934
999
  ;
935
1000
  window.__WEIFUWU_CTX = { ...window.__WEIFUWU_CTX, ...value };
@@ -1014,7 +1079,8 @@ function cors(options) {
1014
1079
  const headers = new Headers(res.headers);
1015
1080
  headers.set("Access-Control-Allow-Origin", acao);
1016
1081
  if (opts.credentials) headers.set("Access-Control-Allow-Credentials", "true");
1017
- if (opts.exposedHeaders?.length) headers.set("Access-Control-Expose-Headers", opts.exposedHeaders.join(", "));
1082
+ if (opts.exposedHeaders?.length)
1083
+ headers.set("Access-Control-Expose-Headers", opts.exposedHeaders.join(", "));
1018
1084
  if (acao !== "*") headers.set("Vary", "Origin");
1019
1085
  return new Response(res.body, { status: res.status, statusText: res.statusText, headers });
1020
1086
  }
@@ -1091,7 +1157,7 @@ function serveStatic(root, options) {
1091
1157
  const headers = {
1092
1158
  "Content-Type": mimeType,
1093
1159
  "Content-Length": String(stat3.size),
1094
- "ETag": etag,
1160
+ ETag: etag,
1095
1161
  "Last-Modified": stat3.mtime.toUTCString(),
1096
1162
  "Cache-Control": opts.immutable ? `public, max-age=${opts.maxAge ?? 31536e3}, immutable` : `public, max-age=${opts.maxAge ?? 0}`
1097
1163
  };
@@ -1181,10 +1247,12 @@ function validate(schemas) {
1181
1247
  if (result.success) {
1182
1248
  parsed.params = result.data;
1183
1249
  } else {
1184
- issues.push(...result.error.issues.map((i) => ({
1185
- path: ["params", ...i.path.map(String)],
1186
- message: i.message
1187
- })));
1250
+ issues.push(
1251
+ ...result.error.issues.map((i) => ({
1252
+ path: ["params", ...i.path.map(String)],
1253
+ message: i.message
1254
+ }))
1255
+ );
1188
1256
  }
1189
1257
  }
1190
1258
  if (schemas?.query) {
@@ -1192,10 +1260,12 @@ function validate(schemas) {
1192
1260
  if (result.success) {
1193
1261
  parsed.query = result.data;
1194
1262
  } else {
1195
- issues.push(...result.error.issues.map((i) => ({
1196
- path: ["query", ...i.path.map(String)],
1197
- message: i.message
1198
- })));
1263
+ issues.push(
1264
+ ...result.error.issues.map((i) => ({
1265
+ path: ["query", ...i.path.map(String)],
1266
+ message: i.message
1267
+ }))
1268
+ );
1199
1269
  }
1200
1270
  }
1201
1271
  if (schemas?.headers) {
@@ -1207,10 +1277,12 @@ function validate(schemas) {
1207
1277
  if (result.success) {
1208
1278
  parsed.headers = result.data;
1209
1279
  } else {
1210
- issues.push(...result.error.issues.map((i) => ({
1211
- path: ["headers", ...i.path.map(String)],
1212
- message: i.message
1213
- })));
1280
+ issues.push(
1281
+ ...result.error.issues.map((i) => ({
1282
+ path: ["headers", ...i.path.map(String)],
1283
+ message: i.message
1284
+ }))
1285
+ );
1214
1286
  }
1215
1287
  }
1216
1288
  if (req.method !== "GET" && req.method !== "HEAD") {
@@ -1234,10 +1306,12 @@ function validate(schemas) {
1234
1306
  if (result.success) {
1235
1307
  parsed.body = result.data;
1236
1308
  } else {
1237
- issues.push(...result.error.issues.map((i) => ({
1238
- path: ["body", ...i.path.map(String)],
1239
- message: i.message
1240
- })));
1309
+ issues.push(
1310
+ ...result.error.issues.map((i) => ({
1311
+ path: ["body", ...i.path.map(String)],
1312
+ message: i.message
1313
+ }))
1314
+ );
1241
1315
  }
1242
1316
  } else {
1243
1317
  parsed.body = bodyValue;
@@ -1305,11 +1379,14 @@ function setCookie(res, name, value, options) {
1305
1379
  }
1306
1380
  function deleteCookie(res, name, options) {
1307
1381
  const headers = new Headers(res.headers);
1308
- headers.append("Set-Cookie", serializeCookie(name, "", {
1309
- ...options,
1310
- maxAge: 0,
1311
- expires: /* @__PURE__ */ new Date(0)
1312
- }));
1382
+ headers.append(
1383
+ "Set-Cookie",
1384
+ serializeCookie(name, "", {
1385
+ ...options,
1386
+ maxAge: 0,
1387
+ expires: /* @__PURE__ */ new Date(0)
1388
+ })
1389
+ );
1313
1390
  return new Response(res.body, {
1314
1391
  status: res.status,
1315
1392
  statusText: res.statusText,
@@ -1411,7 +1488,7 @@ function upload(options) {
1411
1488
  }
1412
1489
 
1413
1490
  // rate-limit.ts
1414
- function defaultKey(_req, _ctx) {
1491
+ function defaultKey(_req, _ctx2) {
1415
1492
  const forwarded = _req.headers.get("x-forwarded-for");
1416
1493
  if (forwarded) return forwarded.split(",")[0].trim();
1417
1494
  const realIp = _req.headers.get("x-real-ip");
@@ -1433,21 +1510,24 @@ function rateLimit(options) {
1433
1510
  const keyPrefix = options?.prefix ?? "ratelimit:";
1434
1511
  const MAX_ENTRIES2 = 1e4;
1435
1512
  const hits = /* @__PURE__ */ new Map();
1436
- const interval = storeType === "memory" ? setInterval(() => {
1437
- const now = Date.now();
1438
- for (const [key, entry] of hits) {
1439
- if (entry.reset < now) hits.delete(key);
1440
- }
1441
- if (hits.size > MAX_ENTRIES2) {
1442
- const toDelete = hits.size - MAX_ENTRIES2;
1443
- let deleted = 0;
1444
- for (const key of hits.keys()) {
1445
- if (deleted >= toDelete) break;
1446
- hits.delete(key);
1447
- deleted++;
1513
+ const interval = storeType === "memory" ? setInterval(
1514
+ () => {
1515
+ const now = Date.now();
1516
+ for (const [key, entry] of hits) {
1517
+ if (entry.reset < now) hits.delete(key);
1518
+ }
1519
+ if (hits.size > MAX_ENTRIES2) {
1520
+ const toDelete = hits.size - MAX_ENTRIES2;
1521
+ let deleted = 0;
1522
+ for (const key of hits.keys()) {
1523
+ if (deleted >= toDelete) break;
1524
+ hits.delete(key);
1525
+ deleted++;
1526
+ }
1448
1527
  }
1449
- }
1450
- }, Math.min(window2, 3e4)) : null;
1528
+ },
1529
+ Math.min(window2, 3e4)
1530
+ ) : null;
1451
1531
  if (interval?.unref) interval.unref();
1452
1532
  async function checkAndIncrement(key) {
1453
1533
  const now = Date.now();
@@ -1461,7 +1541,7 @@ function rateLimit(options) {
1461
1541
  const reset = pttl > 0 ? now + pttl : now + window2;
1462
1542
  return { count, reset };
1463
1543
  }
1464
- let entry = hits.get(key);
1544
+ const entry = hits.get(key);
1465
1545
  if (!entry || entry.reset < now) {
1466
1546
  hits.set(key, { count: 1, reset: now + window2 });
1467
1547
  return { count: 1, reset: now + window2 };
@@ -1492,7 +1572,6 @@ function rateLimit(options) {
1492
1572
  if (interval) clearInterval(interval);
1493
1573
  hits.clear();
1494
1574
  };
1495
- mw.stop = mw.close;
1496
1575
  mw.stats = () => ({
1497
1576
  store: storeType,
1498
1577
  entries: storeType === "memory" ? hits.size : void 0,
@@ -1536,7 +1615,9 @@ function compress(options) {
1536
1615
  let compressed;
1537
1616
  try {
1538
1617
  if (encoding === "br") {
1539
- compressed = await brotliCompressAsync(body, { params: { [constants.BROTLI_PARAM_QUALITY]: Math.min(level, 11) } });
1618
+ compressed = await brotliCompressAsync(body, {
1619
+ params: { [constants.BROTLI_PARAM_QUALITY]: Math.min(level, 11) }
1620
+ });
1540
1621
  } else if (encoding === "gzip") {
1541
1622
  compressed = await gzipAsync(body, { level: Math.min(level, 9) });
1542
1623
  } else {
@@ -1650,9 +1731,7 @@ function createSSEStream(iterable, opts) {
1650
1731
  }
1651
1732
  } catch (e) {
1652
1733
  if (e.name !== "AbortError") {
1653
- controller.enqueue(
1654
- encoder.encode(formatSSE("error", { error: e.message }))
1655
- );
1734
+ controller.enqueue(encoder.encode(formatSSE("error", { error: e.message })));
1656
1735
  }
1657
1736
  } finally {
1658
1737
  controller.close();
@@ -1777,26 +1856,31 @@ var TestApp = class {
1777
1856
  }
1778
1857
  /** Register a GET route — supports route-level middleware via spread args. */
1779
1858
  get(path2, ...args) {
1859
+ ;
1780
1860
  this.router.get(path2, ...args);
1781
1861
  return this;
1782
1862
  }
1783
1863
  /** Register a POST route. */
1784
1864
  post(path2, ...args) {
1865
+ ;
1785
1866
  this.router.post(path2, ...args);
1786
1867
  return this;
1787
1868
  }
1788
1869
  /** Register a PUT route. */
1789
1870
  put(path2, ...args) {
1871
+ ;
1790
1872
  this.router.put(path2, ...args);
1791
1873
  return this;
1792
1874
  }
1793
1875
  /** Register a PATCH route. */
1794
1876
  patch(path2, ...args) {
1877
+ ;
1795
1878
  this.router.patch(path2, ...args);
1796
1879
  return this;
1797
1880
  }
1798
1881
  /** Register a DELETE route. */
1799
1882
  delete(path2, ...args) {
1883
+ ;
1800
1884
  this.router.delete(path2, ...args);
1801
1885
  return this;
1802
1886
  }
@@ -1879,7 +1963,12 @@ async function withTestDb(optionsOrFn, fn) {
1879
1963
  }
1880
1964
 
1881
1965
  // graphql.ts
1882
- import { buildSchema, graphql as executeGraphQL, validate as validateQuery, parse } from "graphql";
1966
+ import {
1967
+ buildSchema,
1968
+ graphql as executeGraphQL,
1969
+ validate as validateQuery,
1970
+ parse
1971
+ } from "graphql";
1883
1972
  import { makeExecutableSchema } from "@graphql-tools/schema";
1884
1973
  function parseParamsFromGet(url) {
1885
1974
  const query = url.searchParams.get("query");
@@ -1940,11 +2029,17 @@ async function executeQuery(schema, params, options, req, ctx) {
1940
2029
  const doc = parse(params.query);
1941
2030
  const depth = queryDepth(doc);
1942
2031
  if (depth > maxDepth) {
1943
- return Response.json({ errors: [{ message: `Query depth ${depth} exceeds limit ${maxDepth}` }] }, { status: 400 });
2032
+ return Response.json(
2033
+ { errors: [{ message: `Query depth ${depth} exceeds limit ${maxDepth}` }] },
2034
+ { status: 400 }
2035
+ );
1944
2036
  }
1945
2037
  const validationErrors = validateQuery(schema, doc);
1946
2038
  if (validationErrors.length > 0) {
1947
- return Response.json({ errors: validationErrors.map((e) => ({ message: e.message })) }, { status: 400 });
2039
+ return Response.json(
2040
+ { errors: validationErrors.map((e) => ({ message: e.message })) },
2041
+ { status: 400 }
2042
+ );
1948
2043
  }
1949
2044
  } catch (err) {
1950
2045
  const msg = err instanceof Error ? err.message : String(err);
@@ -2125,7 +2220,10 @@ function resolveRef(path2, ctx) {
2125
2220
  const propPath = after.slice(dot + 1);
2126
2221
  const output = ctx.nodeOutputs.get(id2);
2127
2222
  if (output === void 0) throw new Error(`Node "${id2}" has no output yet`);
2128
- return getByPath(output, propPath.startsWith("output") ? propPath.slice(7).split(".").filter(Boolean) : propPath.split("."));
2223
+ return getByPath(
2224
+ output,
2225
+ propPath.startsWith("output") ? propPath.slice(7).split(".").filter(Boolean) : propPath.split(".")
2226
+ );
2129
2227
  }
2130
2228
  if (path2.startsWith("$var.")) {
2131
2229
  const name = path2.slice(5);
@@ -2145,7 +2243,8 @@ function resolveValue(v, ctx) {
2145
2243
  if (Array.isArray(v)) return v.map((item) => resolveValue(item, ctx));
2146
2244
  if (typeof v === "object" && v !== null) {
2147
2245
  const result = {};
2148
- for (const [k, val] of Object.entries(v)) result[k] = resolveValue(val, ctx);
2246
+ for (const [k, val] of Object.entries(v))
2247
+ result[k] = resolveValue(val, ctx);
2149
2248
  return result;
2150
2249
  }
2151
2250
  return v;
@@ -2241,7 +2340,7 @@ async function executeNode(node, ctx) {
2241
2340
  iters++;
2242
2341
  ctx.stepCount++;
2243
2342
  if (ctx.stepCount > ctx.maxSteps) throw new Error(`Step limit exceeded`);
2244
- if (!Boolean(evaluateExpression(conditionExpr, ctx))) break;
2343
+ if (!evaluateExpression(conditionExpr, ctx)) break;
2245
2344
  for (const n of body ?? []) {
2246
2345
  last = await executeNode(n, ctx);
2247
2346
  ctx.nodeOutputs.set(n.id, last);
@@ -2273,7 +2372,10 @@ async function executeNode(node, ctx) {
2273
2372
  signal: controller.signal
2274
2373
  });
2275
2374
  const ct = res.headers.get("content-type") ?? "";
2276
- return { status: res.status, body: ct.includes("json") ? await res.json() : await res.text() };
2375
+ return {
2376
+ status: res.status,
2377
+ body: ct.includes("json") ? await res.json() : await res.text()
2378
+ };
2277
2379
  } finally {
2278
2380
  clearTimeout(timer);
2279
2381
  }
@@ -2293,20 +2395,25 @@ function runWorkflow(opts = {}) {
2293
2395
  description: "Execute a multi-step workflow. Supports eval, set, get, if, while, call, http nodes. Use $var.x for variables, $nodes.id.output for previous node results, $input.x for input parameters. Call nodes invoke registered tools.",
2294
2396
  inputSchema: z.object({
2295
2397
  goal: z.string().describe("What the workflow should accomplish"),
2296
- nodes: z.array(z.object({
2297
- id: z.string(),
2298
- tool: z.string(),
2299
- input: z.record(z.string(), z.unknown()).optional(),
2300
- conditions: z.array(z.object({ test: z.any(), body: z.any() })).optional(),
2301
- body: z.array(z.any()).optional()
2302
- })).optional().describe("Workflow nodes. Skip this and provide model for LLM to generate from goal.")
2398
+ nodes: z.array(
2399
+ z.object({
2400
+ id: z.string(),
2401
+ tool: z.string(),
2402
+ input: z.record(z.string(), z.unknown()).optional(),
2403
+ conditions: z.array(z.object({ test: z.any(), body: z.any() })).optional(),
2404
+ body: z.array(z.any()).optional()
2405
+ })
2406
+ ).optional().describe("Workflow nodes. Skip this and provide model for LLM to generate from goal.")
2303
2407
  }),
2304
2408
  execute: async (input) => {
2305
2409
  let nodes;
2306
2410
  if (input.nodes && input.nodes.length > 0) {
2307
2411
  nodes = input.nodes;
2308
2412
  } else {
2309
- if (!opts.provider && !opts.model) throw new Error('Provide either "nodes", a "model", or a "provider" with a model to generate the workflow from "goal"');
2413
+ if (!opts.provider && !opts.model)
2414
+ throw new Error(
2415
+ 'Provide either "nodes", a "model", or a "provider" with a model to generate the workflow from "goal"'
2416
+ );
2310
2417
  const toolsDesc = Object.entries(opts.tools ?? {}).map(([k, t]) => `- ${k}: ${t.description}`).join("\n");
2311
2418
  const system = [
2312
2419
  "You are a workflow generator. Given a user goal and available tools, output a workflow JSON.",
@@ -2318,7 +2425,10 @@ function runWorkflow(opts = {}) {
2318
2425
  "Reference syntax: $var.name, $nodes.id.output, $nodes.id.output.field, $input.field",
2319
2426
  "Output ONLY valid JSON. No explanation, no markdown."
2320
2427
  ].filter(Boolean).join("\n");
2321
- const genParams = { system, messages: [{ role: "user", content: input.goal }] };
2428
+ const genParams = {
2429
+ system,
2430
+ messages: [{ role: "user", content: input.goal }]
2431
+ };
2322
2432
  const result = opts.provider ? await opts.provider.generateText(genParams) : await generateText({ ...genParams, model: opts.model });
2323
2433
  const text2 = result.text.trim();
2324
2434
  const jsonStart = text2.indexOf("{");
@@ -2411,10 +2521,7 @@ import {
2411
2521
  embedMany,
2412
2522
  smoothStream
2413
2523
  } from "ai";
2414
- import {
2415
- openai,
2416
- createOpenAI as createOpenAI2
2417
- } from "@ai-sdk/openai";
2524
+ import { openai, createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
2418
2525
 
2419
2526
  // postgres/client.ts
2420
2527
  import postgresFactory from "postgres";
@@ -2657,7 +2764,10 @@ var Table = class {
2657
2764
  const using = opts?.type ? `USING ${opts.type.toUpperCase()}` : "";
2658
2765
  const colList = cols.map((c) => opts?.desc ? `"${c}" DESC` : `"${c}"`).join(", ");
2659
2766
  const operator = opts?.operator ? ` ${opts.operator}` : "";
2660
- const ddl = `CREATE ${unique} INDEX IF NOT EXISTS ${name} ON "${this.tableName}" ${using} (${colList}${operator})`.replace(/\s+/g, " ");
2767
+ const ddl = `CREATE ${unique} INDEX IF NOT EXISTS ${name} ON "${this.tableName}" ${using} (${colList}${operator})`.replace(
2768
+ /\s+/g,
2769
+ " "
2770
+ );
2661
2771
  await sql2.unsafe(ddl);
2662
2772
  }
2663
2773
  async createUniqueIndex(sql2, columns) {
@@ -2761,7 +2871,10 @@ var Table = class {
2761
2871
  const softDel = this._softDeleteFilter(where, opts);
2762
2872
  if (softDel) conditions.push(softDel);
2763
2873
  const whereClause = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
2764
- const [countRow] = await sql2.unsafe(`SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`, values);
2874
+ const [countRow] = await sql2.unsafe(
2875
+ `SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`,
2876
+ values
2877
+ );
2765
2878
  const count = Number(countRow._total);
2766
2879
  if (conditions.length === 0 && !opts?.orderBy && !opts?.limit && !opts?.offset && !opts?.select) {
2767
2880
  const rows2 = await sql2`SELECT * FROM ${sql2(this.tableName)}`;
@@ -2794,7 +2907,10 @@ var Table = class {
2794
2907
  async updateMany(sql2, where, data) {
2795
2908
  const { sets, values: setValues } = this._buildSET(data);
2796
2909
  if (sets.length === 0) return 0;
2797
- const { conditions: wConditions, values: wValues } = this._buildConditions(where, setValues.length);
2910
+ const { conditions: wConditions, values: wValues } = this._buildConditions(
2911
+ where,
2912
+ setValues.length
2913
+ );
2798
2914
  if (wConditions.length === 0) return 0;
2799
2915
  const rows = await sql2.unsafe(
2800
2916
  `UPDATE "${this.tableName}" SET ${sets.join(", ")} WHERE ${wConditions.join(" AND ")} RETURNING 1`,
@@ -2883,13 +2999,20 @@ var Table = class {
2883
2999
  const softDel = this._softDeleteFilter(where);
2884
3000
  if (softDel) conditions.push(softDel);
2885
3001
  const whereClause = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
2886
- const [row] = await sql2.unsafe(`SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`, values);
3002
+ const [row] = await sql2.unsafe(
3003
+ `SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`,
3004
+ values
3005
+ );
2887
3006
  return Number(row._total);
2888
3007
  }
2889
3008
  };
2890
3009
  var BoundTable = class _BoundTable {
2891
3010
  inner;
2892
3011
  sql;
3012
+ /** The underlying table name. */
3013
+ get tableName() {
3014
+ return this.inner.tableName;
3015
+ }
2893
3016
  constructor(sql2, tableName, builders) {
2894
3017
  this.inner = new Table(tableName, builders);
2895
3018
  this.sql = sql2;
@@ -2977,13 +3100,17 @@ function postgres(opts) {
2977
3100
  connect_timeout: options.connect_timeout
2978
3101
  });
2979
3102
  if (options.signal) {
2980
- options.signal.addEventListener("abort", () => {
2981
- sql2.end();
2982
- }, { once: true });
3103
+ options.signal.addEventListener(
3104
+ "abort",
3105
+ () => {
3106
+ sql2.end();
3107
+ },
3108
+ { once: true }
3109
+ );
2983
3110
  }
2984
3111
  const closeTimeout = options.closeTimeout ?? 5;
2985
- let _active = 0;
2986
- let _waiting = 0;
3112
+ const _active = 0;
3113
+ const _waiting = 0;
2987
3114
  const poolMax = options.max ?? 10;
2988
3115
  const mw = ((req, ctx, next) => {
2989
3116
  ctx.sql = sql2;
@@ -3011,10 +3138,9 @@ function postgres(opts) {
3011
3138
  );
3012
3139
  };
3013
3140
  mw.isMigrated = async (moduleName) => {
3014
- const [row] = await sql2.unsafe(
3015
- `SELECT 1 FROM "${MIGRATIONS_TABLE}" WHERE name = $1`,
3016
- [moduleName]
3017
- );
3141
+ const [row] = await sql2.unsafe(`SELECT 1 FROM "${MIGRATIONS_TABLE}" WHERE name = $1`, [
3142
+ moduleName
3143
+ ]);
3018
3144
  return !!row;
3019
3145
  };
3020
3146
  mw.transaction = (async (fn, retryOpts) => {
@@ -3146,10 +3272,9 @@ function createOAuth2Server(deps) {
3146
3272
  return null;
3147
3273
  }
3148
3274
  function consentPage(client, params) {
3149
- const fields = Object.entries(params).map(
3150
- ([k, v]) => `<input type="hidden" name="${k}" value="${v.replace(/"/g, "&quot;")}">`
3151
- ).join("\n ");
3152
- return new Response(`<!DOCTYPE html>
3275
+ const fields = Object.entries(params).map(([k, v]) => `<input type="hidden" name="${k}" value="${v.replace(/"/g, "&quot;")}">`).join("\n ");
3276
+ return new Response(
3277
+ `<!DOCTYPE html>
3153
3278
  <html lang="en">
3154
3279
  <head><meta charset="utf-8"><title>Authorize</title>
3155
3280
  <style>
@@ -3176,19 +3301,24 @@ function createOAuth2Server(deps) {
3176
3301
  </form>
3177
3302
  </div>
3178
3303
  </body>
3179
- </html>`, { headers: { "Content-Type": "text/html; charset=utf-8" } });
3304
+ </html>`,
3305
+ { headers: { "Content-Type": "text/html; charset=utf-8" } }
3306
+ );
3180
3307
  }
3181
3308
  function errorPage2(error, description) {
3182
- return new Response(`<!DOCTYPE html>
3309
+ return new Response(
3310
+ `<!DOCTYPE html>
3183
3311
  <html lang="en">
3184
3312
  <head><meta charset="utf-8"><title>Error</title>
3185
3313
  <style>body{font-family:sans-serif;max-width:480px;margin:80px auto;padding:0 20px}
3186
3314
  h2{color:#dc2626}.desc{color:#555}</style>
3187
3315
  </head>
3188
3316
  <body><h2>${error}</h2>${description ? `<p class="desc">${description}</p>` : ""}</body>
3189
- </html>`, { status: 400, headers: { "Content-Type": "text/html; charset=utf-8" } });
3317
+ </html>`,
3318
+ { status: 400, headers: { "Content-Type": "text/html; charset=utf-8" } }
3319
+ );
3190
3320
  }
3191
- async function authorizeHandler(req, _ctx) {
3321
+ async function authorizeHandler(req, _ctx2) {
3192
3322
  const url = new URL(req.url);
3193
3323
  const clientId = url.searchParams.get("client_id") || "";
3194
3324
  const redirectUri = url.searchParams.get("redirect_uri") || "";
@@ -3205,7 +3335,10 @@ h2{color:#dc2626}.desc{color:#555}</style>
3205
3335
  return errorPage2("Invalid client_id", "No client found with the given client_id.");
3206
3336
  }
3207
3337
  if (!client.redirectUris.includes(redirectUri)) {
3208
- return errorPage2("Invalid redirect_uri", "The redirect_uri is not registered for this client.");
3338
+ return errorPage2(
3339
+ "Invalid redirect_uri",
3340
+ "The redirect_uri is not registered for this client."
3341
+ );
3209
3342
  }
3210
3343
  const user2 = extractUser(req);
3211
3344
  if (!user2) {
@@ -3291,14 +3424,23 @@ h2{color:#dc2626}.desc{color:#555}</style>
3291
3424
  return Response.json({ error: "invalid_grant" }, { status: 400 });
3292
3425
  }
3293
3426
  if (new Date(stored.expires_at) < /* @__PURE__ */ new Date()) {
3294
- return Response.json({ error: "invalid_grant", error_description: "Code expired" }, { status: 400 });
3427
+ return Response.json(
3428
+ { error: "invalid_grant", error_description: "Code expired" },
3429
+ { status: 400 }
3430
+ );
3295
3431
  }
3296
3432
  if (stored.redirect_uri !== redirectUri) {
3297
- return Response.json({ error: "invalid_grant", error_description: "redirect_uri mismatch" }, { status: 400 });
3433
+ return Response.json(
3434
+ { error: "invalid_grant", error_description: "redirect_uri mismatch" },
3435
+ { status: 400 }
3436
+ );
3298
3437
  }
3299
3438
  if (stored.code_challenge) {
3300
3439
  if (!codeVerifier) {
3301
- return Response.json({ error: "invalid_grant", error_description: "code_verifier required" }, { status: 400 });
3440
+ return Response.json(
3441
+ { error: "invalid_grant", error_description: "code_verifier required" },
3442
+ { status: 400 }
3443
+ );
3302
3444
  }
3303
3445
  let expected;
3304
3446
  if (stored.code_challenge_method === "plain") {
@@ -3307,7 +3449,10 @@ h2{color:#dc2626}.desc{color:#555}</style>
3307
3449
  expected = crypto4.createHash("sha256").update(codeVerifier).digest().toString("base64url");
3308
3450
  }
3309
3451
  if (expected !== stored.code_challenge) {
3310
- return Response.json({ error: "invalid_grant", error_description: "code_verifier mismatch" }, { status: 400 });
3452
+ return Response.json(
3453
+ { error: "invalid_grant", error_description: "code_verifier mismatch" },
3454
+ { status: 400 }
3455
+ );
3311
3456
  }
3312
3457
  }
3313
3458
  await pg.sql`UPDATE "_oauth2_codes" SET "used" = TRUE WHERE "id" = ${stored.id}`;
@@ -3512,7 +3657,7 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3512
3657
  try {
3513
3658
  tokenRes = await fetch(meta.tokenUrl, {
3514
3659
  method: "POST",
3515
- headers: { "Content-Type": "application/json", "Accept": "application/json" },
3660
+ headers: { "Content-Type": "application/json", Accept: "application/json" },
3516
3661
  body: JSON.stringify({
3517
3662
  code,
3518
3663
  client_id: config.clientId,
@@ -3522,7 +3667,10 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3522
3667
  })
3523
3668
  });
3524
3669
  } catch (err) {
3525
- console.error(`[oauth] token exchange network error for ${providerName}:`, err.message);
3670
+ console.error(
3671
+ `[oauth] token exchange network error for ${providerName}:`,
3672
+ err.message
3673
+ );
3526
3674
  return Response.json({ error: "Failed to connect to OAuth provider" }, { status: 502 });
3527
3675
  }
3528
3676
  if (!tokenRes.ok) {
@@ -3539,7 +3687,10 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3539
3687
  try {
3540
3688
  userRes = await fetch(meta.userUrl, { headers: { Authorization: "Bearer " + accessToken } });
3541
3689
  } catch (err) {
3542
- console.error("[oauth] user info network error for " + providerName + ":", err.message);
3690
+ console.error(
3691
+ "[oauth] user info network error for " + providerName + ":",
3692
+ err.message
3693
+ );
3543
3694
  return Response.json({ error: "Failed to connect to OAuth provider" }, { status: 502 });
3544
3695
  }
3545
3696
  if (!userRes.ok) {
@@ -3707,11 +3858,9 @@ function user(options) {
3707
3858
  await tokens.create();
3708
3859
  }
3709
3860
  function signToken(user2) {
3710
- return jwt2.sign(
3711
- { sub: user2.id, email: user2.email, role: user2.role },
3712
- secret,
3713
- { expiresIn }
3714
- );
3861
+ return jwt2.sign({ sub: user2.id, email: user2.email, role: user2.role }, secret, {
3862
+ expiresIn
3863
+ });
3715
3864
  }
3716
3865
  function stripPassword(row) {
3717
3866
  const { password: _, ...user2 } = row;
@@ -3879,6 +4028,7 @@ function user(options) {
3879
4028
  return async (req, ctx, next) => {
3880
4029
  const userData = await resolveUser(req, ctx);
3881
4030
  if (userData) {
4031
+ ;
3882
4032
  ctx.user = userData;
3883
4033
  }
3884
4034
  return next(req, ctx);
@@ -3940,18 +4090,22 @@ function user(options) {
3940
4090
  r.post("/oauth/token", (req) => oauth2.tokenHandler(req));
3941
4091
  }
3942
4092
  if (hasDb && options.oauthLogin) {
3943
- registerOAuthLoginRoutes(r, {
3944
- sql: _pg.sql,
3945
- jwtSecret: secret,
3946
- expiresIn,
3947
- usersTable: table,
3948
- providerTable: "_auth_providers",
3949
- redirectUrl: options.oauthLogin.redirectUrl || "/",
3950
- signToken,
3951
- createPlaceholderUser,
3952
- findUserById: findById,
3953
- findUserByEmail: findByEmail
3954
- }, options.oauthLogin.providers);
4093
+ registerOAuthLoginRoutes(
4094
+ r,
4095
+ {
4096
+ sql: _pg.sql,
4097
+ jwtSecret: secret,
4098
+ expiresIn,
4099
+ usersTable: table,
4100
+ providerTable: "_auth_providers",
4101
+ redirectUrl: options.oauthLogin.redirectUrl || "/",
4102
+ signToken,
4103
+ createPlaceholderUser,
4104
+ findUserById: findById,
4105
+ findUserByEmail: findByEmail
4106
+ },
4107
+ options.oauthLogin.providers
4108
+ );
3955
4109
  }
3956
4110
  const mod = r;
3957
4111
  mod.middleware = middleware;
@@ -4048,9 +4202,7 @@ var FIELD_RANGES = [
4048
4202
  function parsePattern(pattern) {
4049
4203
  const fields = pattern.trim().split(/\s+/);
4050
4204
  if (fields.length !== 5) {
4051
- throw new Error(
4052
- `Invalid cron pattern "${pattern}": expected 5 fields, got ${fields.length}`
4053
- );
4205
+ throw new Error(`Invalid cron pattern "${pattern}": expected 5 fields, got ${fields.length}`);
4054
4206
  }
4055
4207
  return fields.map((f, i) => parseField(f, FIELD_RANGES[i][0], FIELD_RANGES[i][1]));
4056
4208
  }
@@ -4059,7 +4211,7 @@ function matches(fields, date) {
4059
4211
  }
4060
4212
  function cronNext(expr, from = /* @__PURE__ */ new Date()) {
4061
4213
  const fields = parsePattern(expr);
4062
- let candidate = new Date(from.getTime() + 6e4);
4214
+ const candidate = new Date(from.getTime() + 6e4);
4063
4215
  candidate.setSeconds(0, 0);
4064
4216
  for (let i = 0; i < 525600; i++) {
4065
4217
  if (fields[4].has(candidate.getDay()) && fields[3].has(candidate.getMonth() + 1) && fields[2].has(candidate.getDate()) && fields[1].has(candidate.getHours()) && fields[0].has(candidate.getMinutes())) {
@@ -4122,7 +4274,12 @@ function createMemoryQueue(opts) {
4122
4274
  }
4123
4275
  if (job.schedule) {
4124
4276
  try {
4125
- insertJob({ ...job, id: crypto6.randomUUID(), runAt: cronNext(job.schedule), createdAt: Date.now() });
4277
+ insertJob({
4278
+ ...job,
4279
+ id: crypto6.randomUUID(),
4280
+ runAt: cronNext(job.schedule),
4281
+ createdAt: Date.now()
4282
+ });
4126
4283
  } catch (e) {
4127
4284
  console.error("[queue] cron re-queue failed:", e.message);
4128
4285
  }
@@ -4210,7 +4367,14 @@ function createMemoryQueue(opts) {
4210
4367
  mw.dashboard = function dashboard() {
4211
4368
  return buildDashboard(q);
4212
4369
  };
4213
- mw.stats = () => ({ running, inflight, processed: _processed, failed: _failed, handlers: handlers.size, maxConcurrent: MAX_CONCURRENT });
4370
+ mw.stats = () => ({
4371
+ running,
4372
+ inflight,
4373
+ processed: _processed,
4374
+ failed: _failed,
4375
+ handlers: handlers.size,
4376
+ maxConcurrent: MAX_CONCURRENT
4377
+ });
4214
4378
  attachCron(q, handlers);
4215
4379
  return q;
4216
4380
  }
@@ -4225,8 +4389,12 @@ function createPgQueue(opts) {
4225
4389
  const MAX_FAILED = 1e3;
4226
4390
  async function ensureTable() {
4227
4391
  if (ready) return;
4228
- await sql2.unsafe(`CREATE TABLE IF NOT EXISTS ${escapeIdent3(table)} (id UUID PRIMARY KEY, type TEXT NOT NULL, payload JSONB NOT NULL DEFAULT '{}', run_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), schedule TEXT, status TEXT NOT NULL DEFAULT 'pending', error TEXT, failed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW())`);
4229
- await sql2.unsafe(`CREATE INDEX IF NOT EXISTS ${escapeIdent3(table + "_run_at_idx")} ON ${escapeIdent3(table)} (run_at, status)`);
4392
+ await sql2.unsafe(
4393
+ `CREATE TABLE IF NOT EXISTS ${escapeIdent3(table)} (id UUID PRIMARY KEY, type TEXT NOT NULL, payload JSONB NOT NULL DEFAULT '{}', run_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), schedule TEXT, status TEXT NOT NULL DEFAULT 'pending', error TEXT, failed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW())`
4394
+ );
4395
+ await sql2.unsafe(
4396
+ `CREATE INDEX IF NOT EXISTS ${escapeIdent3(table + "_run_at_idx")} ON ${escapeIdent3(table)} (run_at, status)`
4397
+ );
4230
4398
  ready = true;
4231
4399
  }
4232
4400
  async function processJob(job, handler) {
@@ -4239,14 +4407,26 @@ function createPgQueue(opts) {
4239
4407
  _failed++;
4240
4408
  const msg = e.message;
4241
4409
  console.error("[queue] handler error:", msg);
4242
- await sql2.unsafe(`UPDATE ${escapeIdent3(table)} SET status = 'failed', error = $2, failed_at = NOW() WHERE id = $1`, [job.id, msg]);
4410
+ await sql2.unsafe(
4411
+ `UPDATE ${escapeIdent3(table)} SET status = 'failed', error = $2, failed_at = NOW() WHERE id = $1`,
4412
+ [job.id, msg]
4413
+ );
4243
4414
  } finally {
4244
4415
  inflight--;
4245
4416
  }
4246
4417
  if (job.schedule) {
4247
4418
  try {
4248
4419
  const nextRun = cronNext(job.schedule);
4249
- await sql2.unsafe(`INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`, [crypto6.randomUUID(), job.type, JSON.stringify(job.payload), new Date(nextRun).toISOString(), job.schedule]);
4420
+ await sql2.unsafe(
4421
+ `INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`,
4422
+ [
4423
+ crypto6.randomUUID(),
4424
+ job.type,
4425
+ JSON.stringify(job.payload),
4426
+ new Date(nextRun).toISOString(),
4427
+ job.schedule
4428
+ ]
4429
+ );
4250
4430
  } catch (e) {
4251
4431
  console.error("[queue] cron re-queue failed:", e.message);
4252
4432
  }
@@ -4256,10 +4436,20 @@ function createPgQueue(opts) {
4256
4436
  if (!running) return;
4257
4437
  try {
4258
4438
  while (running && inflight < MAX_CONCURRENT) {
4259
- const rows = await sql2.unsafe(`UPDATE ${escapeIdent3(table)} SET status = 'running' WHERE id = (SELECT id FROM ${escapeIdent3(table)} WHERE run_at <= NOW() AND status = 'pending' ORDER BY run_at LIMIT 1 FOR UPDATE SKIP LOCKED) RETURNING *`);
4439
+ const rows = await sql2.unsafe(
4440
+ `UPDATE ${escapeIdent3(table)} SET status = 'running' WHERE id = (SELECT id FROM ${escapeIdent3(table)} WHERE run_at <= NOW() AND status = 'pending' ORDER BY run_at LIMIT 1 FOR UPDATE SKIP LOCKED) RETURNING *`
4441
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4442
+ );
4260
4443
  if (rows.length === 0) break;
4261
4444
  const row = rows[0];
4262
- const job = { id: row.id, type: row.type, payload: typeof row.payload === "string" ? JSON.parse(row.payload) : row.payload, createdAt: new Date(row.created_at).getTime(), runAt: new Date(row.run_at).getTime(), schedule: row.schedule || void 0 };
4445
+ const job = {
4446
+ id: row.id,
4447
+ type: row.type,
4448
+ payload: typeof row.payload === "string" ? JSON.parse(row.payload) : row.payload,
4449
+ createdAt: new Date(row.created_at).getTime(),
4450
+ runAt: new Date(row.run_at).getTime(),
4451
+ schedule: row.schedule || void 0
4452
+ };
4263
4453
  const handler = handlers.get(job.type);
4264
4454
  if (handler) processJob(job, handler);
4265
4455
  }
@@ -4294,7 +4484,10 @@ function createPgQueue(opts) {
4294
4484
  } else {
4295
4485
  runAt = /* @__PURE__ */ new Date();
4296
4486
  }
4297
- await sql2.unsafe(`INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`, [id2, type, JSON.stringify(payload), runAt.toISOString(), opts2?.schedule || null]);
4487
+ await sql2.unsafe(
4488
+ `INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`,
4489
+ [id2, type, JSON.stringify(payload), runAt.toISOString(), opts2?.schedule || null]
4490
+ );
4298
4491
  return id2;
4299
4492
  })();
4300
4493
  };
@@ -4320,25 +4513,64 @@ function createPgQueue(opts) {
4320
4513
  while (inflight > 0) await new Promise((r) => setTimeout(r, 50));
4321
4514
  };
4322
4515
  mw.jobs = async function jobs(limit) {
4323
- const rows = await sql2.unsafe(`SELECT * FROM ${escapeIdent3(table)} WHERE status = 'pending' ORDER BY run_at LIMIT $1`, [limit ?? 50]);
4324
- return rows.map((r) => ({ id: r.id, type: r.type, payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload, createdAt: new Date(r.created_at).getTime(), runAt: new Date(r.run_at).getTime(), schedule: r.schedule || void 0 }));
4516
+ const rows = await sql2.unsafe(
4517
+ `SELECT * FROM ${escapeIdent3(table)} WHERE status = 'pending' ORDER BY run_at LIMIT $1`,
4518
+ [limit ?? 50]
4519
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4520
+ );
4521
+ return rows.map((r) => ({
4522
+ id: r.id,
4523
+ type: r.type,
4524
+ payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload,
4525
+ createdAt: new Date(r.created_at).getTime(),
4526
+ runAt: new Date(r.run_at).getTime(),
4527
+ schedule: r.schedule || void 0
4528
+ }));
4325
4529
  };
4326
4530
  mw.failedJobs = async function failedJobs(limit) {
4327
- const rows = await sql2.unsafe(`SELECT * FROM ${escapeIdent3(table)} WHERE status = 'failed' ORDER BY failed_at DESC LIMIT $1`, [limit ?? 50]);
4328
- return rows.map((r) => ({ id: r.id, type: r.type, payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload, createdAt: new Date(r.created_at).getTime(), runAt: new Date(r.run_at).getTime(), schedule: r.schedule || void 0, error: r.error || "", failedAt: new Date(r.failed_at).getTime() }));
4531
+ const rows = await sql2.unsafe(
4532
+ `SELECT * FROM ${escapeIdent3(table)} WHERE status = 'failed' ORDER BY failed_at DESC LIMIT $1`,
4533
+ [limit ?? 50]
4534
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4535
+ );
4536
+ return rows.map((r) => ({
4537
+ id: r.id,
4538
+ type: r.type,
4539
+ payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload,
4540
+ createdAt: new Date(r.created_at).getTime(),
4541
+ runAt: new Date(r.run_at).getTime(),
4542
+ schedule: r.schedule || void 0,
4543
+ error: r.error || "",
4544
+ failedAt: new Date(r.failed_at).getTime()
4545
+ }));
4329
4546
  };
4330
4547
  mw.retryFailed = async function retryFailed(jobId) {
4331
- const result = await sql2.unsafe(`UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE id = $1 AND status = 'failed' RETURNING id`, [jobId]);
4548
+ const result = await sql2.unsafe(
4549
+ `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE id = $1 AND status = 'failed' RETURNING id`,
4550
+ [jobId]
4551
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4552
+ );
4332
4553
  return result.length > 0;
4333
4554
  };
4334
4555
  mw.retryAllFailed = async function retryAllFailed(type) {
4335
- const result = await sql2.unsafe(type ? `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' AND type = $1 RETURNING id` : `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' RETURNING id`, type ? [type] : []);
4556
+ const result = await sql2.unsafe(
4557
+ type ? `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' AND type = $1 RETURNING id` : `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' RETURNING id`,
4558
+ type ? [type] : []
4559
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4560
+ );
4336
4561
  return result.length;
4337
4562
  };
4338
4563
  mw.dashboard = function dashboard() {
4339
4564
  return buildDashboard(q);
4340
4565
  };
4341
- mw.stats = () => ({ running, inflight, processed: _processed, failed: _failed, handlers: handlers.size, maxConcurrent: MAX_CONCURRENT });
4566
+ mw.stats = () => ({
4567
+ running,
4568
+ inflight,
4569
+ processed: _processed,
4570
+ failed: _failed,
4571
+ handlers: handlers.size,
4572
+ maxConcurrent: MAX_CONCURRENT
4573
+ });
4342
4574
  attachCron(q, handlers);
4343
4575
  return q;
4344
4576
  }
@@ -4367,7 +4599,16 @@ function createRedisQueue(opts) {
4367
4599
  if (job.schedule) {
4368
4600
  try {
4369
4601
  const nextRun = cronNext(job.schedule);
4370
- await redis2.zadd(jobKey, nextRun, JSON.stringify({ ...job, id: crypto6.randomUUID(), runAt: nextRun, createdAt: Date.now() }));
4602
+ await redis2.zadd(
4603
+ jobKey,
4604
+ nextRun,
4605
+ JSON.stringify({
4606
+ ...job,
4607
+ id: crypto6.randomUUID(),
4608
+ runAt: nextRun,
4609
+ createdAt: Date.now()
4610
+ })
4611
+ );
4371
4612
  } catch (e) {
4372
4613
  console.error("[queue] cron re-queue failed:", e.message);
4373
4614
  }
@@ -4501,7 +4742,14 @@ function createRedisQueue(opts) {
4501
4742
  mw.dashboard = function dashboard() {
4502
4743
  return buildDashboard(q);
4503
4744
  };
4504
- mw.stats = () => ({ running, inflight, processed: _processed, failed: _failed, handlers: handlers.size, maxConcurrent: MAX_CONCURRENT });
4745
+ mw.stats = () => ({
4746
+ running,
4747
+ inflight,
4748
+ processed: _processed,
4749
+ failed: _failed,
4750
+ handlers: handlers.size,
4751
+ maxConcurrent: MAX_CONCURRENT
4752
+ });
4505
4753
  attachCron(q, handlers);
4506
4754
  return q;
4507
4755
  }
@@ -4649,10 +4897,14 @@ function createIndexesSQL(tenantId, slug, fields) {
4649
4897
  const name = internalTableName(tenantId, slug);
4650
4898
  const statements = [];
4651
4899
  statements.push(`CREATE INDEX IF NOT EXISTS "${name}_tenant_idx" ON "${name}" ("tenant_id")`);
4652
- statements.push(`CREATE INDEX IF NOT EXISTS "${name}_tenant_id_idx" ON "${name}" ("tenant_id", "id")`);
4900
+ statements.push(
4901
+ `CREATE INDEX IF NOT EXISTS "${name}_tenant_id_idx" ON "${name}" ("tenant_id", "id")`
4902
+ );
4653
4903
  for (const f of fields) {
4654
4904
  if (f.unique) {
4655
- statements.push(`CREATE UNIQUE INDEX IF NOT EXISTS "${name}_${f.name}_uidx" ON "${name}" ("${f.name}")`);
4905
+ statements.push(
4906
+ `CREATE UNIQUE INDEX IF NOT EXISTS "${name}_${f.name}_uidx" ON "${name}" ("${f.name}")`
4907
+ );
4656
4908
  } else if (f.index === "hnsw") {
4657
4909
  statements.push(
4658
4910
  `CREATE INDEX IF NOT EXISTS "${name}_${f.name}_hnsw_idx" ON "${name}" USING hnsw ("${f.name}" vector_cosine_ops)`
@@ -4914,10 +5166,9 @@ function buildRouter(sql2, usersTable) {
4914
5166
  `SELECT *, "${searchField}" ${operator} $1::vector AS "_distance" FROM "${name2}" WHERE tenant_id = $2 ORDER BY "_distance" LIMIT $3 OFFSET $4`,
4915
5167
  [parsed, ctx.tenant.id, limit, offset]
4916
5168
  ),
4917
- sql2.unsafe(
4918
- `SELECT count(*) as count FROM "${name2}" WHERE tenant_id = $1`,
4919
- [ctx.tenant.id]
4920
- )
5169
+ sql2.unsafe(`SELECT count(*) as count FROM "${name2}" WHERE tenant_id = $1`, [
5170
+ ctx.tenant.id
5171
+ ])
4921
5172
  ]);
4922
5173
  return Response.json({ rows: rows2, count: extractCount(countResult2) });
4923
5174
  } catch {
@@ -4930,10 +5181,7 @@ function buildRouter(sql2, usersTable) {
4930
5181
  `SELECT * FROM "${name}" WHERE tenant_id = $1 ORDER BY "${orderCol}" ${orderDir} LIMIT $2 OFFSET $3`,
4931
5182
  [ctx.tenant.id, limit, offset]
4932
5183
  ),
4933
- sql2.unsafe(
4934
- `SELECT count(*) as count FROM "${name}" WHERE tenant_id = $1`,
4935
- [ctx.tenant.id]
4936
- )
5184
+ sql2.unsafe(`SELECT count(*) as count FROM "${name}" WHERE tenant_id = $1`, [ctx.tenant.id])
4937
5185
  ]);
4938
5186
  return Response.json({ rows, count: extractCount(countResult) });
4939
5187
  });
@@ -5015,7 +5263,10 @@ function buildRouter(sql2, usersTable) {
5015
5263
  if (!childTable) return Response.json({ error: "Nested table not found" }, { status: 404 });
5016
5264
  const relField = findRelation(childTable.fields, ctx.params["_slug"]);
5017
5265
  if (!relField) {
5018
- return Response.json({ error: `No relation from "${nestedSlug}" to "${ctx.params["_slug"]}"` }, { status: 400 });
5266
+ return Response.json(
5267
+ { error: `No relation from "${nestedSlug}" to "${ctx.params["_slug"]}"` },
5268
+ { status: 400 }
5269
+ );
5019
5270
  }
5020
5271
  const relFields = getRelationFields(childTable.fields);
5021
5272
  if (relFields.length === 2) {
@@ -5086,11 +5337,11 @@ import {
5086
5337
  GraphQLID,
5087
5338
  GraphQLList,
5088
5339
  GraphQLNonNull,
5089
- GraphQLEnumType
5340
+ GraphQLEnumType,
5341
+ graphql as executeGraphQL2
5090
5342
  } from "graphql";
5091
- import { graphql as executeGraphQL2 } from "graphql";
5092
5343
  function graphqlType(field, required) {
5093
- let t;
5344
+ let t = GraphQLString;
5094
5345
  switch (field.type) {
5095
5346
  case "integer":
5096
5347
  t = GraphQLInt;
@@ -5107,15 +5358,11 @@ function graphqlType(field, required) {
5107
5358
  name: `Enum_${field.name}`,
5108
5359
  values: Object.fromEntries(field.options.map((o) => [o, { value: o }]))
5109
5360
  });
5110
- } else {
5111
- t = GraphQLString;
5112
5361
  }
5113
5362
  break;
5114
5363
  case "vector":
5115
5364
  t = GraphQLString;
5116
5365
  break;
5117
- default:
5118
- t = GraphQLString;
5119
5366
  }
5120
5367
  return required ? new GraphQLNonNull(t) : t;
5121
5368
  }
@@ -5142,6 +5389,7 @@ function buildObjectType(table, ctx) {
5142
5389
  limit: { type: GraphQLInt, defaultValue: 20 },
5143
5390
  offset: { type: GraphQLInt, defaultValue: 0 }
5144
5391
  },
5392
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5145
5393
  resolve: async (parent) => {
5146
5394
  const childName = internalTableName(ctx.tenantId, other.slug);
5147
5395
  const rows = await ctx.sql.unsafe(
@@ -5164,6 +5412,7 @@ function buildObjectType(table, ctx) {
5164
5412
  limit: { type: GraphQLInt, defaultValue: 20 },
5165
5413
  offset: { type: GraphQLInt, defaultValue: 0 }
5166
5414
  },
5415
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5167
5416
  resolve: async (parent) => {
5168
5417
  const childName = internalTableName(ctx.tenantId, other.slug);
5169
5418
  const targetName = internalTableName(ctx.tenantId, targetSlug);
@@ -5185,6 +5434,7 @@ function buildObjectType(table, ctx) {
5185
5434
  if (!targetTable) continue;
5186
5435
  fields[targetSlug] = {
5187
5436
  type: buildObjectType(targetTable, ctx),
5437
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5188
5438
  resolve: async (parent) => {
5189
5439
  const name = internalTableName(ctx.tenantId, targetSlug);
5190
5440
  const [row] = await ctx.sql.unsafe(
@@ -5205,9 +5455,7 @@ function buildInputType(table, prefix) {
5205
5455
  const typeName = pascalCase(`${prefix}_${table.slug}`) + "Input";
5206
5456
  return new GraphQLInputObjectType({
5207
5457
  name: typeName,
5208
- fields: Object.fromEntries(
5209
- table.fields.map((f) => [f.name, { type: inputGraphqlType(f) }])
5210
- )
5458
+ fields: Object.fromEntries(table.fields.map((f) => [f.name, { type: inputGraphqlType(f) }]))
5211
5459
  });
5212
5460
  }
5213
5461
  function buildQueryFields(tables, ctx) {
@@ -5222,6 +5470,7 @@ function buildQueryFields(tables, ctx) {
5222
5470
  limit: { type: GraphQLInt, defaultValue: 20 },
5223
5471
  offset: { type: GraphQLInt, defaultValue: 0 }
5224
5472
  },
5473
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5225
5474
  resolve: async (_, args) => {
5226
5475
  const name = internalTableName(ctx.tenantId, slug);
5227
5476
  const rows = await ctx.sql.unsafe(
@@ -5234,6 +5483,7 @@ function buildQueryFields(tables, ctx) {
5234
5483
  fields[`get${pascal}`] = {
5235
5484
  type: objType,
5236
5485
  args: { id: { type: new GraphQLNonNull(GraphQLID) } },
5486
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5237
5487
  resolve: async (_, args) => {
5238
5488
  const name = internalTableName(ctx.tenantId, slug);
5239
5489
  const [row] = await ctx.sql.unsafe(
@@ -5256,6 +5506,7 @@ function buildMutationFields(tables, ctx) {
5256
5506
  fields[`create${pascal}`] = {
5257
5507
  type: objType,
5258
5508
  args: { data: { type: new GraphQLNonNull(inputType) } },
5509
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5259
5510
  resolve: async (_, args) => {
5260
5511
  const name = internalTableName(ctx.tenantId, table.slug);
5261
5512
  const data = { ...args.data, tenant_id: ctx.tenantId };
@@ -5272,6 +5523,7 @@ function buildMutationFields(tables, ctx) {
5272
5523
  id: { type: new GraphQLNonNull(GraphQLID) },
5273
5524
  data: { type: new GraphQLNonNull(patchType) }
5274
5525
  },
5526
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5275
5527
  resolve: async (_, args) => {
5276
5528
  const name = internalTableName(ctx.tenantId, table.slug);
5277
5529
  const setClauses = table.fields.filter((f) => args.data[f.name] !== void 0).map((f, i) => `"${f.name}" = $${i + 1}`);
@@ -5294,6 +5546,7 @@ function buildMutationFields(tables, ctx) {
5294
5546
  fields[`delete${pascal}`] = {
5295
5547
  type: GraphQLBoolean,
5296
5548
  args: { id: { type: new GraphQLNonNull(GraphQLID) } },
5549
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5297
5550
  resolve: async (_, args) => {
5298
5551
  const name = internalTableName(ctx.tenantId, table.slug);
5299
5552
  const result = await ctx.sql.unsafe(
@@ -5338,23 +5591,23 @@ function buildGraphQLHandler(sql2) {
5338
5591
  });
5339
5592
  return Response.json(result, { status: result.errors ? 400 : 200 });
5340
5593
  });
5341
- r.get("/", async (req, _ctx) => {
5594
+ r.get("/", async (req, _ctx2) => {
5342
5595
  const url = new URL(req.url);
5343
5596
  if (url.searchParams.has("query")) {
5344
- return handleGET(req, _ctx);
5597
+ return handleGET(req, _ctx2);
5345
5598
  }
5346
5599
  return new Response("GraphQL endpoint. Send POST /graphql with { query, variables }", {
5347
5600
  status: 200,
5348
5601
  headers: { "Content-Type": "text/plain" }
5349
5602
  });
5350
5603
  });
5351
- async function handleGET(req, _ctx) {
5604
+ async function handleGET(req, _ctx2) {
5352
5605
  const tables = await sql2`
5353
5606
  SELECT * FROM "_user_tables"
5354
- WHERE tenant_id = ${_ctx.tenant.id}
5607
+ WHERE tenant_id = ${_ctx2.tenant.id}
5355
5608
  ORDER BY created_at ASC
5356
5609
  `;
5357
- const buildCtx = { sql: sql2, tenantId: _ctx.tenant.id, tables, typeCache: /* @__PURE__ */ new Map() };
5610
+ const buildCtx = { sql: sql2, tenantId: _ctx2.tenant.id, tables, typeCache: /* @__PURE__ */ new Map() };
5358
5611
  const schema = new GraphQLSchema({
5359
5612
  query: new GraphQLObjectType({
5360
5613
  name: "Query",
@@ -5374,7 +5627,7 @@ function buildGraphQLHandler(sql2) {
5374
5627
  source: query,
5375
5628
  variableValues: variables,
5376
5629
  operationName: url.searchParams.get("operationName") || void 0,
5377
- contextValue: _ctx
5630
+ contextValue: _ctx2
5378
5631
  });
5379
5632
  return Response.json(result, { status: result.errors ? 400 : 200 });
5380
5633
  }
@@ -5404,7 +5657,9 @@ function tenant(options) {
5404
5657
  });
5405
5658
  await members.create();
5406
5659
  await members.createIndex("user_id");
5407
- await sql2.unsafe(`CREATE UNIQUE INDEX IF NOT EXISTS "_tenant_members_unique_idx" ON "_tenant_members" ("tenant_id", "user_id")`);
5660
+ await sql2.unsafe(
5661
+ `CREATE UNIQUE INDEX IF NOT EXISTS "_tenant_members_unique_idx" ON "_tenant_members" ("tenant_id", "user_id")`
5662
+ );
5408
5663
  const tables = pg.table("_user_tables", {
5409
5664
  id: serial("id").primaryKey(),
5410
5665
  tenant_id: text("tenant_id").notNull().references("_tenants", "id", "cascade"),
@@ -5415,7 +5670,9 @@ function tenant(options) {
5415
5670
  });
5416
5671
  await tables.create();
5417
5672
  await tables.createIndex("tenant_id");
5418
- await sql2.unsafe(`CREATE UNIQUE INDEX IF NOT EXISTS "_user_tables_unique_idx" ON "_user_tables" ("tenant_id", "slug")`);
5673
+ await sql2.unsafe(
5674
+ `CREATE UNIQUE INDEX IF NOT EXISTS "_user_tables_unique_idx" ON "_user_tables" ("tenant_id", "slug")`
5675
+ );
5419
5676
  }
5420
5677
  function middleware() {
5421
5678
  return async (req, ctx, next) => {
@@ -5439,10 +5696,13 @@ function tenant(options) {
5439
5696
  }
5440
5697
  const headerId = req.headers.get("X-Tenant-ID");
5441
5698
  if (!headerId) {
5442
- return Response.json({
5443
- error: "Multiple tenants. Set X-Tenant-ID header.",
5444
- tenants: members.map((m) => ({ id: m.id, name: m.name, role: m.role }))
5445
- }, { status: 300 });
5699
+ return Response.json(
5700
+ {
5701
+ error: "Multiple tenants. Set X-Tenant-ID header.",
5702
+ tenants: members.map((m) => ({ id: m.id, name: m.name, role: m.role }))
5703
+ },
5704
+ { status: 300 }
5705
+ );
5446
5706
  }
5447
5707
  const member = members.find((m) => m.id === headerId);
5448
5708
  if (!member) {
@@ -5483,7 +5743,9 @@ function buildRouter2(deps) {
5483
5743
  return Response.json(row, { status: 201 });
5484
5744
  });
5485
5745
  r.get("/agents", async () => {
5486
- const { data: rows } = await agentsTable.readMany(void 0, { orderBy: { created_at: "desc" } });
5746
+ const { data: rows } = await agentsTable.readMany(void 0, {
5747
+ orderBy: { created_at: "desc" }
5748
+ });
5487
5749
  return Response.json(rows);
5488
5750
  });
5489
5751
  r.get("/agents/:id", async (_req, ctx) => {
@@ -5497,7 +5759,14 @@ function buildRouter2(deps) {
5497
5759
  if (!agent2) return Response.json({ error: "Agent not found" }, { status: 404 });
5498
5760
  const body = await req.json();
5499
5761
  const updateData = {};
5500
- for (const key of ["name", "description", "type", "model", "system_prompt", "active"]) {
5762
+ for (const key of [
5763
+ "name",
5764
+ "description",
5765
+ "type",
5766
+ "model",
5767
+ "system_prompt",
5768
+ "active"
5769
+ ]) {
5501
5770
  if (body[key] !== void 0) {
5502
5771
  updateData[key] = body[key];
5503
5772
  }
@@ -5634,7 +5903,9 @@ function chunkContent(content, chunkSize, overlap) {
5634
5903
 
5635
5904
  // agent/run.ts
5636
5905
  function hasKnowledgeDocs(sql2, agentId) {
5637
- return sql2`SELECT 1 FROM "_knowledge_documents" WHERE agent_id = ${agentId} LIMIT 1`.then((r) => r.length > 0);
5906
+ return sql2`SELECT 1 FROM "_knowledge_documents" WHERE agent_id = ${agentId} LIMIT 1`.then(
5907
+ (r) => r.length > 0
5908
+ );
5638
5909
  }
5639
5910
  async function searchKnowledge(sql2, provider, agentId, query, limit = 5) {
5640
5911
  const embedding = await provider.embed(query);
@@ -5808,7 +6079,14 @@ function agent(options) {
5808
6079
  trace_id: text("trace_id"),
5809
6080
  created_at: timestamptz("created_at").notNull().default(sql`NOW()`)
5810
6081
  });
5811
- const runner = createRunner({ sql: sql2, agents: agentsTable, runs: runsTable, knowledge: knowledgeTable, provider: resolvedProvider, userTools: options.tools });
6082
+ const runner = createRunner({
6083
+ sql: sql2,
6084
+ agents: agentsTable,
6085
+ runs: runsTable,
6086
+ knowledge: knowledgeTable,
6087
+ provider: resolvedProvider,
6088
+ userTools: options.tools
6089
+ });
5812
6090
  const base = new PgModule(pg);
5813
6091
  const r = buildRouter2({ agents: agentsTable, runs: runsTable, knowledge: knowledgeTable, runner });
5814
6092
  const mod = r;
@@ -6376,14 +6654,14 @@ function forkApp(opts) {
6376
6654
  return { child, port: opts.port };
6377
6655
  }
6378
6656
  function stopProcess(mp, timeout = 1e4) {
6379
- return new Promise((resolve14) => {
6657
+ return new Promise((resolve16) => {
6380
6658
  const timer = setTimeout(() => {
6381
6659
  mp.child.kill("SIGKILL");
6382
- resolve14();
6660
+ resolve16();
6383
6661
  }, timeout);
6384
6662
  mp.child.on("exit", () => {
6385
6663
  clearTimeout(timer);
6386
- resolve14();
6664
+ resolve16();
6387
6665
  });
6388
6666
  mp.child.kill("SIGTERM");
6389
6667
  });
@@ -6577,12 +6855,24 @@ async function deploy(config) {
6577
6855
  if (ac.ports && old?.process) {
6578
6856
  targetPort = old.currentPort === ac.ports[0] ? ac.ports[1] : ac.ports[0];
6579
6857
  }
6580
- const mp = await forkAndCheck(name, appDir, ac.entry, targetPort, ac.env, log, ac.healthEndpoint);
6858
+ const mp = await forkAndCheck(
6859
+ name,
6860
+ appDir,
6861
+ ac.entry,
6862
+ targetPort,
6863
+ ac.env,
6864
+ log,
6865
+ ac.healthEndpoint
6866
+ );
6581
6867
  if (!mp) {
6582
6868
  log("[deploy] new process failed to start, keeping old running");
6583
6869
  if (old?.process) apps.set(name, old);
6584
6870
  else {
6585
- setAppRuntime(name, ac, logs, { status: "error", port: targetPort, error: "failed to start" });
6871
+ setAppRuntime(name, ac, logs, {
6872
+ status: "error",
6873
+ port: targetPort,
6874
+ error: "failed to start"
6875
+ });
6586
6876
  }
6587
6877
  return;
6588
6878
  }
@@ -6625,7 +6915,7 @@ async function deploy(config) {
6625
6915
  function setAppRuntime(name, ac, logs, overrides) {
6626
6916
  apps.set(name, {
6627
6917
  config: ac,
6628
- status: { name, ...overrides },
6918
+ status: { name, status: "starting", port: 0, ...overrides },
6629
6919
  logs,
6630
6920
  process: null,
6631
6921
  currentPort: overrides.port ?? ac.port ?? 0,
@@ -6703,22 +6993,168 @@ import { createOpenAI as createOpenAI3 } from "@ai-sdk/openai";
6703
6993
 
6704
6994
  // ssr.ts
6705
6995
  import { createElement as createElement3 } from "react";
6706
- import { createHash as createHash3 } from "node:crypto";
6707
- import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync } from "node:fs";
6996
+ import { createHash as createHash4 } from "node:crypto";
6997
+ import { existsSync as existsSync6, readdirSync } from "node:fs";
6708
6998
  import { readdir, stat } from "node:fs/promises";
6709
- import { dirname as dirname3, join as join5, resolve as resolve6, relative as relative2 } from "node:path";
6999
+ import { dirname as dirname4, join as join5, resolve as resolve8, relative as relative3 } from "node:path";
6710
7000
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
6711
7001
 
6712
7002
  // compile.ts
6713
- import * as esbuild from "esbuild";
6714
- import { existsSync, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
6715
- import { join as join2, resolve as resolve3, dirname } from "node:path";
7003
+ import * as esbuild2 from "esbuild";
7004
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3 } from "node:fs";
7005
+ import { join as join2, resolve as resolve4, dirname as dirname2 } from "node:path";
6716
7006
  import { pathToFileURL } from "node:url";
6717
7007
  import { createHash } from "node:crypto";
7008
+ import { createRequire as createRequire2 } from "node:module";
7009
+
7010
+ // server-registry.ts
7011
+ import * as esbuild from "esbuild";
7012
+ import { existsSync, readFileSync as readFileSync2, statSync } from "node:fs";
7013
+ import { resolve as resolve3, dirname } from "node:path";
6718
7014
  import vm from "node:vm";
6719
7015
  import { createRequire } from "node:module";
6720
- var _cjsRequire = createRequire(import.meta.url);
6721
7016
  var _userRequire = null;
7017
+ function getUserRequire() {
7018
+ if (!_userRequire) {
7019
+ try {
7020
+ _userRequire = createRequire(resolve3(process.cwd(), "package.json"));
7021
+ } catch {
7022
+ _userRequire = createRequire(import.meta.url);
7023
+ }
7024
+ }
7025
+ return _userRequire;
7026
+ }
7027
+ var _alias = null;
7028
+ function resolveAliases() {
7029
+ if (_alias) return _alias;
7030
+ const configFiles = ["tsconfig.json", "jsconfig.json"];
7031
+ for (const file of configFiles) {
7032
+ const p = resolve3(file);
7033
+ if (existsSync(p)) {
7034
+ try {
7035
+ const config = JSON.parse(readFileSync2(p, "utf-8"));
7036
+ const paths = config.compilerOptions?.paths;
7037
+ if (paths) {
7038
+ const alias = {};
7039
+ for (const [key, values] of Object.entries(paths)) {
7040
+ const cleanKey = key.replace("/*", "");
7041
+ const val = values[0]?.replace("/*", "");
7042
+ if (val) alias[cleanKey] = resolve3(dirname(p), val);
7043
+ }
7044
+ _alias = alias;
7045
+ return alias;
7046
+ }
7047
+ } catch {
7048
+ }
7049
+ }
7050
+ }
7051
+ _alias = {};
7052
+ return {};
7053
+ }
7054
+ function applyAlias(id2, _moduleDir) {
7055
+ const aliases = resolveAliases();
7056
+ for (const [prefix, target] of Object.entries(aliases)) {
7057
+ if (id2.startsWith(prefix)) {
7058
+ const rest = id2.slice(prefix.length);
7059
+ return target + rest;
7060
+ }
7061
+ }
7062
+ return null;
7063
+ }
7064
+ var exts = [".tsx", ".ts", ".jsx", ".js"];
7065
+ function tryResolve(base) {
7066
+ if (existsSync(base)) {
7067
+ const stat3 = statSync(base);
7068
+ if (stat3.isFile()) return base;
7069
+ if (stat3.isDirectory()) {
7070
+ for (const ext of exts) {
7071
+ const p = resolve3(base, `index${ext}`);
7072
+ if (existsSync(p)) return p;
7073
+ }
7074
+ return null;
7075
+ }
7076
+ }
7077
+ for (const ext of exts) {
7078
+ const p = base + ext;
7079
+ if (existsSync(p)) return p;
7080
+ }
7081
+ return null;
7082
+ }
7083
+ var registry = /* @__PURE__ */ new Map();
7084
+ var _ctx = vm.createContext(Object.create(globalThis));
7085
+ function transformToCjs(absPath, source) {
7086
+ const isTsx = absPath.endsWith(".tsx");
7087
+ const result = esbuild.transformSync(source, {
7088
+ loader: isTsx ? "tsx" : "ts",
7089
+ format: "cjs",
7090
+ jsx: isTsx ? "automatic" : void 0,
7091
+ jsxImportSource: isTsx ? "react" : void 0,
7092
+ sourcemap: false
7093
+ });
7094
+ return result.code;
7095
+ }
7096
+ function makeRequire(modulePath) {
7097
+ const moduleDir = dirname(modulePath);
7098
+ return (id2) => {
7099
+ if (id2.startsWith(".")) {
7100
+ const base = resolve3(moduleDir, id2);
7101
+ const file = tryResolve(base);
7102
+ if (!file) {
7103
+ throw new Error(
7104
+ `[server-registry] Cannot resolve '${id2}' from '${modulePath}'. Tried: ${[base, ...exts.map((e) => base + e)].filter((p) => !p.endsWith(base)).join(", ")}`
7105
+ );
7106
+ }
7107
+ return getServerModule(file);
7108
+ }
7109
+ const aliased = applyAlias(id2, moduleDir);
7110
+ if (aliased) {
7111
+ const file = tryResolve(aliased);
7112
+ if (file) return getServerModule(file);
7113
+ }
7114
+ return getUserRequire()(id2);
7115
+ };
7116
+ }
7117
+ function evaluateModule(code, modulePath) {
7118
+ const mod = { exports: {} };
7119
+ const require2 = makeRequire(modulePath);
7120
+ const _dirname = dirname(modulePath);
7121
+ const _filename = modulePath;
7122
+ const wrapped = `(function(require,module,exports,__dirname,__filename){
7123
+ ${code}
7124
+ })`;
7125
+ try {
7126
+ new vm.Script(wrapped).runInContext(_ctx)(require2, mod, mod.exports, _dirname, _filename);
7127
+ } catch (err) {
7128
+ const msg = err instanceof Error ? err.message : String(err);
7129
+ const cause = err instanceof Error ? err : void 0;
7130
+ throw new Error(
7131
+ `[server-registry] Error evaluating '${modulePath}': ${msg}`,
7132
+ cause ? { cause } : void 0
7133
+ );
7134
+ }
7135
+ return mod.exports;
7136
+ }
7137
+ function getServerModule(absPath) {
7138
+ const normalized = resolve3(absPath);
7139
+ if (registry.has(normalized)) return registry.get(normalized).exports;
7140
+ const source = readFileSync2(normalized, "utf-8");
7141
+ const code = transformToCjs(normalized, source);
7142
+ const exports = evaluateModule(code, normalized);
7143
+ registry.set(normalized, { exports });
7144
+ return exports;
7145
+ }
7146
+ function clearServerModule(absPath) {
7147
+ if (absPath) {
7148
+ const normalized = resolve3(absPath);
7149
+ registry.delete(normalized);
7150
+ } else {
7151
+ registry.clear();
7152
+ _alias = null;
7153
+ }
7154
+ }
7155
+
7156
+ // compile.ts
7157
+ var _userRequire2 = null;
6722
7158
  var OUT_DIR = ".weifuwu/ssr";
6723
7159
  var cache = /* @__PURE__ */ new Map();
6724
7160
  var externals = [
@@ -6731,31 +7167,31 @@ var externals = [
6731
7167
  "@graphql-tools/schema",
6732
7168
  "ai"
6733
7169
  ];
6734
- var _alias = null;
6735
- function resolveAliases() {
6736
- if (_alias) return _alias;
7170
+ var _alias2 = null;
7171
+ function resolveAliases2() {
7172
+ if (_alias2) return _alias2;
6737
7173
  const configFiles = ["tsconfig.json", "jsconfig.json"];
6738
7174
  for (const file of configFiles) {
6739
- const p = resolve3(file);
6740
- if (existsSync(p)) {
7175
+ const p = resolve4(file);
7176
+ if (existsSync2(p)) {
6741
7177
  try {
6742
- const config = JSON.parse(readFileSync2(p, "utf-8"));
7178
+ const config = JSON.parse(readFileSync3(p, "utf-8"));
6743
7179
  const paths = config.compilerOptions?.paths;
6744
7180
  if (paths) {
6745
7181
  const alias = {};
6746
7182
  for (const [key, values] of Object.entries(paths)) {
6747
7183
  const cleanKey = key.replace("/*", "");
6748
7184
  const val = values[0]?.replace("/*", "");
6749
- if (val) alias[cleanKey] = resolve3(dirname(p), val);
7185
+ if (val) alias[cleanKey] = resolve4(dirname2(p), val);
6750
7186
  }
6751
- _alias = alias;
7187
+ _alias2 = alias;
6752
7188
  return alias;
6753
7189
  }
6754
7190
  } catch {
6755
7191
  }
6756
7192
  }
6757
7193
  }
6758
- _alias = {};
7194
+ _alias2 = {};
6759
7195
  return {};
6760
7196
  }
6761
7197
  function id(s) {
@@ -6763,16 +7199,17 @@ function id(s) {
6763
7199
  }
6764
7200
  function clearCompileCache() {
6765
7201
  cache.clear();
6766
- _alias = null;
7202
+ clearServerModule();
7203
+ _alias2 = null;
6767
7204
  }
6768
7205
  async function compileTsx(path2) {
6769
- const absPath = resolve3(path2);
7206
+ const absPath = resolve4(path2);
6770
7207
  if (cache.has(absPath)) return cache.get(absPath);
6771
- const outDir = resolve3(OUT_DIR);
7208
+ const outDir = resolve4(OUT_DIR);
6772
7209
  mkdirSync(outDir, { recursive: true });
6773
7210
  const hash = id(absPath);
6774
7211
  const outPath = join2(outDir, hash + ".js");
6775
- await esbuild.build({
7212
+ await esbuild2.build({
6776
7213
  entryPoints: { [hash]: absPath },
6777
7214
  outdir: outDir,
6778
7215
  format: "esm",
@@ -6781,7 +7218,7 @@ async function compileTsx(path2) {
6781
7218
  jsxImportSource: "react",
6782
7219
  bundle: true,
6783
7220
  external: externals,
6784
- alias: resolveAliases(),
7221
+ alias: resolveAliases2(),
6785
7222
  write: true,
6786
7223
  allowOverwrite: true
6787
7224
  });
@@ -6789,56 +7226,34 @@ async function compileTsx(path2) {
6789
7226
  cache.set(absPath, mod);
6790
7227
  return mod;
6791
7228
  }
6792
- function loadSSRModule(code) {
6793
- const ctx = vm.createContext(Object.create(globalThis));
6794
- const mod = { exports: {} };
6795
- ctx.require = (name) => _cjsRequire(name);
6796
- ctx.module = mod;
6797
- ctx.exports = mod.exports;
6798
- new vm.Script(code).runInContext(ctx);
6799
- return mod.exports;
6800
- }
6801
- async function compileTsxDev(path2) {
6802
- const absPath = resolve3(path2);
6803
- if (cache.has(absPath)) return cache.get(absPath);
6804
- const result = await esbuild.build({
6805
- entryPoints: { [id(absPath)]: absPath },
6806
- format: "cjs",
6807
- platform: "node",
6808
- jsx: "automatic",
6809
- jsxImportSource: "react",
6810
- bundle: true,
6811
- external: externals,
6812
- alias: resolveAliases(),
6813
- write: false
6814
- });
6815
- const code = new TextDecoder().decode(result.outputFiles[0].contents);
6816
- const mod = loadSSRModule(code);
7229
+ function compileTsxDev(path2) {
7230
+ const absPath = resolve4(path2);
7231
+ const mod = getServerModule(absPath);
6817
7232
  cache.set(absPath, mod);
6818
7233
  return mod;
6819
7234
  }
6820
7235
  function compile(path2) {
6821
- return isDev() ? compileTsxDev(path2) : compileTsx(path2);
7236
+ return isDev() ? Promise.resolve(compileTsxDev(path2)) : compileTsx(path2);
6822
7237
  }
6823
7238
  var vendorBundle = null;
6824
7239
  var vendorHash = "";
6825
7240
  async function compileVendorBundle() {
6826
7241
  if (vendorBundle) return vendorBundle;
6827
- if (!_userRequire) _userRequire = createRequire(join2(process.cwd(), "package.json"));
7242
+ if (!_userRequire2) _userRequire2 = createRequire2(join2(process.cwd(), "package.json"));
6828
7243
  const modules = {
6829
- "react": [],
7244
+ react: [],
6830
7245
  "react-dom": ["react"],
6831
7246
  "react-dom/client": ["react"],
6832
7247
  "react/jsx-runtime": ["react"]
6833
7248
  };
6834
7249
  for (const request of Object.keys(modules)) {
6835
- const mod = _userRequire(request);
7250
+ const mod = _userRequire2(request);
6836
7251
  const keys = Object.keys(mod).filter((k) => !k.startsWith("_") && k !== "default");
6837
7252
  modules[request] = keys;
6838
7253
  }
6839
7254
  const baseDir = import.meta.dirname ?? __dirname;
6840
- const reactAbsPath = isBundled() ? resolve3(baseDir, "react.js") : resolve3(baseDir, "react.ts");
6841
- const reactSrc = readFileSync2(reactAbsPath, "utf-8");
7255
+ const reactAbsPath = isBundled() ? resolve4(baseDir, "react.js") : resolve4(baseDir, "react.ts");
7256
+ const reactSrc = readFileSync3(reactAbsPath, "utf-8");
6842
7257
  const wfwKeys = [];
6843
7258
  if (reactAbsPath.endsWith(".ts")) {
6844
7259
  for (const line of reactSrc.split("\n")) {
@@ -6863,11 +7278,13 @@ async function compileVendorBundle() {
6863
7278
  const stmts = [""];
6864
7279
  for (const [request, keys] of Object.entries(modules)) {
6865
7280
  const unique = keys.filter((k) => !used.has(k) && used.add(k));
6866
- if (unique.length > 0) stmts.push(`export { ${unique.join(", ")} } from ${JSON.stringify(request)};`);
7281
+ if (unique.length > 0)
7282
+ stmts.push(`export { ${unique.join(", ")} } from ${JSON.stringify(request)};`);
6867
7283
  }
6868
7284
  const uidWfw = wfwKeys.filter((k) => !used.has(k) && used.add(k));
6869
- if (uidWfw.length > 0) stmts.push(`export { ${uidWfw.join(", ")} } from ${JSON.stringify(reactAbsPath)};`);
6870
- const result = await esbuild.build({
7285
+ if (uidWfw.length > 0)
7286
+ stmts.push(`export { ${uidWfw.join(", ")} } from ${JSON.stringify(reactAbsPath)};`);
7287
+ const result = await esbuild2.build({
6871
7288
  stdin: { contents: stmts.join("\n"), resolveDir: process.cwd() },
6872
7289
  format: "esm",
6873
7290
  bundle: true,
@@ -6879,81 +7296,6 @@ async function compileVendorBundle() {
6879
7296
  vendorHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
6880
7297
  return vendorBundle;
6881
7298
  }
6882
- async function compileBrowser(path2, outDir) {
6883
- const absPath = resolve3(path2);
6884
- const h = id(absPath);
6885
- outDir = outDir ?? resolve3(OUT_DIR);
6886
- const outPath = join2(outDir, h + ".js");
6887
- if (!isDev() && existsSync(outPath)) return h;
6888
- mkdirSync(outDir, { recursive: true });
6889
- const wfwDir = resolve3(import.meta.dirname ?? __dirname);
6890
- const plugin = {
6891
- name: "wfw-external",
6892
- setup(build2) {
6893
- build2.onResolve({ filter: /./ }, (args) => {
6894
- if (args.kind === "entry-point") return;
6895
- const abs = args.path.startsWith(".") ? join2(args.resolveDir, args.path) : args.path;
6896
- if (abs.startsWith(wfwDir) && !abs.includes("node_modules")) {
6897
- const rel = abs.slice(wfwDir.length + 1);
6898
- if (rel.includes("/")) return;
6899
- return { path: "weifuwu/react", external: true };
6900
- }
6901
- });
6902
- }
6903
- };
6904
- await esbuild.build({
6905
- entryPoints: { [h]: absPath },
6906
- outdir: outDir,
6907
- format: "esm",
6908
- platform: "browser",
6909
- jsx: "automatic",
6910
- jsxImportSource: "react",
6911
- bundle: true,
6912
- external: ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "weifuwu", "weifuwu/react"],
6913
- plugins: [plugin],
6914
- write: true,
6915
- allowOverwrite: true
6916
- });
6917
- return h;
6918
- }
6919
- async function compileHotComponent(path2) {
6920
- const absPath = resolve3(path2);
6921
- const h = id(absPath);
6922
- const stdin = `import C from ${JSON.stringify(absPath)};
6923
- (window.__WFW_REFRESH||function(){})(C)`;
6924
- const wfwDir = resolve3(import.meta.dirname ?? __dirname);
6925
- const plugin = {
6926
- name: "wfw-external",
6927
- setup(build2) {
6928
- build2.onResolve({ filter: /./ }, (args) => {
6929
- if (args.kind === "entry-point") return;
6930
- const abs = args.path.startsWith(".") ? join2(args.resolveDir, args.path) : args.path;
6931
- if (abs.startsWith(wfwDir) && !abs.includes("node_modules")) {
6932
- const rel = abs.slice(wfwDir.length + 1);
6933
- if (rel.includes("/")) return;
6934
- return { path: "weifuwu/react", external: true };
6935
- }
6936
- });
6937
- }
6938
- };
6939
- const result = await esbuild.build({
6940
- stdin: { contents: stdin, loader: "tsx", resolveDir: dirname(absPath) },
6941
- format: "esm",
6942
- platform: "browser",
6943
- jsx: "automatic",
6944
- jsxImportSource: "react",
6945
- bundle: true,
6946
- external: ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "weifuwu", "weifuwu/react"],
6947
- plugins: [plugin],
6948
- write: false
6949
- });
6950
- let code = new TextDecoder().decode(result.outputFiles[0].contents);
6951
- if (code.includes("__require") && (code.includes('"react"') || code.includes("'react'"))) {
6952
- code = `import * as __r from 'react';
6953
- ` + code.replace(/__require\(["']react["']\)/g, "__r");
6954
- }
6955
- return { hash: h, code };
6956
- }
6957
7299
 
6958
7300
  // stream.ts
6959
7301
  import { TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
@@ -6971,6 +7313,8 @@ function getPublicEnv2() {
6971
7313
  function buildHeadPayload(opts) {
6972
7314
  const { ctx, base, tailwind } = opts;
6973
7315
  let result = "";
7316
+ result += `<script>window.__wfw={_cache:{},_k:function(u){return u.split('?')[0]},h:async function(u){var k=this._k(u);if(this._cache[k])return this._cache[k];var m=await import(u);this._cache[k]=m;return m},_update:function(u,mod){var k=this._k(u);this._cache[k]=mod}}</script>
7317
+ `;
6974
7318
  const vUrl = `${base}/__wfw/v/bundle?h=${vendorHash}`;
6975
7319
  result += `<script type="importmap">{
6976
7320
  "imports": {
@@ -7055,26 +7399,37 @@ function streamResponse(reactStream, opts, hydrationScript) {
7055
7399
  if (built) bodyScripts += built;
7056
7400
  if (opts.isDev) {
7057
7401
  const wsUrl = `${opts.base}/__weifuwu/livereload`;
7058
- const hbUrl = `${opts.base}/__wfw/h/`;
7059
7402
  bodyScripts += `
7060
7403
  <script>
7061
7404
  (function(){
7062
7405
  var ws=new WebSocket((location.protocol==='https:'?'wss:':'ws:')+'//'+location.host+'${wsUrl}');
7063
7406
  var t=0;
7407
+ var _w=window;
7064
7408
  ws.onmessage=function(e){
7065
7409
  try{
7066
7410
  var m=JSON.parse(e.data);
7067
- if(m.type==='component'){
7068
- import('${hbUrl}'+m.hash+'?t='+Date.now()).catch(function(){location.reload()});
7069
- if(m.css){
7070
- var s=document.querySelector('style[data-lr]')||function(){
7071
- var x=document.createElement('style');
7072
- x.setAttribute('data-lr','');
7073
- document.head.appendChild(x);
7074
- return x
7075
- }();
7076
- s.textContent=m.css
7077
- }
7411
+ if(m.type==='update'&&m.url&&m.code){
7412
+ var blob=new Blob([m.code],{type:'application/javascript'});
7413
+ var blobUrl=URL.createObjectURL(blob);
7414
+ import(blobUrl).then(function(mod){
7415
+ if(_w.__wfw) _w.__wfw._update(m.url,mod);
7416
+ // Re-import page module so it re-evaluates its __wfw.h() imports
7417
+ var pageUrl=_w.__WFW_PAGE_URL;
7418
+ if(pageUrl&&_w.__WFW_REFRESH){
7419
+ import(pageUrl.split('?')[0]+'?t='+Date.now()).then(function(pageMod){
7420
+ if(pageMod.default) _w.__WFW_REFRESH(pageMod.default);
7421
+ if(m.css){
7422
+ var s=document.querySelector('style[data-lr]')||function(){
7423
+ var x=document.createElement('style');
7424
+ x.setAttribute('data-lr','');
7425
+ document.head.appendChild(x);
7426
+ return x
7427
+ }();
7428
+ s.textContent=m.css
7429
+ }
7430
+ });
7431
+ }else{location.reload()}
7432
+ }).catch(function(){location.reload()});
7078
7433
  return
7079
7434
  }
7080
7435
  if(m.type==='css'){
@@ -7125,12 +7480,12 @@ var ssrEntries = /* @__PURE__ */ new Map();
7125
7480
 
7126
7481
  // tailwind.ts
7127
7482
  import { createHash as createHash2 } from "node:crypto";
7128
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "node:fs";
7129
- import { join as join3, relative, resolve as resolve4 } from "node:path";
7483
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync } from "node:fs";
7484
+ import { join as join3, relative, resolve as resolve5 } from "node:path";
7130
7485
  var extraSources = /* @__PURE__ */ new Set();
7131
7486
  var cssCache = /* @__PURE__ */ new Map();
7132
7487
  function tailwindContext(dir) {
7133
- const cssDir = resolve4(dir);
7488
+ const cssDir = resolve5(dir);
7134
7489
  const cssPath = join3(cssDir, "app", "globals.css");
7135
7490
  return async (req, ctx, next) => {
7136
7491
  if (!cssCache.has(cssPath)) {
@@ -7144,10 +7499,10 @@ function tailwindContext(dir) {
7144
7499
  };
7145
7500
  }
7146
7501
  function tailwindRouter(dir) {
7147
- const cssDir = resolve4(dir);
7502
+ const cssDir = resolve5(dir);
7148
7503
  const cssPath = join3(cssDir, "app", "globals.css");
7149
7504
  const r = new Router();
7150
- r.get("/__wfw/style/:hash.css", async (req, ctx) => {
7505
+ r.get("/__wfw/style/:hash.css", async (_req, _ctx2) => {
7151
7506
  if (!cssCache.has(cssPath)) {
7152
7507
  await compileTailwindCss(cssPath, cssDir);
7153
7508
  }
@@ -7161,13 +7516,13 @@ function tailwindRouter(dir) {
7161
7516
  }
7162
7517
  async function compileTailwindCss(cssPath, cssDir) {
7163
7518
  try {
7164
- if (!existsSync2(cssPath)) {
7519
+ if (!existsSync3(cssPath)) {
7165
7520
  mkdirSync2(cssDir, { recursive: true });
7166
7521
  writeFileSync(cssPath, '@import "tailwindcss"\n', "utf-8");
7167
7522
  }
7168
7523
  const { default: tailwindPlugin } = await import("@tailwindcss/postcss");
7169
7524
  const { default: postcss } = await import("postcss");
7170
- let src = readFileSync3(cssPath, "utf-8");
7525
+ let src = readFileSync4(cssPath, "utf-8");
7171
7526
  src = `@source "./";
7172
7527
  ${src}`;
7173
7528
  for (const srcDir of extraSources) {
@@ -7187,22 +7542,151 @@ ${src}`;
7187
7542
 
7188
7543
  // live.ts
7189
7544
  import chokidar from "chokidar";
7190
- import { existsSync as existsSync3 } from "node:fs";
7191
- import { dirname as dirname2, join as join4, resolve as resolve5 } from "node:path";
7192
- var clients = /* @__PURE__ */ new Set();
7193
- var hotBundleCache = /* @__PURE__ */ new Map();
7194
- var hotKeys = [];
7195
- var MAX_HOT = 10;
7196
- function setHot(hash, code) {
7197
- if (!hotBundleCache.has(hash)) {
7198
- hotKeys.push(hash);
7199
- if (hotKeys.length > MAX_HOT) {
7200
- const old = hotKeys.shift();
7201
- hotBundleCache.delete(old);
7202
- }
7545
+ import { existsSync as existsSync5 } from "node:fs";
7546
+ import { join as join4, resolve as resolve7 } from "node:path";
7547
+
7548
+ // module-server.ts
7549
+ import * as esbuild3 from "esbuild";
7550
+ import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
7551
+ import { resolve as resolve6, dirname as dirname3, relative as relative2 } from "node:path";
7552
+ import { createHash as createHash3 } from "node:crypto";
7553
+ var moduleCache = /* @__PURE__ */ new Map();
7554
+ var hashCache = /* @__PURE__ */ new Map();
7555
+ function clearModuleCache(filePath) {
7556
+ if (filePath) {
7557
+ const abs = resolve6(filePath);
7558
+ for (const key of moduleCache.keys()) {
7559
+ if (key.endsWith(abs)) moduleCache.delete(key);
7560
+ }
7561
+ hashCache.delete(abs);
7562
+ } else {
7563
+ moduleCache.clear();
7564
+ hashCache.clear();
7203
7565
  }
7204
- hotBundleCache.set(hash, code);
7205
7566
  }
7567
+ var _importRoots = [];
7568
+ function _setImportRoots(roots) {
7569
+ _importRoots = roots;
7570
+ }
7571
+ function fileHash(absPath) {
7572
+ const cached = hashCache.get(absPath);
7573
+ if (cached) return cached;
7574
+ try {
7575
+ const content = readFileSync5(absPath);
7576
+ const h = createHash3("md5").update(content).digest("hex").slice(0, 8);
7577
+ hashCache.set(absPath, h);
7578
+ return h;
7579
+ } catch {
7580
+ return "00000000";
7581
+ }
7582
+ }
7583
+ function rewriteImports(code, absPath, mountPath) {
7584
+ const prefix = mountPath ? `${mountPath}/__wfw/m` : "/__wfw/m";
7585
+ let varCounter = 0;
7586
+ return code.replace(
7587
+ /^(import|export)\s+(.+?)\s+from\s+['"]([^'"]+)['"];?\s*$/gm,
7588
+ (_match, keyword, clause, modPath) => {
7589
+ if (!modPath.startsWith(".")) return _match;
7590
+ const isReexport = keyword === "export";
7591
+ const imports = clause.replace(/^type\s+/, "");
7592
+ const resolved = resolve6(dirname3(absPath), modPath);
7593
+ for (const root of _importRoots) {
7594
+ const rel = relative2(root, resolved);
7595
+ if (!rel.startsWith("..") && !rel.startsWith("/")) {
7596
+ const v = fileHash(resolved);
7597
+ const url = `${prefix}/${rel}?v=${v}`;
7598
+ const defaultMatch = imports.match(/^\s*(\w[\w$]*)\s*$/);
7599
+ const namedMatch = imports.match(/^\s*\{\s*([\w$,\s]+)\s*\}\s*$/);
7600
+ const mixedMatch = imports.match(/^\s*(\w[\w$]*)\s*,\s*\{\s*([\w$,\s]+)\s*\}\s*$/);
7601
+ if (defaultMatch) {
7602
+ const name = defaultMatch[1];
7603
+ if (isReexport) {
7604
+ return `const { default: ${name} } = await __wfw.h("${url}");
7605
+ export { ${name} as default }`;
7606
+ }
7607
+ return `const { default: ${name} } = await __wfw.h("${url}");`;
7608
+ }
7609
+ if (namedMatch) {
7610
+ const names = namedMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
7611
+ if (isReexport) {
7612
+ const tmp = `__wfw$${varCounter++}`;
7613
+ const lines = [`const ${tmp} = await __wfw.h("${url}");`];
7614
+ for (const n of names) lines.push(`export const ${n} = ${tmp}.${n};`);
7615
+ return lines.join("\n");
7616
+ }
7617
+ const decl = names.map((n) => `${n}`).join(", ");
7618
+ return `const { ${decl} } = await __wfw.h("${url}");`;
7619
+ }
7620
+ if (mixedMatch) {
7621
+ const defaultName = mixedMatch[1];
7622
+ const namedNames = mixedMatch[2].split(",").map((s) => s.trim()).filter(Boolean);
7623
+ const varName = `__wfw$${varCounter++}`;
7624
+ const lines = [
7625
+ `const ${varName} = await __wfw.h("${url}");`,
7626
+ `const ${defaultName} = ${varName}.default;`
7627
+ ];
7628
+ for (const n of namedNames) lines.push(`const { ${n} } = ${varName};`);
7629
+ return lines.join("\n");
7630
+ }
7631
+ return _match;
7632
+ }
7633
+ }
7634
+ return _match;
7635
+ }
7636
+ );
7637
+ }
7638
+ async function transformModule(absPath, root, mountPath) {
7639
+ const mp = mountPath || "";
7640
+ const cacheKey = mp + absPath;
7641
+ const cached = moduleCache.get(cacheKey);
7642
+ if (cached) return { url: `${mp}/__wfw/m/${relative2(root, absPath)}`, code: cached };
7643
+ const source = readFileSync5(absPath, "utf-8");
7644
+ const isTsx = absPath.endsWith(".tsx");
7645
+ const result = await esbuild3.transform(source, {
7646
+ loader: isTsx ? "tsx" : "ts",
7647
+ jsx: isTsx ? "automatic" : void 0,
7648
+ jsxImportSource: isTsx ? "react" : void 0,
7649
+ sourcemap: false
7650
+ });
7651
+ let code = result.code;
7652
+ code = rewriteImports(code, absPath, mp);
7653
+ moduleCache.set(cacheKey, code);
7654
+ const url = `${mp}/__wfw/m/${relative2(root, absPath)}`;
7655
+ return { url, code };
7656
+ }
7657
+ function moduleServer(opts) {
7658
+ const roots = Array.isArray(opts.root) ? opts.root : [opts.root];
7659
+ _setImportRoots(roots);
7660
+ const router = new Router();
7661
+ router.get("/__wfw/m/*", (async (req, ctx) => {
7662
+ const reqUrl = new URL(req.url);
7663
+ const filePath = (ctx.params["*"] || "").split("?")[0];
7664
+ const ext = filePath.split(".").pop();
7665
+ if (ext !== "tsx" && ext !== "ts") {
7666
+ return new Response("Not Found", { status: 404 });
7667
+ }
7668
+ const mountPath = ctx.mountPath || "";
7669
+ for (const root of roots) {
7670
+ const absPath = resolve6(root, filePath);
7671
+ if (existsSync4(absPath)) {
7672
+ try {
7673
+ const { code } = await transformModule(absPath, root, mountPath);
7674
+ return new Response(code, {
7675
+ headers: { "content-type": "application/javascript; charset=utf-8" }
7676
+ });
7677
+ } catch (err) {
7678
+ const msg = err instanceof Error ? err.message : String(err);
7679
+ return new Response(`/* Error: ${msg} */`, { status: 500 });
7680
+ }
7681
+ }
7682
+ }
7683
+ return new Response("Not Found", { status: 404 });
7684
+ }));
7685
+ return router;
7686
+ }
7687
+
7688
+ // live.ts
7689
+ var clients = /* @__PURE__ */ new Set();
7206
7690
  function broadcastReload() {
7207
7691
  for (const ws of clients) {
7208
7692
  try {
@@ -7224,89 +7708,63 @@ function broadcastCss(css) {
7224
7708
  }
7225
7709
  function liveWs() {
7226
7710
  return {
7227
- open(ws) {
7711
+ open(ws, _ctx2) {
7228
7712
  clients.add(ws);
7229
7713
  ws.on("close", () => clients.delete(ws));
7230
7714
  ws.on("error", () => clients.delete(ws));
7231
7715
  }
7232
7716
  };
7233
7717
  }
7234
- function liveRouter(dir) {
7718
+ function liveRouter(_dir) {
7235
7719
  const r = new Router();
7236
7720
  compileVendorBundle().catch(() => {
7237
7721
  });
7238
- r.get("/__wfw/h/:hash", async (req, ctx) => {
7239
- const hash = ctx.params.hash.replace(/\.js$/i, "");
7240
- const code = hotBundleCache.get(hash);
7241
- if (!code) return new Response("", { status: 404 });
7242
- return new Response(code, {
7243
- headers: { "content-type": "application/javascript; charset=utf-8" }
7244
- });
7245
- });
7246
7722
  return r;
7247
7723
  }
7248
7724
  function liveWatcher(dir) {
7249
- const resolved = resolve5(dir);
7250
- const entryPath = join4(resolved, "page.tsx");
7725
+ const resolved = resolve7(dir);
7251
7726
  const watcher = chokidar.watch(dir, {
7252
7727
  ignored: /(^|[/\\])\.|node_modules|[/\\]\.weifuwu[/\\]/,
7253
7728
  ignoreInitial: true
7254
7729
  });
7255
- function findEntries(changedPath) {
7256
- const matched = [];
7257
- for (const [, entry] of ssrEntries) {
7258
- if (!entry.path.startsWith(resolved)) continue;
7259
- if (entry.path === changedPath) {
7260
- matched.push(entry.path);
7261
- } else {
7262
- const ed = dirname2(entry.path);
7263
- if (changedPath.startsWith(ed)) matched.push(entry.path);
7264
- }
7265
- }
7266
- if (matched.length === 0) {
7267
- for (const [, entry] of ssrEntries) {
7268
- if (entry.path.startsWith(resolved)) matched.push(entry.path);
7269
- }
7270
- }
7271
- return matched;
7272
- }
7273
7730
  watcher.on("change", async (filePath) => {
7274
7731
  if (/\.tsx?$/i.test(filePath)) {
7275
7732
  if (filePath.endsWith("layout.tsx")) {
7276
7733
  return broadcastReload();
7277
7734
  }
7278
7735
  clearCompileCache();
7279
- const targets = existsSync3(entryPath) ? [entryPath] : findEntries(resolve5(filePath));
7280
- if (targets.length === 0) return broadcastReload();
7736
+ clearModuleCache();
7281
7737
  try {
7282
- let css;
7283
- const cssPath = join4(resolved, "app", "globals.css");
7284
- if (existsSync3(cssPath)) {
7285
- css = await compileTailwindCss(cssPath, resolved);
7286
- }
7287
- for (const target of targets) {
7288
- await compileTsxDev(target);
7289
- const { hash, code } = await compileHotComponent(target);
7290
- setHot(hash, code);
7291
- const entry = id(target);
7292
- const msg = { type: "component", hash, entry };
7293
- if (css) msg.css = css;
7294
- const str = JSON.stringify(msg);
7295
- for (const ws of clients) {
7296
- try {
7297
- ws.send(str);
7298
- } catch {
7299
- clients.delete(ws);
7300
- }
7738
+ await compileTsxDev(filePath);
7739
+ } catch (e) {
7740
+ console.error("server-side recompile failed:", e);
7741
+ return broadcastReload();
7742
+ }
7743
+ let css;
7744
+ const cssPath = join4(resolved, "app", "globals.css");
7745
+ if (existsSync5(cssPath)) {
7746
+ css = await compileTailwindCss(cssPath, resolved);
7747
+ }
7748
+ try {
7749
+ const absPath = resolve7(filePath);
7750
+ const { url, code } = await transformModule(absPath, resolved);
7751
+ const msg = { type: "update", url, code };
7752
+ if (css) msg.css = css;
7753
+ const str = JSON.stringify(msg);
7754
+ for (const ws of clients) {
7755
+ try {
7756
+ ws.send(str);
7757
+ } catch {
7758
+ clients.delete(ws);
7301
7759
  }
7302
7760
  }
7303
7761
  } catch (e) {
7304
- console.error("live reload failed, fallback to full reload:", e);
7762
+ console.error("module transform failed for HMR:", e);
7305
7763
  broadcastReload();
7306
7764
  }
7307
7765
  } else if (/\.css$/i.test(filePath)) {
7308
7766
  const cssPath = join4(resolved, "app", "globals.css");
7309
- if (existsSync3(cssPath)) {
7767
+ if (existsSync5(cssPath)) {
7310
7768
  const css = await compileTailwindCss(cssPath, resolved);
7311
7769
  if (css) broadcastCss(css);
7312
7770
  }
@@ -7394,7 +7852,7 @@ var isDev2 = isDev();
7394
7852
  var als2 = new AsyncLocalStorage2();
7395
7853
  __registerAls(() => als2.getStore());
7396
7854
  function hashId(s) {
7397
- return createHash3("md5").update(s).digest("hex").slice(0, 8);
7855
+ return createHash4("md5").update(s).digest("hex").slice(0, 8);
7398
7856
  }
7399
7857
  function serializeLoaderData(ctx) {
7400
7858
  const ld = ctx.loaderData;
@@ -7469,7 +7927,7 @@ async function resolveRoute(ssrDir, segments, routeCache) {
7469
7927
  return null;
7470
7928
  }
7471
7929
  const pageFile = join5(dir, "page.tsx");
7472
- if (!existsSync4(pageFile)) {
7930
+ if (!existsSync6(pageFile)) {
7473
7931
  routeCache.set(cacheKey, null);
7474
7932
  return null;
7475
7933
  }
@@ -7480,35 +7938,40 @@ async function resolveRoute(ssrDir, segments, routeCache) {
7480
7938
  let d = dir;
7481
7939
  while (d.startsWith(appDir)) {
7482
7940
  const lf = join5(d, "layout.tsx");
7483
- if (existsSync4(lf)) layoutFiles.unshift(lf);
7941
+ if (existsSync6(lf)) layoutFiles.unshift(lf);
7484
7942
  if (d === appDir) break;
7485
- d = dirname3(d);
7943
+ d = dirname4(d);
7486
7944
  }
7487
7945
  const errorFiles = [];
7488
7946
  d = dir;
7489
7947
  while (d.startsWith(appDir)) {
7490
7948
  const ef = join5(d, "error.tsx");
7491
- if (existsSync4(ef)) errorFiles.unshift(ef);
7949
+ if (existsSync6(ef)) errorFiles.unshift(ef);
7492
7950
  if (d === appDir) break;
7493
- d = dirname3(d);
7951
+ d = dirname4(d);
7494
7952
  }
7495
7953
  let notFoundFile = null;
7496
7954
  d = dir;
7497
7955
  while (d.startsWith(appDir)) {
7498
7956
  const nf = join5(d, "not-found.tsx");
7499
- if (existsSync4(nf)) {
7957
+ if (existsSync6(nf)) {
7500
7958
  notFoundFile = nf;
7501
7959
  break;
7502
7960
  }
7503
7961
  if (d === appDir) break;
7504
- d = dirname3(d);
7505
- }
7506
- const result = { routePath: "/" + routeParams.join("/"), pageFile, layoutFiles, errorFiles, notFoundFile };
7962
+ d = dirname4(d);
7963
+ }
7964
+ const result = {
7965
+ routePath: "/" + routeParams.join("/"),
7966
+ pageFile,
7967
+ layoutFiles,
7968
+ errorFiles,
7969
+ notFoundFile
7970
+ };
7507
7971
  routeCache.set(cacheKey, result);
7508
7972
  return result;
7509
7973
  }
7510
- function buildHydrationScript(entryId, ctxJson, base) {
7511
- const ssrPrefix = `${base}/__ssr`;
7974
+ function buildHydrationScript(pageUrl, ctxJson) {
7512
7975
  return `
7513
7976
  <script type="module">
7514
7977
  import { setCtx, TsxContext } from 'weifuwu/react';
@@ -7521,10 +7984,11 @@ setCtx(_ctx);
7521
7984
  const _root = document.getElementById('__weifuwu_root');
7522
7985
 
7523
7986
  async function init() {
7524
- const { default: Page } = await import('${ssrPrefix}/${entryId}.js');
7525
- const app = createElement(TsxContext.Provider, { value: _ctx },
7526
- createElement(Page));
7987
+ const { default: Page } = await import('${pageUrl}');
7527
7988
  ${isDev2 ? `
7989
+ // Store page URL for __wfw runtime
7990
+ window.__WFW_PAGE_URL = '${pageUrl}';
7991
+
7528
7992
  // Stable proxy \u2014 same function ref = React preserves fiber + useState state across HMR
7529
7993
  const _pageImpl = { current: Page };
7530
7994
  const _pageProxy = new Proxy(function __wfw_page(){}, {
@@ -7541,14 +8005,22 @@ async function init() {
7541
8005
  }
7542
8006
  renderPage();
7543
8007
 
8008
+ // HMR: re-render page (sub-modules resolved via __wfw.h() pick up changes)
8009
+ window.__WFW_RERENDER = () => {
8010
+ _tick++;
8011
+ reactRoot.render(createElement(TsxContext.Provider, { value: _ctx },
8012
+ createElement(_pageProxy, { __t: _tick })));
8013
+ };
8014
+
8015
+ // Fallback: swap entire page component
7544
8016
  window.__WFW_REFRESH = async (NewComponent) => {
7545
8017
  const store = globalThis.__WEIFUWU_CTX_STORE?._ctx || _ctx;
7546
8018
  _pageImpl.current = NewComponent;
7547
- _tick++;
7548
- reactRoot.render(createElement(TsxContext.Provider, { value: store },
7549
- createElement(_pageProxy, { __t: _tick })));
8019
+ __WFW_RERENDER();
7550
8020
  };
7551
8021
  ` : `
8022
+ const app = createElement(TsxContext.Provider, { value: _ctx },
8023
+ createElement(Page));
7552
8024
  hydrateRoot(_root, app);
7553
8025
  `}
7554
8026
  }
@@ -7556,11 +8028,10 @@ async function init() {
7556
8028
  init();
7557
8029
  </script>`;
7558
8030
  }
7559
- function renderPage(pageFile, outDir) {
7560
- const absPath = resolve6(pageFile);
8031
+ function renderPage(pageFile, projectDir) {
8032
+ const absPath = resolve8(pageFile);
7561
8033
  const entryId = hashId(absPath);
7562
8034
  ssrEntries.set(entryId, { path: absPath });
7563
- const bundleKey = `/__ssr/${entryId}.js`;
7564
8035
  return async (req, ctx) => {
7565
8036
  let pageMod;
7566
8037
  try {
@@ -7574,7 +8045,6 @@ function renderPage(pageFile, outDir) {
7574
8045
  if (!Component) return errorPage("Missing default export", pageFile);
7575
8046
  const layouts = ctx.layoutStack || [];
7576
8047
  const layoutComponents = layouts.map((l) => l.component);
7577
- const layoutPaths = layouts.map((l) => l.path);
7578
8048
  const base = (ctx.mountPath || "").replace(/\/$/, "");
7579
8049
  const loaderData = serializeLoaderData(ctx);
7580
8050
  const ctxValue = {
@@ -7588,28 +8058,29 @@ function renderPage(pageFile, outDir) {
7588
8058
  loaderData,
7589
8059
  env: ctx.env ?? {}
7590
8060
  };
8061
+ const pageRelative = relative3(projectDir, absPath);
8062
+ const pageUrl = `${base}/__wfw/m/${pageRelative}`;
7591
8063
  return als2.run(ctxValue, async () => {
7592
8064
  setCtx(ctxValue);
7593
- await compileBrowser(absPath, outDir);
7594
8065
  let element = createElement3(
7595
8066
  "div",
7596
8067
  { id: "__weifuwu_root" },
7597
- createElement3(
7598
- TsxContext.Provider,
7599
- { value: ctxValue },
7600
- createElement3(Component, null)
7601
- )
8068
+ createElement3(TsxContext.Provider, { value: ctxValue }, createElement3(Component, null))
7602
8069
  );
7603
8070
  element = buildHtmlShell("weifuwu", element, layoutComponents);
7604
8071
  const { renderToReadableStream } = await import("react-dom/server");
7605
8072
  const stream = await renderToReadableStream(element);
7606
- return streamResponse(stream, {
7607
- ctx,
7608
- base,
7609
- isDev: isDev2,
7610
- loaderData,
7611
- tailwind: ctx.tailwind
7612
- }, buildHydrationScript(entryId, JSON.stringify(ctxValue), base));
8073
+ return streamResponse(
8074
+ stream,
8075
+ {
8076
+ ctx,
8077
+ base,
8078
+ isDev: isDev2,
8079
+ loaderData,
8080
+ tailwind: ctx.tailwind
8081
+ },
8082
+ buildHydrationScript(pageUrl, JSON.stringify(ctxValue))
8083
+ );
7613
8084
  });
7614
8085
  };
7615
8086
  }
@@ -7623,7 +8094,7 @@ function runChain(mws, handler, req, ctx) {
7623
8094
  }
7624
8095
  function discoverRoutes(dir) {
7625
8096
  const appDir = join5(dir, "app");
7626
- if (!existsSync4(appDir)) return [];
8097
+ if (!existsSync6(appDir)) return [];
7627
8098
  const result = [];
7628
8099
  function walk(currentDir, routePath) {
7629
8100
  let entries;
@@ -7644,7 +8115,7 @@ function discoverRoutes(dir) {
7644
8115
  } else if (entry.name === "page.tsx") {
7645
8116
  result.push({
7646
8117
  path: routePath || "/",
7647
- file: relative2(appDir, join5(currentDir, entry.name))
8118
+ file: relative3(appDir, join5(currentDir, entry.name))
7648
8119
  });
7649
8120
  }
7650
8121
  }
@@ -7654,28 +8125,19 @@ function discoverRoutes(dir) {
7654
8125
  }
7655
8126
  function ssr(opts) {
7656
8127
  const r = new Router();
7657
- const dir = resolve6(opts.dir);
7658
- const outDir = resolve6(OUT_DIR);
8128
+ const dir = resolve8(opts.dir);
7659
8129
  const routeCache = /* @__PURE__ */ new Map();
8130
+ const wfwRoot = resolve8(import.meta.dirname ?? __dirname);
8131
+ r.use("/", moduleServer({ root: [dir, wfwRoot] }));
7660
8132
  compileVendorBundle().catch(() => {
7661
8133
  });
7662
- r.get("/__ssr/:file", (req, ctx) => {
7663
- const filePath = join5(outDir, ctx.params.file);
7664
- if (!filePath.startsWith(outDir) || !existsSync4(filePath)) {
7665
- return new Response("Not Found", { status: 404 });
7666
- }
7667
- const content = readFileSync4(filePath, "utf-8");
7668
- return new Response(content, {
7669
- headers: { "content-type": "application/javascript; charset=utf-8" }
7670
- });
7671
- });
7672
8134
  r.get("/__wfw/v/bundle", async () => {
7673
8135
  const code = await compileVendorBundle();
7674
8136
  return new Response(code, {
7675
8137
  headers: { "content-type": "application/javascript; charset=utf-8" }
7676
8138
  });
7677
8139
  });
7678
- if (existsSync4(join5(dir, "app", "globals.css"))) {
8140
+ if (existsSync6(join5(dir, "app", "globals.css"))) {
7679
8141
  r.use("/", tailwindRouter(dir));
7680
8142
  }
7681
8143
  let devWatcher;
@@ -7693,13 +8155,16 @@ function ssr(opts) {
7693
8155
  if (!resolved) {
7694
8156
  if (isDev2) {
7695
8157
  const pages = discoverRoutes(dir).map((p) => p.path).sort();
7696
- return Response.json({
7697
- error: "Not Found",
7698
- path: "/" + segments.join("/"),
7699
- method: req.method,
7700
- hint: "Available SSR pages",
7701
- pages
7702
- }, { status: 404 });
8158
+ return Response.json(
8159
+ {
8160
+ error: "Not Found",
8161
+ path: "/" + segments.join("/"),
8162
+ method: req.method,
8163
+ hint: "Available SSR pages",
8164
+ pages
8165
+ },
8166
+ { status: 404 }
8167
+ );
7703
8168
  }
7704
8169
  return new Response("Not Found", { status: 404 });
7705
8170
  }
@@ -7708,7 +8173,7 @@ function ssr(opts) {
7708
8173
  ...resolved.layoutFiles.map((f) => layout(f)),
7709
8174
  tailwindContext(dir)
7710
8175
  ];
7711
- const handler = (req2, ctx2) => renderPage(resolved.pageFile, outDir)(req2, ctx2);
8176
+ const handler = (req2, ctx2) => renderPage(resolved.pageFile, dir)(req2, ctx2);
7712
8177
  return runChain(mws, handler, req, ctx);
7713
8178
  });
7714
8179
  const mod = r;
@@ -7765,7 +8230,11 @@ async function getSession(sql2, id2) {
7765
8230
  async function listSessions(sql2, userId2) {
7766
8231
  const opts = { orderBy: { updated_at: "desc" } };
7767
8232
  if (userId2 !== void 0) {
7768
- const { data: rows2 } = await sessions.readMany(sql2, { user_id: userId2, active: true }, opts);
8233
+ const { data: rows2 } = await sessions.readMany(
8234
+ sql2,
8235
+ { user_id: userId2, active: true },
8236
+ opts
8237
+ );
7769
8238
  return rows2;
7770
8239
  }
7771
8240
  const { data: rows } = await sessions.readMany(sql2, { active: true }, opts);
@@ -7844,7 +8313,14 @@ async function* executeGenerator(opts) {
7844
8313
  totalTokens: result2.usage?.totalTokens ?? 0
7845
8314
  };
7846
8315
  try {
7847
- await addTextMessage(sql2, sessionId, "assistant", currentAssistantText, currentUsage.promptTokens, currentUsage.completionTokens);
8316
+ await addTextMessage(
8317
+ sql2,
8318
+ sessionId,
8319
+ "assistant",
8320
+ currentAssistantText,
8321
+ currentUsage.promptTokens,
8322
+ currentUsage.completionTokens
8323
+ );
7848
8324
  } catch (e) {
7849
8325
  console.error("[opencode] save message failed:", e);
7850
8326
  }
@@ -7887,11 +8363,7 @@ var DENIED_COMMANDS = [
7887
8363
  /^:\(\)\{.*\}:;$/,
7888
8364
  /^fork\s+bomb/i
7889
8365
  ];
7890
- var DENIED_PATHS = [
7891
- /\/\.env$/,
7892
- /\/\.env\.\w+$/,
7893
- /\/node_modules\//
7894
- ];
8366
+ var DENIED_PATHS = [/\/\.env$/, /\/\.env\.\w+$/, /\/node_modules\//];
7895
8367
  function isCommandAllowed(command) {
7896
8368
  const trimmed = command.trim();
7897
8369
  for (const re of DENIED_COMMANDS) {
@@ -7899,7 +8371,7 @@ function isCommandAllowed(command) {
7899
8371
  }
7900
8372
  return true;
7901
8373
  }
7902
- function isPathAllowed(resolvedPath, workspace, perms) {
8374
+ function isPathAllowed(resolvedPath, workspace, _perms) {
7903
8375
  if (!resolvedPath.startsWith(workspace)) return false;
7904
8376
  for (const re of DENIED_PATHS) {
7905
8377
  if (re.test(resolvedPath)) return false;
@@ -7953,17 +8425,21 @@ function createBashTool(ctx) {
7953
8425
  return { stdout: "", stderr: "Command denied: potentially dangerous command", exitCode: 1 };
7954
8426
  }
7955
8427
  const cwd = workdir ? `${ctx.workspace}/${workdir}` : ctx.workspace;
7956
- return new Promise((resolve14) => {
7957
- const child = exec(command, { cwd, timeout: timeout * 1e3, maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
7958
- const truncated = stdout.length > 1e6 || stderr.length > 1e6;
7959
- resolve14({
7960
- stdout: stdout.slice(0, 1e6),
7961
- stderr: stderr.slice(0, 1e6),
7962
- exitCode: error?.code ?? 0,
7963
- signal: error?.signal ?? null,
7964
- truncated
7965
- });
7966
- });
8428
+ return new Promise((resolve16) => {
8429
+ const child = exec(
8430
+ command,
8431
+ { cwd, timeout: timeout * 1e3, maxBuffer: 1024 * 1024 },
8432
+ (error, stdout, stderr) => {
8433
+ const truncated = stdout.length > 1e6 || stderr.length > 1e6;
8434
+ resolve16({
8435
+ stdout: stdout.slice(0, 1e6),
8436
+ stderr: stderr.slice(0, 1e6),
8437
+ exitCode: error?.code ?? 0,
8438
+ signal: error?.signal ?? null,
8439
+ truncated
8440
+ });
8441
+ }
8442
+ );
7967
8443
  });
7968
8444
  }
7969
8445
  });
@@ -7972,8 +8448,8 @@ function createBashTool(ctx) {
7972
8448
  // opencode/tools/read.ts
7973
8449
  import { tool as tool4 } from "ai";
7974
8450
  import { z as z6 } from "zod";
7975
- import { readFileSync as readFileSync5 } from "node:fs";
7976
- import { resolve as resolve7 } from "node:path";
8451
+ import { readFileSync as readFileSync7 } from "node:fs";
8452
+ import { resolve as resolve9 } from "node:path";
7977
8453
  function createReadTool(ctx) {
7978
8454
  return tool4({
7979
8455
  description: "Read file contents. Supports offset and limit for reading specific line ranges.",
@@ -7983,11 +8459,11 @@ function createReadTool(ctx) {
7983
8459
  limit: z6.number().optional().describe("Number of lines to read")
7984
8460
  }),
7985
8461
  execute: async ({ path: path2, offset, limit }) => {
7986
- const resolved = resolve7(ctx.workspace, path2);
8462
+ const resolved = resolve9(ctx.workspace, path2);
7987
8463
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions.permissions)) {
7988
8464
  return { error: "Path not allowed", content: null, totalLines: 0 };
7989
8465
  }
7990
- const content = readFileSync5(resolved, "utf-8");
8466
+ const content = readFileSync7(resolved, "utf-8");
7991
8467
  const lines = content.split("\n");
7992
8468
  const totalLines = lines.length;
7993
8469
  if (offset !== void 0) {
@@ -8015,7 +8491,7 @@ function createReadTool(ctx) {
8015
8491
  import { tool as tool5 } from "ai";
8016
8492
  import { z as z7 } from "zod";
8017
8493
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "node:fs";
8018
- import { resolve as resolve8, dirname as dirname4 } from "node:path";
8494
+ import { resolve as resolve10, dirname as dirname5 } from "node:path";
8019
8495
  function createWriteTool(ctx) {
8020
8496
  return tool5({
8021
8497
  description: "Create or overwrite a file. Parent directories are created automatically.",
@@ -8024,11 +8500,11 @@ function createWriteTool(ctx) {
8024
8500
  content: z7.string().describe("File content")
8025
8501
  }),
8026
8502
  execute: async ({ path: path2, content }) => {
8027
- const resolved = resolve8(ctx.workspace, path2);
8503
+ const resolved = resolve10(ctx.workspace, path2);
8028
8504
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions.permissions)) {
8029
8505
  return { error: "Path not allowed" };
8030
8506
  }
8031
- mkdirSync3(dirname4(resolved), { recursive: true });
8507
+ mkdirSync3(dirname5(resolved), { recursive: true });
8032
8508
  writeFileSync2(resolved, content, "utf-8");
8033
8509
  return { path: path2, size: content.length };
8034
8510
  }
@@ -8038,8 +8514,8 @@ function createWriteTool(ctx) {
8038
8514
  // opencode/tools/edit.ts
8039
8515
  import { tool as tool6 } from "ai";
8040
8516
  import { z as z8 } from "zod";
8041
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "node:fs";
8042
- import { resolve as resolve9 } from "node:path";
8517
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
8518
+ import { resolve as resolve11 } from "node:path";
8043
8519
  function createEditTool(ctx) {
8044
8520
  return tool6({
8045
8521
  description: "Perform exact string replacements in a file. If oldString appears multiple times, provide more surrounding context.",
@@ -8050,11 +8526,11 @@ function createEditTool(ctx) {
8050
8526
  replaceAll: z8.boolean().default(false).describe("Replace all occurrences")
8051
8527
  }),
8052
8528
  execute: async ({ path: path2, oldString, newString, replaceAll }) => {
8053
- const resolved = resolve9(ctx.workspace, path2);
8529
+ const resolved = resolve11(ctx.workspace, path2);
8054
8530
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions.permissions)) {
8055
8531
  return { error: "Path not allowed" };
8056
8532
  }
8057
- const content = readFileSync6(resolved, "utf-8");
8533
+ const content = readFileSync8(resolved, "utf-8");
8058
8534
  if (replaceAll) {
8059
8535
  if (!content.includes(oldString)) {
8060
8536
  return { error: "oldString not found in file", replaced: 0 };
@@ -8070,7 +8546,10 @@ function createEditTool(ctx) {
8070
8546
  }
8071
8547
  const secondIdx = content.indexOf(oldString, firstIdx + 1);
8072
8548
  if (secondIdx !== -1) {
8073
- return { error: "Found multiple matches. Provide more surrounding context in oldString.", replaced: 0 };
8549
+ return {
8550
+ error: "Found multiple matches. Provide more surrounding context in oldString.",
8551
+ replaced: 0
8552
+ };
8074
8553
  }
8075
8554
  const result = content.replace(oldString, newString);
8076
8555
  writeFileSync3(resolved, result, "utf-8");
@@ -8083,8 +8562,8 @@ function createEditTool(ctx) {
8083
8562
  import { tool as tool7 } from "ai";
8084
8563
  import { z as z9 } from "zod";
8085
8564
  import { execFileSync } from "node:child_process";
8086
- import { resolve as resolve10 } from "node:path";
8087
- import { existsSync as existsSync5 } from "node:fs";
8565
+ import { resolve as resolve12 } from "node:path";
8566
+ import { existsSync as existsSync7 } from "node:fs";
8088
8567
  function createGrepTool(ctx) {
8089
8568
  return tool7({
8090
8569
  description: "Search file contents using regex. Supports file type filtering and context lines.",
@@ -8095,10 +8574,10 @@ function createGrepTool(ctx) {
8095
8574
  context: z9.number().default(0).describe("Number of context lines before and after each match")
8096
8575
  }),
8097
8576
  execute: async ({ pattern, include, path: path2, context }) => {
8098
- const searchDir = path2 ? resolve10(ctx.workspace, path2) : ctx.workspace;
8577
+ const searchDir = path2 ? resolve12(ctx.workspace, path2) : ctx.workspace;
8099
8578
  try {
8100
8579
  let stdout;
8101
- if (existsSync5("/usr/bin/rg") || existsSync5("/usr/local/bin/rg")) {
8580
+ if (existsSync7("/usr/bin/rg") || existsSync7("/usr/local/bin/rg")) {
8102
8581
  const args = ["-n"];
8103
8582
  if (context > 0) args.push("-C", String(context));
8104
8583
  if (include) args.push("-g", include);
@@ -8112,7 +8591,11 @@ function createGrepTool(ctx) {
8112
8591
  stdout = execFileSync("grep", args, { timeout: 15e3, maxBuffer: 1024 * 1024 }).toString();
8113
8592
  }
8114
8593
  const lines = stdout.split("\n").filter(Boolean);
8115
- return { matches: lines.length, results: lines.slice(0, 200), truncated: lines.length > 200 };
8594
+ return {
8595
+ matches: lines.length,
8596
+ results: lines.slice(0, 200),
8597
+ truncated: lines.length > 200
8598
+ };
8116
8599
  } catch (e) {
8117
8600
  if (e.status === 1) {
8118
8601
  return { matches: 0, results: [], truncated: false };
@@ -8127,7 +8610,7 @@ function createGrepTool(ctx) {
8127
8610
  import { tool as tool8 } from "ai";
8128
8611
  import { z as z10 } from "zod";
8129
8612
  import { execFileSync as execFileSync2 } from "node:child_process";
8130
- import { resolve as resolve11 } from "node:path";
8613
+ import { resolve as resolve13 } from "node:path";
8131
8614
  function createGlobTool(ctx) {
8132
8615
  return tool8({
8133
8616
  description: "Find files matching a glob pattern.",
@@ -8136,21 +8619,22 @@ function createGlobTool(ctx) {
8136
8619
  path: z10.string().optional().describe("Subdirectory relative to workspace")
8137
8620
  }),
8138
8621
  execute: async ({ pattern, path: path2 }) => {
8139
- const searchDir = path2 ? resolve11(ctx.workspace, path2) : ctx.workspace;
8622
+ const searchDir = path2 ? resolve13(ctx.workspace, path2) : ctx.workspace;
8140
8623
  try {
8141
- const stdout = execFileSync2("find", [
8142
- searchDir,
8143
- "-name",
8144
- pattern,
8145
- "-not",
8146
- "-path",
8147
- "*/node_modules/*"
8148
- ], {
8149
- timeout: 1e4,
8150
- maxBuffer: 1024 * 1024
8151
- }).toString();
8624
+ const stdout = execFileSync2(
8625
+ "find",
8626
+ [searchDir, "-name", pattern, "-not", "-path", "*/node_modules/*"],
8627
+ {
8628
+ timeout: 1e4,
8629
+ maxBuffer: 1024 * 1024
8630
+ }
8631
+ ).toString();
8152
8632
  const lines = stdout.split("\n").filter(Boolean).slice(0, 200);
8153
- return { files: lines, total: lines.length, truncated: stdout.split("\n").filter(Boolean).length > 200 };
8633
+ return {
8634
+ files: lines,
8635
+ total: lines.length,
8636
+ truncated: stdout.split("\n").filter(Boolean).length > 200
8637
+ };
8154
8638
  } catch {
8155
8639
  return { files: [], total: 0, truncated: false };
8156
8640
  }
@@ -8161,7 +8645,7 @@ function createGlobTool(ctx) {
8161
8645
  // opencode/tools/web.ts
8162
8646
  import { tool as tool9 } from "ai";
8163
8647
  import { z as z11 } from "zod";
8164
- function createWebTool(ctx) {
8648
+ function createWebTool(_ctx2) {
8165
8649
  return tool9({
8166
8650
  description: "Fetch a URL and return the content as text.",
8167
8651
  inputSchema: z11.object({
@@ -8197,7 +8681,7 @@ function createQuestionTool(ctx) {
8197
8681
  options: z12.array(z12.string()).optional().describe("Optional multiple choice options")
8198
8682
  }),
8199
8683
  execute: async ({ question, options }, { toolCallId }) => {
8200
- return new Promise((resolve14, reject) => {
8684
+ return new Promise((resolve16, reject) => {
8201
8685
  const timeout = setTimeout(() => {
8202
8686
  ctx.pendingQuestions.delete(toolCallId);
8203
8687
  reject(new Error("Question timed out"));
@@ -8205,7 +8689,7 @@ function createQuestionTool(ctx) {
8205
8689
  ctx.pendingQuestions.set(toolCallId, {
8206
8690
  resolve: (answer) => {
8207
8691
  clearTimeout(timeout);
8208
- resolve14(answer);
8692
+ resolve16(answer);
8209
8693
  },
8210
8694
  reject: (err) => {
8211
8695
  clearTimeout(timeout);
@@ -8290,15 +8774,29 @@ function createTools(ctx) {
8290
8774
 
8291
8775
  // opencode/rest.ts
8292
8776
  async function buildRouter4(deps) {
8293
- const { sql: sql2, model, workspace, systemPrompt, skills, skillsRegistry, permissions: permissions2, pendingQuestions } = deps;
8777
+ const {
8778
+ sql: sql2,
8779
+ model,
8780
+ workspace,
8781
+ systemPrompt,
8782
+ skills,
8783
+ skillsRegistry,
8784
+ permissions: permissions2,
8785
+ pendingQuestions
8786
+ } = deps;
8294
8787
  const router = new Router();
8295
8788
  router.post("/sessions", async (req, ctx) => {
8296
8789
  const body = await req.json().catch(() => ({}));
8297
- const session2 = await createSession(sql2, {
8298
- title: body.title,
8299
- model: body.model,
8300
- systemPrompt: body.systemPrompt || systemPrompt
8301
- }, workspace, ctx.mountPath || "");
8790
+ const session2 = await createSession(
8791
+ sql2,
8792
+ {
8793
+ title: body.title,
8794
+ model: body.model,
8795
+ systemPrompt: body.systemPrompt || systemPrompt
8796
+ },
8797
+ workspace,
8798
+ ctx.mountPath || ""
8799
+ );
8302
8800
  return Response.json(session2, { status: 201 });
8303
8801
  });
8304
8802
  router.get("/sessions", async () => {
@@ -8362,7 +8860,11 @@ async function buildRouter4(deps) {
8362
8860
  FROM "_opencode_messages"
8363
8861
  WHERE session_id = ${sessionId}
8364
8862
  `;
8365
- const stats = rows[0] || { message_count: 0, total_tokens_in: 0, total_tokens_out: 0 };
8863
+ const stats = rows[0] || {
8864
+ message_count: 0,
8865
+ total_tokens_in: 0,
8866
+ total_tokens_out: 0
8867
+ };
8366
8868
  return Response.json({
8367
8869
  session_id: sessionId,
8368
8870
  message_count: stats.message_count,
@@ -8383,7 +8885,16 @@ async function buildRouter4(deps) {
8383
8885
  // opencode/ws.ts
8384
8886
  var clients2 = /* @__PURE__ */ new WeakMap();
8385
8887
  function createWSHandler2(deps) {
8386
- const { sql: sql2, model, workspace, systemPrompt, skills, skillsRegistry, permissions: permissions2, pendingQuestions } = deps;
8888
+ const {
8889
+ sql: sql2,
8890
+ model,
8891
+ workspace,
8892
+ systemPrompt,
8893
+ skills,
8894
+ skillsRegistry,
8895
+ permissions: permissions2,
8896
+ pendingQuestions
8897
+ } = deps;
8387
8898
  return {
8388
8899
  open(ws, ctx) {
8389
8900
  const userId2 = ctx.user?.id ?? 0;
@@ -8403,12 +8914,17 @@ function createWSHandler2(deps) {
8403
8914
  switch (msg.type) {
8404
8915
  case "create": {
8405
8916
  try {
8406
- const session2 = await createSession(sql2, {
8407
- userId: client.userId,
8408
- title: msg.title,
8409
- model: msg.model,
8410
- systemPrompt: msg.systemPrompt || systemPrompt
8411
- }, workspace, client.mountPath);
8917
+ const session2 = await createSession(
8918
+ sql2,
8919
+ {
8920
+ userId: client.userId,
8921
+ title: msg.title,
8922
+ model: msg.model,
8923
+ systemPrompt: msg.systemPrompt || systemPrompt
8924
+ },
8925
+ workspace,
8926
+ client.mountPath
8927
+ );
8412
8928
  ws.send(JSON.stringify({ type: "session_created", session: session2 }));
8413
8929
  } catch (e) {
8414
8930
  ws.send(JSON.stringify({ type: "error", error: e.message }));
@@ -8494,7 +9010,7 @@ function createWSHandler2(deps) {
8494
9010
  clients2.delete(ws);
8495
9011
  }
8496
9012
  },
8497
- error(ws, _ctx, _err) {
9013
+ error(ws, _ctx2, _err) {
8498
9014
  const client = clients2.get(ws);
8499
9015
  if (client) {
8500
9016
  client.abortController?.abort();
@@ -8505,10 +9021,9 @@ function createWSHandler2(deps) {
8505
9021
  }
8506
9022
 
8507
9023
  // opencode/skills.ts
8508
- import { readFile } from "node:fs/promises";
8509
- import { glob } from "node:fs/promises";
9024
+ import { readFile, glob } from "node:fs/promises";
8510
9025
  import { homedir } from "node:os";
8511
- import { resolve as resolve12 } from "node:path";
9026
+ import { resolve as resolve14 } from "node:path";
8512
9027
  import { parse as parseYaml } from "yaml";
8513
9028
  var SEARCH_DIRS = [
8514
9029
  (ws) => `${ws}/.opencode/skills`,
@@ -8546,7 +9061,7 @@ async function scanDir(dir) {
8546
9061
  try {
8547
9062
  const files = [];
8548
9063
  for await (const entry of glob("*/SKILL.md", { cwd: dir })) {
8549
- const skill = await parseSkillFile(resolve12(dir, entry));
9064
+ const skill = await parseSkillFile(resolve14(dir, entry));
8550
9065
  if (skill) files.push(skill);
8551
9066
  }
8552
9067
  return files;
@@ -8603,7 +9118,16 @@ async function opencode(options) {
8603
9118
  const model = provider.chat(modelName);
8604
9119
  const pendingQuestions = /* @__PURE__ */ new Map();
8605
9120
  const base = new PgModule(pg);
8606
- const r = await buildRouter4({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions: permissions2, pendingQuestions });
9121
+ const r = await buildRouter4({
9122
+ sql: sql2,
9123
+ model,
9124
+ workspace,
9125
+ systemPrompt,
9126
+ skills: manualSkills,
9127
+ skillsRegistry,
9128
+ permissions: permissions2,
9129
+ pendingQuestions
9130
+ });
8607
9131
  const mod = r;
8608
9132
  mod.migrate = async () => {
8609
9133
  const sessions2 = pg.table("_opencode_sessions", {
@@ -8636,7 +9160,16 @@ async function opencode(options) {
8636
9160
  await messages2.create();
8637
9161
  await messages2.createIndex(["session_id", "created_at"]);
8638
9162
  };
8639
- mod.wsHandler = () => createWSHandler2({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions: permissions2, pendingQuestions });
9163
+ mod.wsHandler = () => createWSHandler2({
9164
+ sql: sql2,
9165
+ model,
9166
+ workspace,
9167
+ systemPrompt,
9168
+ skills: manualSkills,
9169
+ skillsRegistry,
9170
+ permissions: permissions2,
9171
+ pendingQuestions
9172
+ });
8640
9173
  mod.close = () => base.close();
8641
9174
  return mod;
8642
9175
  }
@@ -8745,7 +9278,10 @@ var MemStore = class {
8745
9278
  daily,
8746
9279
  top_pages: topPages,
8747
9280
  referrers: [...refMap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10).map(([domain, count]) => ({ domain, count })),
8748
- devices: { mobile: Math.round(totalMobile / total * 1e3) / 10, desktop: Math.round(totalDesktop / total * 1e3) / 10 }
9281
+ devices: {
9282
+ mobile: Math.round(totalMobile / total * 1e3) / 10,
9283
+ desktop: Math.round(totalDesktop / total * 1e3) / 10
9284
+ }
8749
9285
  };
8750
9286
  }
8751
9287
  };
@@ -8798,7 +9334,10 @@ async function queryPg(sql2, days) {
8798
9334
  daily: daily.map((d) => ({ date: d.date, pv: d.pv, uv: d.uv })),
8799
9335
  top_pages: pageRows.map((p) => ({ path: p.path, pv: p.pv })),
8800
9336
  referrers: [],
8801
- devices: { mobile: Math.round(t.total_mobile / denom * 1e3) / 10, desktop: Math.round(t.total_desktop / denom * 1e3) / 10 }
9337
+ devices: {
9338
+ mobile: Math.round(t.total_mobile / denom * 1e3) / 10,
9339
+ desktop: Math.round(t.total_desktop / denom * 1e3) / 10
9340
+ }
8802
9341
  };
8803
9342
  }
8804
9343
  function escapeHtml2(s) {
@@ -8813,9 +9352,7 @@ function renderDashboard(days, data) {
8813
9352
  const rows = top_pages.map(
8814
9353
  (p, i) => `<tr><td class="num">${i + 1}</td><td class="path">${escapeHtml2(p.path)}</td><td class="num">${p.pv}</td></tr>`
8815
9354
  ).join("");
8816
- const refRows = referrers.map(
8817
- (r) => `<tr><td>${escapeHtml2(r.domain)}</td><td class="num">${r.count}</td></tr>`
8818
- ).join("");
9355
+ const refRows = referrers.map((r) => `<tr><td>${escapeHtml2(r.domain)}</td><td class="num">${r.count}</td></tr>`).join("");
8819
9356
  return `<!DOCTYPE html><html lang="en">
8820
9357
  <head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Analytics - weifuwu</title>
8821
9358
  <style>*,:before,:after{box-sizing:border-box;margin:0;padding:0}
@@ -8951,7 +9488,7 @@ function theme(options) {
8951
9488
 
8952
9489
  // i18n.ts
8953
9490
  import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
8954
- import { join as join7, resolve as resolve13 } from "node:path";
9491
+ import { join as join7, resolve as resolve15 } from "node:path";
8955
9492
  var DEFAULTS2 = {
8956
9493
  default: "en",
8957
9494
  cookie: "locale",
@@ -8969,7 +9506,7 @@ function translate(msgs, key, params, fallback) {
8969
9506
  }
8970
9507
  function i18n(options) {
8971
9508
  const opts = { ...DEFAULTS2, ...options };
8972
- const dir = opts.dir ? resolve13(opts.dir) : void 0;
9509
+ const dir = opts.dir ? resolve15(opts.dir) : void 0;
8973
9510
  const cache3 = /* @__PURE__ */ new Map();
8974
9511
  function validLocale(locale) {
8975
9512
  return /^[\w-]+$/.test(locale) && !locale.includes("..");
@@ -9022,7 +9559,10 @@ function i18n(options) {
9022
9559
  set: (value, loc) => {
9023
9560
  const cookie = `${opts.cookie}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`;
9024
9561
  const location = loc ?? (req.headers.get("referer") || "/");
9025
- return new Response(null, { status: 302, headers: { Location: location, "Set-Cookie": cookie } });
9562
+ return new Response(null, {
9563
+ status: 302,
9564
+ headers: { Location: location, "Set-Cookie": cookie }
9565
+ });
9026
9566
  }
9027
9567
  };
9028
9568
  return next(req, ctx);
@@ -9041,7 +9581,11 @@ function i18n(options) {
9041
9581
  const accept = req.headers.get("accept") ?? "";
9042
9582
  if (accept.includes("application/json")) {
9043
9583
  return Response.json(
9044
- { ok: true, locale: value, messages: Object.keys(messages2).length > 0 ? messages2 : void 0 },
9584
+ {
9585
+ ok: true,
9586
+ locale: value,
9587
+ messages: Object.keys(messages2).length > 0 ? messages2 : void 0
9588
+ },
9045
9589
  { headers: { "Set-Cookie": cookie } }
9046
9590
  );
9047
9591
  }
@@ -9359,10 +9903,11 @@ function listHandler(entries) {
9359
9903
  if (before) conditions.push(lt("created_at", before));
9360
9904
  const limit = parseInt(url.searchParams.get("limit") ?? "50", 10);
9361
9905
  const offset = parseInt(url.searchParams.get("offset") ?? "0", 10);
9362
- const { count, data } = await entries.readMany(
9363
- conditions.length > 0 ? conditions : void 0,
9364
- { orderBy: { created_at: "desc" }, limit, offset }
9365
- );
9906
+ const { count, data } = await entries.readMany(conditions.length > 0 ? conditions : void 0, {
9907
+ orderBy: { created_at: "desc" },
9908
+ limit,
9909
+ offset
9910
+ });
9366
9911
  return Response.json({ entries: data.map(parseMetadata), total: count });
9367
9912
  };
9368
9913
  }
@@ -9473,12 +10018,15 @@ import crypto8 from "node:crypto";
9473
10018
 
9474
10019
  // iii/stream.ts
9475
10020
  function notify(channels, stream, group, item, event, data) {
9476
- const keys = [
9477
- `${stream}`,
9478
- `${stream}:${group}`,
9479
- `${stream}:${group}:${item}`
9480
- ];
9481
- const msg = JSON.stringify({ type: "stream", stream_name: stream, group_id: group, item_id: item, event, data });
10021
+ const keys = [`${stream}`, `${stream}:${group}`, `${stream}:${group}:${item}`];
10022
+ const msg = JSON.stringify({
10023
+ type: "stream",
10024
+ stream_name: stream,
10025
+ group_id: group,
10026
+ item_id: item,
10027
+ event,
10028
+ data
10029
+ });
9482
10030
  for (const key of keys) {
9483
10031
  const subs = channels.get(key);
9484
10032
  if (!subs) continue;
@@ -9697,10 +10245,13 @@ function createRedisStore(channels, redis2, ttl) {
9697
10245
  async set(stream, group, item, data) {
9698
10246
  const hk = hashKey(stream, group);
9699
10247
  const oldRaw = await redis2.hget(hk, item);
9700
- let old = oldRaw ? JSON.parse(oldRaw) : null;
10248
+ const old = oldRaw ? JSON.parse(oldRaw) : null;
9701
10249
  await redis2.hset(hk, item, JSON.stringify(data));
9702
10250
  setTTL(hk);
9703
- await redis2.publish(`iii:stream:${stream}`, JSON.stringify({ event: "set", group, item, data }));
10251
+ await redis2.publish(
10252
+ `iii:stream:${stream}`,
10253
+ JSON.stringify({ event: "set", group, item, data })
10254
+ );
9704
10255
  notify(channels, stream, group, item, "set", data);
9705
10256
  return { old_value: old, new_value: deepClone(data) };
9706
10257
  },
@@ -9776,7 +10327,10 @@ function createRedisStore(channels, redis2, ttl) {
9776
10327
  const newVal = applyOps(old, ops);
9777
10328
  await redis2.hset(hk, item, JSON.stringify(newVal));
9778
10329
  setTTL(hk);
9779
- await redis2.publish(`iii:stream:${stream}`, JSON.stringify({ event: "update", group, item, data: newVal }));
10330
+ await redis2.publish(
10331
+ `iii:stream:${stream}`,
10332
+ JSON.stringify({ event: "update", group, item, data: newVal })
10333
+ );
9780
10334
  notify(channels, stream, group, item, "update", newVal);
9781
10335
  return { old_value: old, new_value: deepClone(newVal) };
9782
10336
  }
@@ -9844,7 +10398,7 @@ function createWsHandler(deps) {
9844
10398
  return wsToWorkerId.get(ws) || "";
9845
10399
  }
9846
10400
  return {
9847
- open(_ws, _ctx) {
10401
+ open(_ws, _ctx2) {
9848
10402
  },
9849
10403
  async message(ws, ctx, data) {
9850
10404
  let msg;
@@ -9856,10 +10410,7 @@ function createWsHandler(deps) {
9856
10410
  }
9857
10411
  switch (msg.type) {
9858
10412
  case "register_worker": {
9859
- const workerId = deps.registerRemoteWorker(
9860
- ws,
9861
- msg.worker_name || `remote-${Date.now()}`
9862
- );
10413
+ const workerId = deps.registerRemoteWorker(ws, msg.worker_name || `remote-${Date.now()}`);
9863
10414
  wsToWorkerId.set(ws, workerId);
9864
10415
  ws.send(JSON.stringify({ type: "registered", worker_id: workerId }));
9865
10416
  break;
@@ -9963,10 +10514,7 @@ function buildRouter5(engine, wsHandler) {
9963
10514
  }
9964
10515
  return Response.json(result);
9965
10516
  } catch (err) {
9966
- return Response.json(
9967
- { error: err.message || "Internal error" },
9968
- { status: 500 }
9969
- );
10517
+ return Response.json({ error: err.message || "Internal error" }, { status: 500 });
9970
10518
  }
9971
10519
  });
9972
10520
  r.ws("/worker", wsHandler);
@@ -9989,14 +10537,23 @@ function iii(opts = {}) {
9989
10537
  triggers: []
9990
10538
  });
9991
10539
  }
9992
- registerBuiltin("stream::set", (p) => stream.set(p.stream_name, p.group_id, p.item_id, p.data));
10540
+ registerBuiltin(
10541
+ "stream::set",
10542
+ (p) => stream.set(p.stream_name, p.group_id, p.item_id, p.data)
10543
+ );
9993
10544
  registerBuiltin("stream::get", (p) => stream.get(p.stream_name, p.group_id, p.item_id));
9994
10545
  registerBuiltin("stream::delete", (p) => stream.delete(p.stream_name, p.group_id, p.item_id));
9995
10546
  registerBuiltin("stream::list", (p) => stream.list(p.stream_name, p.group_id));
9996
10547
  registerBuiltin("stream::list_groups", (p) => stream.list_groups(p.stream_name));
9997
10548
  registerBuiltin("stream::list_all", () => stream.list_all());
9998
- registerBuiltin("stream::send", (p) => stream.send(p.stream_name, p.group_id, p.type, p.data, p.id));
9999
- registerBuiltin("stream::update", (p) => stream.update(p.stream_name, p.group_id, p.item_id, p.ops));
10549
+ registerBuiltin(
10550
+ "stream::send",
10551
+ (p) => stream.send(p.stream_name, p.group_id, p.type, p.data, p.id)
10552
+ );
10553
+ registerBuiltin(
10554
+ "stream::update",
10555
+ (p) => stream.update(p.stream_name, p.group_id, p.item_id, p.ops)
10556
+ );
10000
10557
  function addLocalWorker(worker) {
10001
10558
  const workerId = crypto8.randomUUID();
10002
10559
  const reg = {
@@ -10043,18 +10600,20 @@ function iii(opts = {}) {
10043
10600
  const handler = async (payload) => {
10044
10601
  if (!worker.ws) throw new Error(`Worker "${worker.name}" disconnected`);
10045
10602
  const invocationId = crypto8.randomUUID();
10046
- return new Promise((resolve14, reject) => {
10603
+ return new Promise((resolve16, reject) => {
10047
10604
  const timer = setTimeout(() => {
10048
10605
  pending.delete(invocationId);
10049
10606
  reject(new Error(`Invocation timed out for "${id2}"`));
10050
10607
  }, 3e4);
10051
- pending.set(invocationId, { resolve: resolve14, reject, timer });
10052
- worker.ws.send(JSON.stringify({
10053
- type: "invoke",
10054
- invocation_id: invocationId,
10055
- function_id: id2,
10056
- payload
10057
- }));
10608
+ pending.set(invocationId, { resolve: resolve16, reject, timer });
10609
+ worker.ws.send(
10610
+ JSON.stringify({
10611
+ type: "invoke",
10612
+ invocation_id: invocationId,
10613
+ function_id: id2,
10614
+ payload
10615
+ })
10616
+ );
10058
10617
  });
10059
10618
  };
10060
10619
  const fnReg = {
@@ -10138,18 +10697,26 @@ function iii(opts = {}) {
10138
10697
  handleInvoke(ws, invocationId, functionId, payload) {
10139
10698
  const fn = functions.get(functionId);
10140
10699
  if (!fn) {
10141
- ws.send(JSON.stringify({
10142
- type: "invoke_error",
10143
- invocation_id: invocationId,
10144
- error: `Function "${functionId}" not found`
10145
- }));
10700
+ ws.send(
10701
+ JSON.stringify({
10702
+ type: "invoke_error",
10703
+ invocation_id: invocationId,
10704
+ error: `Function "${functionId}" not found`
10705
+ })
10706
+ );
10146
10707
  return;
10147
10708
  }
10148
10709
  const ctx = { engine: engineRef, functionId, workerName: fn.workerName };
10149
10710
  Promise.resolve(fn.handler(payload, ctx)).then((result) => {
10150
10711
  ws.send(JSON.stringify({ type: "invoke_result", invocation_id: invocationId, result }));
10151
10712
  }).catch((err) => {
10152
- ws.send(JSON.stringify({ type: "invoke_error", invocation_id: invocationId, error: err.message }));
10713
+ ws.send(
10714
+ JSON.stringify({
10715
+ type: "invoke_error",
10716
+ invocation_id: invocationId,
10717
+ error: err.message
10718
+ })
10719
+ );
10153
10720
  });
10154
10721
  }
10155
10722
  });
@@ -10289,8 +10856,8 @@ function registerWorker(url) {
10289
10856
  function connect() {
10290
10857
  if (intentionalClose) return;
10291
10858
  ws = new WebSocket(url);
10292
- ready = new Promise((resolve14) => {
10293
- resolveReady = resolve14;
10859
+ ready = new Promise((resolve16) => {
10860
+ resolveReady = resolve16;
10294
10861
  });
10295
10862
  ws.onopen = () => {
10296
10863
  reconnectAttempt = 0;
@@ -10313,25 +10880,31 @@ function registerWorker(url) {
10313
10880
  case "invoke": {
10314
10881
  const handler = handlers.get(msg.function_id);
10315
10882
  if (!handler) {
10316
- ws?.send(JSON.stringify({
10317
- type: "invoke_error",
10318
- invocation_id: msg.invocation_id,
10319
- error: `Function "${msg.function_id}" not found`
10320
- }));
10883
+ ws?.send(
10884
+ JSON.stringify({
10885
+ type: "invoke_error",
10886
+ invocation_id: msg.invocation_id,
10887
+ error: `Function "${msg.function_id}" not found`
10888
+ })
10889
+ );
10321
10890
  return;
10322
10891
  }
10323
10892
  Promise.resolve(handler(msg.payload, {})).then((result) => {
10324
- ws?.send(JSON.stringify({
10325
- type: "invoke_result",
10326
- invocation_id: msg.invocation_id,
10327
- result
10328
- }));
10893
+ ws?.send(
10894
+ JSON.stringify({
10895
+ type: "invoke_result",
10896
+ invocation_id: msg.invocation_id,
10897
+ result
10898
+ })
10899
+ );
10329
10900
  }).catch((err) => {
10330
- ws?.send(JSON.stringify({
10331
- type: "invoke_error",
10332
- invocation_id: msg.invocation_id,
10333
- error: err.message
10334
- }));
10901
+ ws?.send(
10902
+ JSON.stringify({
10903
+ type: "invoke_error",
10904
+ invocation_id: msg.invocation_id,
10905
+ error: err.message
10906
+ })
10907
+ );
10335
10908
  });
10336
10909
  break;
10337
10910
  }
@@ -10385,7 +10958,12 @@ function registerWorker(url) {
10385
10958
  },
10386
10959
  registerTrigger(input) {
10387
10960
  registeredTriggers.add(JSON.stringify(input));
10388
- send({ type: "register_trigger", function_id: input.function_id, trigger_type: input.type, config: input.config });
10961
+ send({
10962
+ type: "register_trigger",
10963
+ function_id: input.function_id,
10964
+ trigger_type: input.type,
10965
+ config: input.config
10966
+ });
10389
10967
  },
10390
10968
  unregisterTrigger(functionId) {
10391
10969
  for (const key of registeredTriggers) {
@@ -10410,13 +10988,13 @@ function registerWorker(url) {
10410
10988
  }
10411
10989
  return Promise.resolve(fn(request.payload, ctx));
10412
10990
  }
10413
- return new Promise((resolve14, reject) => {
10991
+ return new Promise((resolve16, reject) => {
10414
10992
  const invocationId = genId();
10415
10993
  const timer = setTimeout(() => {
10416
10994
  pendingInvocations.delete(invocationId);
10417
10995
  reject(new Error(`Invocation timed out for "${request.function_id}"`));
10418
10996
  }, request.timeout_ms || 3e4);
10419
- pendingInvocations.set(invocationId, { resolve: resolve14, reject, timer });
10997
+ pendingInvocations.set(invocationId, { resolve: resolve16, reject, timer });
10420
10998
  send({
10421
10999
  type: "invoke",
10422
11000
  invocation_id: invocationId,
@@ -10560,8 +11138,18 @@ function createSessionObject(data, sid, store2, ttl, createdAt) {
10560
11138
  enumerable: false,
10561
11139
  configurable: false
10562
11140
  });
10563
- Object.defineProperty(obj, "save", { enumerable: false, configurable: true, writable: true, value: obj.save });
10564
- Object.defineProperty(obj, "destroy", { enumerable: false, configurable: true, writable: true, value: obj.destroy });
11141
+ Object.defineProperty(obj, "save", {
11142
+ enumerable: false,
11143
+ configurable: true,
11144
+ writable: true,
11145
+ value: obj.save
11146
+ });
11147
+ Object.defineProperty(obj, "destroy", {
11148
+ enumerable: false,
11149
+ configurable: true,
11150
+ writable: true,
11151
+ value: obj.destroy
11152
+ });
10565
11153
  return obj;
10566
11154
  }
10567
11155
  function isSessionActive(session2) {
@@ -10931,7 +11519,8 @@ function createStripeVerifier(config) {
10931
11519
  }, {});
10932
11520
  const timestamp = parts["t"];
10933
11521
  const signature = parts["v1"];
10934
- if (!timestamp || !signature) return { valid: false, provider: "stripe", event: "", id: void 0 };
11522
+ if (!timestamp || !signature)
11523
+ return { valid: false, provider: "stripe", event: "", id: void 0 };
10935
11524
  const signed = `${timestamp}.${body}`;
10936
11525
  const expected = crypto11.createHmac("sha256", config.secret).update(signed).digest("hex");
10937
11526
  const valid = timingSafeEqual2(signature, expected);
@@ -10952,7 +11541,7 @@ function createGitHubVerifier(config) {
10952
11541
  if (!sig) return { valid: false, provider: "github", event: "", id: void 0 };
10953
11542
  const expected = `sha256=${crypto11.createHmac("sha256", config.secret).update(body).digest("hex")}`;
10954
11543
  const valid = timingSafeEqual2(sig, expected);
10955
- let event = headers["x-github-event"] ?? "";
11544
+ const event = headers["x-github-event"] ?? "";
10956
11545
  let id2;
10957
11546
  try {
10958
11547
  const parsed = JSON.parse(body);
@@ -10966,7 +11555,8 @@ function createSlackVerifier(config) {
10966
11555
  return (body, headers) => {
10967
11556
  const signature = headers["x-slack-signature"];
10968
11557
  const timestamp = headers["x-slack-request-timestamp"];
10969
- if (!signature || !timestamp) return { valid: false, provider: "slack", event: "", id: void 0 };
11558
+ if (!signature || !timestamp)
11559
+ return { valid: false, provider: "slack", event: "", id: void 0 };
10970
11560
  const now = Math.floor(Date.now() / 1e3);
10971
11561
  const ts = parseInt(timestamp, 10);
10972
11562
  if (isNaN(ts) || Math.abs(now - ts) > 300) {
@@ -11128,11 +11718,7 @@ __export(fts_exports, {
11128
11718
  suggest: () => suggest
11129
11719
  });
11130
11720
  function resolveTableName(table) {
11131
- const name = table.inner?.tableName ?? table.tableName;
11132
- if (!name || typeof name !== "string") {
11133
- throw new Error("fts: could not determine table name. Ensure you pass a pg.table() result.");
11134
- }
11135
- return name;
11721
+ return table.tableName;
11136
11722
  }
11137
11723
  function escapeIdent4(s) {
11138
11724
  return `"${s.replace(/"/g, '""')}"`;
@@ -11344,7 +11930,15 @@ function escapeIdent5(s) {
11344
11930
  return `"${s.replace(/"/g, '""')}"`;
11345
11931
  }
11346
11932
  function knowledgeBase(options) {
11347
- const { pg, provider, table = "_kb_docs", chunkSize = 512, chunkOverlap = 64, searchLimit = 5, searchThreshold = 0 } = options;
11933
+ const {
11934
+ pg,
11935
+ provider,
11936
+ table = "_kb_docs",
11937
+ chunkSize = 512,
11938
+ chunkOverlap = 64,
11939
+ searchLimit = 5,
11940
+ searchThreshold = 0
11941
+ } = options;
11348
11942
  const sql2 = pg.sql;
11349
11943
  const dimension = provider.dimension;
11350
11944
  const docsTable = pg.table(table, {