@a5c-ai/babysitter-sdk 0.0.181 → 0.0.182-staging.abeea3e4
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/cli/commands/compressOutput.d.ts +24 -0
- package/dist/cli/commands/compressOutput.d.ts.map +1 -0
- package/dist/cli/commands/compressOutput.js +421 -0
- package/dist/cli/commands/compressionReset.d.ts +15 -0
- package/dist/cli/commands/compressionReset.d.ts.map +1 -0
- package/dist/cli/commands/compressionReset.js +87 -0
- package/dist/cli/commands/compressionSet.d.ts +26 -0
- package/dist/cli/commands/compressionSet.d.ts.map +1 -0
- package/dist/cli/commands/compressionSet.js +179 -0
- package/dist/cli/commands/compressionStatus.d.ts +12 -0
- package/dist/cli/commands/compressionStatus.d.ts.map +1 -0
- package/dist/cli/commands/compressionStatus.js +133 -0
- package/dist/cli/commands/compressionToggle.d.ts +17 -0
- package/dist/cli/commands/compressionToggle.d.ts.map +1 -0
- package/dist/cli/commands/compressionToggle.js +115 -0
- package/dist/cli/commands/hookRun.d.ts +5 -0
- package/dist/cli/commands/hookRun.d.ts.map +1 -1
- package/dist/cli/commands/hookRun.js +127 -2
- package/dist/cli/commands/mcpServe.d.ts +9 -0
- package/dist/cli/commands/mcpServe.d.ts.map +1 -0
- package/dist/cli/commands/mcpServe.js +31 -0
- package/dist/cli/commands/tokensStats.d.ts +70 -0
- package/dist/cli/commands/tokensStats.d.ts.map +1 -0
- package/dist/cli/commands/tokensStats.js +355 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +101 -3
- package/dist/cli/mcpServeEntry.d.ts +3 -0
- package/dist/cli/mcpServeEntry.d.ts.map +1 -0
- package/dist/cli/mcpServeEntry.js +8 -0
- package/dist/compression/config-loader.d.ts +24 -0
- package/dist/compression/config-loader.d.ts.map +1 -0
- package/dist/compression/config-loader.js +179 -0
- package/dist/compression/config.d.ts +49 -0
- package/dist/compression/config.d.ts.map +1 -0
- package/dist/compression/config.js +41 -0
- package/dist/compression/density-filter.d.ts +20 -0
- package/dist/compression/density-filter.d.ts.map +1 -0
- package/dist/compression/density-filter.js +91 -0
- package/dist/compression/library-cache.d.ts +19 -0
- package/dist/compression/library-cache.d.ts.map +1 -0
- package/dist/compression/library-cache.js +149 -0
- package/dist/harness/claudeCode.d.ts.map +1 -1
- package/dist/harness/claudeCode.js +70 -4
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +3 -1
- package/dist/harness/pi.d.ts +10 -0
- package/dist/harness/pi.d.ts.map +1 -0
- package/dist/harness/pi.js +140 -0
- package/dist/harness/registry.d.ts.map +1 -1
- package/dist/harness/registry.js +2 -0
- package/dist/mcp/index.d.ts +7 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +50 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +21 -0
- package/dist/mcp/tools/discovery.d.ts +3 -0
- package/dist/mcp/tools/discovery.d.ts.map +1 -0
- package/dist/mcp/tools/discovery.js +113 -0
- package/dist/mcp/tools/runs.d.ts +3 -0
- package/dist/mcp/tools/runs.d.ts.map +1 -0
- package/dist/mcp/tools/runs.js +273 -0
- package/dist/mcp/tools/sessions.d.ts +3 -0
- package/dist/mcp/tools/sessions.d.ts.map +1 -0
- package/dist/mcp/tools/sessions.js +219 -0
- package/dist/mcp/tools/tasks.d.ts +3 -0
- package/dist/mcp/tools/tasks.d.ts.map +1 -0
- package/dist/mcp/tools/tasks.js +230 -0
- package/dist/mcp/util/errors.d.ts +14 -0
- package/dist/mcp/util/errors.d.ts.map +1 -0
- package/dist/mcp/util/errors.js +10 -0
- package/dist/mcp/util/resolve-run-dir.d.ts +6 -0
- package/dist/mcp/util/resolve-run-dir.d.ts.map +1 -0
- package/dist/mcp/util/resolve-run-dir.js +47 -0
- package/dist/runtime/intrinsics/task.d.ts.map +1 -1
- package/dist/runtime/intrinsics/task.js +2 -1
- package/dist/runtime/replay/effectIndex.d.ts.map +1 -1
- package/dist/runtime/replay/effectIndex.js +4 -3
- package/dist/utils/compressContext.d.ts +50 -0
- package/dist/utils/compressContext.d.ts.map +1 -0
- package/dist/utils/compressContext.js +180 -0
- package/package.json +4 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compress-output — run a command and compress its output.
|
|
3
|
+
*
|
|
4
|
+
* Used by `babysitter hook:run --hook-type pre-tool-use` to replace RTK.
|
|
5
|
+
* Runs the given command, detects its family (git, ls, grep, diff, read),
|
|
6
|
+
* and applies the appropriate compressor — all inlined, zero external deps.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* babysitter compress-output <command and args...>
|
|
10
|
+
*
|
|
11
|
+
* Examples:
|
|
12
|
+
* babysitter compress-output git status
|
|
13
|
+
* babysitter compress-output git log --oneline -20
|
|
14
|
+
* babysitter compress-output ls -la
|
|
15
|
+
* babysitter compress-output grep -rn "foo" src/
|
|
16
|
+
*/
|
|
17
|
+
export interface CompressOutputOptions {
|
|
18
|
+
/** The command + arguments to run and compress. */
|
|
19
|
+
args: string[];
|
|
20
|
+
/** Timeout for the child process in ms (default 30 000). */
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function handleCompressOutput(opts: CompressOutputOptions): number;
|
|
24
|
+
//# sourceMappingURL=compressOutput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressOutput.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compressOutput.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA0VD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAoCxE"}
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* compress-output — run a command and compress its output.
|
|
4
|
+
*
|
|
5
|
+
* Used by `babysitter hook:run --hook-type pre-tool-use` to replace RTK.
|
|
6
|
+
* Runs the given command, detects its family (git, ls, grep, diff, read),
|
|
7
|
+
* and applies the appropriate compressor — all inlined, zero external deps.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* babysitter compress-output <command and args...>
|
|
11
|
+
*
|
|
12
|
+
* Examples:
|
|
13
|
+
* babysitter compress-output git status
|
|
14
|
+
* babysitter compress-output git log --oneline -20
|
|
15
|
+
* babysitter compress-output ls -la
|
|
16
|
+
* babysitter compress-output grep -rn "foo" src/
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.handleCompressOutput = handleCompressOutput;
|
|
20
|
+
const node_child_process_1 = require("node:child_process");
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Command-family detection
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
function detectCommandFamily(command) {
|
|
25
|
+
const first = command.trim().toLowerCase().split(/\s+/)[0] ?? "";
|
|
26
|
+
if (first === "git")
|
|
27
|
+
return "git";
|
|
28
|
+
if (first === "ls" || first === "dir")
|
|
29
|
+
return "ls";
|
|
30
|
+
if (first === "grep" || first === "rg" || first === "ag")
|
|
31
|
+
return "grep";
|
|
32
|
+
if (first === "diff" || first === "delta")
|
|
33
|
+
return "diff";
|
|
34
|
+
if (first === "cat" || first === "head" || first === "tail" || first === "less" || first === "more")
|
|
35
|
+
return "read";
|
|
36
|
+
return "unknown";
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Git compressor
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
function detectGitSubcommand(command) {
|
|
42
|
+
const parts = command.toLowerCase().trim().split(/\s+/);
|
|
43
|
+
const sub = parts.find((p, i) => i > 0 && !p.startsWith("-")) ?? "";
|
|
44
|
+
const map = {
|
|
45
|
+
diff: "diff", log: "log", status: "status", show: "show",
|
|
46
|
+
add: "add", commit: "commit", push: "push", pull: "pull",
|
|
47
|
+
branch: "branch", fetch: "fetch", stash: "stash", worktree: "worktree",
|
|
48
|
+
};
|
|
49
|
+
return map[sub] ?? "unknown";
|
|
50
|
+
}
|
|
51
|
+
function compactDiff(diff, maxLines = 100) {
|
|
52
|
+
const lines = diff.split("\n");
|
|
53
|
+
const result = [];
|
|
54
|
+
let kept = 0;
|
|
55
|
+
let currentFile = "";
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
if (kept >= maxLines)
|
|
58
|
+
break;
|
|
59
|
+
if (line.startsWith("diff --git") || line.startsWith("--- "))
|
|
60
|
+
continue;
|
|
61
|
+
if (line.startsWith("+++ ")) {
|
|
62
|
+
currentFile = line.replace(/^\+\+\+ b?\//, "");
|
|
63
|
+
result.push(`\n--- ${currentFile} ---`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (line.startsWith("@@"))
|
|
67
|
+
continue;
|
|
68
|
+
if (line.startsWith("+") || line.startsWith("-")) {
|
|
69
|
+
result.push(line.length > 120 ? line.slice(0, 117) + "..." : line);
|
|
70
|
+
kept++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (lines.length > maxLines)
|
|
74
|
+
result.push(`\n... ${lines.length - maxLines} more lines`);
|
|
75
|
+
return result.join("\n").trim();
|
|
76
|
+
}
|
|
77
|
+
function compactLog(log, maxEntries = 20) {
|
|
78
|
+
const lines = log.split("\n");
|
|
79
|
+
const entries = [];
|
|
80
|
+
let count = 0;
|
|
81
|
+
for (const line of lines) {
|
|
82
|
+
if (count >= maxEntries)
|
|
83
|
+
break;
|
|
84
|
+
const trimmed = line.trim();
|
|
85
|
+
if (!trimmed)
|
|
86
|
+
continue;
|
|
87
|
+
if (trimmed.startsWith("commit ")) {
|
|
88
|
+
entries.push(trimmed.replace("commit ", "").slice(0, 12));
|
|
89
|
+
}
|
|
90
|
+
else if (/^[0-9a-f]{7,}/.test(trimmed)) {
|
|
91
|
+
entries.push(trimmed.length > 80 ? trimmed.slice(0, 77) + "..." : trimmed);
|
|
92
|
+
count++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return entries.join("\n");
|
|
96
|
+
}
|
|
97
|
+
function compactStatus(status) {
|
|
98
|
+
const lines = status.split("\n");
|
|
99
|
+
const staged = [];
|
|
100
|
+
const unstaged = [];
|
|
101
|
+
const untracked = [];
|
|
102
|
+
for (const line of lines) {
|
|
103
|
+
if (!line.trim() || line.startsWith("On branch") || line.startsWith("HEAD"))
|
|
104
|
+
continue;
|
|
105
|
+
if (line.startsWith("\t")) {
|
|
106
|
+
const name = line.trim();
|
|
107
|
+
if (line.includes("new file:") || line.includes("modified:") || line.includes("deleted:")) {
|
|
108
|
+
staged.push(name);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
unstaged.push(name);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (line.startsWith("?? ")) {
|
|
115
|
+
untracked.push(line.slice(3));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const parts = [];
|
|
119
|
+
if (staged.length)
|
|
120
|
+
parts.push(`staged(${staged.length}): ${staged.slice(0, 5).join(", ")}`);
|
|
121
|
+
if (unstaged.length)
|
|
122
|
+
parts.push(`unstaged(${unstaged.length}): ${unstaged.slice(0, 5).join(", ")}`);
|
|
123
|
+
if (untracked.length)
|
|
124
|
+
parts.push(`untracked(${untracked.length}): ${untracked.slice(0, 5).join(", ")}`);
|
|
125
|
+
return parts.length ? parts.join("\n") : "clean";
|
|
126
|
+
}
|
|
127
|
+
function compressGitOutput(sub, raw) {
|
|
128
|
+
switch (sub) {
|
|
129
|
+
case "diff": return compactDiff(raw);
|
|
130
|
+
case "log": return compactLog(raw);
|
|
131
|
+
case "status": return compactStatus(raw);
|
|
132
|
+
case "show": return compactDiff(raw, 60);
|
|
133
|
+
case "add":
|
|
134
|
+
case "commit":
|
|
135
|
+
case "push":
|
|
136
|
+
case "pull":
|
|
137
|
+
case "fetch":
|
|
138
|
+
return raw.split("\n").filter(l => l.trim()).slice(0, 10).join("\n");
|
|
139
|
+
default:
|
|
140
|
+
return raw.split("\n").slice(0, 50).join("\n");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// Ls compressor
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
const NOISE_DIRS = new Set([
|
|
147
|
+
"node_modules", ".git", "target", "__pycache__", ".next", "dist", "build",
|
|
148
|
+
".cache", ".turbo", ".vercel", ".pytest_cache", ".mypy_cache", ".tox",
|
|
149
|
+
".venv", "venv", "coverage", ".nyc_output", ".DS_Store", "Thumbs.db",
|
|
150
|
+
".idea", ".vscode", ".vs", ".eggs",
|
|
151
|
+
]);
|
|
152
|
+
function humanSize(bytes) {
|
|
153
|
+
if (bytes >= 1_048_576)
|
|
154
|
+
return `${(bytes / 1_048_576).toFixed(1)}M`;
|
|
155
|
+
if (bytes >= 1024)
|
|
156
|
+
return `${(bytes / 1024).toFixed(1)}K`;
|
|
157
|
+
return `${bytes}B`;
|
|
158
|
+
}
|
|
159
|
+
function compressLsOutput(raw) {
|
|
160
|
+
const dirs = [];
|
|
161
|
+
const files = [];
|
|
162
|
+
const byExt = new Map();
|
|
163
|
+
for (const line of raw.split("\n")) {
|
|
164
|
+
if (line.startsWith("total ") || !line.trim())
|
|
165
|
+
continue;
|
|
166
|
+
const parts = line.split(/\s+/);
|
|
167
|
+
if (parts.length < 9)
|
|
168
|
+
continue;
|
|
169
|
+
const name = parts.slice(8).join(" ");
|
|
170
|
+
if (name === "." || name === "..")
|
|
171
|
+
continue;
|
|
172
|
+
if (NOISE_DIRS.has(name))
|
|
173
|
+
continue;
|
|
174
|
+
if (parts[0].startsWith("d")) {
|
|
175
|
+
dirs.push(name);
|
|
176
|
+
}
|
|
177
|
+
else if (parts[0].startsWith("-") || parts[0].startsWith("l")) {
|
|
178
|
+
const size = parseInt(parts[4] ?? "0", 10) || 0;
|
|
179
|
+
const dotPos = name.lastIndexOf(".");
|
|
180
|
+
const ext = dotPos >= 0 ? name.slice(dotPos) : "no ext";
|
|
181
|
+
byExt.set(ext, (byExt.get(ext) ?? 0) + 1);
|
|
182
|
+
files.push([name, humanSize(size)]);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (!dirs.length && !files.length)
|
|
186
|
+
return "(empty)\n";
|
|
187
|
+
let out = "";
|
|
188
|
+
for (const d of dirs)
|
|
189
|
+
out += `${d}/\n`;
|
|
190
|
+
for (const [name, size] of files)
|
|
191
|
+
out += `${name} ${size}\n`;
|
|
192
|
+
out += "\n";
|
|
193
|
+
let summary = `${files.length} files, ${dirs.length} dirs`;
|
|
194
|
+
if (byExt.size) {
|
|
195
|
+
const extCounts = [...byExt.entries()].sort((a, b) => b[1] - a[1]);
|
|
196
|
+
const extParts = extCounts.slice(0, 5).map(([e, c]) => `${c} ${e}`);
|
|
197
|
+
summary += ` (${extParts.join(", ")}`;
|
|
198
|
+
if (extCounts.length > 5)
|
|
199
|
+
summary += `, +${extCounts.length - 5} more`;
|
|
200
|
+
summary += ")";
|
|
201
|
+
}
|
|
202
|
+
return out + summary + "\n";
|
|
203
|
+
}
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// Grep compressor
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
function compressGrepOutput(raw, pattern, maxResults = 50, maxLineLen = 120) {
|
|
208
|
+
if (!raw.trim())
|
|
209
|
+
return `0 matches for '${pattern}'`;
|
|
210
|
+
const byFile = new Map();
|
|
211
|
+
let total = 0;
|
|
212
|
+
for (const line of raw.split("\n")) {
|
|
213
|
+
if (!line.trim())
|
|
214
|
+
continue;
|
|
215
|
+
const parts = line.split(":");
|
|
216
|
+
if (parts.length < 3 || !/^\d+$/.test(parts[1] ?? ""))
|
|
217
|
+
continue;
|
|
218
|
+
const file = parts[0] ?? "";
|
|
219
|
+
const lineNum = parseInt(parts[1] ?? "0", 10);
|
|
220
|
+
const content = parts.slice(2).join(":");
|
|
221
|
+
const cleaned = content.trim().length > maxLineLen
|
|
222
|
+
? content.trim().slice(0, maxLineLen - 3) + "..."
|
|
223
|
+
: content.trim();
|
|
224
|
+
total++;
|
|
225
|
+
if (!byFile.has(file))
|
|
226
|
+
byFile.set(file, []);
|
|
227
|
+
byFile.get(file).push([lineNum, cleaned]);
|
|
228
|
+
}
|
|
229
|
+
if (total === 0)
|
|
230
|
+
return `0 matches for '${pattern}'`;
|
|
231
|
+
let out = `${total} matches in ${byFile.size} files:\n\n`;
|
|
232
|
+
let shown = 0;
|
|
233
|
+
for (const [file, matches] of [...byFile.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
234
|
+
if (shown >= maxResults)
|
|
235
|
+
break;
|
|
236
|
+
out += `${file} (${matches.length}):\n`;
|
|
237
|
+
for (const [ln, content] of matches.slice(0, 10)) {
|
|
238
|
+
out += ` ${String(ln).padStart(4)}: ${content}\n`;
|
|
239
|
+
shown++;
|
|
240
|
+
if (shown >= maxResults)
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
if (matches.length > 10)
|
|
244
|
+
out += ` +${matches.length - 10}\n`;
|
|
245
|
+
out += "\n";
|
|
246
|
+
}
|
|
247
|
+
if (total > shown)
|
|
248
|
+
out += `... +${total - shown} more\n`;
|
|
249
|
+
return out;
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Diff compressor
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
function condenseDiff(diff) {
|
|
255
|
+
const result = [];
|
|
256
|
+
let currentFile = "";
|
|
257
|
+
let added = 0, removed = 0;
|
|
258
|
+
const changes = [];
|
|
259
|
+
const flush = () => {
|
|
260
|
+
if (currentFile && (added > 0 || removed > 0)) {
|
|
261
|
+
result.push(`${currentFile} (+${added} -${removed})`);
|
|
262
|
+
for (const c of changes.slice(0, 10))
|
|
263
|
+
result.push(` ${c}`);
|
|
264
|
+
if (changes.length > 10)
|
|
265
|
+
result.push(` ... +${changes.length - 10} more`);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
for (const line of diff.split("\n")) {
|
|
269
|
+
if (line.startsWith("+++ ")) {
|
|
270
|
+
flush();
|
|
271
|
+
currentFile = line.replace(/^\+\+\+ b?\//, "");
|
|
272
|
+
added = 0;
|
|
273
|
+
removed = 0;
|
|
274
|
+
changes.length = 0;
|
|
275
|
+
}
|
|
276
|
+
else if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
277
|
+
added++;
|
|
278
|
+
if (changes.length < 15)
|
|
279
|
+
changes.push(line.length > 70 ? line.slice(0, 67) + "..." : line);
|
|
280
|
+
}
|
|
281
|
+
else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
282
|
+
removed++;
|
|
283
|
+
if (changes.length < 15)
|
|
284
|
+
changes.push(line.length > 70 ? line.slice(0, 67) + "..." : line);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
flush();
|
|
288
|
+
return result.join("\n");
|
|
289
|
+
}
|
|
290
|
+
function languageFromExtension(ext) {
|
|
291
|
+
const map = {
|
|
292
|
+
rs: "rust", py: "python", pyw: "python",
|
|
293
|
+
js: "javascript", mjs: "javascript", cjs: "javascript",
|
|
294
|
+
ts: "typescript", tsx: "typescript",
|
|
295
|
+
go: "go", c: "c", h: "c", cpp: "cpp", cc: "cpp", cxx: "cpp", hpp: "cpp",
|
|
296
|
+
java: "java", rb: "ruby", sh: "shell", bash: "shell", zsh: "shell",
|
|
297
|
+
};
|
|
298
|
+
return map[ext.toLowerCase()] ?? "unknown";
|
|
299
|
+
}
|
|
300
|
+
function commentPatterns(lang) {
|
|
301
|
+
if (lang === "python")
|
|
302
|
+
return { line: "#", blockStart: '"""', blockEnd: '"""', docBlockStart: '"""' };
|
|
303
|
+
if (lang === "ruby")
|
|
304
|
+
return { line: "#", blockStart: "=begin", blockEnd: "=end" };
|
|
305
|
+
if (lang === "shell")
|
|
306
|
+
return { line: "#" };
|
|
307
|
+
return { line: "//", blockStart: "/*", blockEnd: "*/", docBlockStart: "/**" };
|
|
308
|
+
}
|
|
309
|
+
function minimalFilter(content, lang) {
|
|
310
|
+
const patterns = commentPatterns(lang);
|
|
311
|
+
const lines = content.split("\n");
|
|
312
|
+
const result = [];
|
|
313
|
+
let inBlock = false, inDocstring = false;
|
|
314
|
+
for (const line of lines) {
|
|
315
|
+
const t = line.trim();
|
|
316
|
+
if (patterns.blockStart && patterns.blockEnd) {
|
|
317
|
+
if (!inDocstring && t.includes(patterns.blockStart) &&
|
|
318
|
+
!(patterns.docBlockStart && t.startsWith(patterns.docBlockStart))) {
|
|
319
|
+
inBlock = true;
|
|
320
|
+
}
|
|
321
|
+
if (inBlock) {
|
|
322
|
+
if (t.includes(patterns.blockEnd))
|
|
323
|
+
inBlock = false;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (lang === "python" && t.startsWith('"""')) {
|
|
328
|
+
inDocstring = !inDocstring;
|
|
329
|
+
result.push(line);
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (inDocstring) {
|
|
333
|
+
result.push(line);
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (patterns.line && t.startsWith(patterns.line)) {
|
|
337
|
+
if (patterns.docLine && t.startsWith(patterns.docLine))
|
|
338
|
+
result.push(line);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
result.push(line);
|
|
342
|
+
}
|
|
343
|
+
return result.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
344
|
+
}
|
|
345
|
+
function compressReadOutput(content, ext) {
|
|
346
|
+
const lang = languageFromExtension(ext);
|
|
347
|
+
return minimalFilter(content, lang);
|
|
348
|
+
}
|
|
349
|
+
// ---------------------------------------------------------------------------
|
|
350
|
+
// Generic cap for unknown commands
|
|
351
|
+
// ---------------------------------------------------------------------------
|
|
352
|
+
function capLines(raw, maxLines = 200) {
|
|
353
|
+
const lines = raw.split("\n");
|
|
354
|
+
if (lines.length <= maxLines)
|
|
355
|
+
return raw;
|
|
356
|
+
return lines.slice(0, maxLines).join("\n") + `\n... +${lines.length - maxLines} more lines`;
|
|
357
|
+
}
|
|
358
|
+
// ---------------------------------------------------------------------------
|
|
359
|
+
// Main compressor dispatcher
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
function compressCommandOutput(cmdStr, rawOutput) {
|
|
362
|
+
const family = detectCommandFamily(cmdStr);
|
|
363
|
+
switch (family) {
|
|
364
|
+
case "git": {
|
|
365
|
+
const sub = detectGitSubcommand(cmdStr);
|
|
366
|
+
return compressGitOutput(sub, rawOutput);
|
|
367
|
+
}
|
|
368
|
+
case "ls":
|
|
369
|
+
return compressLsOutput(rawOutput);
|
|
370
|
+
case "grep": {
|
|
371
|
+
const parts = cmdStr.split(/\s+/);
|
|
372
|
+
const pattern = parts.find((p, i) => i > 0 && !p.startsWith("-")) ?? "";
|
|
373
|
+
return compressGrepOutput(rawOutput, pattern);
|
|
374
|
+
}
|
|
375
|
+
case "diff":
|
|
376
|
+
return condenseDiff(rawOutput);
|
|
377
|
+
case "read": {
|
|
378
|
+
const parts = cmdStr.trim().split(/\s+/);
|
|
379
|
+
const filePath = parts[parts.length - 1] ?? "";
|
|
380
|
+
const dotPos = filePath.lastIndexOf(".");
|
|
381
|
+
const ext = dotPos >= 0 ? filePath.slice(dotPos + 1) : "";
|
|
382
|
+
return compressReadOutput(rawOutput, ext);
|
|
383
|
+
}
|
|
384
|
+
default:
|
|
385
|
+
return capLines(rawOutput);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// ---------------------------------------------------------------------------
|
|
389
|
+
// Handler
|
|
390
|
+
// ---------------------------------------------------------------------------
|
|
391
|
+
function handleCompressOutput(opts) {
|
|
392
|
+
const { args, timeout = 30_000 } = opts;
|
|
393
|
+
if (args.length === 0) {
|
|
394
|
+
process.stderr.write("Error: compress-output requires a command\n");
|
|
395
|
+
return 1;
|
|
396
|
+
}
|
|
397
|
+
const [bin, ...cmdArgs] = args;
|
|
398
|
+
const result = (0, node_child_process_1.spawnSync)(bin, cmdArgs, {
|
|
399
|
+
encoding: "buffer",
|
|
400
|
+
timeout,
|
|
401
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
402
|
+
shell: false,
|
|
403
|
+
});
|
|
404
|
+
if (result.error) {
|
|
405
|
+
// Command failed to start (not found, timed out, etc.)
|
|
406
|
+
const msg = result.error instanceof Error ? result.error.message : String(result.error);
|
|
407
|
+
process.stderr.write(`compress-output: ${msg}\n`);
|
|
408
|
+
return 1;
|
|
409
|
+
}
|
|
410
|
+
const stdout = (result.stdout ?? Buffer.alloc(0)).toString("utf8");
|
|
411
|
+
// Write stderr through unchanged so the caller can still see errors
|
|
412
|
+
const stderrOut = (result.stderr ?? Buffer.alloc(0)).toString("utf8");
|
|
413
|
+
if (stderrOut)
|
|
414
|
+
process.stderr.write(stderrOut);
|
|
415
|
+
const cmdStr = args.join(" ");
|
|
416
|
+
const compressed = compressCommandOutput(cmdStr, stdout);
|
|
417
|
+
process.stdout.write(compressed);
|
|
418
|
+
if (compressed && !compressed.endsWith("\n"))
|
|
419
|
+
process.stdout.write("\n");
|
|
420
|
+
return result.status ?? 0;
|
|
421
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compression:reset — remove the project-level compression config file.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* babysitter compression:reset [--json]
|
|
6
|
+
*
|
|
7
|
+
* Deletes .a5c/compression.config.json from the current project, reverting all
|
|
8
|
+
* compression settings to their built-in defaults (subject to env var overrides).
|
|
9
|
+
*/
|
|
10
|
+
export interface CompressionResetOptions {
|
|
11
|
+
json?: boolean;
|
|
12
|
+
cwd?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function handleCompressionReset(opts: CompressionResetOptions): Promise<number>;
|
|
15
|
+
//# sourceMappingURL=compressionReset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressionReset.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compressionReset.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAMD,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmC3F"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* compression:reset — remove the project-level compression config file.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* babysitter compression:reset [--json]
|
|
7
|
+
*
|
|
8
|
+
* Deletes .a5c/compression.config.json from the current project, reverting all
|
|
9
|
+
* compression settings to their built-in defaults (subject to env var overrides).
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.handleCompressionReset = handleCompressionReset;
|
|
46
|
+
const node_fs_1 = require("node:fs");
|
|
47
|
+
const path = __importStar(require("node:path"));
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Handler
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
async function handleCompressionReset(opts) {
|
|
52
|
+
const projectDir = opts.cwd ?? process.cwd();
|
|
53
|
+
const filePath = path.join(projectDir, '.a5c', 'compression.config.json');
|
|
54
|
+
let existed = false;
|
|
55
|
+
try {
|
|
56
|
+
await node_fs_1.promises.unlink(filePath);
|
|
57
|
+
existed = true;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
const code = err.code;
|
|
61
|
+
if (code !== 'ENOENT') {
|
|
62
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
63
|
+
if (opts.json) {
|
|
64
|
+
console.error(JSON.stringify({ error: `Failed to remove config file: ${message}` }));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.error(`Error: Failed to remove config file: ${message}`);
|
|
68
|
+
}
|
|
69
|
+
return 1;
|
|
70
|
+
}
|
|
71
|
+
// File didn't exist — that's fine
|
|
72
|
+
}
|
|
73
|
+
if (opts.json) {
|
|
74
|
+
console.log(JSON.stringify({ removed: existed, configFile: filePath }));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (existed) {
|
|
78
|
+
console.log(`Removed: ${filePath}`);
|
|
79
|
+
console.log('Compression config reset to defaults.');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
console.log(`No project config file found at: ${filePath}`);
|
|
83
|
+
console.log('Nothing to reset — already using defaults.');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compression:set — update a specific compression config value in the project config.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* babysitter compression:set <layer.key> <value> [--json]
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* babysitter compression:set userPromptHook.threshold 300
|
|
9
|
+
* babysitter compression:set userPromptHook.keepRatio 0.85
|
|
10
|
+
* babysitter compression:set sdkContextHook.targetReduction 0.2
|
|
11
|
+
* babysitter compression:set sdkContextHook.minCompressionTokens 100
|
|
12
|
+
* babysitter compression:set commandOutputHook.excludeCommands node,python,ruby
|
|
13
|
+
* babysitter compression:set processLibraryCache.targetReduction 0.3
|
|
14
|
+
* babysitter compression:set processLibraryCache.ttlHours 48
|
|
15
|
+
* babysitter compression:set enabled false
|
|
16
|
+
*
|
|
17
|
+
* Writes the change to .a5c/compression.config.json in the current project.
|
|
18
|
+
*/
|
|
19
|
+
export interface CompressionSetOptions {
|
|
20
|
+
key: string;
|
|
21
|
+
value: string;
|
|
22
|
+
json?: boolean;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function handleCompressionSet(opts: CompressionSetOptions): Promise<number>;
|
|
26
|
+
//# sourceMappingURL=compressionSet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressionSet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compressionSet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAwFD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsDvF"}
|