@diegoaltoworks/chatter 0.45.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,7 +53,22 @@ Bun.serve({ port: 8181, fetch: app.fetch });
53
53
  npx chatter create-apikey --name "my-app" --expires-in 365d
54
54
  ```
55
55
 
56
- **Requirements:** OpenAI API key, Turso database, Bun runtime. See [Requirements Guide](./docs/requirements.md) for setup instructions.
56
+ **Requirements:** OpenAI API key, Turso database, and Bun >= 1.2 or Node >= 24. See [Requirements Guide](./docs/requirements.md) for setup instructions.
57
+
58
+ ### Runtime
59
+
60
+ The package runs on **Bun or Node** (>= 24 — it is built and published for both,
61
+ and CI loads the built bundles under each). Two things differ:
62
+
63
+ - **Serving the app** — `Bun.serve({ port: 8181, fetch: app.fetch })` on Bun;
64
+ `serve({ port: 8181, fetch: app.fetch })` from [`@hono/node-server`](https://github.com/honojs/node-server) on Node.
65
+ - **Static assets** — serving the widget files (`/chatter.js`, `/chatter.css`)
66
+ and a `publicDir` needs a runtime adapter, picked automatically. On Node that
67
+ adapter is `@hono/node-server`, an optional peer dependency: install it, or
68
+ run with `features: { headless: true }` if the server serves no files.
69
+
70
+ Everything else — the chat pipeline, RAG, channels, the OpenAI-compatible API —
71
+ is runtime-neutral. Development and the quality gates run on Bun.
57
72
 
58
73
  ## Examples
59
74
 
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The one place the server touches a runtime-specific static-file adapter.
3
+ *
4
+ * `hono/bun`'s `serveStatic` reads the `Bun` global at import time, so a static
5
+ * `import` of it makes the whole package Bun-only: `import("./dist/server.mjs")`
6
+ * under Node throws "Bun is not defined" before a single route is mounted, even
7
+ * in headless mode where no file is ever served. This module keeps both
8
+ * adapters behind lazy, literal dynamic imports and picks one from the runtime
9
+ * actually executing, so the import graph stays runtime-neutral and only a
10
+ * server that really serves files pays for an adapter.
11
+ *
12
+ * Under Node the adapter is `@hono/node-server/serve-static`, an OPTIONAL peer
13
+ * dependency: a Node consumer running headless never needs it, so a missing
14
+ * package must not be an import-time failure.
15
+ */
16
+ import type { MiddlewareHandler } from "hono";
17
+ /** The subset of both adapters' options this package uses. */
18
+ export interface ServeStaticOptions {
19
+ /** File to serve, relative to `root` (which defaults to the process cwd). */
20
+ path: string;
21
+ root?: string;
22
+ }
23
+ export type ServeStaticFn = (options: ServeStaticOptions) => MiddlewareHandler;
24
+ /** Runtimes we have a static-file adapter for. */
25
+ export type StaticRuntime = "bun" | "node";
26
+ /** Module specifier loaded for each runtime — exported so tests can assert the mapping without importing. */
27
+ export declare const STATIC_ADAPTERS: Record<StaticRuntime, string>;
28
+ /** Which adapter the current process needs. Bun exposes a `Bun` global; nothing else does. */
29
+ export declare function detectRuntime(): StaticRuntime;
30
+ /** Wraps a failed adapter import in an actionable message. Exported separately so the wording is unit-testable without simulating a missing module. */
31
+ export declare function wrapMissingAdapterError(runtime: StaticRuntime, cause: unknown): Error;
32
+ /**
33
+ * Resolve the static-file middleware factory for `runtime`, memoised per
34
+ * runtime. A rejected load is evicted so a later call can retry (the package
35
+ * may have been installed in between), mirroring `loadBaileys()`.
36
+ */
37
+ export declare function loadServeStatic(runtime?: StaticRuntime): Promise<ServeStaticFn>;
38
+ //# sourceMappingURL=serve-static.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-static.d.ts","sourceRoot":"","sources":["../../src/core/serve-static.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE9C,8DAA8D;AAC9D,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,kBAAkB,KAAK,iBAAiB,CAAC;AAE/E,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C,6GAA6G;AAC7G,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAGzD,CAAC;AAEF,8FAA8F;AAC9F,wBAAgB,aAAa,IAAI,aAAa,CAE7C;AAED,uJAAuJ;AACvJ,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,CAUrF;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,aAA+B,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBhG"}
package/dist/index.js CHANGED
@@ -4265,49 +4265,49 @@ var require_fast_uri = __commonJS({
4265
4265
  schemelessOptions.skipEscape = true;
4266
4266
  return serialize(resolved, schemelessOptions);
4267
4267
  }
4268
- function resolveComponent(base, relative, options, skipNormalization) {
4268
+ function resolveComponent(base, relative2, options, skipNormalization) {
4269
4269
  const target = {};
4270
4270
  if (!skipNormalization) {
4271
4271
  base = parse3(serialize(base, options), options);
4272
- relative = parse3(serialize(relative, options), options);
4272
+ relative2 = parse3(serialize(relative2, options), options);
4273
4273
  }
4274
4274
  options = options || {};
4275
- if (!options.tolerant && relative.scheme) {
4276
- target.scheme = relative.scheme;
4277
- target.userinfo = relative.userinfo;
4278
- target.host = relative.host;
4279
- target.port = relative.port;
4280
- target.path = removeDotSegments(relative.path || "");
4281
- target.query = relative.query;
4275
+ if (!options.tolerant && relative2.scheme) {
4276
+ target.scheme = relative2.scheme;
4277
+ target.userinfo = relative2.userinfo;
4278
+ target.host = relative2.host;
4279
+ target.port = relative2.port;
4280
+ target.path = removeDotSegments(relative2.path || "");
4281
+ target.query = relative2.query;
4282
4282
  } else {
4283
- if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
4284
- target.userinfo = relative.userinfo;
4285
- target.host = relative.host;
4286
- target.port = relative.port;
4287
- target.path = removeDotSegments(relative.path || "");
4288
- target.query = relative.query;
4283
+ if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
4284
+ target.userinfo = relative2.userinfo;
4285
+ target.host = relative2.host;
4286
+ target.port = relative2.port;
4287
+ target.path = removeDotSegments(relative2.path || "");
4288
+ target.query = relative2.query;
4289
4289
  } else {
4290
- if (!relative.path) {
4290
+ if (!relative2.path) {
4291
4291
  target.path = base.path;
4292
- if (relative.query !== void 0) {
4293
- target.query = relative.query;
4292
+ if (relative2.query !== void 0) {
4293
+ target.query = relative2.query;
4294
4294
  } else {
4295
4295
  target.query = base.query;
4296
4296
  }
4297
4297
  } else {
4298
- if (relative.path[0] === "/") {
4299
- target.path = removeDotSegments(relative.path);
4298
+ if (relative2.path[0] === "/") {
4299
+ target.path = removeDotSegments(relative2.path);
4300
4300
  } else {
4301
4301
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
4302
- target.path = "/" + relative.path;
4302
+ target.path = "/" + relative2.path;
4303
4303
  } else if (!base.path) {
4304
- target.path = relative.path;
4304
+ target.path = relative2.path;
4305
4305
  } else {
4306
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
4306
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
4307
4307
  }
4308
4308
  target.path = removeDotSegments(target.path);
4309
4309
  }
4310
- target.query = relative.query;
4310
+ target.query = relative2.query;
4311
4311
  }
4312
4312
  target.userinfo = base.userinfo;
4313
4313
  target.host = base.host;
@@ -4315,7 +4315,7 @@ var require_fast_uri = __commonJS({
4315
4315
  }
4316
4316
  target.scheme = base.scheme;
4317
4317
  }
4318
- target.fragment = relative.fragment;
4318
+ target.fragment = relative2.fragment;
4319
4319
  return target;
4320
4320
  }
4321
4321
  function equal(uriA, uriB, options) {
@@ -33178,9 +33178,9 @@ function publicRoutes(deps) {
33178
33178
  }
33179
33179
 
33180
33180
  // src/server.ts
33181
+ var import_node_path4 = require("node:path");
33181
33182
  var import_client2 = require("@libsql/client");
33182
33183
  var import_hono5 = require("hono");
33183
- var import_bun = require("hono/bun");
33184
33184
  var import_openai2 = __toESM(require("openai"));
33185
33185
 
33186
33186
  // src/channels/senders.ts
@@ -33235,6 +33235,36 @@ function createSenderRegistry() {
33235
33235
  };
33236
33236
  }
33237
33237
 
33238
+ // src/core/serve-static.ts
33239
+ var STATIC_ADAPTERS = {
33240
+ bun: "hono/bun",
33241
+ node: "@hono/node-server/serve-static"
33242
+ };
33243
+ function detectRuntime() {
33244
+ return typeof globalThis.Bun === "undefined" ? "node" : "bun";
33245
+ }
33246
+ function wrapMissingAdapterError(runtime, cause) {
33247
+ const specifier = STATIC_ADAPTERS[runtime];
33248
+ return new Error(
33249
+ `Serving static files under ${runtime} requires '${specifier}', which could not be loaded. ` + (runtime === "node" ? "Install the optional peer dependency with `npm install @hono/node-server` (or bun/pnpm/yarn), or run Chatter headless (`features.headless: true`) if it should serve no static assets." : "Upgrade 'hono' to a version that ships the Bun adapter."),
33250
+ { cause }
33251
+ );
33252
+ }
33253
+ var cache = /* @__PURE__ */ new Map();
33254
+ function loadServeStatic(runtime = detectRuntime()) {
33255
+ const cached2 = cache.get(runtime);
33256
+ if (cached2) return cached2;
33257
+ const loading = (runtime === "bun" ? import("hono/bun") : import("@hono/node-server/serve-static")).then(
33258
+ (module2) => module2.serveStatic,
33259
+ (error51) => {
33260
+ cache.delete(runtime);
33261
+ throw wrapMissingAdapterError(runtime, error51);
33262
+ }
33263
+ );
33264
+ cache.set(runtime, loading);
33265
+ return loading;
33266
+ }
33267
+
33238
33268
  // src/core/widgets.ts
33239
33269
  var import_node_fs3 = require("node:fs");
33240
33270
  var import_node_path3 = require("node:path");
@@ -33313,52 +33343,60 @@ async function createServer(config2) {
33313
33343
  chat: config2.chat || {}
33314
33344
  })
33315
33345
  );
33316
- if (!headless && staticDir) {
33317
- const relativePath = require("node:path").relative(process.cwd(), staticDir);
33318
- app.get("/chatter.js", (0, import_bun.serveStatic)({ path: `${relativePath}/chatter.js` }));
33319
- app.get("/chatter.css", (0, import_bun.serveStatic)({ path: `${relativePath}/chatter.css` }));
33320
- }
33321
- if (!headless && publicDir) {
33322
- app.get("/", (0, import_bun.serveStatic)({ path: `${publicDir}/index.html` }));
33323
- app.get("/chat", (0, import_bun.serveStatic)({ path: `${publicDir}/chat.html` }));
33324
- app.get("/private", (0, import_bun.serveStatic)({ path: `${publicDir}/private.html` }));
33325
- app.get("/vanilla/chat", (0, import_bun.serveStatic)({ path: `${publicDir}/vanilla/chat.html` }));
33346
+ let serveStatic = null;
33347
+ if (!headless && (staticDir || publicDir)) {
33348
+ try {
33349
+ serveStatic = await loadServeStatic();
33350
+ } catch (error51) {
33351
+ console.error(`\u274C Static assets disabled: ${error51.message}`);
33352
+ }
33353
+ }
33354
+ if (serveStatic && staticDir) {
33355
+ const relativePath = (0, import_node_path4.relative)(process.cwd(), staticDir);
33356
+ app.get("/chatter.js", serveStatic({ path: `${relativePath}/chatter.js` }));
33357
+ app.get("/chatter.css", serveStatic({ path: `${relativePath}/chatter.css` }));
33358
+ }
33359
+ if (serveStatic && publicDir) {
33360
+ app.get("/", serveStatic({ path: `${publicDir}/index.html` }));
33361
+ app.get("/chat", serveStatic({ path: `${publicDir}/chat.html` }));
33362
+ app.get("/private", serveStatic({ path: `${publicDir}/private.html` }));
33363
+ app.get("/vanilla/chat", serveStatic({ path: `${publicDir}/vanilla/chat.html` }));
33326
33364
  app.get(
33327
33365
  "/demo/widget-button-public",
33328
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-button-public.html` })
33366
+ serveStatic({ path: `${publicDir}/demo/widget-button-public.html` })
33329
33367
  );
