lens-engine 0.1.17 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -4639,7 +4639,7 @@ async function logoutCommand() {
4639
4639
  }
4640
4640
 
4641
4641
  // packages/cli/src/index.ts
4642
- var program2 = new Command().name("lens").description("LENS \u2014 Local-first repo context engine").version("0.1.17");
4642
+ var program2 = new Command().name("lens").description("LENS \u2014 Local-first repo context engine").version("0.1.19");
4643
4643
  function trackCommand(name) {
4644
4644
  if (!isTelemetryEnabled()) return;
4645
4645
  const BASE_URL2 = process.env.LENS_HOST ?? "http://127.0.0.1:4111";
package/daemon.js CHANGED
@@ -8301,6 +8301,15 @@ function extractSections(content) {
8301
8301
  }
8302
8302
  return sections.slice(0, 15);
8303
8303
  }
8304
+ function universalSkipLine(line) {
8305
+ const trimmed = line.trimStart();
8306
+ if (trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*")) return true;
8307
+ if (trimmed.startsWith("#") && !trimmed.startsWith("#!")) return true;
8308
+ return EXPORT_LINE_RE.test(trimmed);
8309
+ }
8310
+ function universalSkipName(name) {
8311
+ return SKIP_NAMES.has(name) || name.startsWith("_");
8312
+ }
8304
8313
  function collectMatches(content, regexes, exportSet, skipLine, skipName) {
8305
8314
  const seen = /* @__PURE__ */ new Set();
8306
8315
  const results = [];
@@ -8319,51 +8328,8 @@ function collectMatches(content, regexes, exportSet, skipLine, skipName) {
8319
8328
  }
8320
8329
  return results.slice(0, 20);
8321
8330
  }
8322
- function extractInternals(content, language, exports) {
8323
- const exportSet = new Set(exports);
8324
- switch (language) {
8325
- case "typescript":
8326
- case "javascript":
8327
- case "tsx":
8328
- case "jsx":
8329
- return collectMatches(
8330
- content,
8331
- [TS_INTERNAL_FN_RE, TS_INTERNAL_CONST_RE],
8332
- exportSet,
8333
- (line) => line.trimStart().startsWith("export")
8334
- );
8335
- case "go":
8336
- return collectMatches(content, GO_INTERNAL_RES, exportSet);
8337
- case "python":
8338
- return collectMatches(
8339
- content,
8340
- PY_INTERNAL_RES,
8341
- exportSet,
8342
- void 0,
8343
- (name) => name.startsWith("_")
8344
- );
8345
- case "rust":
8346
- return collectMatches(
8347
- content,
8348
- RUST_INTERNAL_RES,
8349
- exportSet,
8350
- (line) => /^\s*pub\s/.test(line)
8351
- );
8352
- case "csharp":
8353
- return collectMatches(
8354
- content,
8355
- CSHARP_INTERNAL_RES,
8356
- exportSet,
8357
- (line) => /^\s*public\s/.test(line),
8358
- (name) => /^(?:if|for|foreach|while|switch|using|catch|lock|return|throw|yield|try|do|else|new|await|base|this)$/.test(name)
8359
- );
8360
- case "java":
8361
- return collectMatches(content, JAVA_INTERNAL_RES, exportSet);
8362
- case "kotlin":
8363
- return collectMatches(content, KOTLIN_INTERNAL_RES, exportSet);
8364
- default:
8365
- return [];
8366
- }
8331
+ function extractInternals(content, _language, exports) {
8332
+ return collectMatches(content, UNIVERSAL_DECL_RES, new Set(exports), universalSkipLine, universalSkipName);
8367
8333
  }
8368
8334
  function extractFileMetadata(path, content, language) {
8369
8335
  const exports = extractExports(content, language);
@@ -9251,6 +9217,16 @@ function interpretQuery(query, metadata, fileStats2, vocabClusters, indegrees, m
9251
9217
  const { exact, stemmed, clusterFiles } = expandKeywords(rawWords, vocabClusters ?? null);
9252
9218
  const allTerms = [...exact, ...stemmed];
9253
9219
  const termWeights = buildTermWeights(allTerms, metadata);
9220
+ const exportTokensMap = /* @__PURE__ */ new Map();
9221
+ for (const f of metadata) {
9222
+ const tokens = /* @__PURE__ */ new Set();
9223
+ for (const exp of f.exports ?? []) {
9224
+ for (const part of exp.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/[\s_-]+/)) {
9225
+ if (part.length >= 3 && !STOPWORDS2.has(part)) tokens.add(part);
9226
+ }
9227
+ }
9228
+ exportTokensMap.set(f.path, tokens);
9229
+ }
9254
9230
  const scored = metadata.map((f) => {
9255
9231
  let score = 0;
9256
9232
  let matchedTerms = 0;
@@ -9265,12 +9241,14 @@ function interpretQuery(query, metadata, fileStats2, vocabClusters, indegrees, m
9265
9241
  const fileTokens = fileName.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[._-]/g, " ").toLowerCase().split(/\s+/).filter((t) => t.length >= 2);
9266
9242
  const dirTokens = pathSegments.slice(-4, -1).flatMap((s) => s.replace(/\./g, " ").split(/\s+/)).filter((t) => t.length >= 2);
9267
9243
  const pathTokenSet = /* @__PURE__ */ new Set([...fileTokens, ...dirTokens]);
9244
+ const expTokens = exportTokensMap.get(f.path);
9268
9245
  for (const w of exact) {
9269
9246
  const weight = termWeights.get(w) ?? 1;
9270
9247
  let termScore = 0;
9271
9248
  if (fileTokens.some((t) => t === w || t.includes(w))) termScore += 4 * weight;
9272
9249
  else if (pathTokenSet.has(w)) termScore += 2 * weight;
9273
- if (exportsLower.includes(w)) termScore += 2 * weight;
9250
+ if (expTokens?.has(w)) termScore += 2.5 * weight;
9251
+ else if (exportsLower.includes(w)) termScore += 2 * weight;
9274
9252
  if (docLower.includes(w) || purposeLower.includes(w)) termScore += 1 * weight;
9275
9253
  if (sectionsLower.includes(w)) termScore += 1 * weight;
9276
9254
  if (internalsLower.includes(w)) termScore += 1.5 * weight;
@@ -9294,6 +9272,10 @@ function interpretQuery(query, metadata, fileStats2, vocabClusters, indegrees, m
9294
9272
  if (score > 0 && isNoisePath(f.path)) {
9295
9273
  score *= 0.3;
9296
9274
  }
9275
+ const exportCount = (f.exports ?? []).length;
9276
+ if (exportCount > 5 && score > 0) {
9277
+ score *= 1 / (1 + Math.log2(exportCount / 5) * 0.3);
9278
+ }
9297
9279
  const stats = fileStats2?.get(f.path);
9298
9280
  if (stats && stats.recent_count > 0 && score > 0) {
9299
9281
  score += Math.min(stats.recent_count, 5) * 0.5;
@@ -9601,7 +9583,7 @@ Context generation failed.`,
9601
9583
  };
9602
9584
  }
9603
9585
  }
9604
- var __defProp2, __getOwnPropNames2, __esm2, __export2, schema_exports, uuid, now, updatedAt, repos, chunks, fileMetadata, fileImports, fileStats, fileCochanges, usageCounters, requestLogs, settings, telemetryEvents, init_schema, queries_exports, repoQueries, chunkQueries, metadataQueries, importQueries, statsQueries, cochangeQueries, logQueries, usageQueries, telemetryQueries, settingsQueries, init_queries, _db, _raw, execFileAsync, MAX_FILE_SIZE, BINARY_EXTENSIONS, DOCS_EXTENSIONS, LANG_MAP, DEFAULT_CHUNKING_PARAMS, TS_IMPORT_RE, PY_IMPORT_RE, GO_IMPORT_RE, RUST_USE_RE, TS_EXTENSIONS, PY_EXTENSIONS, TS_EXPORT_RE, PY_EXPORT_RE, GO_EXPORT_RE, RUST_EXPORT_RE, CSHARP_EXPORT_RE, CSHARP_EXPORT_METHOD_RE, JAVA_EXPORT_RE, JSDOC_RE, PY_DOCSTRING_RE, CSHARP_DOC_RE, GO_PKG_RE, RUST_DOC_RE, SECTION_SINGLE_RE, SECTION_BLOCK_RE, TS_INTERNAL_FN_RE, TS_INTERNAL_CONST_RE, GO_INTERNAL_RES, PY_INTERNAL_RES, RUST_INTERNAL_RES, CSHARP_INTERNAL_RES, JAVA_INTERNAL_RES, KOTLIN_INTERNAL_RES, execFileAsync2, MAX_COMMITS, MAX_FILES_PER_COMMIT, RECENT_DAYS, _enabled, MAX_CHUNKS_PER_REPO, locks, MAX_API_CALLS, POOL_SIZE, MAX_BATCH_TOKENS, CHARS_PER_TOKEN, PURPOSE_BATCH_LIMIT, PURPOSE_CONCURRENCY, TERM_BATCH_SIZE, SIMILARITY_THRESHOLD, MAX_TERMS, MAX_CLUSTERS, MAX_CLUSTER_SIZE, STOPWORDS, watchers, debounceTimers, IGNORED, DEBOUNCE_MS, STOPWORDS2, NOISE_EXTENSIONS, NOISE_PATHS, CONCEPT_SYNONYMS, CACHE_TTL, CACHE_MAX, cache, RequestTrace;
9586
+ var __defProp2, __getOwnPropNames2, __esm2, __export2, schema_exports, uuid, now, updatedAt, repos, chunks, fileMetadata, fileImports, fileStats, fileCochanges, usageCounters, requestLogs, settings, telemetryEvents, init_schema, queries_exports, repoQueries, chunkQueries, metadataQueries, importQueries, statsQueries, cochangeQueries, logQueries, usageQueries, telemetryQueries, settingsQueries, init_queries, _db, _raw, execFileAsync, MAX_FILE_SIZE, BINARY_EXTENSIONS, DOCS_EXTENSIONS, LANG_MAP, DEFAULT_CHUNKING_PARAMS, TS_IMPORT_RE, PY_IMPORT_RE, GO_IMPORT_RE, RUST_USE_RE, TS_EXTENSIONS, PY_EXTENSIONS, TS_EXPORT_RE, PY_EXPORT_RE, GO_EXPORT_RE, RUST_EXPORT_RE, CSHARP_EXPORT_RE, CSHARP_EXPORT_METHOD_RE, JAVA_EXPORT_RE, JSDOC_RE, PY_DOCSTRING_RE, CSHARP_DOC_RE, GO_PKG_RE, RUST_DOC_RE, SECTION_SINGLE_RE, SECTION_BLOCK_RE, UNIVERSAL_DECL_RES, EXPORT_LINE_RE, SKIP_NAMES, execFileAsync2, MAX_COMMITS, MAX_FILES_PER_COMMIT, RECENT_DAYS, _enabled, MAX_CHUNKS_PER_REPO, locks, MAX_API_CALLS, POOL_SIZE, MAX_BATCH_TOKENS, CHARS_PER_TOKEN, PURPOSE_BATCH_LIMIT, PURPOSE_CONCURRENCY, TERM_BATCH_SIZE, SIMILARITY_THRESHOLD, MAX_TERMS, MAX_CLUSTERS, MAX_CLUSTER_SIZE, STOPWORDS, watchers, debounceTimers, IGNORED, DEBOUNCE_MS, STOPWORDS2, NOISE_EXTENSIONS, NOISE_PATHS, CONCEPT_SYNONYMS, CACHE_TTL, CACHE_MAX, cache, RequestTrace;
9605
9587
  var init_dist = __esm({
9606
9588
  "packages/engine/dist/index.js"() {
9607
9589
  "use strict";
@@ -10441,38 +10423,40 @@ var init_dist = __esm({
10441
10423
  RUST_DOC_RE = /^(?:\s*\/\/!\s*(.*)(?:\n\s*\/\/!\s*(.*))*)/m;
10442
10424
  SECTION_SINGLE_RE = /^(?:\/\/|#)\s*[-=]{3,}\s*(.+?)\s*[-=]{3,}\s*$/gm;
10443
10425
  SECTION_BLOCK_RE = /^\/\*\s*[-=]{3,}\s*(.+?)\s*[-=]{3,}\s*\*\/$/gm;
10444
- TS_INTERNAL_FN_RE = /^(?:async\s+)?function\s+(\w+)/gm;
10445
- TS_INTERNAL_CONST_RE = /^(?:const|let)\s+(\w+)\s*=/gm;
10446
- GO_INTERNAL_RES = [
10447
- /^func\s+([a-z]\w*)/gm,
10448
- /^var\s+([a-z]\w*)/gm,
10449
- /^const\s+([a-z]\w*)/gm
10450
- ];
10451
- PY_INTERNAL_RES = [/^def\s+(\w+)/gm, /^class\s+(\w+)/gm];
10452
- RUST_INTERNAL_RES = [
10453
- /^(?:async\s+)?fn\s+(\w+)/gm,
10454
- /^struct\s+(\w+)/gm,
10455
- /^enum\s+(\w+)/gm,
10456
- /^trait\s+(\w+)/gm,
10457
- /^type\s+(\w+)/gm,
10458
- /^const\s+(\w+)/gm
10459
- ];
10460
- CSHARP_INTERNAL_RES = [
10461
- // Types with explicit access modifier
10462
- /^\s*(?:private|protected|internal)\s+(?:static\s+)?(?:abstract\s+|sealed\s+|partial\s+)?(?:class|interface|enum|struct|record)\s+(\w+)/gm,
10463
- // Methods with explicit access modifier
10464
- /^\s*(?:private|protected|internal)\s+(?:static\s+)?(?:async\s+)?[\w<>\[\]?.]+\s+(\w+)\s*\(/gm,
10465
- // Methods with no access modifier (implicitly private in C#): returnType Name(
10466
- /^\s+(?:static\s+)?(?:async\s+)?(?:override\s+)?(?:virtual\s+)?[\w<>\[\]?.]+\s+(\w+)\s*\(/gm
10467
- ];
10468
- JAVA_INTERNAL_RES = [
10469
- /^\s*(?:private|protected)\s+(?:static\s+)?(?:final\s+|abstract\s+)?(?:class|interface|enum|record)\s+(\w+)/gm,
10470
- /^\s*(?:private|protected)\s+(?:static\s+)?(?:final\s+|abstract\s+)?[\w<>\[\].]+\s+(\w+)\s*\(/gm
10471
- ];
10472
- KOTLIN_INTERNAL_RES = [
10473
- /^\s*private\s+(?:suspend\s+)?fun\s+(\w+)/gm,
10474
- /^\s*private\s+(?:data\s+)?(?:class|interface|object|enum)\s+(\w+)/gm
10426
+ UNIVERSAL_DECL_RES = [
10427
+ /^\s*(?:async\s+|suspend\s+)?(?:function|def|fn|func|fun)\s+(?:\([^)]+\)\s+)?(\w+)/gm,
10428
+ /^\s*(?:const|let|var|val)\s+(\w+)\s*[=:]/gm,
10429
+ /^\s*(?:abstract\s+|sealed\s+|partial\s+|data\s+)?(?:class|struct|enum|trait|interface|record|object|mod)\s+(\w+)/gm,
10430
+ /^\s*type\s+(\w+)\s*[=<{]/gm,
10431
+ /^\s*(?:private|protected|internal)\s+(?:static\s+)?(?:async\s+)?(?:suspend\s+)?(?:override\s+)?[\w<>\[\]?.]+\s+(\w+)\s*\(/gm
10475
10432
  ];
10433
+ EXPORT_LINE_RE = /^(?:export|pub\s|public\s)/;
10434
+ SKIP_NAMES = /* @__PURE__ */ new Set([
10435
+ "if",
10436
+ "for",
10437
+ "foreach",
10438
+ "while",
10439
+ "switch",
10440
+ "using",
10441
+ "catch",
10442
+ "lock",
10443
+ "return",
10444
+ "throw",
10445
+ "yield",
10446
+ "try",
10447
+ "do",
10448
+ "else",
10449
+ "new",
10450
+ "await",
10451
+ "base",
10452
+ "this",
10453
+ "super",
10454
+ "self",
10455
+ "import",
10456
+ "require",
10457
+ "from",
10458
+ "package"
10459
+ ]);
10476
10460
  init_queries();
10477
10461
  init_queries();
10478
10462
  execFileAsync2 = promisify2(execFile2);
@@ -32396,6 +32380,10 @@ var mcp_exports = {};
32396
32380
  __export(mcp_exports, {
32397
32381
  createMcpServer: () => createMcpServer
32398
32382
  });
32383
+ import { randomUUID as randomUUID3 } from "crypto";
32384
+ function logMcp(method, path, status, duration3, reqBody, resSize, resBody, trace) {
32385
+ getRawDb().prepare(LOG_SQL).run(randomUUID3(), method, path, status, duration3, reqBody ?? null, resSize ?? null, resBody ?? null, trace ?? null);
32386
+ }
32399
32387
  function text2(s) {
32400
32388
  return { content: [{ type: "text", text: s }] };
32401
32389
  }
@@ -32423,15 +32411,16 @@ function createMcpServer(db, caps) {
32423
32411
  trace.step("findRepo");
32424
32412
  const repoId = findOrRegisterRepo(db, repo_path);
32425
32413
  trace.end("findRepo");
32426
- const useEmbeddings = settingsQueries.get(db, "use_embeddings") !== "false";
32414
+ const repo = repoQueries.getById(db, repoId);
32415
+ const useEmbeddings = repo?.enable_embeddings === 1;
32427
32416
  const result = await buildContext(db, repoId, goal, caps, trace, { useEmbeddings });
32428
32417
  const duration3 = Math.round(performance.now() - start);
32429
32418
  const reqBody = JSON.stringify({ repo_path, goal });
32430
- logQueries.insert(db, "MCP", "/tool/get_context", 200, duration3, "mcp", reqBody, result.context_pack.length, result.context_pack, trace.serialize());
32419
+ logMcp("MCP", "/tool/get_context", 200, duration3, reqBody, result.context_pack.length, result.context_pack, trace.serialize());
32431
32420
  return text2(result.context_pack);
32432
32421
  } catch (e) {
32433
32422
  const duration3 = Math.round(performance.now() - start);
32434
- logQueries.insert(db, "MCP", "/tool/get_context", 500, duration3, "mcp", JSON.stringify({ repo_path, goal }), void 0, e.message, trace.serialize());
32423
+ logMcp("MCP", "/tool/get_context", 500, duration3, JSON.stringify({ repo_path, goal }), void 0, e.message, trace.serialize());
32435
32424
  return error2(e.message);
32436
32425
  }
32437
32426
  }
@@ -32448,11 +32437,11 @@ function createMcpServer(db, caps) {
32448
32437
  const repos2 = listRepos(db);
32449
32438
  const body = JSON.stringify(repos2, null, 2);
32450
32439
  const duration3 = Math.round(performance.now() - start);
32451
- logQueries.insert(db, "MCP", "/tool/list_repos", 200, duration3, "mcp", void 0, body.length, body);
32440
+ logMcp("MCP", "/tool/list_repos", 200, duration3, void 0, body.length, body);
32452
32441
  return text2(body);
32453
32442
  } catch (e) {
32454
32443
  const duration3 = Math.round(performance.now() - start);
32455
- logQueries.insert(db, "MCP", "/tool/list_repos", 500, duration3, "mcp", void 0, void 0, e.message);
32444
+ logMcp("MCP", "/tool/list_repos", 500, duration3, void 0, void 0, e.message);
32456
32445
  return error2(e.message);
32457
32446
  }
32458
32447
  }
@@ -32468,17 +32457,17 @@ function createMcpServer(db, caps) {
32468
32457
  try {
32469
32458
  const repo = repoQueries.getByPath(db, repo_path);
32470
32459
  if (!repo) {
32471
- logQueries.insert(db, "MCP", "/tool/get_status", 404, Math.round(performance.now() - start), "mcp", JSON.stringify({ repo_path }));
32460
+ logMcp("MCP", "/tool/get_status", 404, Math.round(performance.now() - start), JSON.stringify({ repo_path }));
32472
32461
  return error2("repo not found at " + repo_path);
32473
32462
  }
32474
32463
  const status = await getRepoStatus(db, repo.id);
32475
32464
  const body = JSON.stringify(status, null, 2);
32476
32465
  const duration3 = Math.round(performance.now() - start);
32477
- logQueries.insert(db, "MCP", "/tool/get_status", 200, duration3, "mcp", JSON.stringify({ repo_path }), body.length, body);
32466
+ logMcp("MCP", "/tool/get_status", 200, duration3, JSON.stringify({ repo_path }), body.length, body);
32478
32467
  return text2(body);
32479
32468
  } catch (e) {
32480
32469
  const duration3 = Math.round(performance.now() - start);
32481
- logQueries.insert(db, "MCP", "/tool/get_status", 500, duration3, "mcp", JSON.stringify({ repo_path }), void 0, e.message);
32470
+ logMcp("MCP", "/tool/get_status", 500, duration3, JSON.stringify({ repo_path }), void 0, e.message);
32482
32471
  return error2(e.message);
32483
32472
  }
32484
32473
  }
@@ -32499,23 +32488,26 @@ function createMcpServer(db, caps) {
32499
32488
  const result = await runIndex(db, repoId, caps, force ?? false, void 0, trace);
32500
32489
  const body = JSON.stringify(result, null, 2);
32501
32490
  const duration3 = Math.round(performance.now() - start);
32502
- logQueries.insert(db, "MCP", "/tool/index_repo", 200, duration3, "mcp", JSON.stringify({ repo_path, force }), body.length, body, trace.serialize());
32491
+ logMcp("MCP", "/tool/index_repo", 200, duration3, JSON.stringify({ repo_path, force }), body.length, body, trace.serialize());
32503
32492
  return text2(body);
32504
32493
  } catch (e) {
32505
32494
  const duration3 = Math.round(performance.now() - start);
32506
- logQueries.insert(db, "MCP", "/tool/index_repo", 500, duration3, "mcp", JSON.stringify({ repo_path, force }), void 0, e.message, trace.serialize());
32495
+ logMcp("MCP", "/tool/index_repo", 500, duration3, JSON.stringify({ repo_path, force }), void 0, e.message, trace.serialize());
32507
32496
  return error2(e.message);
32508
32497
  }
32509
32498
  }
32510
32499
  );
32511
32500
  return server;
32512
32501
  }
32502
+ var LOG_SQL;
32513
32503
  var init_mcp2 = __esm({
32514
32504
  "apps/daemon/src/mcp.ts"() {
32515
32505
  "use strict";
32516
32506
  init_dist();
32517
32507
  init_mcp();
32518
32508
  init_zod();
32509
+ LOG_SQL = `INSERT INTO request_logs (id, method, path, status, duration_ms, source, request_body, response_size, response_body, trace, created_at)
32510
+ VALUES (?, ?, ?, ?, ?, 'mcp', ?, ?, ?, ?, datetime('now'))`;
32519
32511
  }
32520
32512
  });
32521
32513
 
@@ -35098,7 +35090,8 @@ function createApp(db, dashboardDist, initialCaps, initialPlanData) {
35098
35090
  try {
35099
35091
  const { repo_id, goal } = await c.req.json();
35100
35092
  if (!repo_id || !goal) return c.json({ error: "repo_id and goal required" }, 400);
35101
- const useEmbeddings = settingsQueries.get(db, "use_embeddings") !== "false";
35093
+ const repo = repoQueries.getById(db, repo_id);
35094
+ const useEmbeddings = repo?.enable_embeddings === 1;
35102
35095
  const result = await buildContext(db, repo_id, goal, caps, c.get("trace"), { useEmbeddings });
35103
35096
  usageQueries.increment(db, "context_queries");
35104
35097
  return c.json(result);
@@ -35824,27 +35817,6 @@ function createApp(db, dashboardDist, initialCaps, initialPlanData) {
35824
35817
  return c.json({ error: e.message }, 500);
35825
35818
  }
35826
35819
  });
35827
- trackRoute("GET", "/api/dashboard/settings");
35828
- app.get("/api/dashboard/settings", (c) => {
35829
- try {
35830
- const all = settingsQueries.getAll(db);
35831
- return c.json({ settings: all });
35832
- } catch (e) {
35833
- return c.json({ error: e.message }, 500);
35834
- }
35835
- });
35836
- trackRoute("PUT", "/api/dashboard/settings");
35837
- app.put("/api/dashboard/settings", async (c) => {
35838
- try {
35839
- const body = await c.req.json();
35840
- for (const [key, value] of Object.entries(body)) {
35841
- settingsQueries.set(db, key, value);
35842
- }
35843
- return c.json({ ok: true, settings: settingsQueries.getAll(db) });
35844
- } catch (e) {
35845
- return c.json({ error: e.message }, 500);
35846
- }
35847
- });
35848
35820
  trackRoute("GET", "/api/dashboard/routes");
35849
35821
  app.get("/api/dashboard/routes", (c) => {
35850
35822
  return c.json({ routes: registeredRoutes });