driftguard-mcp 0.1.4 → 0.1.5

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.
Files changed (2) hide show
  1. package/dist/bin.js +55 -8
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -51,17 +51,29 @@ function parseJSONL(filePath) {
51
51
  if (entry.type !== "user" && entry.type !== "assistant") continue;
52
52
  const content = entry.message?.content;
53
53
  let text = "";
54
+ let toolTokens = 0;
54
55
  if (typeof content === "string") {
55
56
  text = content.trim();
56
57
  } else if (Array.isArray(content)) {
57
- text = content.filter((block) => block.type === "text" && typeof block.text === "string").map((block) => block.text.trim()).join("\n").trim();
58
+ const blocks = content;
59
+ text = blocks.filter((block) => block.type === "text" && typeof block.text === "string").map((block) => block.text.trim()).join("\n").trim();
60
+ for (const block of blocks) {
61
+ if (block.type === "tool_use" && block.input) {
62
+ const inputText = JSON.stringify(block.input);
63
+ toolTokens += Math.round(inputText.length / 4);
64
+ } else if (block.type === "tool_result") {
65
+ const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n") : "";
66
+ toolTokens += Math.round(resultText.length / 4);
67
+ }
68
+ }
58
69
  }
59
70
  if (!text.trim()) continue;
60
71
  messages.push({
61
72
  id: entry.uuid,
62
73
  role: entry.message.role,
63
74
  content: text,
64
- timestamp: parseTimestamp(entry.timestamp)
75
+ timestamp: parseTimestamp(entry.timestamp),
76
+ ...toolTokens > 0 ? { toolTokens } : {}
65
77
  });
66
78
  } catch {
67
79
  skipped++;
@@ -234,14 +246,25 @@ var init_gemini_adapter = __esm({
234
246
  try {
235
247
  const entry = JSON.parse(line);
236
248
  if (entry.role !== "user" && entry.role !== "model") continue;
237
- const text = (entry.parts ?? []).map((p) => p.text ?? "").join("\n").trim();
249
+ const parts = entry.parts ?? [];
250
+ const text = parts.map((p) => p.text ?? "").join("\n").trim();
238
251
  if (!text) continue;
252
+ let toolTokens = 0;
253
+ for (const part of parts) {
254
+ if (part.functionCall?.args) {
255
+ toolTokens += Math.round(JSON.stringify(part.functionCall.args).length / 4);
256
+ }
257
+ if (part.functionResponse?.response) {
258
+ toolTokens += Math.round(JSON.stringify(part.functionResponse.response).length / 4);
259
+ }
260
+ }
239
261
  const ts = entry.timestamp ? new Date(entry.timestamp).getTime() : Date.now();
240
262
  messages.push({
241
263
  id: `gemini-${index++}`,
242
264
  role: entry.role === "model" ? "assistant" : "user",
243
265
  content: text,
244
- timestamp: isFinite(ts) ? ts : Date.now()
266
+ timestamp: isFinite(ts) ? ts : Date.now(),
267
+ ...toolTokens > 0 ? { toolTokens } : {}
245
268
  });
246
269
  } catch {
247
270
  }
@@ -313,15 +336,37 @@ var init_codex_adapter = __esm({
313
336
  const lines = raw.split("\n").filter((l) => l.trim());
314
337
  const messages = [];
315
338
  let index = 0;
339
+ let pendingToolTokens = 0;
316
340
  for (const line of lines) {
317
341
  try {
318
342
  const entry = JSON.parse(line);
343
+ if (entry.role === "tool") {
344
+ const resultText = typeof entry.content === "string" ? entry.content : "";
345
+ pendingToolTokens += Math.round(resultText.length / 4);
346
+ continue;
347
+ }
319
348
  if (entry.role !== "user" && entry.role !== "assistant") continue;
320
349
  let text = "";
350
+ let toolTokens = pendingToolTokens;
351
+ pendingToolTokens = 0;
321
352
  if (typeof entry.content === "string") {
322
353
  text = entry.content.trim();
323
354
  } else if (Array.isArray(entry.content)) {
324
- text = entry.content.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text.trim()).join("\n").trim();
355
+ for (const block of entry.content) {
356
+ if (block.type === "text" && typeof block.text === "string") {
357
+ text += (text ? "\n" : "") + block.text.trim();
358
+ } else if (block.type === "tool_use" && block.input) {
359
+ toolTokens += Math.round(JSON.stringify(block.input).length / 4);
360
+ }
361
+ }
362
+ text = text.trim();
363
+ }
364
+ if (entry.tool_calls) {
365
+ for (const tc of entry.tool_calls) {
366
+ if (tc.function?.arguments) {
367
+ toolTokens += Math.round(tc.function.arguments.length / 4);
368
+ }
369
+ }
325
370
  }
326
371
  if (!text) continue;
327
372
  let ts = Date.now();
@@ -333,7 +378,8 @@ var init_codex_adapter = __esm({
333
378
  id: `codex-${index++}`,
334
379
  role: entry.role,
335
380
  content: text,
336
- timestamp: ts
381
+ timestamp: ts,
382
+ ...toolTokens > 0 ? { toolTokens } : {}
337
383
  });
338
384
  } catch {
339
385
  }
@@ -1431,7 +1477,7 @@ function calcMessageDecay(messages) {
1431
1477
  const words = msg.content.split(/\s+/).filter((w) => w.length > 0).length;
1432
1478
  const hasCode = msg.content.includes("```");
1433
1479
  const tokenEstimate = Math.round(words * 1.3 * (hasCode ? 1.5 : 1));
1434
- totalTokens += tokenEstimate;
1480
+ totalTokens += tokenEstimate + (msg.toolTokens ?? 0);
1435
1481
  }
1436
1482
  if (totalTokens < 500) return 0;
1437
1483
  let score = Math.min(100, Math.round(15 * Math.log(totalTokens / 1500)));
@@ -2190,7 +2236,8 @@ var init_mcp_server = __esm({
2190
2236
  ...m,
2191
2237
  platform: "claude",
2192
2238
  tabId: 0,
2193
- chatId: "cli"
2239
+ chatId: "cli",
2240
+ ...m.toolTokens !== void 0 ? { toolTokens: m.toolTokens } : {}
2194
2241
  }));
2195
2242
  const analysis = calculateDrift(chatMessages, config.weights);
2196
2243
  const level = scoreToLevel(analysis.score);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "driftguard-mcp",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Real-time AI conversation drift monitor — MCP server for Claude Code, Gemini CLI, Codex CLI, and Cursor",
5
5
  "main": "dist/bin.js",
6
6
  "bin": {