33330
33368
  app.get(
33331
33369
  "/demo/widget-button-private",
33332
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-button-private.html` })
33370
+ serveStatic({ path: `${publicDir}/demo/widget-button-private.html` })
33333
33371
  );
33334
33372
  app.get(
33335
33373
  "/demo/widget-inline-public",
33336
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-inline-public.html` })
33374
+ serveStatic({ path: `${publicDir}/demo/widget-inline-public.html` })
33337
33375
  );
33338
33376
  app.get(
33339
33377
  "/demo/widget-inline-private",
33340
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-inline-private.html` })
33378
+ serveStatic({ path: `${publicDir}/demo/widget-inline-private.html` })
33341
33379
  );
33342
33380
  app.get(
33343
33381
  "/demo/react-button-public",
33344
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-button-public.html` })
33382
+ serveStatic({ path: `${publicDir}/demo/react-button-public.html` })
33345
33383
  );
33346
33384
  app.get(
33347
33385
  "/demo/react-button-private",
33348
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-button-private.html` })
33386
+ serveStatic({ path: `${publicDir}/demo/react-button-private.html` })
33349
33387
  );
33350
33388
  app.get(
33351
33389
  "/demo/react-inline-public",
33352
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-inline-public.html` })
33390
+ serveStatic({ path: `${publicDir}/demo/react-inline-public.html` })
33353
33391
  );
