@llmops/app 1.0.0-beta.11 → 1.0.0-beta.13

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 (3) hide show
  1. package/dist/index.cjs +75 -295
  2. package/dist/index.mjs +47 -266
  3. package/package.json +4 -6
package/dist/index.cjs CHANGED
@@ -41,11 +41,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
41
41
  //#endregion
42
42
  let hono = require("hono");
43
43
  let __llmops_core = require("@llmops/core");
44
- let nunjucks = require("nunjucks");
45
- nunjucks = __toESM(nunjucks);
46
- let node_url = require("node:url");
47
- let node_path = require("node:path");
48
- let node_fs = require("node:fs");
49
44
  let __hono_zod_validator = require("@hono/zod-validator");
50
45
  let __llmops_sdk = require("@llmops/sdk");
51
46
  let hono_pretty_json = require("hono/pretty-json");
@@ -57,10 +52,6 @@ __llmops_gateway = __toESM(__llmops_gateway);
57
52
  let protobufjs = require("protobufjs");
58
53
  protobufjs = __toESM(protobufjs);
59
54
  let node_process = require("node:process");
60
- let hono_serve_static = require("hono/serve-static");
61
- let url = require("url");
62
- let path = require("path");
63
- let fs_promises = require("fs/promises");
64
55
 
65
56
  //#region src/client/index.tsx?url
66
57
  var client_default = "/assets/index-silDa7sW.js";
@@ -408,8 +399,8 @@ const manifest = {
408
399
  "names": ["styles.css"]
409
400
  }
410
401
  };
