chron-mcp 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +2 -3
- package/dist/cli/index.js +26 -8
- package/dist/index.js +133 -46
- package/package.json +1 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chron",
|
|
3
3
|
"description": "Audit-grade timestamped logs for every AI conversation — stored locally, owned by you.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.19",
|
|
5
5
|
"author": {
|
|
6
|
-
"name": "Nivaya"
|
|
7
|
-
"email": "ksrinivas07530@gmail.com"
|
|
6
|
+
"name": "Nivaya"
|
|
8
7
|
},
|
|
9
8
|
"homepage": "https://github.com/sirinivask/chron",
|
|
10
9
|
"repository": "https://github.com/sirinivask/chron",
|
package/dist/cli/index.js
CHANGED
|
@@ -16539,7 +16539,9 @@ var init_schema = __esm({
|
|
|
16539
16539
|
title: text("title").notNull().unique(),
|
|
16540
16540
|
ai_tool: text("ai_tool"),
|
|
16541
16541
|
created_at: text("created_at").notNull(),
|
|
16542
|
-
updated_at: text("updated_at").notNull()
|
|
16542
|
+
updated_at: text("updated_at").notNull(),
|
|
16543
|
+
parent_session_id: text("parent_session_id"),
|
|
16544
|
+
external_ref: text("external_ref")
|
|
16543
16545
|
});
|
|
16544
16546
|
messages = sqliteTable("messages", {
|
|
16545
16547
|
id: text("id").primaryKey(),
|
|
@@ -16548,7 +16550,9 @@ var init_schema = __esm({
|
|
|
16548
16550
|
content: text("content").notNull(),
|
|
16549
16551
|
created_at: text("created_at").notNull(),
|
|
16550
16552
|
prev_hash: text("prev_hash"),
|
|
16551
|
-
content_hash: text("content_hash")
|
|
16553
|
+
content_hash: text("content_hash"),
|
|
16554
|
+
// NULL = pre-migration row (treated as 'message'); set for all new rows
|
|
16555
|
+
event_type: text("event_type")
|
|
16552
16556
|
});
|
|
16553
16557
|
secrets_detected = sqliteTable("secrets_detected", {
|
|
16554
16558
|
id: text("id").primaryKey(),
|
|
@@ -16579,14 +16583,25 @@ async function initDb(dbPath2) {
|
|
|
16579
16583
|
for (const sql2 of CREATE_SQL) {
|
|
16580
16584
|
await client.execute(sql2);
|
|
16581
16585
|
}
|
|
16582
|
-
const
|
|
16583
|
-
const
|
|
16584
|
-
if (!
|
|
16586
|
+
const msgInfo = await client.execute("PRAGMA table_info(messages)");
|
|
16587
|
+
const msgCols = msgInfo.rows.map((r) => r[1]);
|
|
16588
|
+
if (!msgCols.includes("prev_hash")) {
|
|
16585
16589
|
await client.execute("ALTER TABLE messages ADD COLUMN prev_hash TEXT");
|
|
16586
16590
|
}
|
|
16587
|
-
if (!
|
|
16591
|
+
if (!msgCols.includes("content_hash")) {
|
|
16588
16592
|
await client.execute("ALTER TABLE messages ADD COLUMN content_hash TEXT");
|
|
16589
16593
|
}
|
|
16594
|
+
if (!msgCols.includes("event_type")) {
|
|
16595
|
+
await client.execute("ALTER TABLE messages ADD COLUMN event_type TEXT");
|
|
16596
|
+
}
|
|
16597
|
+
const sessInfo = await client.execute("PRAGMA table_info(sessions)");
|
|
16598
|
+
const sessCols = sessInfo.rows.map((r) => r[1]);
|
|
16599
|
+
if (!sessCols.includes("parent_session_id")) {
|
|
16600
|
+
await client.execute("ALTER TABLE sessions ADD COLUMN parent_session_id TEXT");
|
|
16601
|
+
}
|
|
16602
|
+
if (!sessCols.includes("external_ref")) {
|
|
16603
|
+
await client.execute("ALTER TABLE sessions ADD COLUMN external_ref TEXT");
|
|
16604
|
+
}
|
|
16590
16605
|
return drizzle(client, { schema: schema_exports });
|
|
16591
16606
|
}
|
|
16592
16607
|
var import_os, import_fs, import_path, CREATE_SQL;
|
|
@@ -16605,7 +16620,9 @@ var init_db2 = __esm({
|
|
|
16605
16620
|
title TEXT NOT NULL UNIQUE,
|
|
16606
16621
|
ai_tool TEXT,
|
|
16607
16622
|
created_at TEXT NOT NULL,
|
|
16608
|
-
updated_at TEXT NOT NULL
|
|
16623
|
+
updated_at TEXT NOT NULL,
|
|
16624
|
+
parent_session_id TEXT,
|
|
16625
|
+
external_ref TEXT
|
|
16609
16626
|
)`,
|
|
16610
16627
|
`CREATE TABLE IF NOT EXISTS messages (
|
|
16611
16628
|
id TEXT PRIMARY KEY,
|
|
@@ -16615,6 +16632,7 @@ var init_db2 = __esm({
|
|
|
16615
16632
|
created_at TEXT NOT NULL,
|
|
16616
16633
|
prev_hash TEXT,
|
|
16617
16634
|
content_hash TEXT,
|
|
16635
|
+
event_type TEXT,
|
|
16618
16636
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
16619
16637
|
)`,
|
|
16620
16638
|
`CREATE TABLE IF NOT EXISTS secrets_detected (
|
|
@@ -17401,7 +17419,7 @@ var require_package = __commonJS({
|
|
|
17401
17419
|
"package.json"(exports2, module2) {
|
|
17402
17420
|
module2.exports = {
|
|
17403
17421
|
name: "chron-mcp",
|
|
17404
|
-
version: "0.1.
|
|
17422
|
+
version: "0.1.19",
|
|
17405
17423
|
mcpName: "io.github.sirinivask/chron",
|
|
17406
17424
|
description: "Audit-grade timestamped logs for every AI conversation",
|
|
17407
17425
|
repository: {
|
package/dist/index.js
CHANGED
|
@@ -22749,7 +22749,9 @@ var init_schema = __esm({
|
|
|
22749
22749
|
title: text("title").notNull().unique(),
|
|
22750
22750
|
ai_tool: text("ai_tool"),
|
|
22751
22751
|
created_at: text("created_at").notNull(),
|
|
22752
|
-
updated_at: text("updated_at").notNull()
|
|
22752
|
+
updated_at: text("updated_at").notNull(),
|
|
22753
|
+
parent_session_id: text("parent_session_id"),
|
|
22754
|
+
external_ref: text("external_ref")
|
|
22753
22755
|
});
|
|
22754
22756
|
messages = sqliteTable("messages", {
|
|
22755
22757
|
id: text("id").primaryKey(),
|
|
@@ -22758,7 +22760,9 @@ var init_schema = __esm({
|
|
|
22758
22760
|
content: text("content").notNull(),
|
|
22759
22761
|
created_at: text("created_at").notNull(),
|
|
22760
22762
|
prev_hash: text("prev_hash"),
|
|
22761
|
-
content_hash: text("content_hash")
|
|
22763
|
+
content_hash: text("content_hash"),
|
|
22764
|
+
// NULL = pre-migration row (treated as 'message'); set for all new rows
|
|
22765
|
+
event_type: text("event_type")
|
|
22762
22766
|
});
|
|
22763
22767
|
secrets_detected = sqliteTable("secrets_detected", {
|
|
22764
22768
|
id: text("id").primaryKey(),
|
|
@@ -22789,14 +22793,25 @@ async function initDb(dbPath) {
|
|
|
22789
22793
|
for (const sql2 of CREATE_SQL) {
|
|
22790
22794
|
await client.execute(sql2);
|
|
22791
22795
|
}
|
|
22792
|
-
const
|
|
22793
|
-
const
|
|
22794
|
-
if (!
|
|
22796
|
+
const msgInfo = await client.execute("PRAGMA table_info(messages)");
|
|
22797
|
+
const msgCols = msgInfo.rows.map((r) => r[1]);
|
|
22798
|
+
if (!msgCols.includes("prev_hash")) {
|
|
22795
22799
|
await client.execute("ALTER TABLE messages ADD COLUMN prev_hash TEXT");
|
|
22796
22800
|
}
|
|
22797
|
-
if (!
|
|
22801
|
+
if (!msgCols.includes("content_hash")) {
|
|
22798
22802
|
await client.execute("ALTER TABLE messages ADD COLUMN content_hash TEXT");
|
|
22799
22803
|
}
|
|
22804
|
+
if (!msgCols.includes("event_type")) {
|
|
22805
|
+
await client.execute("ALTER TABLE messages ADD COLUMN event_type TEXT");
|
|
22806
|
+
}
|
|
22807
|
+
const sessInfo = await client.execute("PRAGMA table_info(sessions)");
|
|
22808
|
+
const sessCols = sessInfo.rows.map((r) => r[1]);
|
|
22809
|
+
if (!sessCols.includes("parent_session_id")) {
|
|
22810
|
+
await client.execute("ALTER TABLE sessions ADD COLUMN parent_session_id TEXT");
|
|
22811
|
+
}
|
|
22812
|
+
if (!sessCols.includes("external_ref")) {
|
|
22813
|
+
await client.execute("ALTER TABLE sessions ADD COLUMN external_ref TEXT");
|
|
22814
|
+
}
|
|
22800
22815
|
return drizzle(client, { schema: schema_exports });
|
|
22801
22816
|
}
|
|
22802
22817
|
var import_os, import_fs, import_path, CREATE_SQL;
|
|
@@ -22815,7 +22830,9 @@ var init_db2 = __esm({
|
|
|
22815
22830
|
title TEXT NOT NULL UNIQUE,
|
|
22816
22831
|
ai_tool TEXT,
|
|
22817
22832
|
created_at TEXT NOT NULL,
|
|
22818
|
-
updated_at TEXT NOT NULL
|
|
22833
|
+
updated_at TEXT NOT NULL,
|
|
22834
|
+
parent_session_id TEXT,
|
|
22835
|
+
external_ref TEXT
|
|
22819
22836
|
)`,
|
|
22820
22837
|
`CREATE TABLE IF NOT EXISTS messages (
|
|
22821
22838
|
id TEXT PRIMARY KEY,
|
|
@@ -22825,6 +22842,7 @@ var init_db2 = __esm({
|
|
|
22825
22842
|
created_at TEXT NOT NULL,
|
|
22826
22843
|
prev_hash TEXT,
|
|
22827
22844
|
content_hash TEXT,
|
|
22845
|
+
event_type TEXT,
|
|
22828
22846
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
22829
22847
|
)`,
|
|
22830
22848
|
`CREATE TABLE IF NOT EXISTS secrets_detected (
|
|
@@ -38446,7 +38464,7 @@ var init_time = __esm({
|
|
|
38446
38464
|
var version4;
|
|
38447
38465
|
var init_package = __esm({
|
|
38448
38466
|
"package.json"() {
|
|
38449
|
-
version4 = "0.1.
|
|
38467
|
+
version4 = "0.1.19";
|
|
38450
38468
|
}
|
|
38451
38469
|
});
|
|
38452
38470
|
|
|
@@ -38701,7 +38719,9 @@ function startSession(db) {
|
|
|
38701
38719
|
title: args.title,
|
|
38702
38720
|
ai_tool: args.ai_tool ?? null,
|
|
38703
38721
|
created_at: now,
|
|
38704
|
-
updated_at: now
|
|
38722
|
+
updated_at: now,
|
|
38723
|
+
parent_session_id: args.parent_session_id ?? null,
|
|
38724
|
+
external_ref: args.external_ref ?? null
|
|
38705
38725
|
});
|
|
38706
38726
|
emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: id.slice(0, 8), ai_tool: args.ai_tool ?? null } });
|
|
38707
38727
|
return {
|
|
@@ -38741,7 +38761,9 @@ function initSession(db) {
|
|
|
38741
38761
|
title: args.title,
|
|
38742
38762
|
ai_tool: args.ai_tool ?? null,
|
|
38743
38763
|
created_at: now,
|
|
38744
|
-
updated_at: now
|
|
38764
|
+
updated_at: now,
|
|
38765
|
+
parent_session_id: args.parent_session_id ?? null,
|
|
38766
|
+
external_ref: args.external_ref ?? null
|
|
38745
38767
|
});
|
|
38746
38768
|
session_id = id;
|
|
38747
38769
|
created = true;
|
|
@@ -38846,8 +38868,10 @@ var init_sessions = __esm({
|
|
|
38846
38868
|
});
|
|
38847
38869
|
|
|
38848
38870
|
// src/utils/hash.ts
|
|
38849
|
-
function computeContentHash(sessionId, role, content, createdAt, prevHash) {
|
|
38850
|
-
|
|
38871
|
+
function computeContentHash(sessionId, role, content, createdAt, prevHash, eventType) {
|
|
38872
|
+
const base = `${sessionId}|${role}|${content}|${createdAt}|${prevHash ?? ""}`;
|
|
38873
|
+
const input = eventType != null ? `${base}|${eventType}` : base;
|
|
38874
|
+
return (0, import_crypto4.createHash)("sha256").update(input).digest("hex");
|
|
38851
38875
|
}
|
|
38852
38876
|
var import_crypto4;
|
|
38853
38877
|
var init_hash = __esm({
|
|
@@ -39150,32 +39174,37 @@ async function writeDetections(db, session_id, message_id, content) {
|
|
|
39150
39174
|
function isFkError(e) {
|
|
39151
39175
|
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";
|
|
39152
39176
|
}
|
|
39177
|
+
async function insertMessage(db, session_id, role, content, event_type) {
|
|
39178
|
+
return db.transaction(async (tx) => {
|
|
39179
|
+
const last = await tx.select({ content_hash: messages.content_hash }).from(messages).where(eq(messages.session_id, session_id)).orderBy(desc(messages.created_at), desc(sql`rowid`)).limit(1);
|
|
39180
|
+
const ts = localISOString();
|
|
39181
|
+
const msgId = v4_default();
|
|
39182
|
+
const prevHash = last[0]?.content_hash ?? null;
|
|
39183
|
+
const hash = computeContentHash(session_id, role, content, ts, prevHash, event_type);
|
|
39184
|
+
await tx.insert(messages).values({
|
|
39185
|
+
id: msgId,
|
|
39186
|
+
session_id,
|
|
39187
|
+
role,
|
|
39188
|
+
content,
|
|
39189
|
+
created_at: ts,
|
|
39190
|
+
prev_hash: prevHash,
|
|
39191
|
+
content_hash: hash,
|
|
39192
|
+
event_type
|
|
39193
|
+
});
|
|
39194
|
+
await tx.update(sessions).set({ updated_at: ts }).where(eq(sessions.id, session_id));
|
|
39195
|
+
const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, session_id)).limit(1);
|
|
39196
|
+
return { id: msgId, now: ts, contentHash: hash, ai_tool: sessionRow?.ai_tool ?? null };
|
|
39197
|
+
});
|
|
39198
|
+
}
|
|
39153
39199
|
function logMessage(db) {
|
|
39154
39200
|
return async (args) => {
|
|
39201
|
+
const eventType = args.event_type ?? "message";
|
|
39155
39202
|
let id;
|
|
39156
39203
|
let now;
|
|
39157
39204
|
let contentHash;
|
|
39158
39205
|
let sessionAiTool;
|
|
39159
39206
|
try {
|
|
39160
|
-
const result = await db.
|
|
39161
|
-
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);
|
|
39162
|
-
const ts = localISOString();
|
|
39163
|
-
const msgId = v4_default();
|
|
39164
|
-
const prevHash = last[0]?.content_hash ?? null;
|
|
39165
|
-
const hash = computeContentHash(args.session_id, args.role, args.content, ts, prevHash);
|
|
39166
|
-
await tx.insert(messages).values({
|
|
39167
|
-
id: msgId,
|
|
39168
|
-
session_id: args.session_id,
|
|
39169
|
-
role: args.role,
|
|
39170
|
-
content: args.content,
|
|
39171
|
-
created_at: ts,
|
|
39172
|
-
prev_hash: prevHash,
|
|
39173
|
-
content_hash: hash
|
|
39174
|
-
});
|
|
39175
|
-
await tx.update(sessions).set({ updated_at: ts }).where(eq(sessions.id, args.session_id));
|
|
39176
|
-
const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
|
|
39177
|
-
return { id: msgId, now: ts, contentHash: hash, ai_tool: sessionRow?.ai_tool ?? null };
|
|
39178
|
-
});
|
|
39207
|
+
const result = await insertMessage(db, args.session_id, args.role, args.content, eventType);
|
|
39179
39208
|
id = result.id;
|
|
39180
39209
|
now = result.now;
|
|
39181
39210
|
contentHash = result.contentHash;
|
|
@@ -39187,7 +39216,7 @@ function logMessage(db) {
|
|
|
39187
39216
|
throw e;
|
|
39188
39217
|
}
|
|
39189
39218
|
emitEvent({ event_type: "message_logged", timestamp: now, session: { id_prefix: args.session_id.slice(0, 8), ai_tool: sessionAiTool }, message: { role: args.role } });
|
|
39190
|
-
if (args.role === "user") {
|
|
39219
|
+
if (args.role === "user" && eventType === "message") {
|
|
39191
39220
|
setImmediate(() => writeDetections(db, args.session_id, id, args.content).catch(() => void 0));
|
|
39192
39221
|
}
|
|
39193
39222
|
return {
|
|
@@ -39195,15 +39224,45 @@ function logMessage(db) {
|
|
|
39195
39224
|
};
|
|
39196
39225
|
};
|
|
39197
39226
|
}
|
|
39227
|
+
function logToolCall(db) {
|
|
39228
|
+
return async (args) => {
|
|
39229
|
+
const toolCallId = args.tool_call_id ?? v4_default();
|
|
39230
|
+
const content = JSON.stringify({ tool_name: args.tool_name, input: args.tool_input, tool_call_id: toolCallId });
|
|
39231
|
+
let result;
|
|
39232
|
+
try {
|
|
39233
|
+
result = await insertMessage(db, args.session_id, "assistant", content, "tool_call");
|
|
39234
|
+
} catch (e) {
|
|
39235
|
+
if (isFkError(e)) {
|
|
39236
|
+
return { content: [{ type: "text", text: `Session not found: ${args.session_id}` }], isError: true };
|
|
39237
|
+
}
|
|
39238
|
+
throw e;
|
|
39239
|
+
}
|
|
39240
|
+
return {
|
|
39241
|
+
content: [{ type: "text", text: JSON.stringify({ message_id: result.id, tool_call_id: toolCallId, created_at: result.now, content_hash: result.contentHash }) }]
|
|
39242
|
+
};
|
|
39243
|
+
};
|
|
39244
|
+
}
|
|
39245
|
+
function logToolResult(db) {
|
|
39246
|
+
return async (args) => {
|
|
39247
|
+
const content = JSON.stringify({ tool_call_id: args.tool_call_id, output: args.output, exit_code: args.exit_code ?? null });
|
|
39248
|
+
let result;
|
|
39249
|
+
try {
|
|
39250
|
+
result = await insertMessage(db, args.session_id, "user", content, "tool_result");
|
|
39251
|
+
} catch (e) {
|
|
39252
|
+
if (isFkError(e)) {
|
|
39253
|
+
return { content: [{ type: "text", text: `Session not found: ${args.session_id}` }], isError: true };
|
|
39254
|
+
}
|
|
39255
|
+
throw e;
|
|
39256
|
+
}
|
|
39257
|
+
return {
|
|
39258
|
+
content: [{ type: "text", text: JSON.stringify({ message_id: result.id, tool_call_id: args.tool_call_id, created_at: result.now, content_hash: result.contentHash }) }]
|
|
39259
|
+
};
|
|
39260
|
+
};
|
|
39261
|
+
}
|
|
39198
39262
|
function logExchange(db) {
|
|
39199
39263
|
return async (args) => {
|
|
39200
|
-
let userId;
|
|
39201
|
-
let
|
|
39202
|
-
let userNow;
|
|
39203
|
-
let assistantNow;
|
|
39204
|
-
let userHash;
|
|
39205
|
-
let assistantHash;
|
|
39206
|
-
let sessionAiTool;
|
|
39264
|
+
let userId, assistantId, userNow, assistantNow;
|
|
39265
|
+
let userHash, assistantHash, sessionAiTool;
|
|
39207
39266
|
try {
|
|
39208
39267
|
const result = await db.transaction(async (tx) => {
|
|
39209
39268
|
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);
|
|
@@ -39212,8 +39271,8 @@ function logExchange(db) {
|
|
|
39212
39271
|
const aNow = localISOString();
|
|
39213
39272
|
const aId = v4_default();
|
|
39214
39273
|
const prevHash = last[0]?.content_hash ?? null;
|
|
39215
|
-
const uHash = computeContentHash(args.session_id, "user", args.user_content, uNow, prevHash);
|
|
39216
|
-
const aHash = computeContentHash(args.session_id, "assistant", args.assistant_content, aNow, uHash);
|
|
39274
|
+
const uHash = computeContentHash(args.session_id, "user", args.user_content, uNow, prevHash, "message");
|
|
39275
|
+
const aHash = computeContentHash(args.session_id, "assistant", args.assistant_content, aNow, uHash, "message");
|
|
39217
39276
|
await tx.insert(messages).values({
|
|
39218
39277
|
id: uId,
|
|
39219
39278
|
session_id: args.session_id,
|
|
@@ -39221,7 +39280,8 @@ function logExchange(db) {
|
|
|
39221
39280
|
content: args.user_content,
|
|
39222
39281
|
created_at: uNow,
|
|
39223
39282
|
prev_hash: prevHash,
|
|
39224
|
-
content_hash: uHash
|
|
39283
|
+
content_hash: uHash,
|
|
39284
|
+
event_type: "message"
|
|
39225
39285
|
});
|
|
39226
39286
|
await tx.insert(messages).values({
|
|
39227
39287
|
id: aId,
|
|
@@ -39230,7 +39290,8 @@ function logExchange(db) {
|
|
|
39230
39290
|
content: args.assistant_content,
|
|
39231
39291
|
created_at: aNow,
|
|
39232
39292
|
prev_hash: uHash,
|
|
39233
|
-
content_hash: aHash
|
|
39293
|
+
content_hash: aHash,
|
|
39294
|
+
event_type: "message"
|
|
39234
39295
|
});
|
|
39235
39296
|
await tx.update(sessions).set({ updated_at: aNow }).where(eq(sessions.id, args.session_id));
|
|
39236
39297
|
const [sessionRow] = await tx.select({ ai_tool: sessions.ai_tool }).from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
|
|
@@ -39305,7 +39366,7 @@ function verifySession(db) {
|
|
|
39305
39366
|
}]
|
|
39306
39367
|
};
|
|
39307
39368
|
}
|
|
39308
|
-
const expected = computeContentHash(row.session_id, row.role, row.content, row.created_at, row.prev_hash);
|
|
39369
|
+
const expected = computeContentHash(row.session_id, row.role, row.content, row.created_at, row.prev_hash, row.event_type ?? void 0);
|
|
39309
39370
|
if (row.content_hash !== expected) {
|
|
39310
39371
|
return {
|
|
39311
39372
|
content: [{
|
|
@@ -39591,7 +39652,9 @@ function createServer(db) {
|
|
|
39591
39652
|
{
|
|
39592
39653
|
title: external_exports.string().describe('Descriptive session title, e.g. "Contract review \u2014 2026-05-08"'),
|
|
39593
39654
|
ai_tool: external_exports.string().optional().describe('AI tool name: "claude", "cursor", "windsurf", etc.'),
|
|
39594
|
-
limit: external_exports.number().int().positive().optional().describe("Number of recent messages to return (default: 10)")
|
|
39655
|
+
limit: external_exports.number().int().positive().optional().describe("Number of recent messages to return (default: 10)"),
|
|
39656
|
+
parent_session_id: external_exports.string().optional().describe("Parent session ID if this is a subagent session spawned by another session"),
|
|
39657
|
+
external_ref: external_exports.string().optional().describe('External ticket/PR reference, e.g. "jira:ENG-123" or "github:org/repo#456"')
|
|
39595
39658
|
},
|
|
39596
39659
|
initSession(db)
|
|
39597
39660
|
);
|
|
@@ -39600,7 +39663,9 @@ function createServer(db) {
|
|
|
39600
39663
|
"Create a new audit session or resume an existing one by title. Call this at the start of every conversation.",
|
|
39601
39664
|
{
|
|
39602
39665
|
title: external_exports.string().describe('Descriptive session title, e.g. "Contract review \u2014 2026-05-08"'),
|
|
39603
|
-
ai_tool: external_exports.string().optional().describe('AI tool name: "claude", "cursor", "windsurf", etc.')
|
|
39666
|
+
ai_tool: external_exports.string().optional().describe('AI tool name: "claude", "cursor", "windsurf", etc.'),
|
|
39667
|
+
parent_session_id: external_exports.string().optional().describe("Parent session ID if this is a subagent session"),
|
|
39668
|
+
external_ref: external_exports.string().optional().describe('External ticket/PR reference, e.g. "jira:ENG-123"')
|
|
39604
39669
|
},
|
|
39605
39670
|
startSession(db)
|
|
39606
39671
|
);
|
|
@@ -39614,6 +39679,28 @@ function createServer(db) {
|
|
|
39614
39679
|
},
|
|
39615
39680
|
logMessage(db)
|
|
39616
39681
|
);
|
|
39682
|
+
server.tool(
|
|
39683
|
+
"log_tool_call",
|
|
39684
|
+
"Record an AI tool invocation as a first-class audit event (event_type=tool_call). Call immediately before executing a tool. Returns tool_call_id to pass to log_tool_result.",
|
|
39685
|
+
{
|
|
39686
|
+
session_id: external_exports.string().describe("Session ID"),
|
|
39687
|
+
tool_name: external_exports.string().describe('Name of the tool being called (e.g. "Edit", "Bash", "WebFetch")'),
|
|
39688
|
+
tool_input: external_exports.record(external_exports.unknown()).describe("Tool input parameters as an object"),
|
|
39689
|
+
tool_call_id: external_exports.string().optional().describe("Optional ID to link this call to its result. Generated automatically if omitted.")
|
|
39690
|
+
},
|
|
39691
|
+
logToolCall(db)
|
|
39692
|
+
);
|
|
39693
|
+
server.tool(
|
|
39694
|
+
"log_tool_result",
|
|
39695
|
+
"Record the result of a tool call as a first-class audit event (event_type=tool_result). Call immediately after receiving tool output. Links back to log_tool_call via tool_call_id.",
|
|
39696
|
+
{
|
|
39697
|
+
session_id: external_exports.string().describe("Session ID"),
|
|
39698
|
+
tool_call_id: external_exports.string().describe("tool_call_id returned by log_tool_call"),
|
|
39699
|
+
output: external_exports.string().describe("Tool output (stdout, file content, API response, etc.)"),
|
|
39700
|
+
exit_code: external_exports.number().int().optional().describe("Exit code for shell tools (0 = success)")
|
|
39701
|
+
},
|
|
39702
|
+
logToolResult(db)
|
|
39703
|
+
);
|
|
39617
39704
|
server.tool(
|
|
39618
39705
|
"log_exchange",
|
|
39619
39706
|
"Record a user+assistant exchange from historical or batch imports only. Do NOT use for live conversations \u2014 both timestamps are captured at the same instant with no real gap. For live sessions always call log_message twice: once for the user message, once for the assistant response.",
|