33354
33392
  app.get(
33355
33393
  "/demo/react-inline-private",
33356
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-inline-private.html` })
33394
+ serveStatic({ path: `${publicDir}/demo/react-inline-private.html` })
33357
33395
  );
33358
- app.get("/demo/public", (0, import_bun.serveStatic)({ path: `${publicDir}/demo-public.html` }));
33359
- app.get("/demo/private", (0, import_bun.serveStatic)({ path: `${publicDir}/demo-private.html` }));
33360
- app.get("/demo/chatbot", (0, import_bun.serveStatic)({ path: `${publicDir}/demo-chatbot.html` }));
33361
- app.get("/demo/react", (0, import_bun.serveStatic)({ path: `${publicDir}/react-demo.html` }));
33396
+ app.get("/demo/public", serveStatic({ path: `${publicDir}/demo-public.html` }));
33397
+ app.get("/demo/private", serveStatic({ path: `${publicDir}/demo-private.html` }));
33398
+ app.get("/demo/chatbot", serveStatic({ path: `${publicDir}/demo-chatbot.html` }));
33399
+ app.get("/demo/react", serveStatic({ path: `${publicDir}/react-demo.html` }));
33362
33400
  }
33363
33401
  const senders = createSenderRegistry();
33364
33402
  const deps = { client, store, db, config: config2, prompts, apiKeyManager, senders };
package/dist/index.mjs CHANGED
@@ -4,13 +4,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
- }) : x)(function(x) {
10
- if (typeof require !== "undefined") return require.apply(this, arguments);
11
- throw Error('Dynamic require of "' + x + '" is not supported');
12
- });
13
- var __commonJS = (cb, mod) => function __require2() {
7
+ var __commonJS = (cb, mod) => function __require() {
14
8
  try {
15
9
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
16
10
  } catch (e) {
@@ -4269,49 +4263,49 @@ var require_fast_uri = __commonJS({
4269
4263
  schemelessOptions.skipEscape = true;
4270
4264
  return serialize(resolved, schemelessOptions);
4271
4265
  }
4272
- function resolveComponent(base, relative, options, skipNormalization) {
4266
+ function resolveComponent(base, relative2, options, skipNormalization) {
4273
4267
  const target = {};
4274
4268
  if (!skipNormalization) {
4275
4269
  base = parse3(serialize(base, options), options);
4276
- relative = parse3(serialize(relative, options), options);
4270
+ relative2 = parse3(serialize(relative2, options), options);
4277
4271
  }
4278
4272
  options = options || {};
4279
- if (!options.tolerant && relative.scheme) {
4280
- target.scheme = relative.scheme;
4281
- target.userinfo = relative.userinfo;
4282
- target.host = relative.host;
4283
- target.port = relative.port;
4284
- target.path = removeDotSegments(relative.path || "");
4285
- target.query = relative.query;
4273
+ if (!options.tolerant && relative2.scheme) {
4274
+ target.scheme = relative2.scheme;
4275
+ target.userinfo = relative2.userinfo;
4276
+ target.host = relative2.host;
4277
+ target.port = relative2.port;
4278
+ target.path = removeDotSegments(relative2.path || "");
4279
+ target.query = relative2.query;
4286
4280
  } else {
4287
- if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
4288
- target.userinfo = relative.userinfo;
4289
- target.host = relative.host;
4290
- target.port = relative.port;
4291
- target.path = removeDotSegments(relative.path || "");
4292
- target.query = relative.query;
4281
+ if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
4282
+ target.userinfo = relative2.userinfo;
4283
+ target.host = relative2.host;
4284
+ target.port = relative2.port;
4285
+ target.path = removeDotSegments(relative2.path || "");
4286
+ target.query = relative2.query;
4293
4287
  } else {
4294
- if (!relative.path) {
4288
+ if (!relative2.path) {
4295
4289
  target.path = base.path;
4296
- if (relative.query !== void 0) {
4297
- target.query = relative.query;
4290
+ if (relative2.query !== void 0) {
4291
+ target.query = relative2.query;
4298
4292
  } else {
4299
4293
  target.query = base.query;
4300
4294
  }
4301
4295
  } else {
4302
- if (relative.path[0] === "/") {
4303
- target.path = removeDotSegments(relative.path);
4296
+ if (relative2.path[0] === "/") {
4297
+ target.path = removeDotSegments(relative2.path);
4304
4298
  } else {
4305
4299
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
4306
- target.path = "/" + relative.path;
4300
+ target.path = "/" + relative2.path;
4307
4301
  } else if (!base.path) {
4308
- target.path = relative.path;
4302
+ target.path = relative2.path;
4309
4303
  } else {
4310
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
4304
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
4311
4305
  }
4312
4306
  target.path = removeDotSegments(target.path);
4313
4307
  }
4314
- target.query = relative.query;
4308
+ target.query = relative2.query;
4315
4309
  }
4316
4310
  target.userinfo = base.userinfo;
4317
4311
  target.host = base.host;
@@ -4319,7 +4313,7 @@ var require_fast_uri = __commonJS({
4319
4313
  }
4320
4314
  target.scheme = base.scheme;
4321
4315
  }
4322
- target.fragment = relative.fragment;
4316
+ target.fragment = relative2.fragment;
4323
4317
  return target;
4324
4318
  }
4325
4319
  function equal(uriA, uriB, options) {
@@ -33138,9 +33132,9 @@ function publicRoutes(deps) {
33138
33132
  }
33139
33133
 
33140
33134
  // src/server.ts
33135
+ import { relative } from "node:path";
33141
33136
  import { createClient as createClient2 } from "@libsql/client";
33142
33137
  import { Hono as Hono5 } from "hono";
33143
- import { serveStatic } from "hono/bun";
33144
33138
  import OpenAI2 from "openai";
33145
33139
 
33146
33140
  // src/channels/senders.ts
@@ -33195,6 +33189,36 @@ function createSenderRegistry() {
33195
33189
  };
33196
33190
  }
33197
33191
 
33192
+ // src/core/serve-static.ts
33193
+ var STATIC_ADAPTERS = {
33194
+ bun: "hono/bun",
33195
+ node: "@hono/node-server/serve-static"
33196
+ };
33197
+ function detectRuntime() {
33198
+ return typeof globalThis.Bun === "undefined" ? "node" : "bun";
33199
+ }
33200
+ function wrapMissingAdapterError(runtime, cause) {
33201
+ const specifier = STATIC_ADAPTERS[runtime];
33202
+ return new Error(
33203
+ `Serving static files under ${runtime} requires '${specifier}', which could not be loaded. ` + (runtime === "node" ? "Install the optional peer dependency with `npm install @hono/node-server` (or bun/pnpm/yarn), or run Chatter headless (`features.headless: true`) if it should serve no static assets." : "Upgrade 'hono' to a version that ships the Bun adapter."),
33204
+ { cause }
33205
+ );
33206
+ }
33207
+ var cache = /* @__PURE__ */ new Map();
33208
+ function loadServeStatic(runtime = detectRuntime()) {
33209
+ const cached2 = cache.get(runtime);
33210
+ if (cached2) return cached2;
33211
+ const loading = (runtime === "bun" ? import("hono/bun") : import("@hono/node-server/serve-static")).then(
33212
+ (module) => module.serveStatic,
33213
+ (error51) => {
33214
+ cache.delete(runtime);
33215
+ throw wrapMissingAdapterError(runtime, error51);
33216
+ }
33217
+ );
33218
+ cache.set(runtime, loading);
33219
+ return loading;
33220
+ }
33221
+
33198
33222
  // src/core/widgets.ts
33199
33223
  import { existsSync } from "node:fs";
33200
33224
  import { dirname, join as join3 } from "node:path";
@@ -33272,12 +33296,20 @@ async function createServer(config2) {
33272
33296
  chat: config2.chat || {}
33273
33297
  })
33274
33298
  );
33275
- if (!headless && staticDir) {
33276
- const relativePath = __require("node:path").relative(process.cwd(), staticDir);
33299
+ let serveStatic = null;
33300
+ if (!headless && (staticDir || publicDir)) {
33301
+ try {
33302
+ serveStatic = await loadServeStatic();
33303
+ } catch (error51) {
33304
+ console.error(`\u274C Static assets disabled: ${error51.message}`);
33305
+ }
33306
+ }
33307
+ if (serveStatic && staticDir) {
33308
+ const relativePath = relative(process.cwd(), staticDir);
33277
33309
  app.get("/chatter.js", serveStatic({ path: `${relativePath}/chatter.js` }));
33278
33310
  app.get("/chatter.css", serveStatic({ path: `${relativePath}/chatter.css` }));
33279
33311
  }
33280
- if (!headless && publicDir) {
33312
+ if (serveStatic && publicDir) {
33281
33313
  app.get("/", serveStatic({ path: `${publicDir}/index.html` }));
33282
33314
  app.get("/chat", serveStatic({ path: `${publicDir}/chat.html` }));
33283
33315
  app.get("/private", serveStatic({ path: `${publicDir}/private.html` }));
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAc5B,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,SAAS,CAAC;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG;IAAE,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC;AAEtE;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAkM7E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAc5B,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,SAAS,CAAC;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG;IAAE,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC;AAEtE;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CA+M7E"}
package/dist/server.js CHANGED
@@ -33,9 +33,9 @@ __export(server_exports, {
33
33
  createServer: () => createServer
34
34
  });
35
35
  module.exports = __toCommonJS(server_exports);
36
+ var import_node_path4 = require("node:path");
36
37
  var import_client2 = require("@libsql/client");
37
38
  var import_hono5 = require("hono");
38
- var import_bun = require("hono/bun");
39
39
  var import_openai = __toESM(require("openai"));
40
40
 
41
41
  // src/auth/apikeys.ts
@@ -442,6 +442,36 @@ var VectorStore = class _VectorStore {
442
442
  }
443
443
  };
444
444
 
445
+ // src/core/serve-static.ts
446
+ var STATIC_ADAPTERS = {
447
+ bun: "hono/bun",
448
+ node: "@hono/node-server/serve-static"
449
+ };
450
+ function detectRuntime() {
451
+ return typeof globalThis.Bun === "undefined" ? "node" : "bun";
452
+ }
453
+ function wrapMissingAdapterError(runtime, cause) {
454
+ const specifier = STATIC_ADAPTERS[runtime];
455
+ return new Error(
456
+ `Serving static files under ${runtime} requires '${specifier}', which could not be loaded. ` + (runtime === "node" ? "Install the optional peer dependency with `npm install @hono/node-server` (or bun/pnpm/yarn), or run Chatter headless (`features.headless: true`) if it should serve no static assets." : "Upgrade 'hono' to a version that ships the Bun adapter."),
457
+ { cause }
458
+ );
459
+ }
460
+ var cache = /* @__PURE__ */ new Map();
461
+ function loadServeStatic(runtime = detectRuntime()) {
462
+ const cached = cache.get(runtime);
463
+ if (cached) return cached;
464
+ const loading = (runtime === "bun" ? import("hono/bun") : import("@hono/node-server/serve-static")).then(
465
+ (module2) => module2.serveStatic,
466
+ (error) => {
467
+ cache.delete(runtime);
468
+ throw wrapMissingAdapterError(runtime, error);
469
+ }
470
+ );
471
+ cache.set(runtime, loading);
472
+ return loading;
473
+ }
474
+
445
475
  // src/core/widgets.ts
446
476
  var import_node_fs3 = require("node:fs");
447
477
  var import_node_path3 = require("node:path");
@@ -1425,52 +1455,60 @@ async function createServer(config) {
1425
1455
  chat: config.chat || {}
1426
1456
  })
1427
1457
  );
1428
- if (!headless && staticDir) {
1429
- const relativePath = require("node:path").relative(process.cwd(), staticDir);
1430
- app.get("/chatter.js", (0, import_bun.serveStatic)({ path: `${relativePath}/chatter.js` }));
1431
- app.get("/chatter.css", (0, import_bun.serveStatic)({ path: `${relativePath}/chatter.css` }));
1458
+ let serveStatic = null;
1459
+ if (!headless && (staticDir || publicDir)) {
1460
+ try {
1461
+ serveStatic = await loadServeStatic();
1462
+ } catch (error) {
1463
+ console.error(`\u274C Static assets disabled: ${error.message}`);
1464
+ }
1465
+ }
1466
+ if (serveStatic && staticDir) {
1467
+ const relativePath = (0, import_node_path4.relative)(process.cwd(), staticDir);
1468
+ app.get("/chatter.js", serveStatic({ path: `${relativePath}/chatter.js` }));
1469
+ app.get("/chatter.css", serveStatic({ path: `${relativePath}/chatter.css` }));
1432
1470
  }
1433
- if (!headless && publicDir) {
1434
- app.get("/", (0, import_bun.serveStatic)({ path: `${publicDir}/index.html` }));
1435
- app.get("/chat", (0, import_bun.serveStatic)({ path: `${publicDir}/chat.html` }));
1436
- app.get("/private", (0, import_bun.serveStatic)({ path: `${publicDir}/private.html` }));
1437
- app.get("/vanilla/chat", (0, import_bun.serveStatic)({ path: `${publicDir}/vanilla/chat.html` }));
1471
+ if (serveStatic && publicDir) {
1472
+ app.get("/", serveStatic({ path: `${publicDir}/index.html` }));
1473
+ app.get("/chat", serveStatic({ path: `${publicDir}/chat.html` }));
1474
+ app.get("/private", serveStatic({ path: `${publicDir}/private.html` }));
1475
+ app.get("/vanilla/chat", serveStatic({ path: `${publicDir}/vanilla/chat.html` }));
1438
1476
  app.get(
1439
1477
  "/demo/widget-button-public",
1440
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-button-public.html` })
1478
+ serveStatic({ path: `${publicDir}/demo/widget-button-public.html` })
1441
1479
  );
