@hir4ta/mneme 0.23.2 → 0.24.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/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // dashboard/server/index.ts
2
- import fs16 from "node:fs";
3
- import path15 from "node:path";
2
+ import fs17 from "node:fs";
3
+ import path16 from "node:path";
4
4
 
5
5
  // node_modules/@hono/node-server/dist/index.mjs
6
6
  import { createServer as createServerHTTP } from "http";
@@ -666,10 +666,10 @@ var createStreamBody = (stream) => {
666
666
  });
667
667
  return body;
668
668
  };
669
- var getStats = (path16) => {
669
+ var getStats = (path17) => {
670
670
  let stats;
671
671
  try {
672
- stats = statSync(path16);
672
+ stats = statSync(path17);
673
673
  } catch {
674
674
  }
675
675
  return stats;
@@ -698,21 +698,21 @@ var serveStatic = (options = { root: "" }) => {
698
698
  return next();
699
699
  }
700
700
  }
701
- let path16 = join(
701
+ let path17 = join(
702
702
  root,
703
703
  !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c) : filename
704
704
  );
705
- let stats = getStats(path16);
705
+ let stats = getStats(path17);
706
706
  if (stats && stats.isDirectory()) {
707
707
  const indexFile = options.index ?? "index.html";
708
- path16 = join(path16, indexFile);
709
- stats = getStats(path16);
708
+ path17 = join(path17, indexFile);
709
+ stats = getStats(path17);
710
710
  }
711
711
  if (!stats) {
712
- await options.onNotFound?.(path16, c);
712
+ await options.onNotFound?.(path17, c);
713
713
  return next();
714
714
  }
715
- const mimeType = getMimeType(path16);
715
+ const mimeType = getMimeType(path17);
716
716
  c.header("Content-Type", mimeType || "application/octet-stream");
717
717
  if (options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) {
718
718
  const acceptEncodingSet = new Set(
@@ -722,12 +722,12 @@ var serveStatic = (options = { root: "" }) => {
722
722
  if (!acceptEncodingSet.has(encoding)) {
723
723
  continue;
724
724
  }
725
- const precompressedStats = getStats(path16 + ENCODINGS[encoding]);
725
+ const precompressedStats = getStats(path17 + ENCODINGS[encoding]);
726
726
  if (precompressedStats) {
727
727
  c.header("Content-Encoding", encoding);
728
728
  c.header("Vary", "Accept-Encoding", { append: true });
729
729
  stats = precompressedStats;
730
- path16 = path16 + ENCODINGS[encoding];
730
+ path17 = path17 + ENCODINGS[encoding];
731
731
  break;
732
732
  }
733
733
  }
@@ -741,7 +741,7 @@ var serveStatic = (options = { root: "" }) => {
741
741
  result = c.body(null);
742
742
  } else if (!range) {
743
743
  c.header("Content-Length", size.toString());
744
- result = c.body(createStreamBody(createReadStream(path16)), 200);
744
+ result = c.body(createStreamBody(createReadStream(path17)), 200);
745
745
  } else {
746
746
  c.header("Accept-Ranges", "bytes");
747
747
  c.header("Date", stats.birthtime.toUTCString());
@@ -752,12 +752,12 @@ var serveStatic = (options = { root: "" }) => {
752
752
  end = size - 1;
753
753
  }
754
754
  const chunksize = end - start + 1;
755
- const stream = createReadStream(path16, { start, end });
755
+ const stream = createReadStream(path17, { start, end });
756
756
  c.header("Content-Length", chunksize.toString());
757
757
  c.header("Content-Range", `bytes ${start}-${end}/${stats.size}`);
758
758
  result = c.body(createStreamBody(stream), 206);
759
759
  }
760
- await options.onFound?.(path16, c);
760
+ await options.onFound?.(path17, c);
761
761
  return result;
762
762
  };
763
763
  };
@@ -879,26 +879,26 @@ var handleParsingNestedValues = (form, key, value) => {
879
879
  };
880
880
 
881
881
  // node_modules/hono/dist/utils/url.js
882
- var splitPath = (path16) => {
883
- const paths = path16.split("/");
882
+ var splitPath = (path17) => {
883
+ const paths = path17.split("/");
884
884
  if (paths[0] === "") {
885
885
  paths.shift();
886
886
  }
887
887
  return paths;
888
888
  };
889
889
  var splitRoutingPath = (routePath) => {
890
- const { groups, path: path16 } = extractGroupsFromPath(routePath);
891
- const paths = splitPath(path16);
890
+ const { groups, path: path17 } = extractGroupsFromPath(routePath);
891
+ const paths = splitPath(path17);
892
892
  return replaceGroupMarks(paths, groups);
893
893
  };
894
- var extractGroupsFromPath = (path16) => {
894
+ var extractGroupsFromPath = (path17) => {
895
895
  const groups = [];
896
- path16 = path16.replace(/\{[^}]+\}/g, (match2, index) => {
896
+ path17 = path17.replace(/\{[^}]+\}/g, (match2, index) => {
897
897
  const mark = `@${index}`;
898
898
  groups.push([mark, match2]);
899
899
  return mark;
900
900
  });
901
- return { groups, path: path16 };
901
+ return { groups, path: path17 };
902
902
  };
903
903
  var replaceGroupMarks = (paths, groups) => {
904
904
  for (let i = groups.length - 1; i >= 0; i--) {
@@ -955,8 +955,8 @@ var getPath = (request) => {
955
955
  const queryIndex = url.indexOf("?", i);
956
956
  const hashIndex = url.indexOf("#", i);
957
957
  const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
958
- const path16 = url.slice(start, end);
959
- return tryDecodeURI(path16.includes("%25") ? path16.replace(/%25/g, "%2525") : path16);
958
+ const path17 = url.slice(start, end);
959
+ return tryDecodeURI(path17.includes("%25") ? path17.replace(/%25/g, "%2525") : path17);
960
960
  } else if (charCode === 63 || charCode === 35) {
961
961
  break;
962
962
  }
@@ -973,11 +973,11 @@ var mergePath = (base, sub, ...rest) => {
973
973
  }
974
974
  return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
975
975
  };
976
- var checkOptionalParameter = (path16) => {
977
- if (path16.charCodeAt(path16.length - 1) !== 63 || !path16.includes(":")) {
976
+ var checkOptionalParameter = (path17) => {
977
+ if (path17.charCodeAt(path17.length - 1) !== 63 || !path17.includes(":")) {
978
978
  return null;
979
979
  }
980
- const segments = path16.split("/");
980
+ const segments = path17.split("/");
981
981
  const results = [];
982
982
  let basePath = "";
983
983
  segments.forEach((segment) => {
@@ -1118,9 +1118,9 @@ var HonoRequest = class {
1118
1118
  */
1119
1119
  path;
1120
1120
  bodyCache = {};
1121
- constructor(request, path16 = "/", matchResult = [[]]) {
1121
+ constructor(request, path17 = "/", matchResult = [[]]) {
1122
1122
  this.raw = request;
1123
- this.path = path16;
1123
+ this.path = path17;
1124
1124
  this.#matchResult = matchResult;
1125
1125
  this.#validatedData = {};
1126
1126
  }
@@ -1856,8 +1856,8 @@ var Hono = class _Hono {
1856
1856
  return this;
1857
1857
  };
1858
1858
  });
1859
- this.on = (method, path16, ...handlers) => {
1860
- for (const p of [path16].flat()) {
1859
+ this.on = (method, path17, ...handlers) => {
1860
+ for (const p of [path17].flat()) {
1861
1861
  this.#path = p;
1862
1862
  for (const m of [method].flat()) {
1863
1863
  handlers.map((handler) => {
@@ -1914,8 +1914,8 @@ var Hono = class _Hono {
1914
1914
  * app.route("/api", app2) // GET /api/user
1915
1915
  * ```
1916
1916
  */
1917
- route(path16, app2) {
1918
- const subApp = this.basePath(path16);
1917
+ route(path17, app2) {
1918
+ const subApp = this.basePath(path17);
1919
1919
  app2.routes.map((r) => {
1920
1920
  let handler;
1921
1921
  if (app2.errorHandler === errorHandler) {
@@ -1941,9 +1941,9 @@ var Hono = class _Hono {
1941
1941
  * const api = new Hono().basePath('/api')
1942
1942
  * ```
1943
1943
  */
1944
- basePath(path16) {
1944
+ basePath(path17) {
1945
1945
  const subApp = this.#clone();
1946
- subApp._basePath = mergePath(this._basePath, path16);
1946
+ subApp._basePath = mergePath(this._basePath, path17);
1947
1947
  return subApp;
1948
1948
  }
1949
1949
  /**
@@ -2017,7 +2017,7 @@ var Hono = class _Hono {
2017
2017
  * })
2018
2018
  * ```
2019
2019
  */
2020
- mount(path16, applicationHandler, options) {
2020
+ mount(path17, applicationHandler, options) {
2021
2021
  let replaceRequest;
2022
2022
  let optionHandler;
2023
2023
  if (options) {
@@ -2044,7 +2044,7 @@ var Hono = class _Hono {
2044
2044
  return [c.env, executionContext];
2045
2045
  };
2046
2046
  replaceRequest ||= (() => {
2047
- const mergedPath = mergePath(this._basePath, path16);
2047
+ const mergedPath = mergePath(this._basePath, path17);
2048
2048
  const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
2049
2049
  return (request) => {
2050
2050
  const url = new URL(request.url);
@@ -2059,14 +2059,14 @@ var Hono = class _Hono {
2059
2059
  }
2060
2060
  await next();
2061
2061
  };
2062
- this.#addRoute(METHOD_NAME_ALL, mergePath(path16, "*"), handler);
2062
+ this.#addRoute(METHOD_NAME_ALL, mergePath(path17, "*"), handler);
2063
2063
  return this;
2064
2064
  }
2065
- #addRoute(method, path16, handler) {
2065
+ #addRoute(method, path17, handler) {
2066
2066
  method = method.toUpperCase();
2067
- path16 = mergePath(this._basePath, path16);
2068
- const r = { basePath: this._basePath, path: path16, method, handler };
2069
- this.router.add(method, path16, [handler, r]);
2067
+ path17 = mergePath(this._basePath, path17);
2068
+ const r = { basePath: this._basePath, path: path17, method, handler };
2069
+ this.router.add(method, path17, [handler, r]);
2070
2070
  this.routes.push(r);
2071
2071
  }
2072
2072
  #handleError(err, c) {
@@ -2079,10 +2079,10 @@ var Hono = class _Hono {
2079
2079
  if (method === "HEAD") {
2080
2080
  return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
2081
2081
  }
2082
- const path16 = this.getPath(request, { env });
2083
- const matchResult = this.router.match(method, path16);
2082
+ const path17 = this.getPath(request, { env });
2083
+ const matchResult = this.router.match(method, path17);
2084
2084
  const c = new Context(request, {
2085
- path: path16,
2085
+ path: path17,
2086
2086
  matchResult,
2087
2087
  env,
2088
2088
  executionCtx,
@@ -2182,7 +2182,7 @@ var Hono = class _Hono {
2182
2182
 
2183
2183
  // node_modules/hono/dist/router/reg-exp-router/matcher.js
2184
2184
  var emptyParam = [];
2185
- function match(method, path16) {
2185
+ function match(method, path17) {
2186
2186
  const matchers = this.buildAllMatchers();
2187
2187
  const match2 = ((method2, path22) => {
2188
2188
  const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
@@ -2198,7 +2198,7 @@ function match(method, path16) {
2198
2198
  return [matcher[1][index], match3];
2199
2199
  });
2200
2200
  this.match = match2;
2201
- return match2(method, path16);
2201
+ return match2(method, path17);
2202
2202
  }
2203
2203
 
2204
2204
  // node_modules/hono/dist/router/reg-exp-router/node.js
@@ -2313,12 +2313,12 @@ var Node = class _Node {
2313
2313
  var Trie = class {
2314
2314
  #context = { varIndex: 0 };
2315
2315
  #root = new Node();
2316
- insert(path16, index, pathErrorCheckOnly) {
2316
+ insert(path17, index, pathErrorCheckOnly) {
2317
2317
  const paramAssoc = [];
2318
2318
  const groups = [];
2319
2319
  for (let i = 0; ; ) {
2320
2320
  let replaced = false;
2321
- path16 = path16.replace(/\{[^}]+\}/g, (m) => {
2321
+ path17 = path17.replace(/\{[^}]+\}/g, (m) => {
2322
2322
  const mark = `@\\${i}`;
2323
2323
  groups[i] = [mark, m];
2324
2324
  i++;
@@ -2329,7 +2329,7 @@ var Trie = class {
2329
2329
  break;
2330
2330
  }
2331
2331
  }
2332
- const tokens = path16.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
2332
+ const tokens = path17.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
2333
2333
  for (let i = groups.length - 1; i >= 0; i--) {
2334
2334
  const [mark] = groups[i];
2335
2335
  for (let j = tokens.length - 1; j >= 0; j--) {
@@ -2368,9 +2368,9 @@ var Trie = class {
2368
2368
  // node_modules/hono/dist/router/reg-exp-router/router.js
2369
2369
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
2370
2370
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
2371
- function buildWildcardRegExp(path16) {
2372
- return wildcardRegExpCache[path16] ??= new RegExp(
2373
- path16 === "*" ? "" : `^${path16.replace(
2371
+ function buildWildcardRegExp(path17) {
2372
+ return wildcardRegExpCache[path17] ??= new RegExp(
2373
+ path17 === "*" ? "" : `^${path17.replace(
2374
2374
  /\/\*$|([.\\+*[^\]$()])/g,
2375
2375
  (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
2376
2376
  )}$`
@@ -2392,17 +2392,17 @@ function buildMatcherFromPreprocessedRoutes(routes) {
2392
2392
  );
2393
2393
  const staticMap = /* @__PURE__ */ Object.create(null);
2394
2394
  for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
2395
- const [pathErrorCheckOnly, path16, handlers] = routesWithStaticPathFlag[i];
2395
+ const [pathErrorCheckOnly, path17, handlers] = routesWithStaticPathFlag[i];
2396
2396
  if (pathErrorCheckOnly) {
2397
- staticMap[path16] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
2397
+ staticMap[path17] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
2398
2398
  } else {
2399
2399
  j++;
2400
2400
  }
2401
2401
  let paramAssoc;
2402
2402
  try {
2403
- paramAssoc = trie.insert(path16, j, pathErrorCheckOnly);
2403
+ paramAssoc = trie.insert(path17, j, pathErrorCheckOnly);
2404
2404
  } catch (e) {
2405
- throw e === PATH_ERROR ? new UnsupportedPathError(path16) : e;
2405
+ throw e === PATH_ERROR ? new UnsupportedPathError(path17) : e;
2406
2406
  }
2407
2407
  if (pathErrorCheckOnly) {
2408
2408
  continue;
@@ -2436,12 +2436,12 @@ function buildMatcherFromPreprocessedRoutes(routes) {
2436
2436
  }
2437
2437
  return [regexp, handlerMap, staticMap];
2438
2438
  }
2439
- function findMiddleware(middleware, path16) {
2439
+ function findMiddleware(middleware, path17) {
2440
2440
  if (!middleware) {
2441
2441
  return void 0;
2442
2442
  }
2443
2443
  for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
2444
- if (buildWildcardRegExp(k).test(path16)) {
2444
+ if (buildWildcardRegExp(k).test(path17)) {
2445
2445
  return [...middleware[k]];
2446
2446
  }
2447
2447
  }
@@ -2455,7 +2455,7 @@ var RegExpRouter = class {
2455
2455
  this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
2456
2456
  this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
2457
2457
  }
2458
- add(method, path16, handler) {
2458
+ add(method, path17, handler) {
2459
2459
  const middleware = this.#middleware;
2460
2460
  const routes = this.#routes;
2461
2461
  if (!middleware || !routes) {
@@ -2470,18 +2470,18 @@ var RegExpRouter = class {
2470
2470
  });
2471
2471
  });
2472
2472
  }
2473
- if (path16 === "/*") {
2474
- path16 = "*";
2473
+ if (path17 === "/*") {
2474
+ path17 = "*";
2475
2475
  }
2476
- const paramCount = (path16.match(/\/:/g) || []).length;
2477
- if (/\*$/.test(path16)) {
2478
- const re = buildWildcardRegExp(path16);
2476
+ const paramCount = (path17.match(/\/:/g) || []).length;
2477
+ if (/\*$/.test(path17)) {
2478
+ const re = buildWildcardRegExp(path17);
2479
2479
  if (method === METHOD_NAME_ALL) {
2480
2480
  Object.keys(middleware).forEach((m) => {
2481
- middleware[m][path16] ||= findMiddleware(middleware[m], path16) || findMiddleware(middleware[METHOD_NAME_ALL], path16) || [];
2481
+ middleware[m][path17] ||= findMiddleware(middleware[m], path17) || findMiddleware(middleware[METHOD_NAME_ALL], path17) || [];
2482
2482
  });
2483
2483
  } else {
2484
- middleware[method][path16] ||= findMiddleware(middleware[method], path16) || findMiddleware(middleware[METHOD_NAME_ALL], path16) || [];
2484
+ middleware[method][path17] ||= findMiddleware(middleware[method], path17) || findMiddleware(middleware[METHOD_NAME_ALL], path17) || [];
2485
2485
  }
2486
2486
  Object.keys(middleware).forEach((m) => {
2487
2487
  if (method === METHOD_NAME_ALL || method === m) {
@@ -2499,7 +2499,7 @@ var RegExpRouter = class {
2499
2499
  });
2500
2500
  return;
2501
2501
  }
2502
- const paths = checkOptionalParameter(path16) || [path16];
2502
+ const paths = checkOptionalParameter(path17) || [path17];
2503
2503
  for (let i = 0, len = paths.length; i < len; i++) {
2504
2504
  const path22 = paths[i];
2505
2505
  Object.keys(routes).forEach((m) => {
@@ -2526,13 +2526,13 @@ var RegExpRouter = class {
2526
2526
  const routes = [];
2527
2527
  let hasOwnRoute = method === METHOD_NAME_ALL;
2528
2528
  [this.#middleware, this.#routes].forEach((r) => {
2529
- const ownRoute = r[method] ? Object.keys(r[method]).map((path16) => [path16, r[method][path16]]) : [];
2529
+ const ownRoute = r[method] ? Object.keys(r[method]).map((path17) => [path17, r[method][path17]]) : [];
2530
2530
  if (ownRoute.length !== 0) {
2531
2531
  hasOwnRoute ||= true;
2532
2532
  routes.push(...ownRoute);
2533
2533
  } else if (method !== METHOD_NAME_ALL) {
2534
2534
  routes.push(
2535
- ...Object.keys(r[METHOD_NAME_ALL]).map((path16) => [path16, r[METHOD_NAME_ALL][path16]])
2535
+ ...Object.keys(r[METHOD_NAME_ALL]).map((path17) => [path17, r[METHOD_NAME_ALL][path17]])
2536
2536
  );
2537
2537
  }
2538
2538
  });
@@ -2552,13 +2552,13 @@ var SmartRouter = class {
2552
2552
  constructor(init) {
2553
2553
  this.#routers = init.routers;
2554
2554
  }
2555
- add(method, path16, handler) {
2555
+ add(method, path17, handler) {
2556
2556
  if (!this.#routes) {
2557
2557
  throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
2558
2558
  }
2559
- this.#routes.push([method, path16, handler]);
2559
+ this.#routes.push([method, path17, handler]);
2560
2560
  }
2561
- match(method, path16) {
2561
+ match(method, path17) {
2562
2562
  if (!this.#routes) {
2563
2563
  throw new Error("Fatal error");
2564
2564
  }
@@ -2573,7 +2573,7 @@ var SmartRouter = class {
2573
2573
  for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
2574
2574
  router.add(...routes[i2]);
2575
2575
  }
2576
- res = router.match(method, path16);
2576
+ res = router.match(method, path17);
2577
2577
  } catch (e) {
2578
2578
  if (e instanceof UnsupportedPathError) {
2579
2579
  continue;
@@ -2617,10 +2617,10 @@ var Node2 = class _Node2 {
2617
2617
  }
2618
2618
  this.#patterns = [];
2619
2619
  }
2620
- insert(method, path16, handler) {
2620
+ insert(method, path17, handler) {
2621
2621
  this.#order = ++this.#order;
2622
2622
  let curNode = this;
2623
- const parts = splitRoutingPath(path16);
2623
+ const parts = splitRoutingPath(path17);
2624
2624
  const possibleKeys = [];
2625
2625
  for (let i = 0, len = parts.length; i < len; i++) {
2626
2626
  const p = parts[i];
@@ -2671,12 +2671,12 @@ var Node2 = class _Node2 {
2671
2671
  }
2672
2672
  return handlerSets;
2673
2673
  }
2674
- search(method, path16) {
2674
+ search(method, path17) {
2675
2675
  const handlerSets = [];
2676
2676
  this.#params = emptyParams;
2677
2677
  const curNode = this;
2678
2678
  let curNodes = [curNode];
2679
- const parts = splitPath(path16);
2679
+ const parts = splitPath(path17);
2680
2680
  const curNodesQueue = [];
2681
2681
  for (let i = 0, len = parts.length; i < len; i++) {
2682
2682
  const part = parts[i];
@@ -2764,18 +2764,18 @@ var TrieRouter = class {
2764
2764
  constructor() {
2765
2765
  this.#node = new Node2();
2766
2766
  }
2767
- add(method, path16, handler) {
2768
- const results = checkOptionalParameter(path16);
2767
+ add(method, path17, handler) {
2768
+ const results = checkOptionalParameter(path17);
2769
2769
  if (results) {
2770
2770
  for (let i = 0, len = results.length; i < len; i++) {
2771
2771
  this.#node.insert(method, results[i], handler);
2772
2772
  }
2773
2773
  return;
2774
2774
  }
2775
- this.#node.insert(method, path16, handler);
2775
+ this.#node.insert(method, path17, handler);
2776
2776
  }
2777
- match(method, path16) {
2778
- return this.#node.search(method, path16);
2777
+ match(method, path17) {
2778
+ return this.#node.search(method, path17);
2779
2779
  }
2780
2780
  };
2781
2781
 
@@ -3460,7 +3460,8 @@ function collectDevRules() {
3460
3460
  updatedAt: entry.updatedAt ? String(entry.updatedAt) : void 0,
3461
3461
  context: entry.context ? String(entry.context) : void 0,
3462
3462
  reasoning: entry.reasoning ? String(entry.reasoning) : void 0,
3463
- alternatives: alts
3463
+ alternatives: alts,
3464
+ relatedSessions: Array.isArray(entry.relatedSessions) ? entry.relatedSessions.map((s) => String(s)) : void 0
3464
3465
  });
3465
3466
  }
3466
3467
  }
@@ -3489,7 +3490,8 @@ function collectDevRules() {
3489
3490
  updatedAt: entry.updatedAt ? String(entry.updatedAt) : void 0,
3490
3491
  context: entry.context ? String(entry.context) : void 0,
3491
3492
  patternType: entry.type ? String(entry.type) : void 0,
3492
- pattern: entry.pattern ? String(entry.pattern) : void 0
3493
+ pattern: entry.pattern ? String(entry.pattern) : void 0,
3494
+ sourceId: entry.sourceId ? String(entry.sourceId) : void 0
3493
3495
  });
3494
3496
  }
3495
3497
  }
@@ -3501,6 +3503,12 @@ function collectDevRules() {
3501
3503
  for (const entry of doc.items) {
3502
3504
  const id = String(entry.id || "");
3503
3505
  if (!id) continue;
3506
+ const sourceRef = entry.sourceRef && typeof entry.sourceRef === "object" && !Array.isArray(entry.sourceRef) ? {
3507
+ type: String(
3508
+ entry.sourceRef.type || ""
3509
+ ),
3510
+ id: String(entry.sourceRef.id || "")
3511
+ } : void 0;
3504
3512
  items.push({
3505
3513
  id,
3506
3514
  type: "rule",
@@ -3513,7 +3521,10 @@ function collectDevRules() {
3513
3521
  createdAt: String(entry.createdAt || doc.createdAt || ""),
3514
3522
  updatedAt: entry.updatedAt ? String(entry.updatedAt) : void 0,
3515
3523
  rationale: entry.rationale ? String(entry.rationale) : void 0,
3516
- category: entry.category ? String(entry.category) : void 0
3524
+ category: entry.category ? String(entry.category) : void 0,
3525
+ sourceRef,
3526
+ appliedCount: typeof entry.appliedCount === "number" ? entry.appliedCount : void 0,
3527
+ acceptedCount: typeof entry.acceptedCount === "number" ? entry.acceptedCount : void 0
3517
3528
  });
3518
3529
  }
3519
3530
  }
@@ -3689,10 +3700,13 @@ analyticsGraph.get("/knowledge-graph", async (c) => {
3689
3700
  createdAt: item.createdAt,
3690
3701
  unitSubtype: item.type || null,
3691
3702
  sourceId: item.sourceFile || null,
3692
- appliedCount: null,
3693
- acceptedCount: null,
3703
+ appliedCount: item.appliedCount ?? null,
3704
+ acceptedCount: item.acceptedCount ?? null,
3694
3705
  branch: null,
3695
- resumedFrom: null
3706
+ resumedFrom: null,
3707
+ relatedSessions: item.relatedSessions || null,
3708
+ sourceRef: item.sourceRef || null,
3709
+ patternSourceId: item.sourceId || null
3696
3710
  }))
3697
3711
  ];
3698
3712
  const tagToNodes = /* @__PURE__ */ new Map();
@@ -3744,7 +3758,56 @@ analyticsGraph.get("/knowledge-graph", async (c) => {
3744
3758
  }
3745
3759
  }
3746
3760
  }
3747
- const edges = [...tagEdges, ...resumedEdges];
3761
+ const relationEdges = [];
3762
+ for (const node of nodes) {
3763
+ if (node.entityType === "rule" && node.relatedSessions) {
3764
+ const related = node.relatedSessions;
3765
+ for (const sessionId of related) {
3766
+ const targetId = `session:${sessionId}`;
3767
+ if (nodeIdSet.has(targetId)) {
3768
+ relationEdges.push({
3769
+ source: node.id,
3770
+ target: targetId,
3771
+ weight: 1,
3772
+ sharedTags: [],
3773
+ edgeType: "relatedSession",
3774
+ directed: true
3775
+ });
3776
+ }
3777
+ }
3778
+ }
3779
+ if (node.entityType === "rule" && node.sourceRef) {
3780
+ const ref = node.sourceRef;
3781
+ if (ref.type && ref.id) {
3782
+ const targetId = `rule:${ref.type}:${ref.id}`;
3783
+ if (nodeIdSet.has(targetId)) {
3784
+ relationEdges.push({
3785
+ source: node.id,
3786
+ target: targetId,
3787
+ weight: 1,
3788
+ sharedTags: [],
3789
+ edgeType: "sourceRef",
3790
+ directed: true
3791
+ });
3792
+ }
3793
+ }
3794
+ }
3795
+ if (node.entityType === "rule" && node.patternSourceId) {
3796
+ const sessionId = node.patternSourceId;
3797
+ const targetId = `session:${sessionId}`;
3798
+ if (nodeIdSet.has(targetId)) {
3799
+ relationEdges.push({
3800
+ source: node.id,
3801
+ target: targetId,
3802
+ weight: 1,
3803
+ sharedTags: [],
3804
+ edgeType: "sessionRef",
3805
+ directed: true
3806
+ });
3807
+ }
3808
+ }
3809
+ }
3810
+ const edges = [...tagEdges, ...resumedEdges, ...relationEdges];
3748
3811
  return c.json({ nodes, edges });
3749
3812
  } catch (error) {
3750
3813
  console.error("Failed to build knowledge graph:", error);
@@ -4427,7 +4490,7 @@ misc.get("/project", (c) => {
4427
4490
  }
4428
4491
  } catch {
4429
4492
  }
4430
- const version = "0.23.2";
4493
+ const version = "0.24.0";
4431
4494
  return c.json({
4432
4495
  name: projectName,
4433
4496
  path: projectRoot,
@@ -5300,6 +5363,178 @@ sessions.get("/:id/markdown", async (c) => {
5300
5363
  });
5301
5364
  var sessions_default = sessions;
5302
5365
 
5366
+ // dashboard/server/routes/team.ts
5367
+ import fs16 from "node:fs";
5368
+ import path15 from "node:path";
5369
+ var team = new Hono2();
5370
+ function collectTeamData(mnemeDir2) {
5371
+ const sessionsIndex = readAllSessionIndexes(mnemeDir2);
5372
+ const decisionsIndex = readAllDecisionIndexes(mnemeDir2);
5373
+ const memberMap = /* @__PURE__ */ new Map();
5374
+ function ensureMember(name) {
5375
+ if (!memberMap.has(name)) {
5376
+ memberMap.set(name, {
5377
+ sessions: 0,
5378
+ decisions: 0,
5379
+ patterns: 0,
5380
+ rules: 0,
5381
+ lastActive: ""
5382
+ });
5383
+ }
5384
+ return memberMap.get(name);
5385
+ }
5386
+ function updateLastActive(member, date) {
5387
+ if (date && date > member.lastActive) {
5388
+ member.lastActive = date;
5389
+ }
5390
+ }
5391
+ for (const item of sessionsIndex.items) {
5392
+ if (!item.user) continue;
5393
+ const member = ensureMember(item.user);
5394
+ member.sessions++;
5395
+ updateLastActive(member, item.createdAt);
5396
+ }
5397
+ for (const item of decisionsIndex.items) {
5398
+ if (!item.user) continue;
5399
+ const member = ensureMember(item.user);
5400
+ member.decisions++;
5401
+ updateLastActive(member, item.createdAt);
5402
+ }
5403
+ const patDir = patternsDir();
5404
+ let totalPatterns = 0;
5405
+ if (fs16.existsSync(patDir)) {
5406
+ const patternFiles = listJsonFiles(patDir);
5407
+ for (const filePath of patternFiles) {
5408
+ const doc = safeParseJsonFile(filePath);
5409
+ const entries = doc?.items || doc?.patterns || [];
5410
+ totalPatterns += entries.length;
5411
+ }
5412
+ }
5413
+ if (totalPatterns > 0 && memberMap.size > 0) {
5414
+ let primaryMember = memberMap.values().next().value;
5415
+ for (const stats of memberMap.values()) {
5416
+ if (stats.sessions > (primaryMember?.sessions ?? 0)) {
5417
+ primaryMember = stats;
5418
+ }
5419
+ }
5420
+ if (primaryMember) {
5421
+ primaryMember.patterns = totalPatterns;
5422
+ }
5423
+ }
5424
+ return { memberMap, sessionsIndex, decisionsIndex };
5425
+ }
5426
+ team.get("/overview", async (c) => {
5427
+ try {
5428
+ const mnemeDir2 = getMnemeDir();
5429
+ const { memberMap } = collectTeamData(mnemeDir2);
5430
+ const members = Array.from(memberMap.entries()).map(([name, stats]) => ({ name, ...stats })).sort((a, b) => b.sessions - a.sessions);
5431
+ return c.json({ members });
5432
+ } catch (error) {
5433
+ console.error("Failed to get team overview:", error);
5434
+ return c.json({ error: "Failed to get team overview" }, 500);
5435
+ }
5436
+ });
5437
+ team.get("/activity", async (c) => {
5438
+ try {
5439
+ const mnemeDir2 = getMnemeDir();
5440
+ const daysParam = Number.parseInt(c.req.query("days") || "30", 10);
5441
+ const safeDays = Math.min(Math.max(1, daysParam), 365);
5442
+ const { sessionsIndex, decisionsIndex } = collectTeamData(mnemeDir2);
5443
+ const now = /* @__PURE__ */ new Date();
5444
+ const startDate = new Date(
5445
+ now.getTime() - (safeDays - 1) * 24 * 60 * 60 * 1e3
5446
+ );
5447
+ const activityByDate = {};
5448
+ for (let i = 0; i < safeDays; i++) {
5449
+ const d = new Date(startDate.getTime() + i * 24 * 60 * 60 * 1e3);
5450
+ const dateKey = d.toISOString().split("T")[0];
5451
+ activityByDate[dateKey] = {};
5452
+ }
5453
+ for (const session of sessionsIndex.items) {
5454
+ if (!session.user) continue;
5455
+ const dateKey = session.createdAt.split("T")[0];
5456
+ if (activityByDate[dateKey]) {
5457
+ if (!activityByDate[dateKey][session.user]) {
5458
+ activityByDate[dateKey][session.user] = {
5459
+ sessions: 0,
5460
+ decisions: 0
5461
+ };
5462
+ }
5463
+ activityByDate[dateKey][session.user].sessions++;
5464
+ }
5465
+ }
5466
+ for (const decision of decisionsIndex.items) {
5467
+ if (!decision.user) continue;
5468
+ const dateKey = decision.createdAt.split("T")[0];
5469
+ if (activityByDate[dateKey]) {
5470
+ if (!activityByDate[dateKey][decision.user]) {
5471
+ activityByDate[dateKey][decision.user] = {
5472
+ sessions: 0,
5473
+ decisions: 0
5474
+ };
5475
+ }
5476
+ activityByDate[dateKey][decision.user].decisions++;
5477
+ }
5478
+ }
5479
+ const activity = Object.entries(activityByDate).map(([date, members]) => ({ date, members })).sort((a, b) => a.date.localeCompare(b.date));
5480
+ return c.json({ activity, days: safeDays });
5481
+ } catch (error) {
5482
+ console.error("Failed to get team activity:", error);
5483
+ return c.json({ error: "Failed to get team activity" }, 500);
5484
+ }
5485
+ });
5486
+ team.get("/quality", async (c) => {
5487
+ try {
5488
+ const rDir = rulesDir();
5489
+ let totalRules = 0;
5490
+ let approvedRules = 0;
5491
+ const topRules = [];
5492
+ if (fs16.existsSync(rDir)) {
5493
+ for (const ruleFile of ["dev-rules", "review-guidelines"]) {
5494
+ const filePath = path15.join(rDir, `${ruleFile}.json`);
5495
+ const doc = safeParseJsonFile(filePath);
5496
+ if (!doc?.items) continue;
5497
+ for (const item of doc.items) {
5498
+ totalRules++;
5499
+ if (item.status === "approved") approvedRules++;
5500
+ const applied = typeof item.appliedCount === "number" ? item.appliedCount : 0;
5501
+ const accepted = typeof item.acceptedCount === "number" ? item.acceptedCount : 0;
5502
+ if (applied > 0) {
5503
+ topRules.push({
5504
+ id: String(item.id || ""),
5505
+ text: String(item.text || item.title || item.rule || ""),
5506
+ appliedCount: applied,
5507
+ acceptedCount: accepted
5508
+ });
5509
+ }
5510
+ }
5511
+ }
5512
+ }
5513
+ topRules.sort((a, b) => {
5514
+ const rateA = a.appliedCount > 0 ? a.acceptedCount / a.appliedCount : 0;
5515
+ const rateB = b.appliedCount > 0 ? b.acceptedCount / b.appliedCount : 0;
5516
+ return rateB - rateA;
5517
+ });
5518
+ const withApplied = topRules.filter((r) => r.appliedCount > 0);
5519
+ const least = [...withApplied].sort((a, b) => {
5520
+ const rateA = a.acceptedCount / a.appliedCount;
5521
+ const rateB = b.acceptedCount / b.appliedCount;
5522
+ return rateA - rateB;
5523
+ }).slice(0, 5);
5524
+ return c.json({
5525
+ approvalRate: totalRules > 0 ? Math.round(approvedRules / totalRules * 100) : 0,
5526
+ totalRules,
5527
+ approvedRules,
5528
+ topRules: topRules.slice(0, 5),
5529
+ leastEffective: least
5530
+ });
5531
+ } catch (error) {
5532
+ console.error("Failed to get team quality:", error);
5533
+ return c.json({ error: "Failed to get team quality" }, 500);
5534
+ }
5535
+ });
5536
+ var team_default = team;
5537
+
5303
5538
  // dashboard/server/index.ts
5304
5539
  var app = new Hono2();
5305
5540
  app.use(
@@ -5318,15 +5553,16 @@ app.route("/api/rules", rules_default);
5318
5553
  app.route("/api/patterns", patterns_default);
5319
5554
  app.route("/api/dev-rules", dev_rules_default);
5320
5555
  app.route("/api/export", export_default);
5556
+ app.route("/api/team", team_default);
5321
5557
  app.route("/api", analytics_default);
5322
5558
  app.route("/api", misc_default);
5323
- var distPath = path15.join(import.meta.dirname, "public");
5324
- if (fs16.existsSync(distPath)) {
5559
+ var distPath = path16.join(import.meta.dirname, "public");
5560
+ if (fs17.existsSync(distPath)) {
5325
5561
  app.use("/*", serveStatic({ root: distPath }));
5326
5562
  app.get("*", async (c) => {
5327
- const indexPath = path15.join(distPath, "index.html");
5328
- if (fs16.existsSync(indexPath)) {
5329
- const content = fs16.readFileSync(indexPath, "utf-8");
5563
+ const indexPath = path16.join(distPath, "index.html");
5564
+ if (fs17.existsSync(indexPath)) {
5565
+ const content = fs17.readFileSync(indexPath, "utf-8");
5330
5566
  return c.html(content);
5331
5567
  }
5332
5568
  return c.notFound();
@@ -5335,7 +5571,7 @@ if (fs16.existsSync(distPath)) {
5335
5571
  var requestedPort = parseInt(process.env.PORT || "7777", 10);
5336
5572
  var maxPortAttempts = 10;
5337
5573
  var mnemeDir = getMnemeDir();
5338
- if (fs16.existsSync(mnemeDir)) {
5574
+ if (fs17.existsSync(mnemeDir)) {
5339
5575
  try {
5340
5576
  const sessionsIndex = readRecentSessionIndexes(mnemeDir, 1);
5341
5577
  const decisionsIndex = readRecentDecisionIndexes(mnemeDir, 1);