@hasna/logs 0.1.0 → 0.2.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/mcp/index.js CHANGED
@@ -7,7 +7,6 @@ import {
7
7
  deleteAlertRule,
8
8
  getDb,
9
9
  getLatestSnapshot,
10
- getLogContext,
11
10
  getPerfTrend,
12
11
  ingestLog,
13
12
  listAlertRules,
@@ -15,15 +14,18 @@ import {
15
14
  listPages,
16
15
  listProjects,
17
16
  scoreLabel,
18
- searchLogs,
19
17
  summarizeLogs,
20
- tailLogs,
21
18
  updateIssueStatus
22
- } from "../index-qmsvtxax.js";
19
+ } from "../index-77ss2sf4.js";
23
20
  import {
24
21
  createJob,
25
22
  listJobs
26
23
  } from "../jobs-124e878j.js";
24
+ import {
25
+ getLogContext,
26
+ searchLogs,
27
+ tailLogs
28
+ } from "../query-0qv7fvzt.js";
27
29
  import {
28
30
  getHealth
29
31
  } from "../health-f2qrebqc.js";
@@ -10332,7 +10334,7 @@ __export(exports_core2, {
10332
10334
  safeDecode: () => safeDecode,
10333
10335
  registry: () => registry,
10334
10336
  regexes: () => exports_regexes,
10335
- process: () => process,
10337
+ process: () => process2,
10336
10338
  prettifyError: () => prettifyError,
10337
10339
  parseAsync: () => parseAsync,
10338
10340
  parse: () => parse,
@@ -20796,7 +20798,7 @@ function initializeContext(params) {
20796
20798
  external: params?.external ?? undefined
20797
20799
  };
20798
20800
  }
20799
- function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
20801
+ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
20800
20802
  var _a2;
20801
20803
  const def = schema._zod.def;
20802
20804
  const seen = ctx.seen.get(schema);
@@ -20833,7 +20835,7 @@ function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
20833
20835
  if (parent) {
20834
20836
  if (!result.ref)
20835
20837
  result.ref = parent;
20836
- process(parent, ctx, params);
20838
+ process2(parent, ctx, params);
20837
20839
  ctx.seen.get(parent).isParent = true;
20838
20840
  }
20839
20841
  }
@@ -21109,14 +21111,14 @@ function isTransforming(_schema, _ctx) {
21109
21111
  }
21110
21112
  var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
21111
21113
  const ctx = initializeContext({ ...params, processors });
21112
- process(schema, ctx);
21114
+ process2(schema, ctx);
21113
21115
  extractDefs(ctx, schema);
21114
21116
  return finalize(ctx, schema);
21115
21117
  };
21116
21118
  var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
21117
21119
  const { libraryOptions, target } = params ?? {};
21118
21120
  const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
21119
- process(schema, ctx);
21121
+ process2(schema, ctx);
21120
21122
  extractDefs(ctx, schema);
21121
21123
  return finalize(ctx, schema);
21122
21124
  };
@@ -21367,7 +21369,7 @@ var arrayProcessor = (schema, ctx, _json, params) => {
21367
21369
  if (typeof maximum === "number")
21368
21370
  json.maxItems = maximum;
21369
21371
  json.type = "array";
21370
- json.items = process(def.element, ctx, { ...params, path: [...params.path, "items"] });
21372
+ json.items = process2(def.element, ctx, { ...params, path: [...params.path, "items"] });
21371
21373
  };