1442
1480
  app.get(
1443
1481
  "/demo/widget-button-private",
1444
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-button-private.html` })
1482
+ serveStatic({ path: `${publicDir}/demo/widget-button-private.html` })
1445
1483
  );
1446
1484
  app.get(
1447
1485
  "/demo/widget-inline-public",
1448
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-inline-public.html` })
1486
+ serveStatic({ path: `${publicDir}/demo/widget-inline-public.html` })
1449
1487
  );
1450
1488
  app.get(
1451
1489
  "/demo/widget-inline-private",
1452
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/widget-inline-private.html` })
1490
+ serveStatic({ path: `${publicDir}/demo/widget-inline-private.html` })
1453
1491
  );
1454
1492
  app.get(
1455
1493
  "/demo/react-button-public",
1456
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-button-public.html` })
1494
+ serveStatic({ path: `${publicDir}/demo/react-button-public.html` })
1457
1495
  );
1458
1496
  app.get(
1459
1497
  "/demo/react-button-private",
1460
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-button-private.html` })
1498
+ serveStatic({ path: `${publicDir}/demo/react-button-private.html` })
1461
1499
  );
1462
1500
  app.get(
1463
1501
  "/demo/react-inline-public",
1464
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-inline-public.html` })
1502
+ serveStatic({ path: `${publicDir}/demo/react-inline-public.html` })
1465
1503
  );