411
- const getAsset = (path$1) => {
412
- return embeddedAssets[path$1];
402
+ const getAsset = (path) => {
403
+ return embeddedAssets[path];
413
404
  };
414
405
  const decodeAsset = (asset) => {
415
406
  return Buffer.from(asset.content, "base64");
@@ -417,276 +408,43 @@ const decodeAsset = (asset) => {
417
408
 
418
409
  //#endregion
419
410
  //#region src/server/ssr/renderer.ts
420
- const manifestPath = (0, node_path.join)((0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href)), "./.vite/manifest.json");
421
- const manifest$1 = Object.keys(manifest).length > 0 ? manifest : (0, node_fs.existsSync)(manifestPath) ? JSON.parse((0, node_fs.readFileSync)(manifestPath, "utf-8")) : {};
422
- const env$2 = new nunjucks.default.Environment(null, { autoescape: false });
423
- const htmlTemplate = `<!DOCTYPE html>
411
+ const manifest$1 = Object.keys(manifest).length > 0 ? manifest : {};
412
+ const renderer = ({ basePath = "", dev = false }) => {
413
+ const stylesPath = basePath === "/" ? styles_default : basePath + styles_default;
414
+ const clientPath = basePath === "/" ? client_default : basePath + client_default;
415
+ return `<!DOCTYPE html>
424
416
  <html lang="en" class="">
425
417
  <head>
426
418
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
427
419
  <link rel="preconnect" href="https://fonts.googleapis.com" />
428
420
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
429
421
  <link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap" rel="stylesheet" />
430
- <link rel="icon" href="{{ faviconIcoPath }}" sizes="any" />
431
- <link rel="icon" href="{{ faviconSvgPath }}" type="image/svg+xml" />
422
+ <link rel="icon" href="${basePath === "/" ? "/favicon.ico" : basePath + "/favicon.ico"}" sizes="any" />
423
+ <link rel="icon" href="${basePath === "/" ? (!dev ? "/assets" : "") + "/favicon.svg" : basePath + (!dev ? "/assets" : "") + "/favicon.svg"}" type="image/svg+xml" />
432
424
  <style>
433
- /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */
434
-
435
- /*
436
- Document
437
- ========
438
- */
439
-
440
- /**
441
- Use a better box model (opinionated).
442
- */
443
-
444
- *,
445
- ::before,
446
- ::after {
447
- box-sizing: border-box;
448
- }
449
-
450
- /**
451
- 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
452
- 2. Correct the line height in all browsers.
453
- 3. Prevent adjustments of font size after orientation changes in iOS.
454
- 4. Use a more readable tab size (opinionated).
455
- */
456
-
457
- html {
458
- font-family:
459
- system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
460
- 'Apple Color Emoji', 'Segoe UI Emoji'; /* 1 */
461
- line-height: 1.15; /* 2 */
462
- -webkit-text-size-adjust: 100%; /* 3 */
463
- tab-size: 4; /* 4 */
464
- }
465
-
466
- /*
467
- Sections
468
- ========
469
- */
470
-
471
- /**
472
- Remove the margin in all browsers.
473
- */
474
-
475
- body {
476
- margin: 0;
477
- }
478
-
479
- /*
480
- Text-level semantics
481
- ====================
482
- */
483
-
484
- /**
485
- Add the correct font weight in Chrome and Safari.
486
- */
487
-
488
- b,
489
- strong {
490
- font-weight: bolder;
491
- }
492
-
493
- /**
494
- 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
495
- 2. Correct the odd 'em' font sizing in all browsers.
496
- */
497
-
498
- code,
499
- kbd,
500
- samp,
501
- pre {
502
- font-family:
503
- ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace; /* 1 */
504
- font-size: 1em; /* 2 */
505
- }
506
-
507
- /**
508
- Add the correct font size in all browsers.
509
- */
510
-
511
- small {
512
- font-size: 80%;
513
- }
514
-
515
- /**
516
- Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
517
- */
518
-
519
- sub,
520
- sup {
521
- font-size: 75%;
522
- line-height: 0;
523
- position: relative;
524
- vertical-align: baseline;
525
- }
526
-
527
- sub {
528
- bottom: -0.25em;
529
- }
530
-
531
- sup {
532
- top: -0.5em;
533
- }
534
-
535
- /*
536
- Tabular data
537
- ============
538
- */
539
-
540
- /**
541
- Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016)
542
- */
543
-
544
- table {
545
- border-color: currentcolor;
546
- }
547
-
548
- /*
549
- Forms
550
- =====
551
- */
552
-
553
- /**
554
- 1. Change the font styles in all browsers.
555
- 2. Remove the margin in Firefox and Safari.
556
- */
557
-
558
- button,
559
- input,
560
- optgroup,
561
- select,
562
- textarea {
563
- font-family: inherit; /* 1 */
564
- font-size: 100%; /* 1 */
565
- line-height: 1.15; /* 1 */
566
- margin: 0; /* 2 */
567
- }
568
-
569
- /**
570
- Correct the inability to style clickable types in iOS and Safari.
571
- */
572
-
573
- button,
574
- [type='button'],
575
- [type='reset'],
576
- [type='submit'] {
577
- -webkit-appearance: button;
578
- }
579
-
580
- /**
581
- Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
582
- */
583
-
584
- legend {
585
- padding: 0;
586
- }
587
-
588
- /**
589
- Add the correct vertical alignment in Chrome and Firefox.
590
- */
591
-
592
- progress {
593
- vertical-align: baseline;
594
- }
595
-
596
- /**
597
- Correct the cursor style of increment and decrement buttons in Safari.
598
- */
599
-
600
- ::-webkit-inner-spin-button,
601
- ::-webkit-outer-spin-button {
602
- height: auto;
603
- }
604
-
605
- /**
606
- 1. Correct the odd appearance in Chrome and Safari.
607
- 2. Correct the outline style in Safari.
608
- */
609
-
610
- [type='search'] {
611
- -webkit-appearance: textfield; /* 1 */
612
- outline-offset: -2px; /* 2 */
613
- }
614
-
615
- /**
616
- Remove the inner padding in Chrome and Safari on macOS.
617
- */
618
-
619
- ::-webkit-search-decoration {
620
- -webkit-appearance: none;
621
- }
622
-
623
- /**
624
- 1. Correct the inability to style clickable types in iOS and Safari.
625
- 2. Change font properties to 'inherit' in Safari.
626
- */
627
-
628
- ::-webkit-file-upload-button {
629
- -webkit-appearance: button; /* 1 */
630
- font: inherit; /* 2 */
631
- }
632
-
633
- /*
634
- Interactive
635
- ===========
636
- */
637
-
638
- /*
639
- Add the correct display in Chrome and Safari.
640
- */
641
-
642
- summary {
643
- display: list-item;
644
- }
645
-
646
- .root {
647
- isolation: isolate;
648
- }
425
+ *,::before,::after{box-sizing:border-box}html{font-family:system-ui,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji';line-height:1.15;-webkit-text-size-adjust:100%;tab-size:4}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,'Liberation Mono',Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}table{border-color:currentcolor}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,[type='button'],[type='reset'],[type='submit']{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type='search']{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}.root{isolation:isolate}
649
426
  </style>
650
- <link href="{{ stylesPath }}" rel="stylesheet" />
651
- {% for cssFile in entryCSSFiles %}
652
- <link href="{{ cssFile }}" rel="stylesheet" />
653
- {% endfor %}
427
+ <link href="${stylesPath}" rel="stylesheet" />
428
+ ${(Object.keys(manifest$1)?.filter((key) => manifest$1[key].isEntry && manifest$1[key].css)?.flatMap((key) => manifest$1[key].css || []).map((cssFile) => basePath === "/" ? `/${cssFile}` : basePath + `/${cssFile}`).filter((cssFile) => cssFile !== stylesPath) || []).map((cssFile) => `<link href="${cssFile}" rel="stylesheet" />`).join("\n ")}
654
429
  <script>
655
430
  window.bootstrapData = {
656
- basePath: "{{ basePath }}"
431
+ basePath: "${basePath}"
657
432
  };
658
433
  <\/script>
659
- {% if dev %}
660
- <script type="module">
434
+ ${dev ? `<script type="module">
661
435
  import RefreshRuntime from "/@react-refresh";
662
436
  RefreshRuntime.injectIntoGlobalHook(window);
663
437
  window.$RefreshReg$ = () => {};
664
438
  window.$RefreshSig$ = () => (type) => type;
665
439
  window.__vite_plugin_react_preamble_installed__ = true;
666
- <\/script>
667
- {% endif %}
440
+ <\/script>` : ""}
668
441
  </head>
669
442
  <body>
670
443
  <noscript>You need to enable JavaScript to run this app.</noscript>
671
444
  <div id="root" class="root"></div>
672
- <script type="module" src="{{ clientPath }}"><\/script>
445
+ <script type="module" src="${clientPath}"><\/script>
673
446
  </body>
674
447
  </html>`;
675
- const renderer = ({ basePath = "", dev = false }) => {
676
- const stylesPath = basePath === "/" ? styles_default : basePath + styles_default;
677
- const clientPath = basePath === "/" ? client_default : basePath + client_default;
678
- const faviconIcoPath = basePath === "/" ? "/favicon.ico" : basePath + "/favicon.ico";
679
- const faviconSvgPath = basePath === "/" ? (!dev ? "/assets" : "") + "/favicon.svg" : basePath + (!dev ? "/assets" : "") + "/favicon.svg";
680
- const entryCSSFiles = Object.keys(manifest$1)?.filter((key) => manifest$1[key].isEntry && manifest$1[key].css)?.flatMap((key) => manifest$1[key].css || []).map((cssFile) => basePath === "/" ? `/${cssFile}` : basePath + `/${cssFile}`).filter((cssFile) => cssFile !== stylesPath) || [];
681
- return env$2.renderString(htmlTemplate, {
682
- basePath,
683
- dev,
684
- stylesPath,
685
- clientPath,
686
- faviconIcoPath,
687
- faviconSvgPath,
688
- entryCSSFiles
689
- });
690
448
  };
691
449
 
692
450
  //#endregion
@@ -907,9 +665,9 @@ function mergeDefs(...defs) {
907
665
  function cloneDef(schema) {
908
666
  return mergeDefs(schema._zod.def);
909
667
  }
910
- function getElementAtPath(obj, path$1) {
911
- if (!path$1) return obj;
912
- return path$1.reduce((acc, key) => acc?.[key], obj);
668
+ function getElementAtPath(obj, path) {
669
+ if (!path) return obj;
670
+ return path.reduce((acc, key) => acc?.[key], obj);
913
671
  }
914
672
  function promiseAllObject(promisesObj) {
915
673
  const keys = Object.keys(promisesObj);
@@ -1206,11 +964,11 @@ function aborted(x, startIndex = 0) {
1206
964
  for (let i = startIndex; i < x.issues.length; i++) if (x.issues[i]?.continue !== true) return true;
1207
965
  return false;
1208
966
  }
1209
- function prefixIssues(path$1, issues) {
967
+ function prefixIssues(path, issues) {
1210
968
  return issues.map((iss) => {
1211
969
  var _a$1;
1212
970
  (_a$1 = iss).path ?? (_a$1.path = []);
1213
- iss.path.unshift(path$1);
971
+ iss.path.unshift(path);
1214
972
  return iss;
1215
973
  });
1216
974
  }
@@ -1358,13 +1116,13 @@ function formatError(error$47, mapper = (issue$1) => issue$1.message) {
1358
1116
  }
1359
1117
  function treeifyError(error$47, mapper = (issue$1) => issue$1.message) {
1360
1118
  const result = { errors: [] };
1361
- const processError = (error$48, path$1 = []) => {
1119
+ const processError = (error$48, path = []) => {
1362
1120
  var _a$1, _b;
1363
1121
  for (const issue$1 of error$48.issues) if (issue$1.code === "invalid_union" && issue$1.errors.length) issue$1.errors.map((issues) => processError({ issues }, issue$1.path));
1364
1122
  else if (issue$1.code === "invalid_key") processError({ issues: issue$1.issues }, issue$1.path);
1365
1123
  else if (issue$1.code === "invalid_element") processError({ issues: issue$1.issues }, issue$1.path);
1366
1124
  else {
1367
- const fullpath = [...path$1, ...issue$1.path];
1125
+ const fullpath = [...path, ...issue$1.path];
1368
1126
  if (fullpath.length === 0) {
1369
1127
  result.errors.push(mapper(issue$1));
1370
1128
  continue;
@@ -1425,8 +1183,8 @@ function treeifyError(error$47, mapper = (issue$1) => issue$1.message) {
1425
1183
  */
1426
1184
  function toDotPath(_path) {
1427
1185
  const segs = [];
1428
- const path$1 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1429
- for (const seg of path$1) if (typeof seg === "number") segs.push(`[${seg}]`);
1186
+ const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1187
+ for (const seg of path) if (typeof seg === "number") segs.push(`[${seg}]`);
1430
1188
  else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
1431
1189
  else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`);
1432
1190
  else {
@@ -2399,10 +2157,10 @@ const $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
2399
2157
  inst._zod.check = (payload) => {
2400
2158
  try {
2401
2159
  const trimmed = payload.value.trim();
2402
- const url$2 = new URL(trimmed);
2160
+ const url$1 = new URL(trimmed);
2403
2161
  if (def.hostname) {
2404
2162
  def.hostname.lastIndex = 0;
2405
- if (!def.hostname.test(url$2.hostname)) payload.issues.push({
2163
+ if (!def.hostname.test(url$1.hostname)) payload.issues.push({
2406
2164
  code: "invalid_format",
2407
2165
  format: "url",
2408
2166
  note: "Invalid hostname",
@@ -2414,7 +2172,7 @@ const $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
2414
2172
  }
2415
2173
  if (def.protocol) {
2416
2174
  def.protocol.lastIndex = 0;
2417
- if (!def.protocol.test(url$2.protocol.endsWith(":") ? url$2.protocol.slice(0, -1) : url$2.protocol)) payload.issues.push({
2175
+ if (!def.protocol.test(url$1.protocol.endsWith(":") ? url$1.protocol.slice(0, -1) : url$1.protocol)) payload.issues.push({
2418
2176
  code: "invalid_format",
2419
2177
  format: "url",
2420
2178
  note: "Invalid protocol",
@@ -2424,7 +2182,7 @@ const $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
2424
2182
  continue: !def.abort
2425
2183
  });
2426
2184
  }
2427
- if (def.normalize) payload.value = url$2.href;
2185
+ if (def.normalize) payload.value = url$1.href;
2428
2186
  else payload.value = trimmed;
2429
2187
  return;
2430
2188
  } catch (_) {
@@ -11835,7 +11593,7 @@ var schemas_exports = /* @__PURE__ */ __export({
11835
11593
  undefined: () => _undefined,
11836
11594
  union: () => union,
11837
11595
  unknown: () => unknown,
11838
- url: () => url$1,
11596
+ url: () => url,
11839
11597
  uuid: () => uuid,
11840
11598
  uuidv4: () => uuidv4,
11841
11599
  uuidv6: () => uuidv6,
@@ -12017,7 +11775,7 @@ const ZodURL = /* @__PURE__ */ $constructor("ZodURL", (inst, def) => {
12017
11775
  $ZodURL.init(inst, def);
12018
11776
  ZodStringFormat.init(inst, def);
12019
11777
  });
12020
- function url$1(params) {
11778
+ function url(params) {
12021
11779
  return _url(ZodURL, params);
12022
11780
  }
12023
11781
  function httpUrl(params) {
@@ -13022,11 +12780,11 @@ function detectVersion(schema, defaultTarget) {
13022
12780
  }
13023
12781
  function resolveRef(ref, ctx) {
13024
12782
  if (!ref.startsWith("#")) throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
13025
- const path$1 = ref.slice(1).split("/").filter(Boolean);
13026
- if (path$1.length === 0) return ctx.rootSchema;
12783
+ const path = ref.slice(1).split("/").filter(Boolean);
12784
+ if (path.length === 0) return ctx.rootSchema;
13027
12785
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
13028
- if (path$1[0] === defsKey) {
13029
- const key = path$1[1];
12786
+ if (path[0] === defsKey) {
12787
+ const key = path[1];
13030
12788
  if (!key || !ctx.defs[key]) throw new Error(`Reference not found: ${ref}`);
13031
12789
  return ctx.defs[key];
13032
12790
  }
@@ -13527,7 +13285,7 @@ var external_exports = /* @__PURE__ */ __export({
13527
13285
  union: () => union,
13528
13286
  unknown: () => unknown,
13529
13287
  uppercase: () => _uppercase,
13530
- url: () => url$1,
13288
+ url: () => url,
13531
13289
  util: () => util_exports,
13532
13290
  uuid: () => uuid,
13533
13291
  uuidv4: () => uuidv4,
@@ -14710,7 +14468,7 @@ function createCostTrackingMiddleware(config$1 = {}) {
14710
14468
  const log = debug ? (msg) => __llmops_core.logger.debug(`[CostTracking] ${msg}`) : () => {};
14711
14469
  return async (c, next) => {
14712
14470
  if (!enabled) return next();
14713
- const path$1 = c.req.path;
14471
+ const path = c.req.path;
14714
14472
  if (![
14715
14473
  "/chat/completions",
14716
14474
  "/completions",
@@ -14722,7 +14480,7 @@ function createCostTrackingMiddleware(config$1 = {}) {
14722
14480
  "/audio/transcriptions",
14723
14481
  "/audio/translations",
14724
14482
  "/messages"
14725
- ].some((endpoint) => path$1.endsWith(endpoint) || endpoint === "/responses" && path$1.match(/\/responses\/[^/]+$/))) return next();
14483
+ ].some((endpoint) => path.endsWith(endpoint) || endpoint === "/responses" && path.match(/\/responses\/[^/]+$/))) return next();
14726
14484
  const requestId = (0, node_crypto.randomUUID)();
14727
14485
  const startTime = Date.now();
14728
14486
  c.header(__llmops_core.LLMOPS_REQUEST_ID_HEADER, requestId);
@@ -14732,7 +14490,7 @@ function createCostTrackingMiddleware(config$1 = {}) {
14732
14490
  body = await c.req.raw.clone().json();
14733
14491
  isStreaming = body.stream === true;
14734
14492
  __llmops_core.logger.debug({
14735
- endpoint: path$1,
14493
+ endpoint: path,
14736
14494
  isStreaming,
14737
14495
  streamValue: body.stream,
14738
14496
  model: body.model
@@ -14767,7 +14525,7 @@ function createCostTrackingMiddleware(config$1 = {}) {
14767
14525
  provider: "",
14768
14526
  model: body.model || "",
14769
14527
  configId: c.get("configId"),
14770
- endpoint: path$1,
14528
+ endpoint: path,
14771
14529
  isStreaming
14772
14530
  };
14773
14531
  c.set("__costTrackingContext", context);
@@ -15919,17 +15677,16 @@ const createMigrationMiddleware = (config$1) => {
15919
15677
 
15920
15678
  //#endregion
15921
15679
  //#region src/server/middlewares/static-assets.ts
15922
- const __dirname$1 = (0, path.dirname)((0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
15923
15680
  const hasEmbeddedAssets = Object.keys(embeddedAssets).length > 0;
15924
15681
  /**
15925
15682
  * Creates a middleware for serving static assets.
15926
15683
  * In production (single-file mode), serves from embedded base64 assets.
15927
- * In development, serves from the filesystem.
15684
+ * In development, serves from the filesystem via dynamic import().
15928
15685
  */
15929
15686
  const createStaticAssetMiddleware = () => {
15930
15687
  if (hasEmbeddedAssets) return async (c) => {
15931
- const path$1 = c.req.path;
15932
- const asset = getAsset(path$1);
15688
+ const path = c.req.path;
15689
+ const asset = getAsset(path);
15933
15690
  if (!asset) return c.notFound();
15934
15691
  const buffer = decodeAsset(asset);
15935
15692
  return new Response(new Uint8Array(buffer), { headers: {
@@ -15937,16 +15694,39 @@ const createStaticAssetMiddleware = () => {
15937
15694
  "Cache-Control": "public, max-age=31536000, immutable"
15938
15695
  } });
15939
15696
  };
15940
- return (0, hono_serve_static.serveStatic)({
15941
- root: "./",
15942
- getContent: async (path$1) => {
15943
- try {
15944
- return await (0, fs_promises.readFile)((0, path.join)(__dirname$1, "..", path$1));
15945
- } catch {
15946
- return null;
15947
- }
15697
+ let devServe = null;
15698
+ return async (c) => {
15699
+ if (!devServe) {
15700
+ const { fileURLToPath } = await import("node:url");
15701
+ const { dirname, join } = await import("node:path");
15702
+ const { readFile } = await import("node:fs/promises");
15703
+ const currentDir = dirname(fileURLToPath(require("url").pathToFileURL(__filename).href));
15704
+ devServe = async (ctx) => {
15705
+ const path = ctx.req.path;
15706
+ try {
15707
+ const file$1 = await readFile(join(currentDir, "..", path));
15708
+ const ext = path.split(".").pop() || "";
15709
+ const mimeTypes = {
15710
+ js: "application/javascript",
15711
+ mjs: "application/javascript",
15712
+ css: "text/css",
15713
+ svg: "image/svg+xml",
15714
+ png: "image/png",
15715
+ jpg: "image/jpeg",
15716
+ ico: "image/x-icon",
15717
+ woff: "font/woff",
15718
+ woff2: "font/woff2"
15719
+ };
15720
+ return new Response(file$1, { headers: { "Content-Type": mimeTypes[ext] || "application/octet-stream" } });
15721
+ } catch {
15722
+ return;
15723
+ }
15724
+ };
15948
15725
  }
15949
- });
15726
+ const response = await devServe(c);
15727
+ if (response) return response;
15728
+ return c.notFound();
15729
+ };
15950
15730
  };
15951
15731
 
15952
15732
  //#endregion
package/dist/index.mjs CHANGED
@@ -1,9 +1,5 @@
1
1
  import { Hono } from "hono";
2
2
  import { LLMOPS_REQUEST_ID_HEADER, LLMOPS_SESSION_ID_HEADER, LLMOPS_SPAN_ID_HEADER, LLMOPS_SPAN_NAME_HEADER, LLMOPS_TRACE_ID_HEADER, LLMOPS_TRACE_NAME_HEADER, LLMOPS_USER_ID_HEADER, SupportedProviders, calculateCacheAwareCost, getDefaultPricingProvider, logger, validateLLMOpsConfig } from "@llmops/core";
3
- import nunjucks from "nunjucks";
4
- import { fileURLToPath } from "node:url";
5
- import { dirname, join } from "node:path";
6
- import { existsSync, readFileSync } from "node:fs";
7
3
  import { zValidator } from "@hono/zod-validator";
8
4
  import { COST_SUMMARY_GROUP_BY } from "@llmops/sdk";
9
5
  import { prettyJSON } from "hono/pretty-json";
@@ -13,10 +9,6 @@ import { randomBytes, randomUUID } from "node:crypto";
13
9
  import gateway from "@llmops/gateway";
14
10
  import protobuf from "protobufjs";
15
11
  import { env } from "node:process";
16
- import { serveStatic } from "hono/serve-static";
17
- import { fileURLToPath as fileURLToPath$1 } from "url";
18
- import { dirname as dirname$1, join as join$1 } from "path";
19
- import { readFile } from "fs/promises";
20
12
 
21
13
  //#region rolldown:runtime
22
14
  var __defProp = Object.defineProperty;
@@ -390,276 +382,43 @@ const decodeAsset = (asset) => {
390
382
 
391
383
  //#endregion
392
384
  //#region src/server/ssr/renderer.ts
393
- const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "./.vite/manifest.json");
394
- const manifest$1 = Object.keys(manifest).length > 0 ? manifest : existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, "utf-8")) : {};
395
- const env$1 = new nunjucks.Environment(null, { autoescape: false });
396
- const htmlTemplate = `<!DOCTYPE html>
385
+ const manifest$1 = Object.keys(manifest).length > 0 ? manifest : {};
386
+ const renderer = ({ basePath = "", dev = false }) => {
387
+ const stylesPath = basePath === "/" ? styles_default : basePath + styles_default;
388
+ const clientPath = basePath === "/" ? client_default : basePath + client_default;
389
+ return `<!DOCTYPE html>
397
390
  <html lang="en" class="">
398
391
  <head>
399
392
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
400
393
  <link rel="preconnect" href="https://fonts.googleapis.com" />
401
394
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
402
395
  <link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap" rel="stylesheet" />
403
- <link rel="icon" href="{{ faviconIcoPath }}" sizes="any" />
404
- <link rel="icon" href="{{ faviconSvgPath }}" type="image/svg+xml" />
396
+ <link rel="icon" href="${basePath === "/" ? "/favicon.ico" : basePath + "/favicon.ico"}" sizes="any" />
397
+ <link rel="icon" href="${basePath === "/" ? (!dev ? "/assets" : "") + "/favicon.svg" : basePath + (!dev ? "/assets" : "") + "/favicon.svg"}" type="image/svg+xml" />
405
398
  <style>
406
- /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */
407
-
408
- /*
409
- Document
410
- ========
411
- */
412
-
413
- /**
414
- Use a better box model (opinionated).
415
- */
416
-
417
- *,
418
- ::before,
419
- ::after {
420
- box-sizing: border-box;
421
- }
422
-
423
- /**
424
- 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
425
- 2. Correct the line height in all browsers.
426
- 3. Prevent adjustments of font size after orientation changes in iOS.
427
- 4. Use a more readable tab size (opinionated).
428
- */
429
-
430
- html {
431
- font-family:
432
- system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
433
- 'Apple Color Emoji', 'Segoe UI Emoji'; /* 1 */
434
- line-height: 1.15; /* 2 */
435
- -webkit-text-size-adjust: 100%; /* 3 */
436
- tab-size: 4; /* 4 */
437
- }
438
-
439
- /*
440
- Sections
441
- ========
442
- */
443
-
444
- /**
445
- Remove the margin in all browsers.
446
- */
447
-
448
- body {
449
- margin: 0;
450
- }
451
-
452
- /*
453
- Text-level semantics
454
- ====================
455
- */
456
-
457
- /**
458
- Add the correct font weight in Chrome and Safari.
459
- */
460
-
461
- b,
462
- strong {
463
- font-weight: bolder;
464
- }
465
-
466
- /**
467
- 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
468
- 2. Correct the odd 'em' font sizing in all browsers.
469
- */
470
-
471
- code,
472
- kbd,
473
- samp,
474
- pre {
475
- font-family:
476
- ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace; /* 1 */
477
- font-size: 1em; /* 2 */
478
- }
479
-
480
- /**
481
- Add the correct font size in all browsers.
482
- */
483
-
484
- small {
485
- font-size: 80%;
486
- }
487
-
488
- /**
489
- Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
490
- */
491
-
492
- sub,
493
- sup {
494
- font-size: 75%;
495
- line-height: 0;
496
- position: relative;
497
- vertical-align: baseline;
498
- }
499
-
500
- sub {
501
- bottom: -0.25em;
502
- }
503
-
504
- sup {
505
- top: -0.5em;
506
- }
507
-
508
- /*
509
- Tabular data
510
- ============
511
- */
512
-
513
- /**
514
- Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016)
515
- */
516
-
517
- table {
518
- border-color: currentcolor;
519
- }
520
-
521
- /*
522
- Forms
523
- =====
524
- */
525
-
526
- /**
527
- 1. Change the font styles in all browsers.
528
- 2. Remove the margin in Firefox and Safari.
529
- */
530
-
531
- button,
532
- input,
533
- optgroup,
534
- select,
535
- textarea {
536
- font-family: inherit; /* 1 */
537
- font-size: 100%; /* 1 */
538
- line-height: 1.15; /* 1 */
539
- margin: 0; /* 2 */
540
- }
541
-
542
- /**
543
- Correct the inability to style clickable types in iOS and Safari.
544
- */
545
-
546
- button,
547
- [type='button'],
548
- [type='reset'],
549
- [type='submit'] {
550
- -webkit-appearance: button;
551
- }
552
-
553
- /**
554
- Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
555
- */
556
-
557
- legend {
558
- padding: 0;
559
- }
560
-
561
- /**
562
- Add the correct vertical alignment in Chrome and Firefox.
563
- */
564
-
565
- progress {
566
- vertical-align: baseline;
567
- }
568
-
569
- /**
570
- Correct the cursor style of increment and decrement buttons in Safari.
571
- */
572
-
573
- ::-webkit-inner-spin-button,
574
- ::-webkit-outer-spin-button {
575
- height: auto;
576
- }
577
-
578
- /**
579
- 1. Correct the odd appearance in Chrome and Safari.
580
- 2. Correct the outline style in Safari.
581
- */
582
-
583
- [type='search'] {
584
- -webkit-appearance: textfield; /* 1 */
585
- outline-offset: -2px; /* 2 */
586
- }
587
-
588
- /**
589
- Remove the inner padding in Chrome and Safari on macOS.
590
- */
591
-
592
- ::-webkit-search-decoration {
593
- -webkit-appearance: none;
594
- }
595
-
596
- /**
597
- 1. Correct the inability to style clickable types in iOS and Safari.
598
- 2. Change font properties to 'inherit' in Safari.
599
- */
600
-
601
- ::-webkit-file-upload-button {
602
- -webkit-appearance: button; /* 1 */
603
- font: inherit; /* 2 */
604
- }
605
-
606
- /*
607
- Interactive
608
- ===========
609
- */
610
-
611
- /*
612
- Add the correct display in Chrome and Safari.
613
- */
614
-
615
- summary {
616
- display: list-item;
617
- }
618
-
619
- .root {
620
- isolation: isolate;
621
- }
399
+ *,::before,::after{box-sizing:border-box}html{font-family:system-ui,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji';line-height:1.15;-webkit-text-size-adjust:100%;tab-size:4}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,'Liberation Mono',Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}table{border-color:currentcolor}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,[type='button'],[type='reset'],[type='submit']{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type='search']{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}.root{isolation:isolate}
622
400
  </style>
623
- <link href="{{ stylesPath }}" rel="stylesheet" />
624
- {% for cssFile in entryCSSFiles %}
625
- <link href="{{ cssFile }}" rel="stylesheet" />
626
- {% endfor %}
401
+ <link href="${stylesPath}" rel="stylesheet" />
402
+ ${(Object.keys(manifest$1)?.filter((key) => manifest$1[key].isEntry && manifest$1[key].css)?.flatMap((key) => manifest$1[key].css || []).map((cssFile) => basePath === "/" ? `/${cssFile}` : basePath + `/${cssFile}`).filter((cssFile) => cssFile !== stylesPath) || []).map((cssFile) => `<link href="${cssFile}" rel="stylesheet" />`).join("\n ")}
627
403
  <script>
628
404
  window.bootstrapData = {
629
- basePath: "{{ basePath }}"
405
+ basePath: "${basePath}"
630
406
  };
631
407
  <\/script>
632
- {% if dev %}
633
- <script type="module">
408
+ ${dev ? `<script type="module">
634
409
  import RefreshRuntime from "/@react-refresh";
635
410
  RefreshRuntime.injectIntoGlobalHook(window);
636
411
  window.$RefreshReg$ = () => {};
637
412
  window.$RefreshSig$ = () => (type) => type;
638
413
  window.__vite_plugin_react_preamble_installed__ = true;
639
- <\/script>
640
- {% endif %}
414
+ <\/script>` : ""}
641
415
  </head>
642
416
  <body>
643
417
  <noscript>You need to enable JavaScript to run this app.</noscript>
644
418
  <div id="root" class="root"></div>
645
- <script type="module" src="{{ clientPath }}"><\/script>
419
+ <script type="module" src="${clientPath}"><\/script>
646
420
  </body>
647
421
  </html>`;
648
- const renderer = ({ basePath = "", dev = false }) => {
649
- const stylesPath = basePath === "/" ? styles_default : basePath + styles_default;
650
- const clientPath = basePath === "/" ? client_default : basePath + client_default;
651
- const faviconIcoPath = basePath === "/" ? "/favicon.ico" : basePath + "/favicon.ico";
652
- const faviconSvgPath = basePath === "/" ? (!dev ? "/assets" : "") + "/favicon.svg" : basePath + (!dev ? "/assets" : "") + "/favicon.svg";
653
- const entryCSSFiles = Object.keys(manifest$1)?.filter((key) => manifest$1[key].isEntry && manifest$1[key].css)?.flatMap((key) => manifest$1[key].css || []).map((cssFile) => basePath === "/" ? `/${cssFile}` : basePath + `/${cssFile}`).filter((cssFile) => cssFile !== stylesPath) || [];
654
- return env$1.renderString(htmlTemplate, {
655
- basePath,
656
- dev,
657
- stylesPath,
658
- clientPath,
659
- faviconIcoPath,
660
- faviconSvgPath,
661
- entryCSSFiles
662
- });
663
422
  };
664
423
 
665
424
  //#endregion
@@ -15892,12 +15651,11 @@ const createMigrationMiddleware = (config$1) => {
15892
15651
 
15893
15652
  //#endregion
15894
15653
  //#region src/server/middlewares/static-assets.ts
15895
- const __dirname = dirname$1(fileURLToPath$1(import.meta.url));
15896
15654
  const hasEmbeddedAssets = Object.keys(embeddedAssets).length > 0;
15897
15655
  /**
15898
15656
  * Creates a middleware for serving static assets.
15899
15657
  * In production (single-file mode), serves from embedded base64 assets.
15900
- * In development, serves from the filesystem.
15658
+ * In development, serves from the filesystem via dynamic import().
15901
15659
  */
15902
15660
  const createStaticAssetMiddleware = () => {
15903
15661
  if (hasEmbeddedAssets) return async (c) => {
@@ -15910,16 +15668,39 @@ const createStaticAssetMiddleware = () => {
15910
15668
  "Cache-Control": "public, max-age=31536000, immutable"
15911
15669
  } });
15912
15670
  };
15913
- return serveStatic({
15914
- root: "./",
15915
- getContent: async (path) => {
15916
- try {
15917
- return await readFile(join$1(__dirname, "..", path));
15918
- } catch {
15919
- return null;
15920
- }
15671
+ let devServe = null;
15672
+ return async (c) => {
15673
+ if (!devServe) {
15674
+ const { fileURLToPath } = await import("node:url");
15675
+ const { dirname, join } = await import("node:path");
15676
+ const { readFile } = await import("node:fs/promises");
15677
+ const currentDir = dirname(fileURLToPath(import.meta.url));
15678
+ devServe = async (ctx) => {
15679
+ const path = ctx.req.path;
15680
+ try {
15681
+ const file$1 = await readFile(join(currentDir, "..", path));
15682
+ const ext = path.split(".").pop() || "";
15683
+ const mimeTypes = {
15684
+ js: "application/javascript",
15685
+ mjs: "application/javascript",
15686
+ css: "text/css",
15687
+ svg: "image/svg+xml",
15688
+ png: "image/png",
15689
+ jpg: "image/jpeg",
15690
+ ico: "image/x-icon",
15691
+ woff: "font/woff",
15692
+ woff2: "font/woff2"
15693
+ };
15694
+ return new Response(file$1, { headers: { "Content-Type": mimeTypes[ext] || "application/octet-stream" } });
15695
+ } catch {
15696
+ return;
15697
+ }
15698
+ };
15921
15699
  }
15922
- });
15700
+ const response = await devServe(c);
15701
+ if (response) return response;
15702
+ return c.notFound();
15703
+ };
15923
15704
  };
15924
15705
 
15925
15706
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmops/app",
3
- "version": "1.0.0-beta.11",
3
+ "version": "1.0.0-beta.13",
4
4
  "description": "LLMOps application with server and client",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -69,16 +69,15 @@
69
69
  "lexical": "^0.39.0",
70
70
  "lucide-react": "^0.556.0",
71
71
  "motion": "^12.23.25",
72
- "nunjucks": "^3.2.4",
73
72
  "openai": "^6.10.0",
74
73
  "protobufjs": "^8.0.0",
75
74
  "react-aria-components": "^1.13.0",
76
75
  "react-hook-form": "^7.68.0",
77
76
  "recharts": "^3.6.0",
78
77
  "uuid": "^13.0.0",
79
- "@llmops/core": "^1.0.0-beta.11",
80
- "@llmops/sdk": "^1.0.0-beta.11",
81
- "@llmops/gateway": "^1.0.0-beta.11"
78
+ "@llmops/core": "^1.0.0-beta.13",
79
+ "@llmops/gateway": "^1.0.0-beta.13",
80
+ "@llmops/sdk": "^1.0.0-beta.13"
82
81
  },
83
82
  "peerDependencies": {
84
83
  "react": "^19.2.1",
@@ -89,7 +88,6 @@
89
88
  "@hono/vite-build": "^1.8.0",
90
89
  "@hono/vite-dev-server": "^0.23.0",
91
90
  "@tanstack/router-plugin": "^1.139.14",
92
- "@types/nunjucks": "^3.2.6",
93
91
  "@types/pg": "^8.15.6",
94
92
  "@types/react": "^19.2.7",
95
93
  "@types/react-dom": "^19.2.3",