21372
21374
  var objectProcessor = (schema, ctx, _json, params) => {
21373
21375
  const json = _json;
@@ -21376,7 +21378,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
21376
21378
  json.properties = {};
21377
21379
  const shape = def.shape;
21378
21380
  for (const key in shape) {
21379
- json.properties[key] = process(shape[key], ctx, {
21381
+ json.properties[key] = process2(shape[key], ctx, {
21380
21382
  ...params,
21381
21383
  path: [...params.path, "properties", key]
21382
21384
  });
@@ -21399,7 +21401,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
21399
21401
  if (ctx.io === "output")
21400
21402
  json.additionalProperties = false;
21401
21403
  } else if (def.catchall) {
21402
- json.additionalProperties = process(def.catchall, ctx, {
21404
+ json.additionalProperties = process2(def.catchall, ctx, {
21403
21405
  ...params,
21404
21406
  path: [...params.path, "additionalProperties"]
21405
21407
  });
@@ -21408,7 +21410,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
21408
21410
  var unionProcessor = (schema, ctx, json, params) => {
21409
21411
  const def = schema._zod.def;
21410
21412
  const isExclusive = def.inclusive === false;
21411
- const options = def.options.map((x, i) => process(x, ctx, {
21413
+ const options = def.options.map((x, i) => process2(x, ctx, {
21412
21414
  ...params,
21413
21415
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
21414
21416
  }));
@@ -21420,11 +21422,11 @@ var unionProcessor = (schema, ctx, json, params) => {
21420
21422
  };
21421
21423
  var intersectionProcessor = (schema, ctx, json, params) => {
21422
21424
  const def = schema._zod.def;
21423
- const a = process(def.left, ctx, {
21425
+ const a = process2(def.left, ctx, {
21424
21426
  ...params,
21425
21427
  path: [...params.path, "allOf", 0]
21426
21428
  });
21427
- const b = process(def.right, ctx, {
21429
+ const b = process2(def.right, ctx, {
21428
21430
  ...params,
21429
21431
  path: [...params.path, "allOf", 1]
21430
21432
  });
@@ -21441,11 +21443,11 @@ var tupleProcessor = (schema, ctx, _json, params) => {
21441
21443
  json.type = "array";
21442
21444
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
21443
21445
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
21444
- const prefixItems = def.items.map((x, i) => process(x, ctx, {
21446
+ const prefixItems = def.items.map((x, i) => process2(x, ctx, {
21445
21447
  ...params,
21446
21448
  path: [...params.path, prefixPath, i]
21447
21449
  }));
21448
- const rest = def.rest ? process(def.rest, ctx, {
21450
+ const rest = def.rest ? process2(def.rest, ctx, {
21449
21451
  ...params,
21450
21452
  path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
21451
21453
  }) : null;
@@ -21485,7 +21487,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
21485
21487
  const keyBag = keyType._zod.bag;
21486
21488
  const patterns = keyBag?.patterns;
21487
21489
  if (def.mode === "loose" && patterns && patterns.size > 0) {
21488
- const valueSchema = process(def.valueType, ctx, {
21490
+ const valueSchema = process2(def.valueType, ctx, {
21489
21491
  ...params,
21490
21492
  path: [...params.path, "patternProperties", "*"]
21491
21493
  });
@@ -21495,12 +21497,12 @@ var recordProcessor = (schema, ctx, _json, params) => {
21495
21497
  }
21496
21498
  } else {
21497
21499
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
21498
- json.propertyNames = process(def.keyType, ctx, {
21500
+ json.propertyNames = process2(def.keyType, ctx, {
21499
21501
  ...params,
21500
21502
  path: [...params.path, "propertyNames"]
21501
21503
  });
21502
21504
  }
21503
- json.additionalProperties = process(def.valueType, ctx, {
21505
+ json.additionalProperties = process2(def.valueType, ctx, {
21504
21506
  ...params,
21505
21507
  path: [...params.path, "additionalProperties"]
21506
21508
  });
@@ -21515,7 +21517,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
21515
21517
  };
21516
21518
  var nullableProcessor = (schema, ctx, json, params) => {
21517
21519
  const def = schema._zod.def;
21518
- const inner = process(def.innerType, ctx, params);
21520
+ const inner = process2(def.innerType, ctx, params);
21519
21521
  const seen = ctx.seen.get(schema);
21520
21522
  if (ctx.target === "openapi-3.0") {
21521
21523
  seen.ref = def.innerType;
@@ -21526,20 +21528,20 @@ var nullableProcessor = (schema, ctx, json, params) => {
21526
21528
  };
21527
21529
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
21528
21530
  const def = schema._zod.def;
21529
- process(def.innerType, ctx, params);
21531
+ process2(def.innerType, ctx, params);
21530
21532
  const seen = ctx.seen.get(schema);
21531
21533
  seen.ref = def.innerType;
21532
21534
  };
21533
21535
  var defaultProcessor = (schema, ctx, json, params) => {
21534
21536
  const def = schema._zod.def;
21535
- process(def.innerType, ctx, params);
21537
+ process2(def.innerType, ctx, params);
21536
21538
  const seen = ctx.seen.get(schema);
21537
21539
  seen.ref = def.innerType;
21538
21540
  json.default = JSON.parse(JSON.stringify(def.defaultValue));
21539
21541
  };
21540
21542
  var prefaultProcessor = (schema, ctx, json, params) => {
21541
21543
  const def = schema._zod.def;
21542
- process(def.innerType, ctx, params);
21544
+ process2(def.innerType, ctx, params);
21543
21545
  const seen = ctx.seen.get(schema);
21544
21546
  seen.ref = def.innerType;
21545
21547
  if (ctx.io === "input")
@@ -21547,7 +21549,7 @@ var prefaultProcessor = (schema, ctx, json, params) => {
21547
21549
  };
21548
21550
  var catchProcessor = (schema, ctx, json, params) => {
21549
21551
  const def = schema._zod.def;
21550
- process(def.innerType, ctx, params);
21552
+ process2(def.innerType, ctx, params);
21551
21553
  const seen = ctx.seen.get(schema);
21552
21554
  seen.ref = def.innerType;
21553
21555
  let catchValue;
@@ -21561,32 +21563,32 @@ var catchProcessor = (schema, ctx, json, params) => {
21561
21563
  var pipeProcessor = (schema, ctx, _json, params) => {
21562
21564
  const def = schema._zod.def;
21563
21565
  const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
21564
- process(innerType, ctx, params);
21566
+ process2(innerType, ctx, params);
21565
21567
  const seen = ctx.seen.get(schema);
21566
21568
  seen.ref = innerType;
21567
21569
  };
21568
21570
  var readonlyProcessor = (schema, ctx, json, params) => {
21569
21571
  const def = schema._zod.def;
21570
- process(def.innerType, ctx, params);
21572
+ process2(def.innerType, ctx, params);
21571
21573
  const seen = ctx.seen.get(schema);
21572
21574
  seen.ref = def.innerType;
21573
21575
  json.readOnly = true;
21574
21576
  };
21575
21577
  var promiseProcessor = (schema, ctx, _json, params) => {
21576
21578
  const def = schema._zod.def;
21577
- process(def.innerType, ctx, params);
21579
+ process2(def.innerType, ctx, params);
21578
21580
  const seen = ctx.seen.get(schema);
21579
21581
  seen.ref = def.innerType;
21580
21582
  };
21581
21583
  var optionalProcessor = (schema, ctx, _json, params) => {
21582
21584
  const def = schema._zod.def;
21583
- process(def.innerType, ctx, params);
21585
+ process2(def.innerType, ctx, params);
21584
21586
  const seen = ctx.seen.get(schema);
21585
21587
  seen.ref = def.innerType;
21586
21588
  };
21587
21589
  var lazyProcessor = (schema, ctx, _json, params) => {
21588
21590
  const innerType = schema._zod.innerType;
21589
- process(innerType, ctx, params);
21591
+ process2(innerType, ctx, params);
21590
21592
  const seen = ctx.seen.get(schema);
21591
21593
  seen.ref = innerType;
21592
21594
  };
@@ -21638,7 +21640,7 @@ function toJSONSchema(input, params) {
21638
21640
  const defs = {};
21639
21641
  for (const entry of registry2._idmap.entries()) {
21640
21642
  const [_, schema] = entry;
21641
- process(schema, ctx2);
21643
+ process2(schema, ctx2);
21642
21644
  }
21643
21645
  const schemas = {};
21644
21646
  const external = {
@@ -21661,7 +21663,7 @@ function toJSONSchema(input, params) {
21661
21663
  return { schemas };
21662
21664
  }
21663
21665
  const ctx = initializeContext({ ...params, processors: allProcessors });
21664
- process(input, ctx);
21666
+ process2(input, ctx);
21665
21667
  extractDefs(ctx, input);
21666
21668
  return finalize(ctx, input);
21667
21669
  }
@@ -21707,7 +21709,7 @@ class JSONSchemaGenerator {
21707
21709
  });
21708
21710
  }
21709
21711
  process(schema, _params = { path: [], schemaPath: [] }) {
21710
- return process(schema, this.ctx, _params);
21712
+ return process2(schema, this.ctx, _params);
21711
21713
  }
21712
21714
  emit(schema, _params) {
21713
21715
  if (_params) {
@@ -28288,7 +28290,7 @@ var EMPTY_COMPLETION_RESULT = {
28288
28290
  };
28289
28291
 
28290
28292
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
28291
- import process2 from "process";
28293
+ import process3 from "process";
28292
28294
 
28293
28295
  // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
28294
28296
  class ReadBuffer {
@@ -28322,7 +28324,7 @@ function serializeMessage(message) {
28322
28324
 
28323
28325
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
28324
28326
  class StdioServerTransport {
28325
- constructor(_stdin = process2.stdin, _stdout = process2.stdout) {
28327
+ constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
28326
28328
  this._stdin = _stdin;
28327
28329
  this._stdout = _stdout;
28328
28330
  this._readBuffer = new ReadBuffer;
@@ -28495,6 +28497,24 @@ function compare(db, projectId, aSince, aUntil, bSince, bUntil) {
28495
28497
  };
28496
28498
  }
28497
28499
 
28500
+ // src/lib/session-context.ts
28501
+ async function getSessionContext(db, sessionId) {
28502
+ const logs = db.prepare("SELECT * FROM logs WHERE session_id = $s ORDER BY timestamp ASC").all({ $s: sessionId });
28503
+ const sessionsUrl = process.env.SESSIONS_URL;
28504
+ if (!sessionsUrl) {
28505
+ return { session_id: sessionId, logs };
28506
+ }
28507
+ try {
28508
+ const res = await fetch(`${sessionsUrl.replace(/\/$/, "")}/api/sessions/${sessionId}`);
28509
+ if (!res.ok)
28510
+ return { session_id: sessionId, logs };
28511
+ const session = await res.json();
28512
+ return { session_id: sessionId, logs, session };
28513
+ } catch (err) {
28514
+ return { session_id: sessionId, logs, error: String(err) };
28515
+ }
28516
+ }
28517
+
28498
28518
  // src/mcp/index.ts
28499
28519
  var db = getDb();
28500
28520
  var server = new McpServer({ name: "logs", version: "0.1.0" });
@@ -28524,6 +28544,7 @@ var TOOLS = {
28524
28544
  create_alert_rule: "Create alert rule (project_id, name, level, threshold_count, window_seconds, webhook_url?)",
28525
28545
  list_alert_rules: "List alert rules (project_id?)",
28526
28546
  delete_alert_rule: "Delete alert rule (id)",
28547
+ log_session_context: "Logs + session metadata for a session_id (requires SESSIONS_URL env)",
28527
28548
  get_health: "Server health + DB stats",
28528
28549
  search_tools: "Search tools by keyword (query)",
28529
28550
  describe_tools: "List all tools"
@@ -28678,6 +28699,13 @@ server.tool("delete_alert_rule", { id: exports_external.string() }, ({ id }) =>
28678
28699
  deleteAlertRule(db, id);
28679
28700
  return { content: [{ type: "text", text: "deleted" }] };
28680
28701
  });
28702
+ server.tool("log_session_context", {
28703
+ session_id: exports_external.string(),
28704
+ brief: exports_external.boolean().optional()
28705
+ }, async ({ session_id, brief }) => {
28706
+ const ctx = await getSessionContext(db, session_id);
28707
+ return { content: [{ type: "text", text: JSON.stringify({ ...ctx, logs: applyBrief(ctx.logs, brief !== false) }) }] };
28708
+ });
28681
28709
  server.tool("get_health", {}, () => ({
28682
28710
  content: [{ type: "text", text: JSON.stringify(getHealth(db)) }]
28683
28711
  }));
@@ -6,7 +6,7 @@ import {
6
6
  setPageAuth,
7
7
  setRetentionPolicy,
8
8
  startScheduler
9
- } from "../index-4x090f69.js";
9
+ } from "../index-2p6ynjet.js";
10
10
  import {
11
11
  createAlertRule,
12
12
  createPage,
@@ -15,7 +15,6 @@ import {
15
15
  getDb,
16
16
  getIssue,
17
17
  getLatestSnapshot,
18
- getLogContext,
19
18
  getPerfTrend,
20
19
  getProject,
21
20
  ingestBatch,
@@ -24,19 +23,22 @@ import {
24
23
  listIssues,
25
24
  listPages,
26
25
  listProjects,
27
- searchLogs,
28
26
  summarizeLogs,
29
- tailLogs,
30
27
  updateAlertRule,
31
28
  updateIssueStatus,
32
29
  updateProject
33
- } from "../index-qmsvtxax.js";
30
+ } from "../index-77ss2sf4.js";
34
31
  import {
35
32
  createJob,
36
33
  deleteJob,
37
34
  listJobs,
38
35
  updateJob
39
36
  } from "../jobs-124e878j.js";
37
+ import {
38
+ getLogContext,
39
+ searchLogs,
40
+ tailLogs
41
+ } from "../query-0qv7fvzt.js";
40
42
  import {
41
43
  exportToCsv,
42
44
  exportToJson
@@ -1669,6 +1671,277 @@ var cors = (options) => {
1669
1671
  };
1670
1672
  };
1671
1673
 
1674
+ // node_modules/hono/dist/adapter/bun/serve-static.js
1675
+ import { stat } from "fs/promises";
1676
+ import { join } from "path";
1677
+
1678
+ // node_modules/hono/dist/utils/compress.js
1679
+ var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/(?!event-stream(?:[;\s]|$))[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
1680
+
1681
+ // node_modules/hono/dist/utils/mime.js
1682
+ var getMimeType = (filename, mimes = baseMimes) => {
1683
+ const regexp = /\.([a-zA-Z0-9]+?)$/;
1684
+ const match2 = filename.match(regexp);
1685
+ if (!match2) {
1686
+ return;
1687
+ }
1688
+ let mimeType = mimes[match2[1].toLowerCase()];
1689
+ if (mimeType && mimeType.startsWith("text")) {
1690
+ mimeType += "; charset=utf-8";
1691
+ }
1692
+ return mimeType;
1693
+ };
1694
+ var _baseMimes = {
1695
+ aac: "audio/aac",
1696
+ avi: "video/x-msvideo",
1697
+ avif: "image/avif",
1698
+ av1: "video/av1",
1699
+ bin: "application/octet-stream",
1700
+ bmp: "image/bmp",
1701
+ css: "text/css",
1702
+ csv: "text/csv",
1703
+ eot: "application/vnd.ms-fontobject",
1704
+ epub: "application/epub+zip",
1705
+ gif: "image/gif",
1706
+ gz: "application/gzip",
1707
+ htm: "text/html",
1708
+ html: "text/html",
1709
+ ico: "image/x-icon",
1710
+ ics: "text/calendar",
1711
+ jpeg: "image/jpeg",
1712
+ jpg: "image/jpeg",
1713
+ js: "text/javascript",
1714
+ json: "application/json",
1715
+ jsonld: "application/ld+json",
1716
+ map: "application/json",
1717
+ mid: "audio/x-midi",
1718
+ midi: "audio/x-midi",
1719
+ mjs: "text/javascript",
1720
+ mp3: "audio/mpeg",
1721
+ mp4: "video/mp4",
1722
+ mpeg: "video/mpeg",
1723
+ oga: "audio/ogg",
1724
+ ogv: "video/ogg",
1725
+ ogx: "application/ogg",
1726
+ opus: "audio/opus",
1727
+ otf: "font/otf",
1728
+ pdf: "application/pdf",
1729
+ png: "image/png",
1730
+ rtf: "application/rtf",
1731
+ svg: "image/svg+xml",
1732
+ tif: "image/tiff",
1733
+ tiff: "image/tiff",
1734
+ ts: "video/mp2t",
1735
+ ttf: "font/ttf",
1736
+ txt: "text/plain",
1737
+ wasm: "application/wasm",
1738
+ webm: "video/webm",
1739
+ weba: "audio/webm",
1740
+ webmanifest: "application/manifest+json",
1741
+ webp: "image/webp",
1742
+ woff: "font/woff",
1743
+ woff2: "font/woff2",
1744
+ xhtml: "application/xhtml+xml",
1745
+ xml: "application/xml",
1746
+ zip: "application/zip",
1747
+ "3gp": "video/3gpp",
1748
+ "3g2": "video/3gpp2",
1749
+ gltf: "model/gltf+json",
1750
+ glb: "model/gltf-binary"
1751
+ };
1752
+ var baseMimes = _baseMimes;
1753
+
1754
+ // node_modules/hono/dist/middleware/serve-static/path.js
1755
+ var defaultJoin = (...paths) => {
1756
+ let result = paths.filter((p) => p !== "").join("/");
1757
+ result = result.replace(/(?<=\/)\/+/g, "");
1758
+ const segments = result.split("/");
1759
+ const resolved = [];
1760
+ for (const segment of segments) {
1761
+ if (segment === ".." && resolved.length > 0 && resolved.at(-1) !== "..") {
1762
+ resolved.pop();
1763
+ } else if (segment !== ".") {
1764
+ resolved.push(segment);
1765
+ }
1766
+ }
1767
+ return resolved.join("/") || ".";
1768
+ };
1769
+
1770
+ // node_modules/hono/dist/middleware/serve-static/index.js
1771
+ var ENCODINGS = {
1772
+ br: ".br",
1773
+ zstd: ".zst",
1774
+ gzip: ".gz"
1775
+ };
1776
+ var ENCODINGS_ORDERED_KEYS = Object.keys(ENCODINGS);
1777
+ var DEFAULT_DOCUMENT = "index.html";
1778
+ var serveStatic = (options) => {
1779
+ const root = options.root ?? "./";
1780
+ const optionPath = options.path;
1781
+ const join = options.join ?? defaultJoin;
1782
+ return async (c, next) => {
1783
+ if (c.finalized) {
1784
+ return next();
1785
+ }
1786
+ let filename;
1787
+ if (options.path) {
1788
+ filename = options.path;
1789
+ } else {
1790
+ try {
1791
+ filename = tryDecodeURI(c.req.path);
1792
+ if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
1793
+ throw new Error;
1794
+ }
1795
+ } catch {
1796
+ await options.onNotFound?.(c.req.path, c);
1797
+ return next();
1798
+ }
1799
+ }
1800
+ let path = join(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename);
1801
+ if (options.isDir && await options.isDir(path)) {
1802
+ path = join(path, DEFAULT_DOCUMENT);
1803
+ }
1804
+ const getContent = options.getContent;
1805
+ let content = await getContent(path, c);
1806
+ if (content instanceof Response) {
1807
+ return c.newResponse(content.body, content);
1808
+ }
1809
+ if (content) {
1810
+ const mimeType = options.mimes && getMimeType(path, options.mimes) || getMimeType(path);
1811
+ c.header("Content-Type", mimeType || "application/octet-stream");
1812
+ if (options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) {
1813
+ const acceptEncodingSet = new Set(c.req.header("Accept-Encoding")?.split(",").map((encoding) => encoding.trim()));
1814
+ for (const encoding of ENCODINGS_ORDERED_KEYS) {
1815
+ if (!acceptEncodingSet.has(encoding)) {
1816
+ continue;
1817
+ }
1818
+ const compressedContent = await getContent(path + ENCODINGS[encoding], c);
1819
+ if (compressedContent) {
1820
+ content = compressedContent;
1821
+ c.header("Content-Encoding", encoding);
1822
+ c.header("Vary", "Accept-Encoding", { append: true });
1823
+ break;
1824
+ }
1825
+ }
1826
+ }
1827
+ await options.onFound?.(path, c);
1828
+ return c.body(content);
1829
+ }
1830
+ await options.onNotFound?.(path, c);
1831
+ await next();
1832
+ return;
1833
+ };
1834
+ };
1835
+
1836
+ // node_modules/hono/dist/adapter/bun/serve-static.js
1837
+ var serveStatic2 = (options) => {
1838
+ return async function serveStatic2(c, next) {
1839
+ const getContent = async (path) => {
1840
+ const file = Bun.file(path);
1841
+ return await file.exists() ? file : null;
1842
+ };
1843
+ const isDir = async (path) => {
1844
+ let isDir2;
1845
+ try {
1846
+ const stats = await stat(path);
1847
+ isDir2 = stats.isDirectory();
1848
+ } catch {}
1849
+ return isDir2;
1850
+ };
1851
+ return serveStatic({
1852
+ ...options,
1853
+ getContent,
1854
+ join,
1855
+ isDir
1856
+ })(c, next);
1857
+ };
1858
+ };
1859
+
1860
+ // node_modules/hono/dist/helper/ssg/middleware.js
1861
+ var X_HONO_DISABLE_SSG_HEADER_KEY = "x-hono-disable-ssg";
1862
+ var SSG_DISABLED_RESPONSE = (() => {
1863
+ try {
1864
+ return new Response("SSG is disabled", {
1865
+ status: 404,
1866
+ headers: { [X_HONO_DISABLE_SSG_HEADER_KEY]: "true" }
1867
+ });
1868
+ } catch {
1869
+ return null;
1870
+ }
1871
+ })();
1872
+ // node_modules/hono/dist/adapter/bun/ssg.js
1873
+ var { write } = Bun;
1874
+
1875
+ // node_modules/hono/dist/helper/websocket/index.js
1876
+ var WSContext = class {
1877
+ #init;
1878
+ constructor(init) {
1879
+ this.#init = init;
1880
+ this.raw = init.raw;
1881
+ this.url = init.url ? new URL(init.url) : null;
1882
+ this.protocol = init.protocol ?? null;
1883
+ }
1884
+ send(source, options) {
1885
+ this.#init.send(source, options ?? {});
1886
+ }
1887
+ raw;
1888
+ binaryType = "arraybuffer";
1889
+ get readyState() {
1890
+ return this.#init.readyState;
1891
+ }
1892
+ url;
1893
+ protocol;
1894
+ close(code, reason) {
1895
+ this.#init.close(code, reason);
1896
+ }
1897
+ };
1898
+ var defineWebSocketHelper = (handler) => {
1899
+ return (...args) => {
1900
+ if (typeof args[0] === "function") {
1901
+ const [createEvents, options] = args;
1902
+ return async function upgradeWebSocket(c, next) {
1903
+ const events = await createEvents(c);
1904
+ const result = await handler(c, events, options);
1905
+ if (result) {
1906
+ return result;
1907
+ }
1908
+ await next();
1909
+ };
1910
+ } else {
1911
+ const [c, events, options] = args;
1912
+ return (async () => {
1913
+ const upgraded = await handler(c, events, options);
1914
+ if (!upgraded) {
1915
+ throw new Error("Failed to upgrade WebSocket");
1916
+ }
1917
+ return upgraded;
1918
+ })();
1919
+ }
1920
+ };
1921
+ };
1922
+
1923
+ // node_modules/hono/dist/adapter/bun/server.js
1924
+ var getBunServer = (c) => ("server" in c.env) ? c.env.server : c.env;
1925
+
1926
+ // node_modules/hono/dist/adapter/bun/websocket.js
1927
+ var upgradeWebSocket = defineWebSocketHelper((c, events) => {
1928
+ const server = getBunServer(c);
1929
+ if (!server) {
1930
+ throw new TypeError("env has to include the 2nd argument of fetch.");
1931
+ }
1932
+ const upgradeResult = server.upgrade(c.req.raw, {
1933
+ data: {
1934
+ events,
1935
+ url: new URL(c.req.url),
1936
+ protocol: c.req.url
1937
+ }
1938
+ });
1939
+ if (upgradeResult) {
1940
+ return new Response(null);
1941
+ }
1942
+ return;
1943
+ });
1944
+
1672
1945
  // src/lib/browser-script.ts
1673
1946
  function getBrowserScript(serverUrl) {
1674
1947
  return `(function(){
@@ -2160,7 +2433,9 @@ app.route("/api/alerts", alertsRoutes(db));
2160
2433
  app.route("/api/issues", issuesRoutes(db));
2161
2434
  app.route("/api/perf", perfRoutes(db));
2162
2435
  app.get("/health", (c) => c.json(getHealth(db)));
2163
- app.get("/", (c) => c.json({ service: "@hasna/logs", port: PORT, status: "ok" }));
2436
+ app.get("/dashboard", (c) => c.redirect("/dashboard/"));
2437
+ app.use("/dashboard/*", serveStatic2({ root: "./dashboard/dist", rewriteRequestPath: (p) => p.replace(/^\/dashboard/, "") }));
2438
+ app.get("/", (c) => c.json({ service: "@hasna/logs", port: PORT, status: "ok", dashboard: `http://localhost:${PORT}/dashboard/` }));
2164
2439
  startScheduler(db);
2165
2440
  console.log(`@hasna/logs server running on http://localhost:${PORT}`);
2166
2441
  var server_default = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/logs",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Log aggregation + browser script + headless page scanner + performance monitoring for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,6 +12,8 @@
12
12
  },
13
13
  "scripts": {
14
14
  "build": "bun build src/cli/index.ts src/mcp/index.ts src/server/index.ts --outdir dist --target bun --splitting --external playwright --external playwright-core --external electron --external chromium-bidi --external lighthouse",
15
+ "build:dashboard": "cd dashboard && bun run build",
16
+ "build:all": "bun run build:dashboard && bun run build",
15
17
  "dev": "bun run src/server/index.ts",
16
18
  "test": "bun test",
17
19
  "test:coverage": "bun test --coverage",
package/sdk/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hasna/logs-sdk",
3
- "version": "0.0.1",
4
- "description": "Zero-dependency fetch client for @hasna/logs",
3
+ "version": "0.1.0",
4
+ "description": "Zero-dependency fetch client for @hasna/logs — push logs, query, browse issues, perf snapshots",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  "scripts": {
17
17
  "build": "bun build src/index.ts --outdir dist --target browser"
18
18
  },
19
+ "keywords": ["logs", "monitoring", "sdk", "ai-agents"],
19
20
  "author": "Andrei Hasna <andrei@hasna.com>",
20
21
  "license": "MIT"
21
22
  }