1466
1504
  app.get(
1467
1505
  "/demo/react-inline-private",
1468
- (0, import_bun.serveStatic)({ path: `${publicDir}/demo/react-inline-private.html` })
1506
+ serveStatic({ path: `${publicDir}/demo/react-inline-private.html` })
1469
1507
  );
1470
- app.get("/demo/public", (0, import_bun.serveStatic)({ path: `${publicDir}/demo-public.html` }));
1471
- app.get("/demo/private", (0, import_bun.serveStatic)({ path: `${publicDir}/demo-private.html` }));
1472
- app.get("/demo/chatbot", (0, import_bun.serveStatic)({ path: `${publicDir}/demo-chatbot.html` }));
1473
- app.get("/demo/react", (0, import_bun.serveStatic)({ path: `${publicDir}/react-demo.html` }));
1508
+ app.get("/demo/public", serveStatic({ path: `${publicDir}/demo-public.html` }));
1509
+ app.get("/demo/private", serveStatic({ path: `${publicDir}/demo-private.html` }));
1510
+ app.get("/demo/chatbot", serveStatic({ path: `${publicDir}/demo-chatbot.html` }));
1511
+ app.get("/demo/react", serveStatic({ path: `${publicDir}/react-demo.html` }));
1474
1512
  }
1475
1513
  const senders = createSenderRegistry();
