debug-toolkit 0.4.0

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/README.md ADDED
@@ -0,0 +1,236 @@
1
+ # debug-toolkit
2
+
3
+ Closed-loop debugging for AI coding agents. One MCP server gives your agent the ability to **see code running** — not just read and write it.
4
+
5
+ ```
6
+ npx debug-toolkit demo # see it work (no AI needed)
7
+ npx debug-toolkit init # install in your project
8
+ ```
9
+
10
+ ## The Problem
11
+
12
+ When an AI agent hits a bug, it reads code and guesses a fix. You run it, paste the error back, the agent guesses again. Repeat 5-8 times.
13
+
14
+ debug-toolkit eliminates that loop. The agent investigates the error, instruments the code, captures runtime output, verifies the fix, and cleans up — all through MCP tool calls. No copy-pasting. No manual log hunting.
15
+
16
+ ## How It Works
17
+
18
+ ```
19
+ investigate → instrument → capture → fix → verify → cleanup
20
+ ```
21
+
22
+ One debug session. Full context. Diagnosis saved for next time.
23
+
24
+ ```
25
+ ┌─────────────────────────────────────────────────────────┐
26
+ │ Agent gets error from user │
27
+ │ ↓ │
28
+ │ debug_investigate → error type, source code, git, │
29
+ │ environment, past solutions │
30
+ │ ↓ │
31
+ │ debug_instrument → adds tagged logging to source │
32
+ │ ↓ │
33
+ │ debug_capture → collects runtime output │
34
+ │ ↓ │
35
+ │ Agent applies fix │
36
+ │ ↓ │
37
+ │ debug_verify → runs tests, confirms fix │
38
+ │ ↓ │
39
+ │ debug_cleanup → removes markers, saves diagnosis │
40
+ │ + causal chain to memory │
41
+ │ ↓ │
42
+ │ Next session: debug_investigate auto-recalls the fix │
43
+ └─────────────────────────────────────────────────────────┘
44
+ ```
45
+
46
+ ## Setup
47
+
48
+ ### Any project (JS/TS/Python/Go)
49
+
50
+ ```bash
51
+ npx debug-toolkit init
52
+ ```
53
+
54
+ Generates `.claude/mcp.json`, installs a pre-commit safety hook, detects your dev command. Restart Claude Code and you're done.
55
+
56
+ ### Tauri projects (auto-detected)
57
+
58
+ ```bash
59
+ cd my-tauri-app
60
+ npx debug-toolkit init
61
+ ```
62
+
63
+ If `src-tauri/` exists, debug-toolkit automatically:
64
+ - Sets dev command to `cargo tauri dev`
65
+ - Enables `RUST_BACKTRACE=1` and `RUST_LOG=info`
66
+ - Parses Rust panics, backtraces, and cargo build errors
67
+ - Discovers and tails `tauri-plugin-log` files from platform-specific paths
68
+ - Detects Tauri-specific errors (invoke, capability, plugin, window, asset)
69
+
70
+ ### Manual MCP config
71
+
72
+ Add to `.claude/mcp.json`:
73
+
74
+ ```json
75
+ {
76
+ "mcpServers": {
77
+ "debug-toolkit": {
78
+ "command": "npx",
79
+ "args": ["-y", "debug-toolkit"]
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## Two Modes
86
+
87
+ **Pure MCP** (default) — Just the MCP server on stdio. Agent gets all tools. No wrapper needed.
88
+
89
+ ```bash
90
+ npx debug-toolkit
91
+ ```
92
+
93
+ **Serve** — Wraps your dev server. Adds browser console/network capture via HTTP proxy + WebSocket.
94
+
95
+ ```bash
96
+ npx debug-toolkit serve -- npm run dev
97
+ npx debug-toolkit serve -- cargo tauri dev
98
+ ```
99
+
100
+ ## Tools
101
+
102
+ ### debug_investigate
103
+
104
+ **Start here.** Give it an error message or stack trace. Returns:
105
+
106
+ - Error classification (type, category, severity, suggestion)
107
+ - Source code at the exact crash site (highlighted)
108
+ - Git context (branch, commit, recent changes to those files)
109
+ - Runtime environment (Node/Rust version, frameworks, env vars — secrets redacted)
110
+ - Past solutions from memory (with staleness info and causal chains)
111
+
112
+ ```
113
+ Input: { error: "TypeError: Cannot read properties of undefined (reading 'map')" }
114
+ Output: { error, sourceCode, git, environment, pastSolutions, nextStep }
115
+ ```
116
+
117
+ ### debug_recall
118
+
119
+ Search past debug sessions for similar errors. Returns diagnoses ranked by relevance, with staleness tracking (has the code changed since?) and causal chains (where was the actual bug?).
120
+
121
+ ```
122
+ Input: { query: "TypeError undefined map" }
123
+ Output: { matches: [{ diagnosis, stale, rootCause }] }
124
+ ```
125
+
126
+ ### debug_patterns
127
+
128
+ Detect systemic issues across all past sessions:
129
+
130
+ | Pattern | What it finds |
131
+ |---------|--------------|
132
+ | **Recurring error** | Same error type in same file, 3+ times |
133
+ | **Hot file** | Files in 15%+ of debug sessions |
134
+ | **Regression** | Bug fixed once, came back |
135
+ | **Error cluster** | Multiple errors within 2 hours |
136
+
137
+ ### debug_instrument
138
+
139
+ Add tagged logging to source files. Supports JS/TS, Python, Go, and Rust:
140
+
141
+ | Language | Output |
142
+ |----------|--------|
143
+ | JS/TS | `console.log("[DBG_001]", expr)` |
144
+ | Python | `print(f"[DBG_001] {expr}")` |
145
+ | Go | `fmt.Printf("[DBG_001] %v\n", expr)` |
146
+ | Rust | `eprintln!("[DBG_001] {:?}", expr)` |
147
+
148
+ Each marker links to a hypothesis. Respects indentation. Auto-cleans on cleanup.
149
+
150
+ ### debug_capture
151
+
152
+ Run a command and capture output, or drain buffered events from terminal, browser, and Tauri log files. Tagged output is linked to hypotheses. Results are paginated.
153
+
154
+ ### debug_verify
155
+
156
+ After applying a fix, run the test command and get a clear pass/fail with exit code and error output.
157
+
158
+ ### debug_cleanup
159
+
160
+ Remove ALL instrumentation, verify files are restored, and save the diagnosis + causal chain to memory. Provide `rootCause` to teach the system where the actual bug was:
161
+
162
+ ```json
163
+ {
164
+ "diagnosis": "getUsers() returns undefined when db not connected",
165
+ "rootCause": {
166
+ "trigger": "missing db.connect() call",
167
+ "errorFile": "src/api.ts",
168
+ "causeFile": "src/db.ts",
169
+ "fixDescription": "added connect() before query"
170
+ }
171
+ }
172
+ ```
173
+
174
+ ### debug_session
175
+
176
+ Lightweight view of current state: hypotheses, active instruments, recent captures.
177
+
178
+ ## Memory System
179
+
180
+ debug-toolkit learns from every session:
181
+
182
+ **Recall** — When you investigate a new error, it auto-searches past diagnoses. If a similar error was solved before, the agent gets the previous diagnosis, which files were involved, and the causal chain.
183
+
184
+ **Staleness** — Every diagnosis is tagged with the git SHA. When recalled, the system checks if the referenced files have changed. Stale diagnoses are flagged but still shown.
185
+
186
+ **Causal chains** — Records where the error appeared vs. where the actual bug was. Next time, the agent goes straight to the cause file instead of the symptom.
187
+
188
+ **Patterns** — Detects recurring errors, hot files, regressions, and error clusters across all sessions.
189
+
190
+ ## Language Support
191
+
192
+ | Feature | JS/TS | Python | Go | Rust/Tauri |
193
+ |---------|-------|--------|----|------------|
194
+ | Stack trace parsing | Node.js frames | Python tracebacks | — | Panics, backtraces, cargo errors |
195
+ | Error classification | TypeError, ReferenceError, etc. | — | — | Panic, borrow, Tauri IPC/capability/plugin |
196
+ | Code instrumentation | `console.log` | `print()` | `fmt.Printf` | `eprintln!` |
197
+ | Source extraction | Yes | Yes | Yes | Yes |
198
+ | Log file tailing | — | — | — | `tauri-plugin-log` auto-discovery |
199
+ | Environment detection | package.json, frameworks | Python version | — | Cargo.toml, tauri.conf.json, plugins |
200
+
201
+ ## Security
202
+
203
+ - **Path traversal protection** — all file operations validated against project root
204
+ - **Expression validation** — blocks `eval`, `require`, `exec` in instrumentation
205
+ - **Secret redaction** — tokens, API keys, passwords, JWTs auto-redacted before storage
206
+ - **Localhost-only proxy** — binds to 127.0.0.1
207
+ - **Pre-commit hook** — blocks commits containing debug markers
208
+ - **Atomic writes** — temp file + rename, no corruption on crash
209
+ - **`.debug/` auto-gitignored**
210
+
211
+ ## Architecture
212
+
213
+ 15 files, 3,451 lines of TypeScript. 4 npm dependencies.
214
+
215
+ ```
216
+ src/
217
+ mcp.ts 473 lines — 8 tools + 1 resource + MCP server
218
+ context.ts 420 lines — Investigation engine (stack parsing, source, git, env)
219
+ demo.ts 398 lines — Self-contained interactive demo
220
+ memory.ts 369 lines — Cross-session memory with staleness + patterns
221
+ capture.ts 276 lines — Ring buffers, terminal pipe, Tauri log tailing
222
+ proxy.ts 200 lines — HTTP proxy + HTML injection + WebSocket
223
+ index.ts 204 lines — CLI entry point (mcp, serve, init, demo, clean)
224
+ security.ts 185 lines — Path traversal, expression validation, redaction
225
+ session.ts 162 lines — Data model, atomic persistence, marker index
226
+ injected.js 151 lines — Browser console/network/error capture script
227
+ instrument.ts 140 lines — Language-aware instrumentation (JS/TS/Py/Go/Rust)
228
+ cleanup.ts 126 lines — Single-pass marker removal with verification
229
+ cli.ts 125 lines — ANSI terminal UI
230
+ hook.ts 122 lines — Git pre-commit hook
231
+ methodology.ts 100 lines — Always-available debugging guide
232
+ ```
233
+
234
+ ## License
235
+
236
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: debug-toolkit
3
+ description: Closed-loop debugging for AI agents with cross-session memory. Investigate errors, recall past fixes, detect patterns, instrument code, capture output, verify fixes, auto-cleanup with causal chains. Start every debugging task with debug_investigate.
4
+ tools: ["debug_investigate", "debug_recall", "debug_patterns", "debug_instrument", "debug_capture", "debug_verify", "debug_cleanup", "debug_session"]
5
+ ---
6
+
7
+ # debug-toolkit
8
+
9
+ You have access to a debugging toolkit via MCP. These tools let you SEE code running — not just read and write it. They also learn from every debug session and get smarter over time.
10
+
11
+ ## When to Use
12
+
13
+ Use these tools whenever you encounter:
14
+ - A runtime error or stack trace
15
+ - A test failure
16
+ - Code that runs but produces wrong output
17
+ - A bug report from the user
18
+
19
+ ## The Workflow
20
+
21
+ **ALWAYS start with `debug_investigate`.** It auto-recalls past solutions.
22
+
23
+ ```
24
+ 1. debug_investigate → understand the error + auto-recall past fixes
25
+ 2. debug_instrument → add logging if investigation wasn't enough
26
+ 3. debug_capture → collect runtime output
27
+ 4. (apply fix) → edit the code
28
+ 5. debug_verify → confirm the fix works
29
+ 6. debug_cleanup → remove markers, save diagnosis + causal chain
30
+ ```
31
+
32
+ ## Tool Reference
33
+
34
+ ### debug_investigate
35
+ **Start here.** Parses error text, finds source files, shows the exact lines, gets git context. Auto-searches memory for past solutions with staleness info.
36
+ ```
37
+ Input: { error: "<stack trace>", problem?: "description" }
38
+ Output: { error, sourceCode, git, environment, pastSolutions?, nextStep }
39
+ ```
40
+ Past solutions include `stale` (has code changed?) and `rootCause` (causal chain from last fix).
41
+
42
+ ### debug_recall
43
+ Explicitly search past debug sessions. Returns diagnoses with staleness and causal chains.
44
+ ```
45
+ Input: { query: "TypeError Cannot read properties email" }
46
+ Output: { matches: [{ problem, diagnosis, stale, staleness?, rootCause? }] }
47
+ ```
48
+
49
+ ### debug_patterns
50
+ Detect patterns across ALL past sessions. Use periodically.
51
+ ```
52
+ Input: {}
53
+ Output: { patterns: [{ type, severity, message }] }
54
+ ```
55
+ Pattern types: `recurring_error`, `hot_file`, `regression`, `error_cluster`.
56
+
57
+ ### debug_instrument
58
+ Add tagged logging. Each marker links to a hypothesis.
59
+ ```
60
+ Input: { sessionId, filePath, lineNumber, expression: "req.body", hypothesis?: "body is undefined" }
61
+ ```
62
+
63
+ ### debug_capture
64
+ Run a command and capture output, or drain buffered events.
65
+ ```
66
+ Input: { sessionId, command?: "npm test", limit?: 30 }
67
+ ```
68
+
69
+ ### debug_verify
70
+ After applying a fix, run the test command and check pass/fail.
71
+ ```
72
+ Input: { sessionId, command: "npm test" }
73
+ ```
74
+
75
+ ### debug_cleanup
76
+ Remove ALL instrumentation, save diagnosis + causal chain to memory.
77
+ ```
78
+ Input: {
79
+ sessionId,
80
+ diagnosis?: "root cause was...",
81
+ rootCause?: {
82
+ trigger: "missing null check",
83
+ errorFile: "src/api.ts",
84
+ causeFile: "src/db.ts",
85
+ fixDescription: "added null check before .map()"
86
+ }
87
+ }
88
+ ```
89
+ **Always provide rootCause** — it's the most valuable data for future sessions.
90
+
91
+ ### debug_session
92
+ Lightweight view of current session state.
93
+ ```
94
+ Input: { sessionId }
95
+ ```
96
+
97
+ ## Rules
98
+ 1. NEVER skip debug_investigate. It's the highest-leverage step.
99
+ 2. Read `nextStep` in every response — it tells you what to do.
100
+ 3. If past solutions are found, check `stale` — fresh solutions can be trusted.
101
+ 4. Instrument 1-2 files, not 10. Narrow first.
102
+ 5. ALWAYS run debug_verify before claiming a fix works.
103
+ 6. ALWAYS provide `rootCause` in debug_cleanup — it teaches the system.
104
+ 7. Run debug_patterns periodically to spot systemic issues.
@@ -0,0 +1,46 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import { type Capture, type DebugSession } from "./session.js";
3
+ declare class RingBuffer<T> {
4
+ private buf;
5
+ private head;
6
+ private count;
7
+ private cap;
8
+ constructor(capacity: number);
9
+ push(item: T): void;
10
+ drain(): T[];
11
+ get length(): number;
12
+ }
13
+ export declare const terminalBuffer: RingBuffer<Capture>;
14
+ export declare const browserBuffer: RingBuffer<Capture>;
15
+ export declare function pipeProcess(child: ChildProcess): void;
16
+ export declare function runAndCapture(command: string, timeoutMs?: number): Promise<Capture[]>;
17
+ export declare function onBrowserEvent(event: {
18
+ type: string;
19
+ data: unknown;
20
+ ts: number;
21
+ }): void;
22
+ export declare function drainCaptures(cwd: string, session: DebugSession): Capture[];
23
+ /**
24
+ * Discover Tauri log files for a project.
25
+ * Searches platform-specific log directories based on the bundle identifier.
26
+ */
27
+ export declare function discoverTauriLogs(cwd: string): {
28
+ logDir: string | null;
29
+ logFiles: string[];
30
+ identifier: string | null;
31
+ };
32
+ /**
33
+ * Read recent lines from Tauri log files.
34
+ * Returns captures from the most recent log file.
35
+ */
36
+ export declare function readTauriLogs(cwd: string, tailLines?: number): Capture[];
37
+ export declare function getRecentCaptures(session: DebugSession, opts?: {
38
+ limit?: number;
39
+ source?: string;
40
+ markerOnly?: boolean;
41
+ }): {
42
+ captures: Capture[];
43
+ total: number;
44
+ showing: number;
45
+ };
46
+ export {};
@@ -0,0 +1,246 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
+ import { join, basename } from "node:path";
4
+ import { redactSensitiveData } from "./security.js";
5
+ import { newCaptureId, lookupHypothesis, saveSession, } from "./session.js";
6
+ // --- Marker tag extraction ---
7
+ const MARKER_RE = /\[DBG_(\d{3})\]/;
8
+ function extractMarkerTag(text) {
9
+ const m = MARKER_RE.exec(text);
10
+ return m ? `DBG_${m[1]}` : null;
11
+ }
12
+ // --- Ring buffer: fixed-size, no allocation on push ---
13
+ class RingBuffer {
14
+ buf;
15
+ head = 0;
16
+ count = 0;
17
+ cap;
18
+ constructor(capacity) {
19
+ this.cap = capacity;
20
+ this.buf = new Array(capacity);
21
+ }
22
+ push(item) {
23
+ this.buf[this.head] = item;
24
+ this.head = (this.head + 1) % this.cap;
25
+ if (this.count < this.cap)
26
+ this.count++;
27
+ }
28
+ drain() {
29
+ if (this.count === 0)
30
+ return [];
31
+ const start = (this.head - this.count + this.cap) % this.cap;
32
+ const result = [];
33
+ for (let i = 0; i < this.count; i++) {
34
+ result.push(this.buf[(start + i) % this.cap]);
35
+ }
36
+ this.count = 0;
37
+ this.head = 0;
38
+ return result;
39
+ }
40
+ get length() { return this.count; }
41
+ }
42
+ // --- Buffers ---
43
+ export const terminalBuffer = new RingBuffer(500);
44
+ export const browserBuffer = new RingBuffer(200);
45
+ // --- Terminal pipe ---
46
+ export function pipeProcess(child) {
47
+ const pipe = (stream, isErr) => {
48
+ if (!stream)
49
+ return;
50
+ stream.on("data", (chunk) => {
51
+ const text = chunk.toString();
52
+ (isErr ? process.stderr : process.stdout).write(chunk);
53
+ for (const line of text.split("\n")) {
54
+ const t = line.trim();
55
+ if (!t)
56
+ continue;
57
+ terminalBuffer.push({
58
+ id: newCaptureId(),
59
+ timestamp: new Date().toISOString(),
60
+ source: "terminal",
61
+ markerTag: extractMarkerTag(t),
62
+ data: { text: redactSensitiveData(t), stream: isErr ? "stderr" : "stdout" },
63
+ hypothesisId: null,
64
+ });
65
+ }
66
+ });
67
+ };
68
+ pipe(child.stdout, false);
69
+ pipe(child.stderr, true);
70
+ }
71
+ // --- Run command and capture ---
72
+ export function runAndCapture(command, timeoutMs = 30_000) {
73
+ return new Promise((resolve, reject) => {
74
+ const out = [];
75
+ const child = spawn(command, { shell: true, stdio: "pipe" });
76
+ const timer = setTimeout(() => { child.kill(); resolve(out); }, timeoutMs);
77
+ const handle = (stream, name) => {
78
+ if (!stream)
79
+ return;
80
+ stream.on("data", (chunk) => {
81
+ for (const line of chunk.toString().split("\n")) {
82
+ const t = line.trim();
83
+ if (!t)
84
+ continue;
85
+ out.push({
86
+ id: newCaptureId(),
87
+ timestamp: new Date().toISOString(),
88
+ source: "terminal",
89
+ markerTag: extractMarkerTag(t),
90
+ data: { text: redactSensitiveData(t), stream: name },
91
+ hypothesisId: null,
92
+ });
93
+ }
94
+ });
95
+ };
96
+ handle(child.stdout, "stdout");
97
+ handle(child.stderr, "stderr");
98
+ child.on("close", (code) => {
99
+ clearTimeout(timer);
100
+ out.push({
101
+ id: newCaptureId(), timestamp: new Date().toISOString(),
102
+ source: "terminal", markerTag: null,
103
+ data: { text: `exit:${code}`, stream: "meta" }, hypothesisId: null,
104
+ });
105
+ resolve(out);
106
+ });
107
+ child.on("error", (e) => { clearTimeout(timer); reject(e); });
108
+ });
109
+ }
110
+ // --- Browser event handler ---
111
+ export function onBrowserEvent(event) {
112
+ const srcMap = {
113
+ console: "browser-console", network: "browser-network", error: "browser-error",
114
+ };
115
+ const src = srcMap[event.type] ?? "browser-console";
116
+ const str = typeof event.data === "object" ? JSON.stringify(event.data) : String(event.data);
117
+ browserBuffer.push({
118
+ id: newCaptureId(),
119
+ timestamp: new Date(event.ts).toISOString(),
120
+ source: src,
121
+ markerTag: extractMarkerTag(str),
122
+ data: event.data,
123
+ hypothesisId: null,
124
+ });
125
+ }
126
+ // --- Drain + link (O(n) using pre-built index, not O(n*m)) ---
127
+ export function drainCaptures(cwd, session) {
128
+ const all = [...terminalBuffer.drain(), ...browserBuffer.drain()];
129
+ for (const c of all) {
130
+ if (c.markerTag) {
131
+ // O(1) lookup via pre-built index instead of O(m) scan
132
+ const hypId = lookupHypothesis(session, c.markerTag);
133
+ if (hypId) {
134
+ c.hypothesisId = hypId;
135
+ const hyp = session.hypotheses.find((h) => h.id === hypId);
136
+ if (hyp && !hyp.evidence.includes(c.id))
137
+ hyp.evidence.push(c.id);
138
+ }
139
+ }
140
+ }
141
+ session.captures.push(...all);
142
+ saveSession(cwd, session);
143
+ return all;
144
+ }
145
+ // --- Tauri log file discovery and reading ---
146
+ /**
147
+ * Discover Tauri log files for a project.
148
+ * Searches platform-specific log directories based on the bundle identifier.
149
+ */
150
+ export function discoverTauriLogs(cwd) {
151
+ // Read bundle identifier from tauri.conf.json
152
+ let identifier = null;
153
+ const confPath = join(cwd, "src-tauri", "tauri.conf.json");
154
+ if (existsSync(confPath)) {
155
+ try {
156
+ const conf = JSON.parse(readFileSync(confPath, "utf-8"));
157
+ identifier = conf.identifier ?? conf.bundle?.identifier ?? null;
158
+ }
159
+ catch { }
160
+ }
161
+ if (!identifier)
162
+ return { logDir: null, logFiles: [], identifier: null };
163
+ // Platform-specific log directories
164
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
165
+ const candidates = [];
166
+ if (process.platform === "darwin") {
167
+ candidates.push(join(home, "Library", "Logs", identifier));
168
+ }
169
+ else if (process.platform === "win32") {
170
+ const appdata = process.env.APPDATA ?? join(home, "AppData", "Roaming");
171
+ candidates.push(join(appdata, identifier, "logs"));
172
+ }
173
+ else {
174
+ // Linux
175
+ candidates.push(join(home, ".config", identifier, "logs"));
176
+ }
177
+ for (const dir of candidates) {
178
+ if (existsSync(dir)) {
179
+ try {
180
+ const files = readdirSync(dir)
181
+ .filter((f) => f.endsWith(".log"))
182
+ .map((f) => join(dir, f))
183
+ .sort((a, b) => {
184
+ // Most recently modified first
185
+ try {
186
+ return statSync(b).mtimeMs - statSync(a).mtimeMs;
187
+ }
188
+ catch {
189
+ return 0;
190
+ }
191
+ });
192
+ return { logDir: dir, logFiles: files, identifier };
193
+ }
194
+ catch { }
195
+ }
196
+ }
197
+ return { logDir: null, logFiles: [], identifier };
198
+ }
199
+ /**
200
+ * Read recent lines from Tauri log files.
201
+ * Returns captures from the most recent log file.
202
+ */
203
+ export function readTauriLogs(cwd, tailLines = 50) {
204
+ const { logFiles } = discoverTauriLogs(cwd);
205
+ if (logFiles.length === 0)
206
+ return [];
207
+ const captures = [];
208
+ const logFile = logFiles[0]; // Most recent
209
+ try {
210
+ const content = readFileSync(logFile, "utf-8");
211
+ const lines = content.split("\n").slice(-tailLines);
212
+ for (const line of lines) {
213
+ const t = line.trim();
214
+ if (!t)
215
+ continue;
216
+ captures.push({
217
+ id: newCaptureId(),
218
+ timestamp: new Date().toISOString(),
219
+ source: "tauri-log",
220
+ markerTag: extractMarkerTag(t),
221
+ data: { text: redactSensitiveData(t), file: basename(logFile), stream: "log" },
222
+ hypothesisId: null,
223
+ });
224
+ }
225
+ }
226
+ catch { }
227
+ return captures;
228
+ }
229
+ // --- Paginated capture retrieval (avoids dumping entire session) ---
230
+ export function getRecentCaptures(session, opts = {}) {
231
+ let filtered = session.captures;
232
+ if (opts.source) {
233
+ filtered = filtered.filter((c) => c.source === opts.source);
234
+ }
235
+ if (opts.markerOnly) {
236
+ filtered = filtered.filter((c) => c.markerTag !== null);
237
+ }
238
+ const limit = opts.limit ?? 50;
239
+ const recent = filtered.slice(-limit);
240
+ return {
241
+ captures: recent,
242
+ total: filtered.length,
243
+ showing: recent.length,
244
+ };
245
+ }
246
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type DebugSession } from "./session.js";
2
+ export interface CleanupResult {
3
+ cleaned: number;
4
+ verified: boolean;
5
+ errors: string[];
6
+ filesProcessed: string[];
7
+ }
8
+ export declare function cleanupSession(cwd: string, session: DebugSession): CleanupResult;
9
+ /**
10
+ * Emergency cleanup from manifest-less scan of session files.
11
+ */
12
+ export declare function cleanupFromManifest(cwd: string): CleanupResult;