karajan-code 1.53.0 → 1.53.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karajan-code",
3
- "version": "1.53.0",
3
+ "version": "1.53.1",
4
4
  "description": "Local multi-agent coding orchestrator with TDD, SonarQube, and code review pipeline",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -0,0 +1,81 @@
1
+ /**
2
+ * MCP response compressor — reduces token consumption by stripping
3
+ * verbose fields from list payloads and truncating oversized arrays.
4
+ */
5
+
6
+ // Fields to strip from list items (keep in single-item detail views)
7
+ const STRIP_FROM_LIST_ITEMS = [
8
+ "descriptionStructured", "acceptanceCriteriaStructured",
9
+ "implementationPlan", "implementationNotes",
10
+ "developmentInstructions", "raw", "textSummary",
11
+ "workCycles", "config_snapshot", "paused_state",
12
+ "checkpoints"
13
+ ];
14
+
15
+ // Fields to strip from all responses (never useful to the LLM)
16
+ const ALWAYS_STRIP = [
17
+ "firebaseId", "cardType", "group", "createdBy", "updatedBy",
18
+ "_instance"
19
+ ];
20
+
21
+ const MAX_ARRAY_ITEMS = 20;
22
+ const MAX_COMMITS = 5;
23
+ const MAX_FINDINGS = 10;
24
+
25
+ export function compressResponse(data, toolName = "") {
26
+ if (!data || typeof data !== "object") return data;
27
+ if (Array.isArray(data)) return compressArray(data);
28
+
29
+ const compressed = { ...data };
30
+
31
+ // Strip always-remove fields
32
+ for (const key of ALWAYS_STRIP) delete compressed[key];
33
+
34
+ // Compress nested arrays and objects
35
+ for (const [key, value] of Object.entries(compressed)) {
36
+ if (Array.isArray(value)) {
37
+ if (key === "commits") compressed[key] = truncateFromEnd(value, MAX_COMMITS);
38
+ else if (key === "findings" || key === "blocking_issues") compressed[key] = truncateFromStart(value, MAX_FINDINGS);
39
+ else compressed[key] = compressArray(value);
40
+ } else if (value && typeof value === "object") {
41
+ compressed[key] = compressResponse(value, toolName);
42
+ }
43
+ }
44
+
45
+ return compressed;
46
+ }
47
+
48
+ function compressArray(arr) {
49
+ if (!Array.isArray(arr) || arr.length === 0) return arr;
50
+
51
+ // Strip verbose fields from list items
52
+ const stripped = arr.map(item => {
53
+ if (!item || typeof item !== "object") return item;
54
+ const clean = { ...item };
55
+ for (const key of STRIP_FROM_LIST_ITEMS) delete clean[key];
56
+ for (const key of ALWAYS_STRIP) delete clean[key];
57
+ return clean;
58
+ });
59
+
60
+ if (stripped.length <= MAX_ARRAY_ITEMS) return stripped;
61
+
62
+ const truncated = stripped.slice(0, MAX_ARRAY_ITEMS);
63
+ truncated.push({ _truncated: true, _total: arr.length, _showing: MAX_ARRAY_ITEMS });
64
+ return truncated;
65
+ }
66
+
67
+ function truncateFromEnd(arr, max) {
68
+ if (arr.length <= max) return arr;
69
+ return [{ _note: `${arr.length - max} earlier items omitted` }, ...arr.slice(-max)];
70
+ }
71
+
72
+ function truncateFromStart(arr, max) {
73
+ if (arr.length <= max) return arr;
74
+ const truncated = arr.slice(0, max);
75
+ truncated.push({ _note: `... and ${arr.length - max} more` });
76
+ return truncated;
77
+ }
78
+
79
+ export function compactStringify(data) {
80
+ return JSON.stringify(data);
81
+ }
@@ -9,6 +9,7 @@ import fs from "node:fs/promises";
9
9
  import { loadConfig, applyRunOverrides, validateConfig } from "../config.js";
10
10
  import { currentBranch } from "../utils/git.js";
11
11
  import { buildProgressNotifier } from "./progress.js";
12
+ import { compressResponse, compactStringify } from "./response-compressor.js";
12
13
 
13
14
  // ── Sub-module re-exports ────────────────────────────────────────────
14
15
  export { handleRunDirect, handleResumeDirect, validateResumeAnswer, handleRun, handleResume } from "./handlers/run-handler.js";
@@ -58,8 +59,9 @@ export function asObject(value) {
58
59
  }
59
60
 
60
61
  export function responseText(payload) {
62
+ const compressed = compressResponse(payload);
61
63
  return {
62
- content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
64
+ content: [{ type: "text", text: compactStringify(compressed) }]
63
65
  };
64
66
  }
65
67