1476
1514
  const deps = { client, store, db, config, prompts, apiKeyManager, senders };
package/dist/server.mjs CHANGED
@@ -1,14 +1,7 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/server.ts
2
+ import { relative } from "node:path";
9
3
  import { createClient as createClient2 } from "@libsql/client";
10
4
  import { Hono as Hono5 } from "hono";
11
- import { serveStatic } from "hono/bun";
12
5
  import OpenAI from "openai";
13
6
 
14
7
  // src/auth/apikeys.ts
@@ -415,6 +408,36 @@ var VectorStore = class _VectorStore {
415
408
  }
416
409
  };
417
410
 
411
+ // src/core/serve-static.ts
412
+ var STATIC_ADAPTERS = {
413
+ bun: "hono/bun",
414
+ node: "@hono/node-server/serve-static"
415
+ };
416
+ function detectRuntime() {
417
+ return typeof globalThis.Bun === "undefined" ? "node" : "bun";
418
+ }
419
+ function wrapMissingAdapterError(runtime, cause) {
420
+ const specifier = STATIC_ADAPTERS[runtime];
421
+ return new Error(
422
+ `Serving static files under ${runtime} requires '${specifier}', which could not be loaded. ` + (runtime === "node" ? "Install the optional peer dependency with `npm install @hono/node-server` (or bun/pnpm/yarn), or run Chatter headless (`features.headless: true`) if it should serve no static assets." : "Upgrade 'hono' to a version that ships the Bun adapter."),
423
+ { cause }
424
+ );
425
+ }
426
+ var cache = /* @__PURE__ */ new Map();
427
+ function loadServeStatic(runtime = detectRuntime()) {
428
+ const cached = cache.get(runtime);
429
+ if (cached) return cached;
430
+ const loading = (runtime === "bun" ? import("hono/bun") : import("@hono/node-server/serve-static")).then(
431
+ (module) => module.serveStatic,
432
+ (error) => {
433
+ cache.delete(runtime);
434
+ throw wrapMissingAdapterError(runtime, error);
435
+ }
436
+ );
437
+ cache.set(runtime, loading);
438
+ return loading;
439
+ }
440
+
418
441
  // src/core/widgets.ts
