chron-mcp 0.1.13 → 0.1.17

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/index.js CHANGED
@@ -6402,7 +6402,7 @@ var require_filesystem = __commonJS({
6402
6402
  "use strict";
6403
6403
  var fs = require("fs");
6404
6404
  var LDD_PATH = "/usr/bin/ldd";
6405
- var readFileSync2 = (path) => fs.readFileSync(path, "utf-8");
6405
+ var readFileSync3 = (path) => fs.readFileSync(path, "utf-8");
6406
6406
  var readFile = (path) => new Promise((resolve, reject) => {
6407
6407
  fs.readFile(path, "utf-8", (err, data) => {
6408
6408
  if (err) {
@@ -6414,7 +6414,7 @@ var require_filesystem = __commonJS({
6414
6414
  });
6415
6415
  module2.exports = {
6416
6416
  LDD_PATH,
6417
- readFileSync: readFileSync2,
6417
+ readFileSync: readFileSync3,
6418
6418
  readFile
6419
6419
  };
6420
6420
  }
@@ -6426,7 +6426,7 @@ var require_detect_libc = __commonJS({
6426
6426
  "use strict";
6427
6427
  var childProcess = require("child_process");
6428
6428
  var { isLinux, getReport } = require_process();
6429
- var { LDD_PATH, readFile, readFileSync: readFileSync2 } = require_filesystem();
6429
+ var { LDD_PATH, readFile, readFileSync: readFileSync3 } = require_filesystem();
6430
6430
  var cachedFamilyFilesystem;
6431
6431
  var cachedVersionFilesystem;
6432
6432
  var command = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
@@ -6507,7 +6507,7 @@ var require_detect_libc = __commonJS({
6507
6507
  }
6508
6508
  cachedFamilyFilesystem = null;
6509
6509
  try {
6510
- const lddContent = readFileSync2(LDD_PATH);
6510
+ const lddContent = readFileSync3(LDD_PATH);
6511
6511
  cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
6512
6512
  } catch (e) {
6513
6513
  }
@@ -6564,7 +6564,7 @@ var require_detect_libc = __commonJS({
6564
6564
  }
6565
6565
  cachedVersionFilesystem = null;
6566
6566
  try {
6567
- const lddContent = readFileSync2(LDD_PATH);
6567
+ const lddContent = readFileSync3(LDD_PATH);
6568
6568
  const versionMatch = lddContent.match(RE_GLIBC_VERSION);
6569
6569
  if (versionMatch) {
6570
6570
  cachedVersionFilesystem = versionMatch[1];
@@ -9320,7 +9320,7 @@ var require_websocket = __commonJS({
9320
9320
  var http = require("http");
9321
9321
  var net = require("net");
9322
9322
  var tls = require("tls");
9323
- var { randomBytes, createHash: createHash2 } = require("crypto");
9323
+ var { randomBytes, createHash: createHash3 } = require("crypto");
9324
9324
  var { Duplex, Readable } = require("stream");
9325
9325
  var { URL: URL3 } = require("url");
9326
9326
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -10000,7 +10000,7 @@ var require_websocket = __commonJS({
10000
10000
  abortHandshake(websocket, socket, "Invalid Upgrade header");
10001
10001
  return;
10002
10002
  }
10003
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
10003
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
10004
10004
  if (res.headers["sec-websocket-accept"] !== digest) {
10005
10005
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
10006
10006
  return;
@@ -10387,7 +10387,7 @@ var require_websocket_server = __commonJS({
10387
10387
  var EventEmitter = require("events");
10388
10388
  var http = require("http");
10389
10389
  var { Duplex } = require("stream");
10390
- var { createHash: createHash2 } = require("crypto");
10390
+ var { createHash: createHash3 } = require("crypto");
10391
10391
  var extension2 = require_extension();
10392
10392
  var PerMessageDeflate2 = require_permessage_deflate();
10393
10393
  var subprotocol2 = require_subprotocol();
@@ -10696,7 +10696,7 @@ var require_websocket_server = __commonJS({
10696
10696
  }
10697
10697
  if (this._state > RUNNING)
10698
10698
  return abortHandshake(socket, 503);
10699
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
10699
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
10700
10700
  const headers = [
10701
10701
  "HTTP/1.1 101 Switching Protocols",
10702
10702
  "Upgrade: websocket",
@@ -12014,7 +12014,7 @@ var init_sql = __esm({
12014
12014
  return new SQL([new StringChunk(str)]);
12015
12015
  }
12016
12016
  sql2.raw = raw;
12017
- function join4(chunks, separator) {
12017
+ function join5(chunks, separator) {
12018
12018
  const result = [];
12019
12019
  for (const [i, chunk] of chunks.entries()) {
12020
12020
  if (i > 0 && separator !== void 0) {
@@ -12024,7 +12024,7 @@ var init_sql = __esm({
12024
12024
  }
12025
12025
  return new SQL(result);
12026
12026
  }
12027
- sql2.join = join4;
12027
+ sql2.join = join5;
12028
12028
  function identifier(value) {
12029
12029
  return new Name(value);
12030
12030
  }
@@ -14955,7 +14955,7 @@ var init_select2 = __esm({
14955
14955
  const tableName = getTableLikeName(table);
14956
14956
  for (const item of extractUsedTable(table))
14957
14957
  this.usedTables.add(item);
14958
- if (typeof tableName === "string" && this.config.joins?.some((join4) => join4.alias === tableName)) {
14958
+ if (typeof tableName === "string" && this.config.joins?.some((join5) => join5.alias === tableName)) {
14959
14959
  throw new Error(`Alias "${tableName}" is already used in this query`);
14960
14960
  }
14961
14961
  if (!this.isPartialSelect) {
@@ -15844,7 +15844,7 @@ var init_update = __esm({
15844
15844
  createJoin(joinType) {
15845
15845
  return (table, on) => {
15846
15846
  const tableName = getTableLikeName(table);
15847
- if (typeof tableName === "string" && this.config.joins.some((join4) => join4.alias === tableName)) {
15847
+ if (typeof tableName === "string" && this.config.joins.some((join5) => join5.alias === tableName)) {
15848
15848
  throw new Error(`Alias "${tableName}" is already used in this query`);
15849
15849
  }
15850
15850
  if (typeof on === "function") {
@@ -32535,6 +32535,234 @@ var init_time = __esm({
32535
32535
  }
32536
32536
  });
32537
32537
 
32538
+ // package.json
32539
+ var version4;
32540
+ var init_package = __esm({
32541
+ "package.json"() {
32542
+ version4 = "0.1.17";
32543
+ }
32544
+ });
32545
+
32546
+ // src/utils/relay.ts
32547
+ function getSplunkConfig() {
32548
+ const envUrl = process.env.CHRON_SPLUNK_URL;
32549
+ const envToken = process.env.CHRON_SPLUNK_TOKEN;
32550
+ if (envUrl && envToken) {
32551
+ return { url: envUrl, token: envToken, insecure: process.env.CHRON_SPLUNK_INSECURE === "1" };
32552
+ }
32553
+ const now = Date.now();
32554
+ if (now < _splunkCacheExpiry)
32555
+ return _splunkCache;
32556
+ _splunkCacheExpiry = now + 1e4;
32557
+ try {
32558
+ const cfg = JSON.parse((0, import_fs2.readFileSync)((0, import_path2.join)((0, import_os2.homedir)(), ".chron", "config.json"), "utf8"));
32559
+ const s = cfg?.splunk;
32560
+ _splunkCache = s?.url && s?.token ? { url: s.url, token: s.token, insecure: s.insecure ?? false } : null;
32561
+ } catch {
32562
+ _splunkCache = null;
32563
+ }
32564
+ if (_splunkCache?.insecure)
32565
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
32566
+ return _splunkCache;
32567
+ }
32568
+ async function getAzureToken(tenantId, clientId, clientSecret) {
32569
+ const now = Date.now();
32570
+ if (_azureTokenCache && _azureTokenCache.expiry > now + 6e4) {
32571
+ return _azureTokenCache.token;
32572
+ }
32573
+ try {
32574
+ const res = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
32575
+ method: "POST",
32576
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
32577
+ body: new URLSearchParams({
32578
+ grant_type: "client_credentials",
32579
+ client_id: clientId,
32580
+ client_secret: clientSecret,
32581
+ scope: "https://monitor.azure.com/.default"
32582
+ }).toString()
32583
+ });
32584
+ if (!res.ok)
32585
+ return null;
32586
+ const data = await res.json();
32587
+ _azureTokenCache = { token: data.access_token, expiry: now + data.expires_in * 1e3 };
32588
+ return data.access_token;
32589
+ } catch {
32590
+ return null;
32591
+ }
32592
+ }
32593
+ function getMachineId() {
32594
+ if (!_machineId) {
32595
+ _machineId = "sha256:" + (0, import_crypto3.createHash)("sha256").update((0, import_os2.hostname)()).digest("hex").slice(0, 16);
32596
+ }
32597
+ return _machineId;
32598
+ }
32599
+ function toSplunkEvent(payload) {
32600
+ const event = {
32601
+ event_type: payload.event_type,
32602
+ session_id_prefix: payload.session.id_prefix,
32603
+ ai_tool: payload.session.ai_tool ?? "",
32604
+ os: process.platform,
32605
+ chron_version: version4
32606
+ };
32607
+ if (payload.event_type === "message_logged") {
32608
+ event.role = payload.message.role;
32609
+ } else if (payload.event_type === "secret_detected") {
32610
+ event.detection_type = payload.detection.type;
32611
+ event.masked_value = payload.detection.masked_value;
32612
+ }
32613
+ return {
32614
+ time: new Date(payload.timestamp).getTime() / 1e3,
32615
+ host: (0, import_os2.hostname)(),
32616
+ source: "chron-mcp",
32617
+ sourcetype: "chron:event",
32618
+ event
32619
+ };
32620
+ }
32621
+ function emitToSplunk(payload) {
32622
+ const cfg = getSplunkConfig();
32623
+ if (!cfg)
32624
+ return;
32625
+ const url = `${cfg.url.replace(/\/$/, "")}/services/collector/event`;
32626
+ setImmediate(
32627
+ () => fetch(url, {
32628
+ method: "POST",
32629
+ headers: {
32630
+ "Authorization": `Splunk ${cfg.token}`,
32631
+ "Content-Type": "application/json"
32632
+ },
32633
+ body: JSON.stringify(toSplunkEvent(payload))
32634
+ }).catch(() => void 0)
32635
+ );
32636
+ }
32637
+ function toSentinelRecord(payload) {
32638
+ const record2 = {
32639
+ TimeGenerated: payload.timestamp,
32640
+ EventType: payload.event_type,
32641
+ SessionIdPrefix: payload.session.id_prefix,
32642
+ AiTool: payload.session.ai_tool ?? "",
32643
+ OS: process.platform,
32644
+ ChronVersion: version4,
32645
+ Computer: (0, import_os2.hostname)(),
32646
+ Role: "",
32647
+ DetectionType: "",
32648
+ MaskedValue: ""
32649
+ };
32650
+ if (payload.event_type === "message_logged") {
32651
+ record2.Role = payload.message.role;
32652
+ } else if (payload.event_type === "secret_detected") {
32653
+ record2.DetectionType = payload.detection.type;
32654
+ record2.MaskedValue = payload.detection.masked_value;
32655
+ }
32656
+ return record2;
32657
+ }
32658
+ function emitToSentinel(payload) {
32659
+ const dce = process.env.CHRON_SENTINEL_DCE;
32660
+ const dcrId = process.env.CHRON_SENTINEL_DCR_ID;
32661
+ const stream = process.env.CHRON_SENTINEL_STREAM;
32662
+ const tenantId = process.env.CHRON_SENTINEL_TENANT_ID;
32663
+ const clientId = process.env.CHRON_SENTINEL_CLIENT_ID;
32664
+ const clientSecret = process.env.CHRON_SENTINEL_CLIENT_SECRET;
32665
+ if (!dce || !dcrId || !stream || !tenantId || !clientId || !clientSecret)
32666
+ return;
32667
+ setImmediate(async () => {
32668
+ try {
32669
+ const token = await getAzureToken(tenantId, clientId, clientSecret);
32670
+ if (!token)
32671
+ return;
32672
+ const url = `${dce}/dataCollectionRules/${dcrId}/streams/${stream}?api-version=2023-01-01`;
32673
+ await fetch(url, {
32674
+ method: "POST",
32675
+ headers: {
32676
+ "Authorization": `Bearer ${token}`,
32677
+ "Content-Type": "application/json"
32678
+ },
32679
+ body: JSON.stringify([toSentinelRecord(payload)])
32680
+ });
32681
+ } catch {
32682
+ }
32683
+ });
32684
+ }
32685
+ function toLogScaleAttributes(payload) {
32686
+ const attrs = {
32687
+ event_type: payload.event_type,
32688
+ session_id_prefix: payload.session.id_prefix,
32689
+ ai_tool: payload.session.ai_tool ?? "",
32690
+ os: process.platform,
32691
+ chron_version: version4
32692
+ };
32693
+ if (payload.event_type === "message_logged") {
32694
+ attrs.role = payload.message.role;
32695
+ } else if (payload.event_type === "secret_detected") {
32696
+ attrs.detection_type = payload.detection.type;
32697
+ attrs.masked_value = payload.detection.masked_value;
32698
+ }
32699
+ return attrs;
32700
+ }
32701
+ function emitToLogScale(payload) {
32702
+ const url = process.env.CHRON_LOGSCALE_URL;
32703
+ const token = process.env.CHRON_LOGSCALE_TOKEN;
32704
+ if (!url || !token)
32705
+ return;
32706
+ const body = JSON.stringify([{
32707
+ tags: { host: (0, import_os2.hostname)(), source: "chron-mcp" },
32708
+ events: [{ timestamp: payload.timestamp, attributes: toLogScaleAttributes(payload) }]
32709
+ }]);
32710
+ setImmediate(
32711
+ () => fetch(url, {
32712
+ method: "POST",
32713
+ headers: {
32714
+ "Authorization": `Bearer ${token}`,
32715
+ "Content-Type": "application/json"
32716
+ },
32717
+ body
32718
+ }).catch(() => void 0)
32719
+ );
32720
+ }
32721
+ function emitEvent(payload) {
32722
+ const url = process.env.CHRON_RELAY_URL;
32723
+ const token = process.env.CHRON_RELAY_TOKEN;
32724
+ if (url && token) {
32725
+ const event = {
32726
+ schema_version: "1.0",
32727
+ chron_version: version4,
32728
+ machine_id: getMachineId(),
32729
+ os: process.platform,
32730
+ ...payload
32731
+ };
32732
+ setImmediate(
32733
+ () => fetch(url, {
32734
+ method: "POST",
32735
+ headers: {
32736
+ "Authorization": `Bearer ${token}`,
32737
+ "Content-Type": "application/json"
32738
+ },
32739
+ body: JSON.stringify(event)
32740
+ }).catch(() => void 0)
32741
+ );
32742
+ }
32743
+ emitToLogScale(payload);
32744
+ emitToSentinel(payload);
32745
+ emitToSplunk(payload);
32746
+ }
32747
+ var import_fs2, import_path2, import_crypto3, import_os2, _splunkCache, _splunkCacheExpiry, _azureTokenCache, _machineId;
32748
+ var init_relay = __esm({
32749
+ "src/utils/relay.ts"() {
32750
+ "use strict";
32751
+ import_fs2 = require("fs");
32752
+ import_path2 = require("path");
32753
+ import_crypto3 = require("crypto");
32754
+ import_os2 = require("os");
32755
+ init_package();
32756
+ if (process.env.CHRON_SPLUNK_INSECURE === "1") {
32757
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
32758
+ }
32759
+ _splunkCache = null;
32760
+ _splunkCacheExpiry = 0;
32761
+ _azureTokenCache = null;
32762
+ _machineId = null;
32763
+ }
32764
+ });
32765
+
32538
32766
  // src/tools/sessions.ts
32539
32767
  function startSession(db) {
32540
32768
  return async (args) => {
@@ -32548,6 +32776,7 @@ function startSession(db) {
32548
32776
  created_at: now,
32549
32777
  updated_at: now
32550
32778
  });
32779
+ emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: id.slice(0, 8), ai_tool: args.ai_tool ?? null } });
32551
32780
  return {
32552
32781
  content: [{
32553
32782
  type: "text",
@@ -32562,6 +32791,7 @@ function startSession(db) {
32562
32791
  const session = existing[0];
32563
32792
  const [countRow] = await db.select({ count: sql`count(*)` }).from(messages).where(eq(messages.session_id, session.id));
32564
32793
  await db.update(sessions).set({ updated_at: now }).where(eq(sessions.id, session.id));
32794
+ emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: session.id.slice(0, 8), ai_tool: session.ai_tool } });
32565
32795
  return {
32566
32796
  content: [{
32567
32797
  type: "text",
@@ -32600,6 +32830,7 @@ function initSession(db) {
32600
32830
  created = false;
32601
32831
  ai_tool = session.ai_tool;
32602
32832
  }
32833
+ emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: session_id.slice(0, 8), ai_tool } });
32603
32834
  const limit = args.limit ?? 10;
32604
32835
  const [countRow] = await db.select({
32605
32836
  count: sql`count(*)`,
@@ -32683,18 +32914,19 @@ var init_sessions = __esm({
32683
32914
  init_esm2();
32684
32915
  init_schema();
32685
32916
  init_time();
32917
+ init_relay();
32686
32918
  }
32687
32919
  });
32688
32920
 
32689
32921
  // src/utils/hash.ts
32690
32922
  function computeContentHash(sessionId, role, content, createdAt, prevHash) {
32691
- return (0, import_crypto3.createHash)("sha256").update(`${sessionId}|${role}|${content}|${createdAt}|${prevHash ?? ""}`).digest("hex");
32923
+ return (0, import_crypto4.createHash)("sha256").update(`${sessionId}|${role}|${content}|${createdAt}|${prevHash ?? ""}`).digest("hex");
32692
32924
  }
32693
- var import_crypto3;
32925
+ var import_crypto4;
32694
32926
  var init_hash = __esm({
32695
32927
  "src/utils/hash.ts"() {
32696
32928
  "use strict";
32697
- import_crypto3 = require("crypto");
32929
+ import_crypto4 = require("crypto");
32698
32930
  }
32699
32931
  });
32700
32932
 
@@ -32823,16 +33055,19 @@ async function writeDetections(db, session_id, message_id, content) {
32823
33055
  if (found.length === 0)
32824
33056
  return;
32825
33057
  const now = localISOString();
32826
- await db.insert(secrets_detected).values(
32827
- found.map((s) => ({
32828
- id: v4_default(),
32829
- session_id,
32830
- message_id,
32831
- type: s.type,
32832
- masked_value: maskValue(s.value),
32833
- detected_at: now
32834
- }))
32835
- );
33058
+ const rows = found.map((s) => ({
33059
+ id: v4_default(),
33060
+ session_id,
33061
+ message_id,
33062
+ type: s.type,
33063
+ masked_value: maskValue(s.value),
33064
+ detected_at: now
33065
+ }));
33066
+ await db.insert(secrets_detected).values(rows);
33067
+ const sessionIdPrefix = session_id.slice(0, 8);
33068
+ for (const row of rows) {
33069
+ emitEvent({ event_type: "secret_detected", timestamp: now, session: { id_prefix: sessionIdPrefix, ai_tool: null }, detection: { type: row.type, masked_value: row.masked_value } });
33070
+ }
32836
33071
  }
32837
33072
  function isFkError(e) {
32838
33073
  return e?.message?.includes("FOREIGN KEY constraint failed") || e?.code === "SQLITE_CONSTRAINT_FOREIGNKEY" || e?.cause?.message?.includes("FOREIGN KEY constraint failed") || e?.cause?.extendedCode === "SQLITE_CONSTRAINT_FOREIGNKEY";
@@ -32842,6 +33077,7 @@ function logMessage(db) {
32842
33077
  let id;
32843
33078
  let now;
32844
33079
  let contentHash;
33080
+ let sessionAiTool;
32845
33081
  try {
32846
33082
  const result = await db.transaction(async (tx) => {
32847
33083
  const last = await tx.select({ content_hash: messages.content_hash }).from(messages).where(eq(messages.session_id, args.session_id)).orderBy(desc(messages.created_at), desc(sql`rowid`)).limit(1);
@@ -32859,17 +33095,20 @@ function logMessage(db) {
32859
33095
  content_hash: hash
32860
33096
  });
32861
33097
  await tx.update(sessions).set({ updated_at: ts }).where(eq(sessions.id, args.session_id));
32862
- return { id: msgId, now: ts, contentHash: hash };
33098
+ const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
33099
+ return { id: msgId, now: ts, contentHash: hash, ai_tool: sessionRow?.ai_tool ?? null };
32863
33100
  });
32864
33101
  id = result.id;
32865
33102
  now = result.now;
32866
33103
  contentHash = result.contentHash;
33104
+ sessionAiTool = result.ai_tool;
32867
33105
  } catch (e) {
32868
33106
  if (isFkError(e)) {
32869
33107
  return { content: [{ type: "text", text: `Session not found: ${args.session_id}` }], isError: true };
32870
33108
  }
32871
33109
  throw e;
32872
33110
  }
33111
+ emitEvent({ event_type: "message_logged", timestamp: now, session: { id_prefix: args.session_id.slice(0, 8), ai_tool: sessionAiTool }, message: { role: args.role } });
32873
33112
  if (args.role === "user") {
32874
33113
  setImmediate(() => writeDetections(db, args.session_id, id, args.content).catch(() => void 0));
32875
33114
  }
@@ -32886,6 +33125,7 @@ function logExchange(db) {
32886
33125
  let assistantNow;
32887
33126
  let userHash;
32888
33127
  let assistantHash;
33128
+ let sessionAiTool;
32889
33129
  try {
32890
33130
  const result = await db.transaction(async (tx) => {
32891
33131
  const last = await tx.select({ content_hash: messages.content_hash }).from(messages).where(eq(messages.session_id, args.session_id)).orderBy(desc(messages.created_at), desc(sql`rowid`)).limit(1);
@@ -32915,7 +33155,8 @@ function logExchange(db) {
32915
33155
  content_hash: aHash
32916
33156
  });
32917
33157
  await tx.update(sessions).set({ updated_at: aNow }).where(eq(sessions.id, args.session_id));
32918
- return { uId, aId, uNow, aNow, uHash, aHash };
33158
+ const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
33159
+ return { uId, aId, uNow, aNow, uHash, aHash, ai_tool: sessionRow?.ai_tool ?? null };
32919
33160
  });
32920
33161
  userId = result.uId;
32921
33162
  assistantId = result.aId;
@@ -32923,12 +33164,16 @@ function logExchange(db) {
32923
33164
  assistantNow = result.aNow;
32924
33165
  userHash = result.uHash;
32925
33166
  assistantHash = result.aHash;
33167
+ sessionAiTool = result.ai_tool;
32926
33168
  } catch (e) {
32927
33169
  if (isFkError(e)) {
32928
33170
  return { content: [{ type: "text", text: `Session not found: ${args.session_id}` }], isError: true };
32929
33171
  }
32930
33172
  throw e;
32931
33173
  }
33174
+ const idPrefix = args.session_id.slice(0, 8);
33175
+ emitEvent({ event_type: "message_logged", timestamp: userNow, session: { id_prefix: idPrefix, ai_tool: sessionAiTool }, message: { role: "user" } });
33176
+ emitEvent({ event_type: "message_logged", timestamp: assistantNow, session: { id_prefix: idPrefix, ai_tool: sessionAiTool }, message: { role: "assistant" } });
32932
33177
  setImmediate(() => writeDetections(db, args.session_id, userId, args.user_content).catch(() => void 0));
32933
33178
  return {
32934
33179
  content: [{
@@ -32954,6 +33199,7 @@ var init_messages = __esm({
32954
33199
  init_time();
32955
33200
  init_hash();
32956
33201
  init_detect();
33202
+ init_relay();
32957
33203
  }
32958
33204
  });
32959
33205
 
@@ -33082,14 +33328,6 @@ var init_detect2 = __esm({
33082
33328
  }
33083
33329
  });
33084
33330
 
33085
- // package.json
33086
- var version4;
33087
- var init_package = __esm({
33088
- "package.json"() {
33089
- version4 = "0.1.13";
33090
- }
33091
- });
33092
-
33093
33331
  // src/server.ts
33094
33332
  function createServer(db) {
33095
33333
  const server = new McpServer({
@@ -33208,24 +33446,24 @@ __export(setup_exports, {
33208
33446
  runSetup: () => runSetup
33209
33447
  });
33210
33448
  function configPath(...parts) {
33211
- return (0, import_path2.join)((0, import_os2.homedir)(), ...parts);
33449
+ return (0, import_path3.join)((0, import_os3.homedir)(), ...parts);
33212
33450
  }
33213
33451
  function readJson(filePath) {
33214
- if (!(0, import_fs2.existsSync)(filePath))
33452
+ if (!(0, import_fs3.existsSync)(filePath))
33215
33453
  return {};
33216
33454
  try {
33217
- return JSON.parse((0, import_fs2.readFileSync)(filePath, "utf8"));
33455
+ return JSON.parse((0, import_fs3.readFileSync)(filePath, "utf8"));
33218
33456
  } catch {
33219
33457
  return {};
33220
33458
  }
33221
33459
  }
33222
33460
  function writeJson(filePath, data) {
33223
- (0, import_fs2.mkdirSync)((0, import_path2.dirname)(filePath), { recursive: true });
33224
- (0, import_fs2.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf8");
33461
+ (0, import_fs3.mkdirSync)((0, import_path3.dirname)(filePath), { recursive: true });
33462
+ (0, import_fs3.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf8");
33225
33463
  }
33226
33464
  function configureTool(name, filePath) {
33227
- const dir = (0, import_path2.dirname)(filePath);
33228
- if (!(0, import_fs2.existsSync)(dir) && name !== "Claude Code") {
33465
+ const dir = (0, import_path3.dirname)(filePath);
33466
+ if (!(0, import_fs3.existsSync)(dir) && name !== "Claude Code") {
33229
33467
  return { tool: name, status: "skipped" };
33230
33468
  }
33231
33469
  try {
@@ -33246,7 +33484,7 @@ function configureClaudeCode() {
33246
33484
  try {
33247
33485
  (0, import_child_process.execSync)("claude mcp add chron -- npx -y chron-mcp", { stdio: "pipe" });
33248
33486
  } catch {
33249
- const result = configureTool("Claude Code", (0, import_path2.join)((0, import_os2.homedir)(), ".claude", "settings.json"));
33487
+ const result = configureTool("Claude Code", (0, import_path3.join)((0, import_os3.homedir)(), ".claude", "settings.json"));
33250
33488
  if (result.status === "error")
33251
33489
  return result;
33252
33490
  }
@@ -33254,13 +33492,13 @@ function configureClaudeCode() {
33254
33492
  return { tool: "Claude Code", status: "added" };
33255
33493
  }
33256
33494
  function installClaudeCodeHook() {
33257
- const skillSrc = (0, import_path2.join)(__dirname, "..", "skills", "chron.skill.md");
33258
- const skillDst = (0, import_path2.join)((0, import_os2.homedir)(), ".chron", "chron.skill.md");
33259
- if ((0, import_fs2.existsSync)(skillSrc)) {
33260
- (0, import_fs2.mkdirSync)((0, import_path2.dirname)(skillDst), { recursive: true });
33261
- (0, import_fs2.copyFileSync)(skillSrc, skillDst);
33495
+ const skillSrc = (0, import_path3.join)(__dirname, "..", "skills", "chron.skill.md");
33496
+ const skillDst = (0, import_path3.join)((0, import_os3.homedir)(), ".chron", "chron.skill.md");
33497
+ if ((0, import_fs3.existsSync)(skillSrc)) {
33498
+ (0, import_fs3.mkdirSync)((0, import_path3.dirname)(skillDst), { recursive: true });
33499
+ (0, import_fs3.copyFileSync)(skillSrc, skillDst);
33262
33500
  }
33263
- const settingsPath = (0, import_path2.join)((0, import_os2.homedir)(), ".claude", "settings.json");
33501
+ const settingsPath = (0, import_path3.join)((0, import_os3.homedir)(), ".claude", "settings.json");
33264
33502
  const settings = readJson(settingsPath);
33265
33503
  if (!settings.hooks)
33266
33504
  settings.hooks = {};
@@ -33284,13 +33522,13 @@ async function runSetup() {
33284
33522
  }
33285
33523
  return results.filter((r) => r.status !== "skipped");
33286
33524
  }
33287
- var import_fs2, import_os2, import_path2, import_child_process, CHRON_ENTRY, TOOLS;
33525
+ var import_fs3, import_os3, import_path3, import_child_process, CHRON_ENTRY, TOOLS;
33288
33526
  var init_setup = __esm({
33289
33527
  "src/setup.ts"() {
33290
33528
  "use strict";
33291
- import_fs2 = require("fs");
33292
- import_os2 = require("os");
33293
- import_path2 = require("path");
33529
+ import_fs3 = require("fs");
33530
+ import_os3 = require("os");
33531
+ import_path3 = require("path");
33294
33532
  import_child_process = require("child_process");
33295
33533
  CHRON_ENTRY = {
33296
33534
  command: "npx",
@@ -33299,11 +33537,11 @@ var init_setup = __esm({
33299
33537
  TOOLS = [
33300
33538
  {
33301
33539
  name: "Claude Desktop",
33302
- path: process.platform === "win32" ? (0, import_path2.join)(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : configPath("Library", "Application Support", "Claude", "claude_desktop_config.json")
33540
+ path: process.platform === "win32" ? (0, import_path3.join)(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : configPath("Library", "Application Support", "Claude", "claude_desktop_config.json")
33303
33541
  },
33304
33542
  {
33305
33543
  name: "Cursor",
33306
- path: process.platform === "win32" ? (0, import_path2.join)(process.env.APPDATA ?? "", "Cursor", "User", "globalStorage", "cursor.mcp", "mcp.json") : configPath(".cursor", "mcp.json")
33544
+ path: process.platform === "win32" ? (0, import_path3.join)(process.env.APPDATA ?? "", "Cursor", "User", "globalStorage", "cursor.mcp", "mcp.json") : configPath(".cursor", "mcp.json")
33307
33545
  },
33308
33546
  {
33309
33547
  name: "Windsurf",
@@ -53491,7 +53729,7 @@ var require_view = __commonJS({
53491
53729
  var dirname3 = path.dirname;
53492
53730
  var basename = path.basename;
53493
53731
  var extname = path.extname;
53494
- var join4 = path.join;
53732
+ var join5 = path.join;
53495
53733
  var resolve = path.resolve;
53496
53734
  module2.exports = View2;
53497
53735
  function View2(name, options) {
@@ -53539,12 +53777,12 @@ var require_view = __commonJS({
53539
53777
  };
53540
53778
  View2.prototype.resolve = function resolve2(dir, file) {
53541
53779
  var ext = this.ext;
53542
- var path2 = join4(dir, file);
53780
+ var path2 = join5(dir, file);
53543
53781
  var stat = tryStat(path2);
53544
53782
  if (stat && stat.isFile()) {
53545
53783
  return path2;
53546
53784
  }
53547
- path2 = join4(dir, basename(file, ext), "index" + ext);
53785
+ path2 = join5(dir, basename(file, ext), "index" + ext);
53548
53786
  stat = tryStat(path2);
53549
53787
  if (stat && stat.isFile()) {
53550
53788
  return path2;
@@ -54611,7 +54849,7 @@ var require_send = __commonJS({
54611
54849
  var Stream2 = require("stream");
54612
54850
  var util2 = require("util");
54613
54851
  var extname = path.extname;
54614
- var join4 = path.join;
54852
+ var join5 = path.join;
54615
54853
  var normalize = path.normalize;
54616
54854
  var resolve = path.resolve;
54617
54855
  var sep = path.sep;
@@ -54830,7 +55068,7 @@ var require_send = __commonJS({
54830
55068
  return res;
54831
55069
  }
54832
55070
  parts = path2.split(sep);
54833
- path2 = normalize(join4(root, path2));
55071
+ path2 = normalize(join5(root, path2));
54834
55072
  } else {
54835
55073
  if (UP_PATH_REGEXP.test(path2)) {
54836
55074
  debug('malicious path "%s"', path2);
@@ -54971,7 +55209,7 @@ var require_send = __commonJS({
54971
55209
  return self.onStatError(err);
54972
55210
  return self.error(404);
54973
55211
  }
54974
- var p = join4(path2, self._index[i]);
55212
+ var p = join5(path2, self._index[i]);
54975
55213
  debug('stat "%s"', p);
54976
55214
  fs.stat(p, function(err2, stat) {
54977
55215
  if (err2)
@@ -57090,17 +57328,17 @@ var require_request = __commonJS({
57090
57328
  return addrs;
57091
57329
  });
57092
57330
  defineGetter(req, "subdomains", function subdomains() {
57093
- var hostname2 = this.hostname;
57094
- if (!hostname2)
57331
+ var hostname3 = this.hostname;
57332
+ if (!hostname3)
57095
57333
  return [];
57096
57334
  var offset = this.app.get("subdomain offset");
57097
- var subdomains2 = !isIP(hostname2) ? hostname2.split(".").reverse() : [hostname2];
57335
+ var subdomains2 = !isIP(hostname3) ? hostname3.split(".").reverse() : [hostname3];
57098
57336
  return subdomains2.slice(offset);
57099
57337
  });
57100
57338
  defineGetter(req, "path", function path() {
57101
57339
  return parse3(this).pathname;
57102
57340
  });
57103
- defineGetter(req, "hostname", function hostname2() {
57341
+ defineGetter(req, "hostname", function hostname3() {
57104
57342
  var trust = this.app.get("trust proxy fn");
57105
57343
  var host = this.get("X-Forwarded-Host");
57106
57344
  if (!host || !trust(this.connection.remoteAddress, 0)) {
@@ -62419,8 +62657,8 @@ var StdioServerTransport = class {
62419
62657
  };
62420
62658
 
62421
62659
  // src/index.ts
62422
- var import_os3 = require("os");
62423
- var import_path3 = require("path");
62660
+ var import_os4 = require("os");
62661
+ var import_path4 = require("path");
62424
62662
 
62425
62663
  // node_modules/@libsql/core/lib-esm/api.js
62426
62664
  var LibsqlError = class extends Error {
@@ -66420,8 +66658,8 @@ var HttpStream = class extends Stream {
66420
66658
  let promise;
66421
66659
  try {
66422
66660
  const request = createRequest();
66423
- const fetch = this.#fetch;
66424
- promise = fetch(request);
66661
+ const fetch2 = this.#fetch;
66662
+ promise = fetch2(request);
66425
66663
  } catch (error2) {
66426
66664
  promise = Promise.reject(error2);
66427
66665
  }
@@ -66641,11 +66879,11 @@ var HttpClient = class extends Client {
66641
66879
  }
66642
66880
  };
66643
66881
  async function findEndpoint(customFetch, clientUrl) {
66644
- const fetch = customFetch;
66882
+ const fetch2 = customFetch;
66645
66883
  for (const endpoint of checkEndpoints) {
66646
66884
  const url = new URL(endpoint.versionPath, clientUrl);
66647
66885
  const request = new Request(url.toString(), { method: "GET" });
66648
- const response = await fetch(request);
66886
+ const response = await fetch2(request);
66649
66887
  await response.arrayBuffer();
66650
66888
  if (response.ok) {
66651
66889
  return endpoint;
@@ -67896,7 +68134,7 @@ if (process.argv[2] === "--version" || process.argv[2] === "-v") {
67896
68134
  process.exit(0);
67897
68135
  }
67898
68136
  async function main() {
67899
- const dbPath = process.env.CHRON_DB_PATH ?? (0, import_path3.join)((0, import_os3.homedir)(), ".chron", "chron.db");
68137
+ const dbPath = process.env.CHRON_DB_PATH ?? (0, import_path4.join)((0, import_os4.homedir)(), ".chron", "chron.db");
67900
68138
  if (process.stdin.isTTY) {
67901
68139
  process.stdout.write(`chron-mcp ${version4}
67902
68140