chron-mcp 0.1.13 → 0.1.14
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/dashboards/logscale/ai-tool-usage.lql +5 -0
- package/dashboards/logscale/api-key-alert.lql +5 -0
- package/dashboards/logscale/chron-ai-activity.yaml +66 -0
- package/dashboards/logscale/daily-active-developers.lql +3 -0
- package/dashboards/logscale/secrets-by-type.lql +3 -0
- package/dashboards/logscale/sessions-by-developer.lql +6 -0
- package/dist/cli/index.js +263 -13
- package/dist/index.js +139 -43
- package/package.json +2 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Alert: API key or credential sent to AI tool
|
|
2
|
+
// Use as a Scheduled Search alert — notify SOC on any match
|
|
3
|
+
event_type = "secret_detected"
|
|
4
|
+
| detection_type in ["api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt"]
|
|
5
|
+
| table([#host, ai_tool, detection_type, masked_value, session_id_prefix, @timestamp])
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
$schema: "https://schemas.humio.com/dashboard/v0.1.0"
|
|
2
|
+
name: "Chron — AI Activity"
|
|
3
|
+
updateFrequency: 60
|
|
4
|
+
timeSelector:
|
|
5
|
+
defaultRelativeTimeRange: "7d"
|
|
6
|
+
|
|
7
|
+
widgets:
|
|
8
|
+
- id: daily-active-developers
|
|
9
|
+
title: "Daily Active Developers"
|
|
10
|
+
type: time-chart
|
|
11
|
+
x: 0
|
|
12
|
+
y: 0
|
|
13
|
+
width: 8
|
|
14
|
+
height: 4
|
|
15
|
+
query: |
|
|
16
|
+
event_type = "session_started"
|
|
17
|
+
| timechart(unit=1d, function=count(#host, distinct=true))
|
|
18
|
+
|
|
19
|
+
- id: ai-tool-usage
|
|
20
|
+
title: "AI Tool Usage"
|
|
21
|
+
type: pie-chart
|
|
22
|
+
x: 8
|
|
23
|
+
y: 0
|
|
24
|
+
width: 4
|
|
25
|
+
height: 4
|
|
26
|
+
query: |
|
|
27
|
+
event_type = "session_started"
|
|
28
|
+
| groupby(ai_tool, function=count())
|
|
29
|
+
| rename(count(), as=sessions)
|
|
30
|
+
| sort(sessions, order=desc)
|
|
31
|
+
|
|
32
|
+
- id: secrets-by-type
|
|
33
|
+
title: "Secrets Detected by Type (7d)"
|
|
34
|
+
type: time-chart
|
|
35
|
+
x: 0
|
|
36
|
+
y: 4
|
|
37
|
+
width: 8
|
|
38
|
+
height: 4
|
|
39
|
+
query: |
|
|
40
|
+
event_type = "secret_detected"
|
|
41
|
+
| timechart(detection_type, unit=1d, function=count())
|
|
42
|
+
|
|
43
|
+
- id: sessions-by-developer
|
|
44
|
+
title: "Sessions by Developer"
|
|
45
|
+
type: table
|
|
46
|
+
x: 8
|
|
47
|
+
y: 4
|
|
48
|
+
width: 4
|
|
49
|
+
height: 4
|
|
50
|
+
query: |
|
|
51
|
+
event_type = "session_started"
|
|
52
|
+
| groupby([#host, ai_tool], function=count())
|
|
53
|
+
| rename(count(), as=sessions)
|
|
54
|
+
| sort(sessions, order=desc)
|
|
55
|
+
|
|
56
|
+
- id: api-key-alerts
|
|
57
|
+
title: "Credential Exposures — Requires Attention"
|
|
58
|
+
type: table
|
|
59
|
+
x: 0
|
|
60
|
+
y: 8
|
|
61
|
+
width: 12
|
|
62
|
+
height: 4
|
|
63
|
+
query: |
|
|
64
|
+
event_type = "secret_detected"
|
|
65
|
+
| detection_type in ["api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt"]
|
|
66
|
+
| table([#host, ai_tool, detection_type, masked_value, session_id_prefix, @timestamp])
|
package/dist/cli/index.js
CHANGED
|
@@ -1184,7 +1184,7 @@ var init_sql = __esm({
|
|
|
1184
1184
|
return new SQL([new StringChunk(str)]);
|
|
1185
1185
|
}
|
|
1186
1186
|
sql2.raw = raw;
|
|
1187
|
-
function
|
|
1187
|
+
function join4(chunks, separator) {
|
|
1188
1188
|
const result = [];
|
|
1189
1189
|
for (const [i, chunk] of chunks.entries()) {
|
|
1190
1190
|
if (i > 0 && separator !== void 0) {
|
|
@@ -1194,7 +1194,7 @@ var init_sql = __esm({
|
|
|
1194
1194
|
}
|
|
1195
1195
|
return new SQL(result);
|
|
1196
1196
|
}
|
|
1197
|
-
sql2.join =
|
|
1197
|
+
sql2.join = join4;
|
|
1198
1198
|
function identifier(value) {
|
|
1199
1199
|
return new Name(value);
|
|
1200
1200
|
}
|
|
@@ -2806,7 +2806,7 @@ var require_filesystem = __commonJS({
|
|
|
2806
2806
|
"use strict";
|
|
2807
2807
|
var fs = require("fs");
|
|
2808
2808
|
var LDD_PATH = "/usr/bin/ldd";
|
|
2809
|
-
var
|
|
2809
|
+
var readFileSync2 = (path) => fs.readFileSync(path, "utf-8");
|
|
2810
2810
|
var readFile = (path) => new Promise((resolve, reject) => {
|
|
2811
2811
|
fs.readFile(path, "utf-8", (err, data) => {
|
|
2812
2812
|
if (err) {
|
|
@@ -2818,7 +2818,7 @@ var require_filesystem = __commonJS({
|
|
|
2818
2818
|
});
|
|
2819
2819
|
module2.exports = {
|
|
2820
2820
|
LDD_PATH,
|
|
2821
|
-
readFileSync,
|
|
2821
|
+
readFileSync: readFileSync2,
|
|
2822
2822
|
readFile
|
|
2823
2823
|
};
|
|
2824
2824
|
}
|
|
@@ -2830,7 +2830,7 @@ var require_detect_libc = __commonJS({
|
|
|
2830
2830
|
"use strict";
|
|
2831
2831
|
var childProcess = require("child_process");
|
|
2832
2832
|
var { isLinux, getReport } = require_process();
|
|
2833
|
-
var { LDD_PATH, readFile, readFileSync } = require_filesystem();
|
|
2833
|
+
var { LDD_PATH, readFile, readFileSync: readFileSync2 } = require_filesystem();
|
|
2834
2834
|
var cachedFamilyFilesystem;
|
|
2835
2835
|
var cachedVersionFilesystem;
|
|
2836
2836
|
var command2 = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
|
|
@@ -2911,7 +2911,7 @@ var require_detect_libc = __commonJS({
|
|
|
2911
2911
|
}
|
|
2912
2912
|
cachedFamilyFilesystem = null;
|
|
2913
2913
|
try {
|
|
2914
|
-
const lddContent =
|
|
2914
|
+
const lddContent = readFileSync2(LDD_PATH);
|
|
2915
2915
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
2916
2916
|
} catch (e) {
|
|
2917
2917
|
}
|
|
@@ -2968,7 +2968,7 @@ var require_detect_libc = __commonJS({
|
|
|
2968
2968
|
}
|
|
2969
2969
|
cachedVersionFilesystem = null;
|
|
2970
2970
|
try {
|
|
2971
|
-
const lddContent =
|
|
2971
|
+
const lddContent = readFileSync2(LDD_PATH);
|
|
2972
2972
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
2973
2973
|
if (versionMatch) {
|
|
2974
2974
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -11068,8 +11068,8 @@ var init_stream3 = __esm({
|
|
|
11068
11068
|
let promise;
|
|
11069
11069
|
try {
|
|
11070
11070
|
const request = createRequest();
|
|
11071
|
-
const
|
|
11072
|
-
promise =
|
|
11071
|
+
const fetch2 = this.#fetch;
|
|
11072
|
+
promise = fetch2(request);
|
|
11073
11073
|
} catch (error) {
|
|
11074
11074
|
promise = Promise.reject(error);
|
|
11075
11075
|
}
|
|
@@ -11136,11 +11136,11 @@ var init_stream3 = __esm({
|
|
|
11136
11136
|
|
|
11137
11137
|
// node_modules/@libsql/hrana-client/lib-esm/http/client.js
|
|
11138
11138
|
async function findEndpoint(customFetch, clientUrl) {
|
|
11139
|
-
const
|
|
11139
|
+
const fetch2 = customFetch;
|
|
11140
11140
|
for (const endpoint of checkEndpoints) {
|
|
11141
11141
|
const url = new URL(endpoint.versionPath, clientUrl);
|
|
11142
11142
|
const request = new Request(url.toString(), { method: "GET" });
|
|
11143
|
-
const response = await
|
|
11143
|
+
const response = await fetch2(request);
|
|
11144
11144
|
await response.arrayBuffer();
|
|
11145
11145
|
if (response.ok) {
|
|
11146
11146
|
return endpoint;
|
|
@@ -14252,7 +14252,7 @@ var init_select2 = __esm({
|
|
|
14252
14252
|
const tableName = getTableLikeName(table);
|
|
14253
14253
|
for (const item of extractUsedTable(table))
|
|
14254
14254
|
this.usedTables.add(item);
|
|
14255
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
14255
|
+
if (typeof tableName === "string" && this.config.joins?.some((join4) => join4.alias === tableName)) {
|
|
14256
14256
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
14257
14257
|
}
|
|
14258
14258
|
if (!this.isPartialSelect) {
|
|
@@ -15141,7 +15141,7 @@ var init_update = __esm({
|
|
|
15141
15141
|
createJoin(joinType) {
|
|
15142
15142
|
return (table, on) => {
|
|
15143
15143
|
const tableName = getTableLikeName(table);
|
|
15144
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
15144
|
+
if (typeof tableName === "string" && this.config.joins.some((join4) => join4.alias === tableName)) {
|
|
15145
15145
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
15146
15146
|
}
|
|
15147
15147
|
if (typeof on === "function") {
|
|
@@ -17026,6 +17026,250 @@ var init_secrets = __esm({
|
|
|
17026
17026
|
}
|
|
17027
17027
|
});
|
|
17028
17028
|
|
|
17029
|
+
// package.json
|
|
17030
|
+
var require_package = __commonJS({
|
|
17031
|
+
"package.json"(exports2, module2) {
|
|
17032
|
+
module2.exports = {
|
|
17033
|
+
name: "chron-mcp",
|
|
17034
|
+
version: "0.1.14",
|
|
17035
|
+
mcpName: "io.github.sirinivask/chron",
|
|
17036
|
+
description: "Audit-grade timestamped logs for every AI conversation",
|
|
17037
|
+
repository: {
|
|
17038
|
+
type: "git",
|
|
17039
|
+
url: "https://github.com/sirinivask/chron.git"
|
|
17040
|
+
},
|
|
17041
|
+
main: "dist/index.js",
|
|
17042
|
+
vitest: {
|
|
17043
|
+
include: [
|
|
17044
|
+
"tests/**/*.test.ts"
|
|
17045
|
+
],
|
|
17046
|
+
globals: true
|
|
17047
|
+
},
|
|
17048
|
+
bin: {
|
|
17049
|
+
"chron-mcp": "dist/index.js",
|
|
17050
|
+
chron: "dist/cli/index.js"
|
|
17051
|
+
},
|
|
17052
|
+
files: [
|
|
17053
|
+
"dist",
|
|
17054
|
+
"skills",
|
|
17055
|
+
".claude-plugin",
|
|
17056
|
+
"assets",
|
|
17057
|
+
"dashboards",
|
|
17058
|
+
"README.md"
|
|
17059
|
+
],
|
|
17060
|
+
engines: {
|
|
17061
|
+
node: ">=18"
|
|
17062
|
+
},
|
|
17063
|
+
scripts: {
|
|
17064
|
+
build: "npx esbuild src/index.ts --bundle --format=cjs --outfile=dist/index.js --platform=node && chmod +x dist/index.js && npx esbuild src/cli/index.ts --bundle --format=cjs --outfile=dist/cli/index.js --platform=node && chmod +x dist/cli/index.js",
|
|
17065
|
+
"build:cli": "npx esbuild src/cli/index.ts --bundle --format=cjs --outfile=dist/cli/index.js --platform=node && chmod +x dist/cli/index.js",
|
|
17066
|
+
typecheck: "tsc --noEmit",
|
|
17067
|
+
dev: "tsc --watch",
|
|
17068
|
+
start: "node dist/index.js",
|
|
17069
|
+
test: "vitest run",
|
|
17070
|
+
"test:watch": "vitest",
|
|
17071
|
+
prepublishOnly: "npm test && npm run build"
|
|
17072
|
+
},
|
|
17073
|
+
keywords: [
|
|
17074
|
+
"mcp",
|
|
17075
|
+
"ai",
|
|
17076
|
+
"audit",
|
|
17077
|
+
"logging",
|
|
17078
|
+
"claude",
|
|
17079
|
+
"cursor"
|
|
17080
|
+
],
|
|
17081
|
+
license: "SEE LICENSE IN LICENSE",
|
|
17082
|
+
dependencies: {
|
|
17083
|
+
"@libsql/client": "^0.17.3",
|
|
17084
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
17085
|
+
"drizzle-orm": "^0.45.2",
|
|
17086
|
+
express: "^4.18.2",
|
|
17087
|
+
uuid: "^11.1.1",
|
|
17088
|
+
zod: "^3.22.4"
|
|
17089
|
+
},
|
|
17090
|
+
devDependencies: {
|
|
17091
|
+
"@types/express": "^4.17.21",
|
|
17092
|
+
"@types/node": "^20.0.0",
|
|
17093
|
+
"@types/uuid": "^9.0.0",
|
|
17094
|
+
"drizzle-kit": "^0.20.14",
|
|
17095
|
+
typescript: "^5.4.5",
|
|
17096
|
+
vitest: "^1.4.0"
|
|
17097
|
+
}
|
|
17098
|
+
};
|
|
17099
|
+
}
|
|
17100
|
+
});
|
|
17101
|
+
|
|
17102
|
+
// src/cli/connect.ts
|
|
17103
|
+
var connect_exports = {};
|
|
17104
|
+
__export(connect_exports, {
|
|
17105
|
+
runConnect: () => runConnect
|
|
17106
|
+
});
|
|
17107
|
+
function prompt(rl, question) {
|
|
17108
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
17109
|
+
}
|
|
17110
|
+
function configPath() {
|
|
17111
|
+
return (0, import_path3.join)((0, import_os3.homedir)(), ".chron", "config.json");
|
|
17112
|
+
}
|
|
17113
|
+
function loadConfig() {
|
|
17114
|
+
try {
|
|
17115
|
+
return JSON.parse((0, import_fs2.readFileSync)(configPath(), "utf8"));
|
|
17116
|
+
} catch {
|
|
17117
|
+
return {};
|
|
17118
|
+
}
|
|
17119
|
+
}
|
|
17120
|
+
function saveConfig(data) {
|
|
17121
|
+
const dir = (0, import_path3.join)((0, import_os3.homedir)(), ".chron");
|
|
17122
|
+
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
17123
|
+
(0, import_fs2.writeFileSync)(configPath(), JSON.stringify(data, null, 2), "utf8");
|
|
17124
|
+
}
|
|
17125
|
+
async function connectCrowdStrike() {
|
|
17126
|
+
process.stdout.write(`
|
|
17127
|
+
${BOLD5}Connect Chron \u2192 CrowdStrike LogScale${RESET5}
|
|
17128
|
+
|
|
17129
|
+
`);
|
|
17130
|
+
process.stdout.write(`${DIM4}Events will be sent directly to your LogScale repository.
|
|
17131
|
+
`);
|
|
17132
|
+
process.stdout.write(`No message content is transmitted \u2014 metadata only.${RESET5}
|
|
17133
|
+
|
|
17134
|
+
`);
|
|
17135
|
+
const rl = (0, import_readline.createInterface)({ input: process.stdin, output: process.stdout });
|
|
17136
|
+
let url;
|
|
17137
|
+
let token;
|
|
17138
|
+
try {
|
|
17139
|
+
url = (await prompt(rl, ` LogScale ingest URL ${DIM4}(e.g. https://cloud.us.humio.com/api/v1/ingest/humio-structured)${RESET5}
|
|
17140
|
+
${CYAN4}>${RESET5} `)).trim();
|
|
17141
|
+
if (!url.startsWith("https://")) {
|
|
17142
|
+
process.stdout.write(`
|
|
17143
|
+
${RED}URL must start with https://${RESET5}
|
|
17144
|
+
`);
|
|
17145
|
+
process.exit(1);
|
|
17146
|
+
}
|
|
17147
|
+
token = (await prompt(rl, `
|
|
17148
|
+
LogScale ingest token
|
|
17149
|
+
${CYAN4}>${RESET5} `)).trim();
|
|
17150
|
+
if (!token) {
|
|
17151
|
+
process.stdout.write(`
|
|
17152
|
+
${RED}Token cannot be empty${RESET5}
|
|
17153
|
+
`);
|
|
17154
|
+
process.exit(1);
|
|
17155
|
+
}
|
|
17156
|
+
} finally {
|
|
17157
|
+
rl.close();
|
|
17158
|
+
}
|
|
17159
|
+
process.stdout.write(`
|
|
17160
|
+
${DIM4}Sending test event...${RESET5} `);
|
|
17161
|
+
const testPayload = JSON.stringify([{
|
|
17162
|
+
tags: { host: require("os").hostname(), source: "chron-mcp" },
|
|
17163
|
+
events: [{
|
|
17164
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17165
|
+
attributes: {
|
|
17166
|
+
event_type: "connection_test",
|
|
17167
|
+
chron_version: require_package().version,
|
|
17168
|
+
os: process.platform,
|
|
17169
|
+
message: "chron connect crowdstrike \u2014 test event"
|
|
17170
|
+
}
|
|
17171
|
+
}]
|
|
17172
|
+
}]);
|
|
17173
|
+
let ok = false;
|
|
17174
|
+
let statusCode = 0;
|
|
17175
|
+
try {
|
|
17176
|
+
const res = await fetch(url, {
|
|
17177
|
+
method: "POST",
|
|
17178
|
+
headers: {
|
|
17179
|
+
"Authorization": `Bearer ${token}`,
|
|
17180
|
+
"Content-Type": "application/json"
|
|
17181
|
+
},
|
|
17182
|
+
body: testPayload
|
|
17183
|
+
});
|
|
17184
|
+
statusCode = res.status;
|
|
17185
|
+
ok = res.ok;
|
|
17186
|
+
} catch (e) {
|
|
17187
|
+
process.stdout.write(`${RED}failed${RESET5}
|
|
17188
|
+
`);
|
|
17189
|
+
process.stderr.write(` ${RED}Error: ${e.message}${RESET5}
|
|
17190
|
+
|
|
17191
|
+
`);
|
|
17192
|
+
process.exit(1);
|
|
17193
|
+
}
|
|
17194
|
+
if (!ok) {
|
|
17195
|
+
process.stdout.write(`${RED}failed (HTTP ${statusCode})${RESET5}
|
|
17196
|
+
`);
|
|
17197
|
+
process.stderr.write(` ${RED}Check your URL and token, then try again.${RESET5}
|
|
17198
|
+
|
|
17199
|
+
`);
|
|
17200
|
+
process.exit(1);
|
|
17201
|
+
}
|
|
17202
|
+
process.stdout.write(`${GREEN}OK${RESET5}
|
|
17203
|
+
|
|
17204
|
+
`);
|
|
17205
|
+
const config = loadConfig();
|
|
17206
|
+
config.logscale = { url, connected_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
17207
|
+
saveConfig(config);
|
|
17208
|
+
process.stdout.write(`${GREEN}${BOLD5}Connected!${RESET5} Test event appeared in LogScale.
|
|
17209
|
+
|
|
17210
|
+
`);
|
|
17211
|
+
process.stdout.write(`${BOLD5}Add these env vars to your MCP client config:${RESET5}
|
|
17212
|
+
|
|
17213
|
+
`);
|
|
17214
|
+
process.stdout.write(` ${CYAN4}CHRON_LOGSCALE_URL${RESET5} ${url}
|
|
17215
|
+
`);
|
|
17216
|
+
process.stdout.write(` ${CYAN4}CHRON_LOGSCALE_TOKEN${RESET5} ${DIM4}<your-token>${RESET5}
|
|
17217
|
+
|
|
17218
|
+
`);
|
|
17219
|
+
process.stdout.write(`${DIM4}For Claude Code \u2014 add to the "env" block of the chron entry in ~/.claude.json:${RESET5}
|
|
17220
|
+
|
|
17221
|
+
`);
|
|
17222
|
+
process.stdout.write(` ${DIM4}"env": {
|
|
17223
|
+
`);
|
|
17224
|
+
process.stdout.write(` "CHRON_LOGSCALE_URL": "${url}",
|
|
17225
|
+
`);
|
|
17226
|
+
process.stdout.write(` "CHRON_LOGSCALE_TOKEN": "<your-token>"
|
|
17227
|
+
`);
|
|
17228
|
+
process.stdout.write(` }${RESET5}
|
|
17229
|
+
|
|
17230
|
+
`);
|
|
17231
|
+
process.stdout.write(`${DIM4}Connection saved to ~/.chron/config.json${RESET5}
|
|
17232
|
+
|
|
17233
|
+
`);
|
|
17234
|
+
}
|
|
17235
|
+
async function runConnect(args2) {
|
|
17236
|
+
const [subcommand] = args2;
|
|
17237
|
+
switch (subcommand) {
|
|
17238
|
+
case "crowdstrike":
|
|
17239
|
+
await connectCrowdStrike();
|
|
17240
|
+
break;
|
|
17241
|
+
default: {
|
|
17242
|
+
const name = subcommand ? `Unknown integration: ${subcommand}
|
|
17243
|
+
|
|
17244
|
+
` : "";
|
|
17245
|
+
process.stdout.write(
|
|
17246
|
+
`${name}Usage: chron connect <integration>
|
|
17247
|
+
|
|
17248
|
+
Integrations:
|
|
17249
|
+
crowdstrike Connect to CrowdStrike LogScale (direct ingest)
|
|
17250
|
+
`
|
|
17251
|
+
);
|
|
17252
|
+
process.exit(subcommand ? 1 : 0);
|
|
17253
|
+
}
|
|
17254
|
+
}
|
|
17255
|
+
}
|
|
17256
|
+
var import_readline, import_os3, import_path3, import_fs2, RESET5, BOLD5, DIM4, CYAN4, GREEN, RED;
|
|
17257
|
+
var init_connect = __esm({
|
|
17258
|
+
"src/cli/connect.ts"() {
|
|
17259
|
+
"use strict";
|
|
17260
|
+
import_readline = require("readline");
|
|
17261
|
+
import_os3 = require("os");
|
|
17262
|
+
import_path3 = require("path");
|
|
17263
|
+
import_fs2 = require("fs");
|
|
17264
|
+
RESET5 = "\x1B[0m";
|
|
17265
|
+
BOLD5 = "\x1B[1m";
|
|
17266
|
+
DIM4 = "\x1B[2m";
|
|
17267
|
+
CYAN4 = "\x1B[36m";
|
|
17268
|
+
GREEN = "\x1B[32m";
|
|
17269
|
+
RED = "\x1B[31m";
|
|
17270
|
+
}
|
|
17271
|
+
});
|
|
17272
|
+
|
|
17029
17273
|
// src/cli/index.ts
|
|
17030
17274
|
var [, , command, ...args] = process.argv;
|
|
17031
17275
|
async function main() {
|
|
@@ -17055,6 +17299,11 @@ async function main() {
|
|
|
17055
17299
|
await runSecrets2(args);
|
|
17056
17300
|
break;
|
|
17057
17301
|
}
|
|
17302
|
+
case "connect": {
|
|
17303
|
+
const { runConnect: runConnect2 } = await Promise.resolve().then(() => (init_connect(), connect_exports));
|
|
17304
|
+
await runConnect2(args);
|
|
17305
|
+
break;
|
|
17306
|
+
}
|
|
17058
17307
|
default: {
|
|
17059
17308
|
const name = command ? `Unknown command: ${command}
|
|
17060
17309
|
|
|
@@ -17068,6 +17317,7 @@ Commands:
|
|
|
17068
17317
|
export Export a session as markdown
|
|
17069
17318
|
secrets List detected secrets across sessions
|
|
17070
17319
|
settings View current configuration
|
|
17320
|
+
connect Connect to a SIEM integration (crowdstrike)
|
|
17071
17321
|
|
|
17072
17322
|
Options (history):
|
|
17073
17323
|
--limit=<n> Max sessions to show (default: 20)
|
package/dist/index.js
CHANGED
|
@@ -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:
|
|
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 =
|
|
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:
|
|
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 =
|
|
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",
|
|
@@ -32535,6 +32535,92 @@ 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.14";
|
|
32543
|
+
}
|
|
32544
|
+
});
|
|
32545
|
+
|
|
32546
|
+
// src/utils/relay.ts
|
|
32547
|
+
function getMachineId() {
|
|
32548
|
+
if (!_machineId) {
|
|
32549
|
+
_machineId = "sha256:" + (0, import_crypto3.createHash)("sha256").update((0, import_os2.hostname)()).digest("hex").slice(0, 16);
|
|
32550
|
+
}
|
|
32551
|
+
return _machineId;
|
|
32552
|
+
}
|
|
32553
|
+
function toLogScaleAttributes(payload) {
|
|
32554
|
+
const attrs = {
|
|
32555
|
+
event_type: payload.event_type,
|
|
32556
|
+
session_id_prefix: payload.session.id_prefix,
|
|
32557
|
+
ai_tool: payload.session.ai_tool ?? "",
|
|
32558
|
+
os: process.platform,
|
|
32559
|
+
chron_version: version4
|
|
32560
|
+
};
|
|
32561
|
+
if (payload.event_type === "message_logged") {
|
|
32562
|
+
attrs.role = payload.message.role;
|
|
32563
|
+
} else if (payload.event_type === "secret_detected") {
|
|
32564
|
+
attrs.detection_type = payload.detection.type;
|
|
32565
|
+
attrs.masked_value = payload.detection.masked_value;
|
|
32566
|
+
}
|
|
32567
|
+
return attrs;
|
|
32568
|
+
}
|
|
32569
|
+
function emitToLogScale(payload) {
|
|
32570
|
+
const url = process.env.CHRON_LOGSCALE_URL;
|
|
32571
|
+
const token = process.env.CHRON_LOGSCALE_TOKEN;
|
|
32572
|
+
if (!url || !token)
|
|
32573
|
+
return;
|
|
32574
|
+
const body = JSON.stringify([{
|
|
32575
|
+
tags: { host: (0, import_os2.hostname)(), source: "chron-mcp" },
|
|
32576
|
+
events: [{ timestamp: payload.timestamp, attributes: toLogScaleAttributes(payload) }]
|
|
32577
|
+
}]);
|
|
32578
|
+
setImmediate(
|
|
32579
|
+
() => fetch(url, {
|
|
32580
|
+
method: "POST",
|
|
32581
|
+
headers: {
|
|
32582
|
+
"Authorization": `Bearer ${token}`,
|
|
32583
|
+
"Content-Type": "application/json"
|
|
32584
|
+
},
|
|
32585
|
+
body
|
|
32586
|
+
}).catch(() => void 0)
|
|
32587
|
+
);
|
|
32588
|
+
}
|
|
32589
|
+
function emitEvent(payload) {
|
|
32590
|
+
const url = process.env.CHRON_RELAY_URL;
|
|
32591
|
+
const token = process.env.CHRON_RELAY_TOKEN;
|
|
32592
|
+
if (url && token) {
|
|
32593
|
+
const event = {
|
|
32594
|
+
schema_version: "1.0",
|
|
32595
|
+
chron_version: version4,
|
|
32596
|
+
machine_id: getMachineId(),
|
|
32597
|
+
os: process.platform,
|
|
32598
|
+
...payload
|
|
32599
|
+
};
|
|
32600
|
+
setImmediate(
|
|
32601
|
+
() => fetch(url, {
|
|
32602
|
+
method: "POST",
|
|
32603
|
+
headers: {
|
|
32604
|
+
"Authorization": `Bearer ${token}`,
|
|
32605
|
+
"Content-Type": "application/json"
|
|
32606
|
+
},
|
|
32607
|
+
body: JSON.stringify(event)
|
|
32608
|
+
}).catch(() => void 0)
|
|
32609
|
+
);
|
|
32610
|
+
}
|
|
32611
|
+
emitToLogScale(payload);
|
|
32612
|
+
}
|
|
32613
|
+
var import_crypto3, import_os2, _machineId;
|
|
32614
|
+
var init_relay = __esm({
|
|
32615
|
+
"src/utils/relay.ts"() {
|
|
32616
|
+
"use strict";
|
|
32617
|
+
import_crypto3 = require("crypto");
|
|
32618
|
+
import_os2 = require("os");
|
|
32619
|
+
init_package();
|
|
32620
|
+
_machineId = null;
|
|
32621
|
+
}
|
|
32622
|
+
});
|
|
32623
|
+
|
|
32538
32624
|
// src/tools/sessions.ts
|
|
32539
32625
|
function startSession(db) {
|
|
32540
32626
|
return async (args) => {
|
|
@@ -32548,6 +32634,7 @@ function startSession(db) {
|
|
|
32548
32634
|
created_at: now,
|
|
32549
32635
|
updated_at: now
|
|
32550
32636
|
});
|
|
32637
|
+
emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: id.slice(0, 8), ai_tool: args.ai_tool ?? null } });
|
|
32551
32638
|
return {
|
|
32552
32639
|
content: [{
|
|
32553
32640
|
type: "text",
|
|
@@ -32562,6 +32649,7 @@ function startSession(db) {
|
|
|
32562
32649
|
const session = existing[0];
|
|
32563
32650
|
const [countRow] = await db.select({ count: sql`count(*)` }).from(messages).where(eq(messages.session_id, session.id));
|
|
32564
32651
|
await db.update(sessions).set({ updated_at: now }).where(eq(sessions.id, session.id));
|
|
32652
|
+
emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: session.id.slice(0, 8), ai_tool: session.ai_tool } });
|
|
32565
32653
|
return {
|
|
32566
32654
|
content: [{
|
|
32567
32655
|
type: "text",
|
|
@@ -32600,6 +32688,7 @@ function initSession(db) {
|
|
|
32600
32688
|
created = false;
|
|
32601
32689
|
ai_tool = session.ai_tool;
|
|
32602
32690
|
}
|
|
32691
|
+
emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: session_id.slice(0, 8), ai_tool } });
|
|
32603
32692
|
const limit = args.limit ?? 10;
|
|
32604
32693
|
const [countRow] = await db.select({
|
|
32605
32694
|
count: sql`count(*)`,
|
|
@@ -32683,18 +32772,19 @@ var init_sessions = __esm({
|
|
|
32683
32772
|
init_esm2();
|
|
32684
32773
|
init_schema();
|
|
32685
32774
|
init_time();
|
|
32775
|
+
init_relay();
|
|
32686
32776
|
}
|
|
32687
32777
|
});
|
|
32688
32778
|
|
|
32689
32779
|
// src/utils/hash.ts
|
|
32690
32780
|
function computeContentHash(sessionId, role, content, createdAt, prevHash) {
|
|
32691
|
-
return (0,
|
|
32781
|
+
return (0, import_crypto4.createHash)("sha256").update(`${sessionId}|${role}|${content}|${createdAt}|${prevHash ?? ""}`).digest("hex");
|
|
32692
32782
|
}
|
|
32693
|
-
var
|
|
32783
|
+
var import_crypto4;
|
|
32694
32784
|
var init_hash = __esm({
|
|
32695
32785
|
"src/utils/hash.ts"() {
|
|
32696
32786
|
"use strict";
|
|
32697
|
-
|
|
32787
|
+
import_crypto4 = require("crypto");
|
|
32698
32788
|
}
|
|
32699
32789
|
});
|
|
32700
32790
|
|
|
@@ -32823,16 +32913,19 @@ async function writeDetections(db, session_id, message_id, content) {
|
|
|
32823
32913
|
if (found.length === 0)
|
|
32824
32914
|
return;
|
|
32825
32915
|
const now = localISOString();
|
|
32826
|
-
|
|
32827
|
-
|
|
32828
|
-
|
|
32829
|
-
|
|
32830
|
-
|
|
32831
|
-
|
|
32832
|
-
|
|
32833
|
-
|
|
32834
|
-
|
|
32835
|
-
);
|
|
32916
|
+
const rows = found.map((s) => ({
|
|
32917
|
+
id: v4_default(),
|
|
32918
|
+
session_id,
|
|
32919
|
+
message_id,
|
|
32920
|
+
type: s.type,
|
|
32921
|
+
masked_value: maskValue(s.value),
|
|
32922
|
+
detected_at: now
|
|
32923
|
+
}));
|
|
32924
|
+
await db.insert(secrets_detected).values(rows);
|
|
32925
|
+
const sessionIdPrefix = session_id.slice(0, 8);
|
|
32926
|
+
for (const row of rows) {
|
|
32927
|
+
emitEvent({ event_type: "secret_detected", timestamp: now, session: { id_prefix: sessionIdPrefix, ai_tool: null }, detection: { type: row.type, masked_value: row.masked_value } });
|
|
32928
|
+
}
|
|
32836
32929
|
}
|
|
32837
32930
|
function isFkError(e) {
|
|
32838
32931
|
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 +32935,7 @@ function logMessage(db) {
|
|
|
32842
32935
|
let id;
|
|
32843
32936
|
let now;
|
|
32844
32937
|
let contentHash;
|
|
32938
|
+
let sessionAiTool;
|
|
32845
32939
|
try {
|
|
32846
32940
|
const result = await db.transaction(async (tx) => {
|
|
32847
32941
|
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 +32953,20 @@ function logMessage(db) {
|
|
|
32859
32953
|
content_hash: hash
|
|
32860
32954
|
});
|
|
32861
32955
|
await tx.update(sessions).set({ updated_at: ts }).where(eq(sessions.id, args.session_id));
|
|
32862
|
-
|
|
32956
|
+
const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
|
|
32957
|
+
return { id: msgId, now: ts, contentHash: hash, ai_tool: sessionRow?.ai_tool ?? null };
|
|
32863
32958
|
});
|
|
32864
32959
|
id = result.id;
|
|
32865
32960
|
now = result.now;
|
|
32866
32961
|
contentHash = result.contentHash;
|
|
32962
|
+
sessionAiTool = result.ai_tool;
|
|
32867
32963
|
} catch (e) {
|
|
32868
32964
|
if (isFkError(e)) {
|
|
32869
32965
|
return { content: [{ type: "text", text: `Session not found: ${args.session_id}` }], isError: true };
|
|
32870
32966
|
}
|
|
32871
32967
|
throw e;
|
|
32872
32968
|
}
|
|
32969
|
+
emitEvent({ event_type: "message_logged", timestamp: now, session: { id_prefix: args.session_id.slice(0, 8), ai_tool: sessionAiTool }, message: { role: args.role } });
|
|
32873
32970
|
if (args.role === "user") {
|
|
32874
32971
|
setImmediate(() => writeDetections(db, args.session_id, id, args.content).catch(() => void 0));
|
|
32875
32972
|
}
|
|
@@ -32886,6 +32983,7 @@ function logExchange(db) {
|
|
|
32886
32983
|
let assistantNow;
|
|
32887
32984
|
let userHash;
|
|
32888
32985
|
let assistantHash;
|
|
32986
|
+
let sessionAiTool;
|
|
32889
32987
|
try {
|
|
32890
32988
|
const result = await db.transaction(async (tx) => {
|
|
32891
32989
|
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 +33013,8 @@ function logExchange(db) {
|
|
|
32915
33013
|
content_hash: aHash
|
|
32916
33014
|
});
|
|
32917
33015
|
await tx.update(sessions).set({ updated_at: aNow }).where(eq(sessions.id, args.session_id));
|
|
32918
|
-
|
|
33016
|
+
const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
|
|
33017
|
+
return { uId, aId, uNow, aNow, uHash, aHash, ai_tool: sessionRow?.ai_tool ?? null };
|
|
32919
33018
|
});
|
|
32920
33019
|
userId = result.uId;
|
|
32921
33020
|
assistantId = result.aId;
|
|
@@ -32923,12 +33022,16 @@ function logExchange(db) {
|
|
|
32923
33022
|
assistantNow = result.aNow;
|
|
32924
33023
|
userHash = result.uHash;
|
|
32925
33024
|
assistantHash = result.aHash;
|
|
33025
|
+
sessionAiTool = result.ai_tool;
|
|
32926
33026
|
} catch (e) {
|
|
32927
33027
|
if (isFkError(e)) {
|
|
32928
33028
|
return { content: [{ type: "text", text: `Session not found: ${args.session_id}` }], isError: true };
|
|
32929
33029
|
}
|
|
32930
33030
|
throw e;
|
|
32931
33031
|
}
|
|
33032
|
+
const idPrefix = args.session_id.slice(0, 8);
|
|
33033
|
+
emitEvent({ event_type: "message_logged", timestamp: userNow, session: { id_prefix: idPrefix, ai_tool: sessionAiTool }, message: { role: "user" } });
|
|
33034
|
+
emitEvent({ event_type: "message_logged", timestamp: assistantNow, session: { id_prefix: idPrefix, ai_tool: sessionAiTool }, message: { role: "assistant" } });
|
|
32932
33035
|
setImmediate(() => writeDetections(db, args.session_id, userId, args.user_content).catch(() => void 0));
|
|
32933
33036
|
return {
|
|
32934
33037
|
content: [{
|
|
@@ -32954,6 +33057,7 @@ var init_messages = __esm({
|
|
|
32954
33057
|
init_time();
|
|
32955
33058
|
init_hash();
|
|
32956
33059
|
init_detect();
|
|
33060
|
+
init_relay();
|
|
32957
33061
|
}
|
|
32958
33062
|
});
|
|
32959
33063
|
|
|
@@ -33082,14 +33186,6 @@ var init_detect2 = __esm({
|
|
|
33082
33186
|
}
|
|
33083
33187
|
});
|
|
33084
33188
|
|
|
33085
|
-
// package.json
|
|
33086
|
-
var version4;
|
|
33087
|
-
var init_package = __esm({
|
|
33088
|
-
"package.json"() {
|
|
33089
|
-
version4 = "0.1.13";
|
|
33090
|
-
}
|
|
33091
|
-
});
|
|
33092
|
-
|
|
33093
33189
|
// src/server.ts
|
|
33094
33190
|
function createServer(db) {
|
|
33095
33191
|
const server = new McpServer({
|
|
@@ -33208,7 +33304,7 @@ __export(setup_exports, {
|
|
|
33208
33304
|
runSetup: () => runSetup
|
|
33209
33305
|
});
|
|
33210
33306
|
function configPath(...parts) {
|
|
33211
|
-
return (0, import_path2.join)((0,
|
|
33307
|
+
return (0, import_path2.join)((0, import_os3.homedir)(), ...parts);
|
|
33212
33308
|
}
|
|
33213
33309
|
function readJson(filePath) {
|
|
33214
33310
|
if (!(0, import_fs2.existsSync)(filePath))
|
|
@@ -33246,7 +33342,7 @@ function configureClaudeCode() {
|
|
|
33246
33342
|
try {
|
|
33247
33343
|
(0, import_child_process.execSync)("claude mcp add chron -- npx -y chron-mcp", { stdio: "pipe" });
|
|
33248
33344
|
} catch {
|
|
33249
|
-
const result = configureTool("Claude Code", (0, import_path2.join)((0,
|
|
33345
|
+
const result = configureTool("Claude Code", (0, import_path2.join)((0, import_os3.homedir)(), ".claude", "settings.json"));
|
|
33250
33346
|
if (result.status === "error")
|
|
33251
33347
|
return result;
|
|
33252
33348
|
}
|
|
@@ -33255,12 +33351,12 @@ function configureClaudeCode() {
|
|
|
33255
33351
|
}
|
|
33256
33352
|
function installClaudeCodeHook() {
|
|
33257
33353
|
const skillSrc = (0, import_path2.join)(__dirname, "..", "skills", "chron.skill.md");
|
|
33258
|
-
const skillDst = (0, import_path2.join)((0,
|
|
33354
|
+
const skillDst = (0, import_path2.join)((0, import_os3.homedir)(), ".chron", "chron.skill.md");
|
|
33259
33355
|
if ((0, import_fs2.existsSync)(skillSrc)) {
|
|
33260
33356
|
(0, import_fs2.mkdirSync)((0, import_path2.dirname)(skillDst), { recursive: true });
|
|
33261
33357
|
(0, import_fs2.copyFileSync)(skillSrc, skillDst);
|
|
33262
33358
|
}
|
|
33263
|
-
const settingsPath = (0, import_path2.join)((0,
|
|
33359
|
+
const settingsPath = (0, import_path2.join)((0, import_os3.homedir)(), ".claude", "settings.json");
|
|
33264
33360
|
const settings = readJson(settingsPath);
|
|
33265
33361
|
if (!settings.hooks)
|
|
33266
33362
|
settings.hooks = {};
|
|
@@ -33284,12 +33380,12 @@ async function runSetup() {
|
|
|
33284
33380
|
}
|
|
33285
33381
|
return results.filter((r) => r.status !== "skipped");
|
|
33286
33382
|
}
|
|
33287
|
-
var import_fs2,
|
|
33383
|
+
var import_fs2, import_os3, import_path2, import_child_process, CHRON_ENTRY, TOOLS;
|
|
33288
33384
|
var init_setup = __esm({
|
|
33289
33385
|
"src/setup.ts"() {
|
|
33290
33386
|
"use strict";
|
|
33291
33387
|
import_fs2 = require("fs");
|
|
33292
|
-
|
|
33388
|
+
import_os3 = require("os");
|
|
33293
33389
|
import_path2 = require("path");
|
|
33294
33390
|
import_child_process = require("child_process");
|
|
33295
33391
|
CHRON_ENTRY = {
|
|
@@ -57090,17 +57186,17 @@ var require_request = __commonJS({
|
|
|
57090
57186
|
return addrs;
|
|
57091
57187
|
});
|
|
57092
57188
|
defineGetter(req, "subdomains", function subdomains() {
|
|
57093
|
-
var
|
|
57094
|
-
if (!
|
|
57189
|
+
var hostname3 = this.hostname;
|
|
57190
|
+
if (!hostname3)
|
|
57095
57191
|
return [];
|
|
57096
57192
|
var offset = this.app.get("subdomain offset");
|
|
57097
|
-
var subdomains2 = !isIP(
|
|
57193
|
+
var subdomains2 = !isIP(hostname3) ? hostname3.split(".").reverse() : [hostname3];
|
|
57098
57194
|
return subdomains2.slice(offset);
|
|
57099
57195
|
});
|
|
57100
57196
|
defineGetter(req, "path", function path() {
|
|
57101
57197
|
return parse3(this).pathname;
|
|
57102
57198
|
});
|
|
57103
|
-
defineGetter(req, "hostname", function
|
|
57199
|
+
defineGetter(req, "hostname", function hostname3() {
|
|
57104
57200
|
var trust = this.app.get("trust proxy fn");
|
|
57105
57201
|
var host = this.get("X-Forwarded-Host");
|
|
57106
57202
|
if (!host || !trust(this.connection.remoteAddress, 0)) {
|
|
@@ -62419,7 +62515,7 @@ var StdioServerTransport = class {
|
|
|
62419
62515
|
};
|
|
62420
62516
|
|
|
62421
62517
|
// src/index.ts
|
|
62422
|
-
var
|
|
62518
|
+
var import_os4 = require("os");
|
|
62423
62519
|
var import_path3 = require("path");
|
|
62424
62520
|
|
|
62425
62521
|
// node_modules/@libsql/core/lib-esm/api.js
|
|
@@ -66420,8 +66516,8 @@ var HttpStream = class extends Stream {
|
|
|
66420
66516
|
let promise;
|
|
66421
66517
|
try {
|
|
66422
66518
|
const request = createRequest();
|
|
66423
|
-
const
|
|
66424
|
-
promise =
|
|
66519
|
+
const fetch2 = this.#fetch;
|
|
66520
|
+
promise = fetch2(request);
|
|
66425
66521
|
} catch (error2) {
|
|
66426
66522
|
promise = Promise.reject(error2);
|
|
66427
66523
|
}
|
|
@@ -66641,11 +66737,11 @@ var HttpClient = class extends Client {
|
|
|
66641
66737
|
}
|
|
66642
66738
|
};
|
|
66643
66739
|
async function findEndpoint(customFetch, clientUrl) {
|
|
66644
|
-
const
|
|
66740
|
+
const fetch2 = customFetch;
|
|
66645
66741
|
for (const endpoint of checkEndpoints) {
|
|
66646
66742
|
const url = new URL(endpoint.versionPath, clientUrl);
|
|
66647
66743
|
const request = new Request(url.toString(), { method: "GET" });
|
|
66648
|
-
const response = await
|
|
66744
|
+
const response = await fetch2(request);
|
|
66649
66745
|
await response.arrayBuffer();
|
|
66650
66746
|
if (response.ok) {
|
|
66651
66747
|
return endpoint;
|
|
@@ -67896,7 +67992,7 @@ if (process.argv[2] === "--version" || process.argv[2] === "-v") {
|
|
|
67896
67992
|
process.exit(0);
|
|
67897
67993
|
}
|
|
67898
67994
|
async function main() {
|
|
67899
|
-
const dbPath = process.env.CHRON_DB_PATH ?? (0, import_path3.join)((0,
|
|
67995
|
+
const dbPath = process.env.CHRON_DB_PATH ?? (0, import_path3.join)((0, import_os4.homedir)(), ".chron", "chron.db");
|
|
67900
67996
|
if (process.stdin.isTTY) {
|
|
67901
67997
|
process.stdout.write(`chron-mcp ${version4}
|
|
67902
67998
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chron-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"mcpName": "io.github.sirinivask/chron",
|
|
5
5
|
"description": "Audit-grade timestamped logs for every AI conversation",
|
|
6
6
|
"repository": {
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"skills",
|
|
24
24
|
".claude-plugin",
|
|
25
25
|
"assets",
|
|
26
|
+
"dashboards",
|
|
26
27
|
"README.md"
|
|
27
28
|
],
|
|
28
29
|
"engines": {
|