419
442
  import { existsSync } from "node:fs";
420
443
  import { dirname, join as join3 } from "node:path";
@@ -1397,12 +1420,20 @@ async function createServer(config) {
1397
1420
  chat: config.chat || {}
1398
1421
  })
1399
1422
  );
1400
- if (!headless && staticDir) {
1401
- const relativePath = __require("node:path").relative(process.cwd(), staticDir);
1423
+ let serveStatic = null;
1424
+ if (!headless && (staticDir || publicDir)) {
1425
+ try {
1426
+ serveStatic = await loadServeStatic();
1427
+ } catch (error) {
1428
+ console.error(`\u274C Static assets disabled: ${error.message}`);
1429
+ }
1430
+ }
1431
+ if (serveStatic && staticDir) {
1432
+ const relativePath = relative(process.cwd(), staticDir);
1402
1433
  app.get("/chatter.js", serveStatic({ path: `${relativePath}/chatter.js` }));
1403
1434
  app.get("/chatter.css", serveStatic({ path: `${relativePath}/chatter.css` }));
1404
1435
  }
1405
- if (!headless && publicDir) {
1436
+ if (serveStatic && publicDir) {
1406
1437
  app.get("/", serveStatic({ path: `${publicDir}/index.html` }));
1407
1438
  app.get("/chat", serveStatic({ path: `${publicDir}/chat.html` }));
1408
1439
  app.get("/private", serveStatic({ path: `${publicDir}/private.html` }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegoaltoworks/chatter",
3
- "version": "0.45.0",
3
+ "version": "0.47.0",
4
4
  "description": "Embeddable AI chatbot framework with RAG, authentication, and customizable widgets",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -78,9 +78,9 @@
78
78
  "build": "bun run build:clean && bun run build:types && bun run build:esm && bun run build:cjs && bun run build:server && bun run build:mcp && bun run build:usage && bun run build:personas && bun run build:channels && bun run build:whatsapp && bun run build:flows && bun run build:images && bun run build:scheduler && bun run build:bin && bun run build:client && bun run build:copy-client",
79
79
  "build:clean": "rm -rf dist",
80
80
  "build:types": "tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
81
- "build:esm": "esbuild src/index.ts --bundle --format=esm --outfile=dist/index.mjs --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24",
82
- "build:cjs": "esbuild src/index.ts --bundle --format=cjs --outfile=dist/index.js --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24",
83
- "build:server": "esbuild src/server.ts --bundle --format=esm --outfile=dist/server.mjs --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24 && esbuild src/server.ts --bundle --format=cjs --outfile=dist/server.js --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24",
81
+ "build:esm": "esbuild src/index.ts --bundle --format=esm --outfile=dist/index.mjs --external:@hono/node-server --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24",
82
+ "build:cjs": "esbuild src/index.ts --bundle --format=cjs --outfile=dist/index.js --external:@hono/node-server --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24",
83
+ "build:server": "esbuild src/server.ts --bundle --format=esm --outfile=dist/server.mjs --external:@hono/node-server --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24 && esbuild src/server.ts --bundle --format=cjs --outfile=dist/server.js --external:@hono/node-server --external:hono --external:openai --external:@libsql/client --external:jose --platform=node --target=node24",
84
84
  "build:mcp": "esbuild src/mcp-server.ts --bundle --format=esm --outfile=dist/mcp-server.mjs --external:@modelcontextprotocol/sdk --external:openai --external:@libsql/client --external:zod --platform=node --target=node24 && esbuild src/mcp-server.ts --bundle --format=cjs --outfile=dist/mcp-server.js --external:@modelcontextprotocol/sdk --external:openai --external:@libsql/client --external:zod --platform=node --target=node24",
85
85
  "build:usage": "esbuild src/usage/index.ts --bundle --format=esm --outfile=dist/usage/index.mjs --external:@libsql/client --platform=node --target=node24 && esbuild src/usage/index.ts --bundle --format=cjs --outfile=dist/usage/index.js --external:@libsql/client --platform=node --target=node24",
86
86
  "build:personas": "esbuild src/personas/index.ts --bundle --format=esm --outfile=dist/personas/index.mjs --platform=node --target=node24 && esbuild src/personas/index.ts --bundle --format=cjs --outfile=dist/personas/index.js --platform=node --target=node24",
@@ -96,6 +96,7 @@
96
96
  "test:unit": "bun test src/**/*.test.ts",
97
97
  "test:integration": "bun test test/integration/**/*.test.ts",
98
98
  "test:pack": "bun scripts/verify-pack.ts",
99
+ "test:node": "node scripts/verify-node.mjs",
99
100
  "test:watch": "bun test --watch",
100
101
  "test:coverage": "bun test --coverage",
101
102
  "typecheck": "tsc --noEmit",
@@ -139,9 +140,11 @@
139
140
  },
140
141
  "homepage": "https://github.com/diegoaltoworks/chatter#readme",
141
142
  "engines": {
142
- "node": ">=24.0.0"
143
+ "node": ">=24.0.0",
144
+ "bun": ">=1.2.0"
143
145
  },
144
146
  "peerDependencies": {
147
+ "@hono/node-server": "^2.0.5",
145
148
  "@libsql/client": "^0.17.2",
146
149
  "@modelcontextprotocol/sdk": "^1.30.0",
147
150
  "@whiskeysockets/baileys": "^7.0.0-rc14",
@@ -151,6 +154,9 @@
151
154
  "zod": "^3.25.76 || ^4.4.3"
152
155
  },
153
156
  "peerDependenciesMeta": {
157
+ "@hono/node-server": {
158
+ "optional": true
159
+ },
154
160
  "@whiskeysockets/baileys": {
155
161
  "optional": true
156
162
  },
@@ -163,6 +169,7 @@
163
169
  },
164
170
  "devDependencies": {
165
171
  "@biomejs/biome": "2.5.7",
172
+ "@hono/node-server": "2.0.12",
166
173
  "@libsql/client": "0.17.4",
167
174
  "@modelcontextprotocol/sdk": "1.30.0",
168
175
  "@types/bun": "1.3.14",
@@ -188,7 +195,6 @@
188
195
  "overrides": {
189
196
  "qs": "^6.15.3",
190
197
  "ws": "^8.21.1",
191
- "@hono/node-server": "^2.0.5",
192
198
  "fast-uri": "^3.1.3",
193
199
  "ip-address": "^10.4.0"
194
200
  }