debuganything 0.0.0-stage → 1.0.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.
Files changed (59) hide show
  1. package/.claude-plugin/plugin.json +15 -0
  2. package/DISCLAIMER.md +101 -0
  3. package/GEMINI.md +97 -0
  4. package/LICENSE +21 -0
  5. package/README.md +283 -2
  6. package/assets/README.md +9 -0
  7. package/assets/debuganything-logo.png +0 -0
  8. package/assets/debuganything-mark-512.png +0 -0
  9. package/dist/chunk-32IDKAZK.js +9 -0
  10. package/dist/chunk-32IDKAZK.js.map +1 -0
  11. package/dist/chunk-5BXTDASF.js +135 -0
  12. package/dist/chunk-5BXTDASF.js.map +1 -0
  13. package/dist/chunk-5RAKTYW5.js +292 -0
  14. package/dist/chunk-5RAKTYW5.js.map +1 -0
  15. package/dist/chunk-7MMXFUUN.js +79 -0
  16. package/dist/chunk-7MMXFUUN.js.map +1 -0
  17. package/dist/chunk-D742WJPT.js +436 -0
  18. package/dist/chunk-D742WJPT.js.map +1 -0
  19. package/dist/chunk-EMR42ZJQ.js +102 -0
  20. package/dist/chunk-EMR42ZJQ.js.map +1 -0
  21. package/dist/chunk-MLDOO673.js +1416 -0
  22. package/dist/chunk-MLDOO673.js.map +1 -0
  23. package/dist/chunk-NFL22T3H.js +309 -0
  24. package/dist/chunk-NFL22T3H.js.map +1 -0
  25. package/dist/chunk-STFC7C5C.js +245 -0
  26. package/dist/chunk-STFC7C5C.js.map +1 -0
  27. package/dist/chunk-VGYXHXTY.js +1015 -0
  28. package/dist/chunk-VGYXHXTY.js.map +1 -0
  29. package/dist/chunk-YY6M5RIJ.js +215 -0
  30. package/dist/chunk-YY6M5RIJ.js.map +1 -0
  31. package/dist/cli.js +254 -0
  32. package/dist/cli.js.map +1 -0
  33. package/dist/docker-ORXYMES4.js +23 -0
  34. package/dist/docker-ORXYMES4.js.map +1 -0
  35. package/dist/hook-QYLLBUNK.js +14 -0
  36. package/dist/hook-QYLLBUNK.js.map +1 -0
  37. package/dist/import-CT55AEEE.js +268 -0
  38. package/dist/import-CT55AEEE.js.map +1 -0
  39. package/dist/investigate-2GFD6EWB.js +102 -0
  40. package/dist/investigate-2GFD6EWB.js.map +1 -0
  41. package/dist/lsof-GBLZJBJR.js +22 -0
  42. package/dist/lsof-GBLZJBJR.js.map +1 -0
  43. package/dist/psmem-UB3VCMG3.js +20 -0
  44. package/dist/psmem-UB3VCMG3.js.map +1 -0
  45. package/dist/report_html-2ENM7HLC.js +99 -0
  46. package/dist/report_html-2ENM7HLC.js.map +1 -0
  47. package/dist/server.js +190 -0
  48. package/dist/server.js.map +1 -0
  49. package/dist/setup-NTPRUTMT.js +265 -0
  50. package/dist/setup-NTPRUTMT.js.map +1 -0
  51. package/dist/target-WJE4WFYA.js +36 -0
  52. package/dist/target-WJE4WFYA.js.map +1 -0
  53. package/gemini-extension.json +9 -0
  54. package/hooks/debuganything-hook.mjs +36 -0
  55. package/hooks/hooks.json +10 -0
  56. package/package.json +85 -3
  57. package/server.json +30 -0
  58. package/skills/debug-anything/SKILL.md +102 -0
  59. package/skills/inspect-product/SKILL.md +138 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/import.ts","../src/adapters/goruntime.ts","../src/analyze.ts"],"sourcesContent":["/**\n * `debuganything import` / import_artifact: analyze raw tool output the user captured\n * themselves (typically with sudo, or on another machine). File handling lives\n * here; the parsing and finding logic is in analyze.ts (shared with the\n * in-browser analyzer).\n */\nimport { readFile, stat } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport type { ImportTool, Session, ToolResult } from \"./contracts.js\";\nimport { ResultBuilder } from \"./evidence.js\";\nimport { LIMITS } from \"./safety.js\";\nimport { analyzeRaw, IMPORT_TOOL_MAP } from \"./analyze.js\";\n\nexport { IMPORT_TOOL_MAP, spanSeconds, analyzeText, detectTool } from \"./analyze.js\";\n\nexport async function importArtifact(session: Session, args: { tool: ImportTool; path: string; duration_s?: number }): Promise<ToolResult> {\n const toolName = IMPORT_TOOL_MAP[args.tool];\n const b = new ResultBuilder(toolName, session, session.target);\n let raw: string;\n try {\n const st = await stat(args.path);\n if (!st.isFile()) return b.fail(`${args.path} is not a regular file`).build();\n if (st.size > LIMITS.MAX_RAW_BYTES) return b.fail(`${args.path} is ${Math.round(st.size / 1024 / 1024)} MB; the import cap is ${LIMITS.MAX_RAW_BYTES / 1024 / 1024} MB (trim it first)`).build();\n raw = await readFile(args.path, \"utf8\");\n } catch (err) {\n return b.fail(`cannot read ${args.path}: ${(err as Error).message}`).build();\n }\n if (!raw.trim()) return b.fail(`${args.path} is empty`).build();\n const art = await b.writeArtifact(`imported-${basename(args.path)}`, raw, \"raw_text\", `imported ${args.tool} output from ${args.path}`);\n b.limitation(`imported from ${args.path}: Debug Anything did not run the tool, so flags, timing and target scope are whatever you used`);\n return analyzeRaw(b, { tool: args.tool, raw, duration_s: args.duration_s, art });\n}\n","/**\n * Go goroutine dumps: parse `/debug/pprof/goroutine?debug=2` or SIGQUIT\n * output, detect goroutine leaks, long-blocked goroutines and deadlocks.\n * Pure parsing/summarizing (debuganything import + web analyzer).\n */\nimport type { ToolResult } from \"../contracts.js\";\nimport { ResultBuilder } from \"../evidence.js\";\n\nexport type Goroutine = { id: number; state: string; minutes?: number; frames: Array<{ func: string; loc?: string }> };\n\nexport function parseGoroutines(raw: string): Goroutine[] {\n const out: Goroutine[] = [];\n let cur: Goroutine | undefined;\n let lastFunc: string | undefined;\n for (const line of raw.split(\"\\n\")) {\n const head = line.match(/^goroutine\\s+(\\d+)\\s+\\[([^\\],]+)(?:,\\s*(\\d+)\\s*minutes)?\\]:/);\n if (head) {\n cur = { id: Number(head[1]), state: head[2]!.trim(), minutes: head[3] ? Number(head[3]) : undefined, frames: [] };\n out.push(cur);\n lastFunc = undefined;\n continue;\n }\n if (!cur) continue;\n const loc = line.match(/^\\s+(\\S+\\.go:\\d+)/);\n if (loc && lastFunc) {\n cur.frames[cur.frames.length - 1]!.loc = loc[1];\n lastFunc = undefined;\n continue;\n }\n const fn = line.match(/^(\\S+?)\\(.*\\)$/) ?? line.match(/^(created by .+)$/);\n if (fn && line && !line.startsWith(\"\\t\")) {\n cur.frames.push({ func: fn[1]! });\n lastFunc = fn[1];\n }\n }\n return out;\n}\n\nconst BLOCKED_STATES = /^(chan receive|chan send|select|semacquire|sync\\.(Mutex|RWMutex)\\.|IO wait|sleep|GC assist wait|force gc \\(idle\\)|sync\\.Cond\\.Wait)/;\n\nexport async function summarizeGoroutines(b: ResultBuilder, gs: Goroutine[], artifact: string): Promise<ToolResult> {\n if (!gs.length) {\n b.limitation(\"no goroutines parsed (expected `curl localhost:PORT/debug/pprof/goroutine?debug=2` or SIGQUIT dump output)\");\n return b.fail(\"goroutines: none parsed\").build();\n }\n const byState = new Map<string, Goroutine[]>();\n for (const g of gs) byState.set(g.state, [...(byState.get(g.state) ?? []), g]);\n const states = [...byState].sort((a, c) => c[1].length - a[1].length);\n const summaryEv = b.evidenceOf(\n \"stack_summary\",\n `${gs.length} goroutine(s): ${states.slice(0, 6).map(([s, v]) => `${s}=${v.length}`).join(\" \")}`,\n states.map(([s, v]) => ({ state: s, count: v.length, example_top: v[0]?.frames[0]?.func })),\n { artifact },\n );\n\n // Leak heuristic: many goroutines parked at the same site\n const bySite = new Map<string, Goroutine[]>();\n for (const g of gs) {\n if (!BLOCKED_STATES.test(g.state)) continue;\n const site = `${g.state} @ ${g.frames[0]?.func ?? \"?\"}`;\n bySite.set(site, [...(bySite.get(site) ?? []), g]);\n }\n const hot = [...bySite].sort((a, c) => c[1].length - a[1].length)[0];\n if (hot && hot[1].length >= 100) {\n const g0 = hot[1][0]!;\n const ev = b.evidenceOf(\"stack\", `${hot[1].length} goroutines parked at ${hot[0]}`, { site: hot[0], example: g0.frames.slice(0, 8).map((f) => `${f.func}${f.loc ? ` (${f.loc})` : \"\"}`) }, { artifact });\n b.finding(hot[1].length >= 1000 ? \"high\" : \"warn\", `goroutine leak: ${hot[1].length} goroutines blocked at ${hot[0]}${g0.frames[0]?.loc ? ` (${g0.frames[0].loc})` : \"\"} — something creates them and never lets them finish`, [ev, summaryEv], \"inferred\", \"Find who spawns them: the `created by` frame in the dump names the call site.\");\n }\n const old = gs.filter((g) => (g.minutes ?? 0) >= 10).sort((a, c) => (c.minutes ?? 0) - (a.minutes ?? 0));\n if (old.length) {\n const ev = b.evidenceOf(\"lock_wait\", `${old.length} goroutine(s) blocked ≥10 minutes; oldest ${old[0]!.minutes} min in ${old[0]!.state} at ${old[0]!.frames[0]?.func ?? \"?\"}`, old.slice(0, 15).map((g) => ({ id: g.id, state: g.state, minutes: g.minutes, top: g.frames[0]?.func, loc: g.frames[0]?.loc })), { artifact });\n b.finding(old[0]!.minutes! >= 60 ? \"high\" : \"warn\", `${old.length} goroutine(s) stuck for ${old[0]!.minutes}+ minutes (${old[0]!.state} at ${old[0]!.frames[0]?.func ?? \"?\"}) — a peer, channel or lock never delivered`, [ev], \"observed\");\n }\n const mutex = gs.filter((g) => /^sync\\.(Mutex|RWMutex)/.test(g.state) || g.state === \"semacquire\" && /sync\\.\\(\\*(Mutex|RWMutex)\\)/.test(g.frames[0]?.func ?? \"\"));\n if (mutex.length >= 5) {\n const ev = b.evidenceOf(\"lock_wait\", `${mutex.length} goroutines acquiring mutexes; top site ${mutex[0]!.frames.find((f) => !/^sync\\./.test(f.func))?.func ?? \"?\"}`, mutex.slice(0, 10).map((g) => ({ id: g.id, top: g.frames.find((f) => !/^sync\\./.test(f.func))?.func })), { artifact });\n b.finding(\"warn\", `mutex contention: ${mutex.length} goroutines waiting to lock`, [ev], \"observed\");\n }\n const running = byState.get(\"running\") ?? [];\n if (!running.length && gs.length > 1 && gs.every((g) => BLOCKED_STATES.test(g.state) || g.state === \"runnable\")) {\n b.finding(gs.length <= 20 ? \"high\" : \"warn\", `no goroutine is running — all ${gs.length} are parked (${states.slice(0, 3).map(([s, v]) => `${v.length} in ${s}`).join(\", \")})`, [summaryEv], \"inferred\", \"If the process should be serving traffic, this is a global stall: check channel senders and lock holders.\");\n }\n if (!b.findingCount) b.finding(\"info\", `${gs.length} goroutines, ${running.length} running — nothing alarming in this snapshot`, [summaryEv]);\n b.next(\"inspect_sockets\", \"profile_cpu\", \"trace_syscalls\");\n return b.build();\n}\n","/**\n * Pure analysis of captured tool output: the same parsers and finding logic\n * the live adapters and `debuganything import` use, with no filesystem dependency.\n * This is the module the in-browser analyzer on debuganything.dev builds from.\n */\nimport type { ImportTool, ToolResult } from \"./contracts.js\";\nimport { ResultBuilder, humanBytes } from \"./evidence.js\";\nimport { parseStrace, summarizeSyscallRecords, type SyscallRecord } from \"./adapters/strace.js\";\nimport { parseFsUsage } from \"./adapters/fs_usage.js\";\nimport { perfScriptToFolded } from \"./adapters/perf.js\";\nimport { parsePySpyDump, summarizePySpyDump, summarizeProfile } from \"./adapters/pyspy.js\";\nimport { sampleToFolded } from \"./adapters/sample_macos.js\";\nimport { parseGdbBacktrace, summarizeNativeStacks } from \"./adapters/gdb.js\";\nimport { parseLldbBacktrace } from \"./adapters/lldb.js\";\nimport { parseLsofFields, summarizeSockets, summarizeFiles } from \"./adapters/lsof.js\";\nimport { parseTcpdump, summarizeCaptureEvidence } from \"./adapters/tcpdump.js\";\nimport { parseJstack, summarizeJavaStacks } from \"./adapters/jvm.js\";\nimport { parseGoroutines, summarizeGoroutines } from \"./adapters/goruntime.js\";\n\n/** Which Debug Anything tool an imported file corresponds to (so diff_runs/report treat it like a live run). */\nexport const IMPORT_TOOL_MAP: Record<ImportTool, string> = {\n strace: \"trace_syscalls\",\n fs_usage: \"trace_syscalls\",\n perf_script: \"profile_cpu\",\n folded: \"profile_cpu\",\n pyspy_dump: \"dump_stacks\",\n sample: \"profile_cpu\",\n gdb: \"dump_stacks\",\n lldb: \"dump_stacks\",\n lsof: \"inspect_sockets\",\n tcpdump: \"capture_traffic\",\n jstack: \"dump_stacks\",\n goroutines: \"dump_stacks\",\n};\n\n/** Seconds between first and last timestamp of records with HH:MM:SS.ffffff times. Pure. */\nexport function spanSeconds(records: SyscallRecord[]): number | undefined {\n const ts = records.map((r) => r.time).filter((t): t is string => Boolean(t));\n if (ts.length < 2) return undefined;\n const toS = (t: string) => {\n const [h, m, s] = t.split(\":\");\n return Number(h) * 3600 + Number(m) * 60 + Number(s);\n };\n let span = toS(ts[ts.length - 1]!) - toS(ts[0]!);\n if (span < 0) span += 86400;\n return Math.max(1, Math.round(span));\n}\n\n/** Run the import analysis for one tool's raw text on an existing builder. `art` is the registered raw artifact path. */\nexport async function analyzeRaw(b: ResultBuilder, args: { tool: ImportTool; raw: string; duration_s?: number; art: string }): Promise<ToolResult> {\n const raw = args.raw;\n const art = args.art;\n switch (args.tool) {\n case \"strace\":\n case \"fs_usage\": {\n const records = args.tool === \"strace\" ? parseStrace(raw) : parseFsUsage(raw);\n if (!records.length) return b.fail(`no ${args.tool} records parsed; expected ${args.tool === \"strace\" ? \"strace -f -T -tt\" : \"fs_usage -w\"} output`).build();\n const duration = args.duration_s ?? spanSeconds(records) ?? 1;\n summarizeSyscallRecords(b, records, duration, art);\n if (args.tool === \"fs_usage\") b.limitation(\"fs_usage shows file and network calls only; futex/select/kevent waits are not included\");\n b.next(\"profile_cpu\", \"inspect_sockets\");\n return b.build();\n }\n case \"perf_script\":\n case \"folded\":\n case \"sample\": {\n const folded = args.tool === \"perf_script\" ? perfScriptToFolded(raw) : args.tool === \"sample\" ? sampleToFolded(raw) : raw;\n if (!folded.trim()) return b.fail(`no stacks parsed from ${args.tool} output`).build();\n await b.writeArtifact(\"imported-folded.txt\", folded, \"folded_stacks\", \"folded stacks\");\n const duration = args.duration_s ?? 10;\n if (!args.duration_s) b.limitation(\"duration not given; assumed 10 s for rate estimates (pass duration_s)\");\n const hz = args.tool === \"perf_script\" ? 99 : args.tool === \"sample\" ? 1000 : undefined;\n return summarizeProfile(b, folded, duration, args.tool === \"perf_script\" ? \"perf\" : args.tool, hz);\n }\n case \"pyspy_dump\": {\n const dump = parsePySpyDump(raw);\n if (!dump.threads.length) return b.fail(\"no threads parsed; expected `py-spy dump` output\").build();\n await summarizePySpyDump(b, dump, art, undefined);\n b.limitation(\"relative source paths could not be resolved (no live process); run with --locals or from the app directory for lock classification\");\n return b.build();\n }\n case \"jstack\": {\n const dump = parseJstack(raw);\n return summarizeJavaStacks(b, dump, art);\n }\n case \"goroutines\": {\n const gs = parseGoroutines(raw);\n return summarizeGoroutines(b, gs, art);\n }\n case \"gdb\":\n case \"lldb\": {\n const threads = args.tool === \"gdb\" ? parseGdbBacktrace(raw) : parseLldbBacktrace(raw);\n return summarizeNativeStacks(b, threads, art, args.tool);\n }\n case \"lsof\": {\n const entries = parseLsofFields(raw);\n if (!entries.length) return b.fail(\"no lsof entries parsed; expected `lsof -nP -F pcufatsinTP` output\").build();\n const s = summarizeSockets(entries);\n const f = summarizeFiles(entries);\n const listenEv = b.evidenceOf(\"socket_summary\", s.listening.length ? `listening: ${s.listening.map((l) => `${l.proto} ${l.addr}:${l.port} (pid ${l.pid})`).join(\", \")}` : \"no listening sockets\", s.listening, { artifact: art });\n const stateEv = b.evidenceOf(\"socket_summary\", `${s.total_sockets} inet socket(s): ${Object.entries(s.byState).map(([k, v]) => `${k}=${v}`).join(\" \") || \"none established\"}; udp=${s.udp}; unix=${s.unix_sockets}`, { by_state: s.byState, total: s.total_sockets }, { artifact: art });\n const remoteEv = b.evidenceOf(\"socket\", s.byRemote.length ? `top remotes: ${s.byRemote.slice(0, 5).map((r) => `${r.remote} ×${r.count}`).join(\", \")}` : \"no remote connections\", s.byRemote.slice(0, 30), { artifact: art });\n const fdEv = b.evidenceOf(\"fd_summary\", `${f.total_fds} fd(s): ${Object.entries(f.byType).sort((a, c) => c[1] - a[1]).map(([k, v]) => `${k}=${v}`).join(\" \")}`, Object.entries(f.byType).map(([type, count]) => ({ type, count })), { artifact: art });\n if (s.listening.length) b.finding(\"info\", `listening on ${s.listening.map((l) => `${l.proto}/${l.port}`).join(\", \")}`, [listenEv]);\n const cw = s.byState.CLOSE_WAIT ?? 0;\n if (cw >= 20) b.finding(\"high\", `${cw} sockets in CLOSE_WAIT — the peer closed and the target never called close()`, [stateEv], \"inferred\");\n else if (cw >= 5) b.finding(\"warn\", `${cw} sockets in CLOSE_WAIT`, [stateEv], \"inferred\");\n if ((s.byState.TIME_WAIT ?? 0) >= 100) b.finding(\"warn\", `${s.byState.TIME_WAIT} sockets in TIME_WAIT — connection churn`, [stateEv], \"inferred\");\n if (s.byRemote[0] && s.byRemote[0].count >= 50) b.finding(\"warn\", `${s.byRemote[0].count} connections to ${s.byRemote[0].remote}`, [remoteEv], \"inferred\");\n if (f.deleted.length) {\n const delEv = b.evidenceOf(\"fd\", `${f.deleted.length} deleted-but-open file(s), ${humanBytes(f.deleted.reduce((n, d) => n + d.size, 0))} held`, f.deleted.slice(0, 20), { artifact: art });\n b.finding(\"high\", `${f.deleted.length} file(s) deleted while still open hold ${humanBytes(f.deleted.reduce((n, d) => n + d.size, 0))} of disk`, [delEv]);\n }\n if (b.findingCount === 0) b.finding(\"info\", `${f.total_fds} fds, ${s.total_sockets} inet sockets, nothing alarming`, [fdEv, stateEv]);\n b.next(\"inspect_files\", \"trace_syscalls\");\n return b.build();\n }\n case \"tcpdump\": {\n const pkts = parseTcpdump(raw);\n if (!pkts.length) return b.fail(\"no packets parsed; expected `tcpdump -nn -tt` text output (not a .pcap)\").build();\n // Local ports unknown for an import: treat the most common port as local.\n const freq = new Map<number, number>();\n for (const p of pkts) for (const port of [p.sport, p.dport]) if (port) freq.set(port, (freq.get(port) ?? 0) + 1);\n const local = new Set([...freq].sort((a, c) => c[1] - a[1]).slice(0, 2).map(([p]) => p));\n b.limitation(`local ports inferred as ${[...local].join(\", \")} (most frequent); per-remote grouping may be inverted for other flows`);\n summarizeCaptureEvidence(b, pkts, local, { filter: \"(imported)\", duration: args.duration_s ?? 0, textPath: art });\n return b.build();\n }\n }\n}\n\n/** Analyze pasted text fully in memory (no session directory, browser-safe). */\nexport async function analyzeText(tool: ImportTool, raw: string, opts: { duration_s?: number } = {}): Promise<ToolResult> {\n const b = new ResultBuilder(IMPORT_TOOL_MAP[tool], { id: \"paste\", dir: \":memory:\" }, { kind: \"command\", id: \"(pasted output)\", host: \"browser\" });\n if (!raw.trim()) return b.fail(\"pasted text is empty\").build();\n const art = await b.writeArtifact(`${tool}.txt`, raw, \"raw_text\", `pasted ${tool} output`);\n b.limitation(\"analyzed from pasted output: Debug Anything did not run the tool, so flags, timing and target scope are whatever you used\");\n return analyzeRaw(b, { tool, raw, duration_s: opts.duration_s, art });\n}\n\n/** Guess which tool produced this output. Returns undefined when unsure. */\nexport function detectTool(raw: string): ImportTool | undefined {\n const head = raw.slice(0, 20000);\n if (/^goroutine \\d+ \\[/m.test(head)) return \"goroutines\";\n if (/java\\.lang\\.Thread\\.State:/.test(head) || /^Full thread dump /m.test(head)) return \"jstack\";\n if (/^Process\\s+\\d+:|^Thread (0x[0-9a-f]+|\\d+) \\((idle|active)\\)/m.test(head)) return \"pyspy_dump\";\n if (/^\\* thread #\\d+/m.test(head)) return \"lldb\";\n if (/^Thread \\d+ \\(.*\\):\\s*$/m.test(head) && /^#\\d+\\s/m.test(head)) return \"gdb\";\n if (/^Call graph:/m.test(head) || /^Analysis of sampling/m.test(head)) return \"sample\";\n if (/^p\\d+\\s*$/m.test(head) && /^f\\d+/m.test(head)) return \"lsof\";\n if (/^\\d+\\.\\d+\\s+(\\S+\\s+(In|Out)\\s+)?IP6? /m.test(head) || /^\\d{2}:\\d{2}:\\d{2}\\.\\d+\\s+(\\S+\\s+(In|Out)\\s+)?IP6? /m.test(head)) return \"tcpdump\";\n if (/^[\\w.$:;<>()[\\]~/+-]+(;[^ ]+)+ \\d+$/m.test(head)) return \"folded\";\n if (/^\\s*[0-9a-f]+ .+ \\(.*\\)$/m.test(head) && /^\\S+\\s+\\d+(\\/\\d+)? (\\[\\d+\\] )?\\d+\\.\\d+:/m.test(head)) return \"perf_script\";\n if (/\\b\\w+\\(.*\\)\\s+=\\s+(-?\\d+|0x[0-9a-f]+|\\?)/.test(head) && /<\\d+\\.\\d+>|^\\d{2}:\\d{2}:\\d{2}/m.test(head)) return \"strace\";\n if (/\\b\\w+\\(.*\\)\\s+=\\s+(-?\\d+|0x[0-9a-f]+)/.test(head)) return \"strace\";\n if (/^\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?\\s+\\S+/m.test(head) && /\\S+\\.\\d+\\s*$/m.test(head)) return \"fs_usage\";\n return undefined;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ cachedReadiness,
4
+ runTool
5
+ } from "./chunk-VGYXHXTY.js";
6
+ import "./chunk-YY6M5RIJ.js";
7
+ import "./chunk-EMR42ZJQ.js";
8
+ import "./chunk-MLDOO673.js";
9
+ import "./chunk-NFL22T3H.js";
10
+ import "./chunk-5BXTDASF.js";
11
+ import "./chunk-5RAKTYW5.js";
12
+ import "./chunk-D742WJPT.js";
13
+ import "./chunk-32IDKAZK.js";
14
+ import "./chunk-STFC7C5C.js";
15
+
16
+ // src/investigate.ts
17
+ var PLANS = {
18
+ slow: [
19
+ { tool: "snapshot_memory", args: () => ({ window_s: 2, heap: false }) },
20
+ { tool: "profile_cpu", args: (o) => ({ duration_s: o.durationS ?? 10 }) },
21
+ { tool: "trace_syscalls", args: (o) => ({ duration_s: Math.min(o.durationS ?? 10, 10), categories: ["file", "network"] }) },
22
+ { tool: "inspect_sockets" }
23
+ ],
24
+ leak: [
25
+ { tool: "snapshot_memory", args: () => ({ window_s: 2 }) },
26
+ { tool: "__wait__", note: "exercise the target now (send traffic, run the job)" },
27
+ { tool: "snapshot_memory", args: () => ({ window_s: 2 }) },
28
+ { tool: "diff_runs", args: () => ({ a: "snapshot_memory", b: "snapshot_memory" }) }
29
+ ],
30
+ hang: [
31
+ { tool: "dump_stacks" },
32
+ { tool: "inspect_sockets" },
33
+ { tool: "trace_syscalls", args: () => ({ duration_s: 5, categories: ["all"] }) },
34
+ { tool: "dump_stacks", note: "second snapshot: identical positions confirm a hang" }
35
+ ],
36
+ crash: [{ tool: "container_info" }, { tool: "snapshot_memory", args: () => ({ window_s: 2 }) }],
37
+ triage: [
38
+ { tool: "inspect_sockets" },
39
+ { tool: "inspect_files", args: () => ({ window_s: 2 }) },
40
+ { tool: "snapshot_memory", args: () => ({ window_s: 2 }) },
41
+ { tool: "dump_stacks" },
42
+ { tool: "profile_cpu", args: (o) => ({ duration_s: o.durationS ?? 8 }) }
43
+ ]
44
+ };
45
+ async function investigate(target, opts) {
46
+ const note = opts.onNote ?? (() => {
47
+ });
48
+ const emit = opts.onResult ?? (() => {
49
+ });
50
+ const readiness = await cachedReadiness();
51
+ const attach = await runTool("attach", { target, kind: opts.kind });
52
+ emit(attach);
53
+ if (!attach.ok) return { session_id: "", results: [attach] };
54
+ const session_id = attach.session_id;
55
+ const results = [attach];
56
+ let firstMem;
57
+ for (const step of PLANS[opts.symptom]) {
58
+ if (step.tool === "__wait__") {
59
+ const w = opts.waitS ?? 15;
60
+ note(`waiting ${w}s \u2014 ${step.note}`);
61
+ await new Promise((r2) => setTimeout(r2, w * 1e3));
62
+ continue;
63
+ }
64
+ if (!readiness.tools_available.includes(step.tool)) {
65
+ const reason = readiness.tools_unavailable.find((u) => u.tool === step.tool)?.reason ?? "unavailable";
66
+ note(`skipping ${step.tool}: ${reason}`);
67
+ continue;
68
+ }
69
+ if (step.tool === "container_info" && attach.target.kind !== "container" && attach.target.kind !== "pod") {
70
+ note("skipping container_info: target is not a container");
71
+ continue;
72
+ }
73
+ if (step.note) note(step.note);
74
+ let args = step.args?.(opts) ?? {};
75
+ if (step.tool === "diff_runs") {
76
+ const mems = results.filter((r2) => r2.tool === "snapshot_memory" && r2.run_id).map((r2) => r2.run_id);
77
+ if (mems.length < 2) {
78
+ note("skipping diff_runs: need two snapshot_memory runs");
79
+ continue;
80
+ }
81
+ args = { a: mems[mems.length - 2], b: mems[mems.length - 1] };
82
+ }
83
+ const r = await runTool(step.tool, { session_id, ...args });
84
+ results.push(r);
85
+ emit(r);
86
+ if (step.tool === "snapshot_memory" && !firstMem) firstMem = r.run_id;
87
+ }
88
+ const report = await runTool("report", { session_id });
89
+ results.push(report);
90
+ const detach = await runTool("detach", { session_id });
91
+ results.push(detach);
92
+ return { session_id, results, report_path: report.artifacts[0]?.path };
93
+ }
94
+ function summarizeFindings(results) {
95
+ const order = { high: 0, warn: 1, info: 2 };
96
+ return results.flatMap((r) => r.findings.map((f) => ({ severity: f.severity, summary: f.summary, ref: `${r.run_id ?? r.tool}/${f.evidence_ids.join(",")}`, confidence: f.confidence }))).sort((a, b) => order[a.severity] - order[b.severity]);
97
+ }
98
+ export {
99
+ investigate,
100
+ summarizeFindings
101
+ };
102
+ //# sourceMappingURL=investigate-2GFD6EWB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/investigate.ts"],"sourcesContent":["/**\n * `debuganything why <target>` — a one-command investigation for people without an agent.\n * Runs the same tool sequence the MCP prompts prescribe, prints each result,\n * and ends with a ranked summary + report path. Skips tools readiness says are\n * unavailable instead of failing.\n */\nimport type { ToolResult } from \"./contracts.js\";\nimport { runTool, cachedReadiness } from \"./tools.js\";\n\nexport type Symptom = \"slow\" | \"leak\" | \"hang\" | \"crash\" | \"triage\";\n\nexport interface InvestigateOptions {\n symptom: Symptom;\n kind?: \"pid\" | \"container\" | \"pod\" | \"command\";\n /** Seconds to wait between the two memory snapshots (leak). */\n waitS?: number;\n /** Profile / trace durations. */\n durationS?: number;\n /** Allow capture_traffic (needs consent). */\n consent?: boolean;\n onResult?: (r: ToolResult) => void;\n onNote?: (s: string) => void;\n}\n\nconst PLANS: Record<Symptom, Array<{ tool: string; args?: (o: InvestigateOptions) => Record<string, unknown>; note?: string }>> = {\n slow: [\n { tool: \"snapshot_memory\", args: () => ({ window_s: 2, heap: false }) },\n { tool: \"profile_cpu\", args: (o) => ({ duration_s: o.durationS ?? 10 }) },\n { tool: \"trace_syscalls\", args: (o) => ({ duration_s: Math.min(o.durationS ?? 10, 10), categories: [\"file\", \"network\"] }) },\n { tool: \"inspect_sockets\" },\n ],\n leak: [\n { tool: \"snapshot_memory\", args: () => ({ window_s: 2 }) },\n { tool: \"__wait__\", note: \"exercise the target now (send traffic, run the job)\" },\n { tool: \"snapshot_memory\", args: () => ({ window_s: 2 }) },\n { tool: \"diff_runs\", args: () => ({ a: \"snapshot_memory\", b: \"snapshot_memory\" }) },\n ],\n hang: [\n { tool: \"dump_stacks\" },\n { tool: \"inspect_sockets\" },\n { tool: \"trace_syscalls\", args: () => ({ duration_s: 5, categories: [\"all\"] }) },\n { tool: \"dump_stacks\", note: \"second snapshot: identical positions confirm a hang\" },\n ],\n crash: [{ tool: \"container_info\" }, { tool: \"snapshot_memory\", args: () => ({ window_s: 2 }) }],\n triage: [\n { tool: \"inspect_sockets\" },\n { tool: \"inspect_files\", args: () => ({ window_s: 2 }) },\n { tool: \"snapshot_memory\", args: () => ({ window_s: 2 }) },\n { tool: \"dump_stacks\" },\n { tool: \"profile_cpu\", args: (o) => ({ duration_s: o.durationS ?? 8 }) },\n ],\n};\n\nexport interface InvestigateOutcome {\n session_id: string;\n results: ToolResult[];\n report_path?: string;\n}\n\nexport async function investigate(target: string, opts: InvestigateOptions): Promise<InvestigateOutcome> {\n const note = opts.onNote ?? (() => {});\n const emit = opts.onResult ?? (() => {});\n const readiness = await cachedReadiness();\n const attach = await runTool(\"attach\", { target, kind: opts.kind });\n emit(attach);\n if (!attach.ok) return { session_id: \"\", results: [attach] };\n const session_id = attach.session_id;\n const results: ToolResult[] = [attach];\n let firstMem: string | undefined;\n for (const step of PLANS[opts.symptom]) {\n if (step.tool === \"__wait__\") {\n const w = opts.waitS ?? 15;\n note(`waiting ${w}s — ${step.note}`);\n await new Promise((r) => setTimeout(r, w * 1000));\n continue;\n }\n if (!readiness.tools_available.includes(step.tool)) {\n const reason = readiness.tools_unavailable.find((u) => u.tool === step.tool)?.reason ?? \"unavailable\";\n note(`skipping ${step.tool}: ${reason}`);\n continue;\n }\n if (step.tool === \"container_info\" && attach.target.kind !== \"container\" && attach.target.kind !== \"pod\") {\n note(\"skipping container_info: target is not a container\");\n continue;\n }\n if (step.note) note(step.note);\n let args = step.args?.(opts) ?? {};\n if (step.tool === \"diff_runs\") {\n const mems = results.filter((r) => r.tool === \"snapshot_memory\" && r.run_id).map((r) => r.run_id!);\n if (mems.length < 2) {\n note(\"skipping diff_runs: need two snapshot_memory runs\");\n continue;\n }\n args = { a: mems[mems.length - 2], b: mems[mems.length - 1] };\n }\n const r = await runTool(step.tool, { session_id, ...args });\n results.push(r);\n emit(r);\n if (step.tool === \"snapshot_memory\" && !firstMem) firstMem = r.run_id;\n }\n const report = await runTool(\"report\", { session_id });\n results.push(report);\n const detach = await runTool(\"detach\", { session_id });\n results.push(detach);\n return { session_id, results, report_path: report.artifacts[0]?.path };\n}\n\n/** Rank all findings across results for the final summary. Pure. */\nexport function summarizeFindings(results: ToolResult[]): Array<{ severity: string; summary: string; ref: string; confidence: string }> {\n const order = { high: 0, warn: 1, info: 2 } as const;\n return results\n .flatMap((r) => r.findings.map((f) => ({ severity: f.severity, summary: f.summary, ref: `${r.run_id ?? r.tool}/${f.evidence_ids.join(\",\")}`, confidence: f.confidence })))\n .sort((a, b) => order[a.severity as keyof typeof order] - order[b.severity as keyof typeof order]);\n}\n"],"mappings":"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","names":["r"]}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ lsofAdapter,
4
+ parseLsofFields,
5
+ parseProcLimits,
6
+ summarizeFiles,
7
+ summarizeSockets,
8
+ whoHoldsPort
9
+ } from "./chunk-NFL22T3H.js";
10
+ import "./chunk-5BXTDASF.js";
11
+ import "./chunk-5RAKTYW5.js";
12
+ import "./chunk-D742WJPT.js";
13
+ import "./chunk-STFC7C5C.js";
14
+ export {
15
+ lsofAdapter,
16
+ parseLsofFields,
17
+ parseProcLimits,
18
+ summarizeFiles,
19
+ summarizeSockets,
20
+ whoHoldsPort
21
+ };
22
+ //# sourceMappingURL=lsof-GBLZJBJR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ parseProcStatus,
4
+ parsePsMem,
5
+ psmemAdapter,
6
+ sampleMemory,
7
+ snapshotMemoryGeneric
8
+ } from "./chunk-EMR42ZJQ.js";
9
+ import "./chunk-5BXTDASF.js";
10
+ import "./chunk-5RAKTYW5.js";
11
+ import "./chunk-D742WJPT.js";
12
+ import "./chunk-STFC7C5C.js";
13
+ export {
14
+ parseProcStatus,
15
+ parsePsMem,
16
+ psmemAdapter,
17
+ sampleMemory,
18
+ snapshotMemoryGeneric
19
+ };
20
+ //# sourceMappingURL=psmem-UB3VCMG3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ VERSION
4
+ } from "./chunk-32IDKAZK.js";
5
+ import {
6
+ redact
7
+ } from "./chunk-STFC7C5C.js";
8
+
9
+ // src/report_html.ts
10
+ import { readFile } from "fs/promises";
11
+ var esc = (s) => String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12
+ async function renderHtmlReport(session) {
13
+ const runs = [];
14
+ for (const r of session.runs) {
15
+ try {
16
+ runs.push(JSON.parse(await readFile(r.file, "utf8")));
17
+ } catch {
18
+ }
19
+ }
20
+ const flames = [];
21
+ for (const r of runs) {
22
+ for (const a of r.artifacts ?? []) {
23
+ if (a.kind === "flamegraph_svg" && flames.length < 3) {
24
+ try {
25
+ const svg = await readFile(a.path, "utf8");
26
+ if (svg.includes("<svg") && svg.length < 3e6) flames.push({ name: a.path.split("/").pop(), svg });
27
+ } catch {
28
+ }
29
+ }
30
+ }
31
+ }
32
+ return renderHtmlReportFromRuns(session, runs, flames);
33
+ }
34
+ function renderHtmlReportFromRuns(session, runs, flames = []) {
35
+ const t = session.target;
36
+ const all = runs.flatMap((r) => r.findings.map((f) => ({ run: r, f })));
37
+ const order = { high: 0, warn: 1, info: 2 };
38
+ all.sort((a, b) => order[a.f.severity] - order[b.f.severity]);
39
+ const evOf = (run, id) => run.evidence.find((e) => e.id === id);
40
+ const counts = { high: 0, warn: 0, info: 0 };
41
+ for (const { f } of all) counts[f.severity] = (counts[f.severity] ?? 0) + 1;
42
+ const findingCards = all.map(({ run, f }) => `
43
+ <div class="finding ${f.severity}">
44
+ <div><span class="sev">${f.severity}</span> ${esc(redact(f.summary))} <span class="dim">\xB7 ${esc(f.confidence)} \xB7 ${esc(run.run_id ?? run.tool)}</span></div>
45
+ ${f.detail ? `<div class="detail">${esc(redact(f.detail))}</div>` : ""}
46
+ <div class="ev">${f.evidence_ids.map((id) => {
47
+ const e = evOf(run, id);
48
+ if (!e) return "";
49
+ const payload = e.data !== void 0 ? JSON.stringify(e.data, null, 2) : "";
50
+ return `<details><summary><code>${esc(id)}</code> ${esc(redact(e.summary))}</summary>${payload ? `<pre>${esc(redact(payload).slice(0, 8e3))}</pre>` : ""}${e.artifact ? `<div class="dim">source: <code>${esc(e.artifact.split("/").pop())}</code>${e.lines ? ` L${e.lines[0]}\u2013${e.lines[1]}` : ""}</div>` : ""}</details>`;
51
+ }).join("")}</div>
52
+ </div>`).join("\n");
53
+ const runRows = runs.map((r) => `
54
+ <details class="run"><summary><b>${esc(r.run_id ?? r.tool)}</b> \u2014 ${r.ok ? "ok" : "FAILED"} \xB7 ${r.duration_ms} ms \xB7 ${r.evidence.length} evidence \xB7 ${r.findings.length} finding(s)</summary>
55
+ ${r.error ? `<div class="detail">error: ${esc(redact(r.error))}</div>` : ""}
56
+ <table><tr><th>id</th><th>kind</th><th>summary</th></tr>
57
+ ${r.evidence.map((e) => `<tr><td><code>${esc(e.id)}</code></td><td>${esc(e.kind)}</td><td>${esc(redact(e.summary))}</td></tr>`).join("")}
58
+ </table>
59
+ ${r.limitations?.length ? `<div class="dim">limitations: ${r.limitations.map((l) => esc(redact(l))).join(" \xB7 ")}</div>` : ""}
60
+ </details>`).join("\n");
61
+ const flameBlocks = flames.map((f) => `<details open class="run"><summary><b>flamegraph</b> \u2014 ${esc(f.name)}</summary><div class="flame">${f.svg.replace(/<script[\s\S]*?<\/script>/gi, "")}</div></details>`).join("\n");
62
+ return `<!doctype html>
63
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
64
+ <title>Debug Anything report \u2014 ${esc(t.kind)} ${esc(t.id)}</title>
65
+ <style>
66
+ :root{--bg:#0b0d12;--fg:#eef2f8;--muted:#9aa3b2;--dim:#5f6878;--acc:#7cc4ff;--warn:#ffb86b;--high:#ff7b7b;--card:#121521;--line:#1f2434;color-scheme:dark}
67
+ *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,sans-serif;padding:32px 20px}
68
+ .wrap{max-width:920px;margin:0 auto}code,pre{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
69
+ h1{font-size:24px;margin:0 0 4px}.dim{color:var(--dim);font-size:13px}.meta{color:var(--muted);font-size:14px;margin-bottom:22px}
70
+ .badges span{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:2px 10px;font-size:12.5px;margin-right:6px}
71
+ .finding{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--dim);border-radius:10px;padding:12px 14px;margin-top:10px}
72
+ .finding.high{border-left-color:var(--high)}.finding.warn{border-left-color:var(--warn)}.finding.info{border-left-color:var(--acc)}
73
+ .sev{font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
74
+ .finding.high .sev{color:var(--high)}.finding.warn .sev{color:var(--warn)}.finding.info .sev{color:var(--acc)}
75
+ .detail{color:var(--muted);font-size:13.5px;margin-top:6px;white-space:pre-wrap}
76
+ .ev{margin-top:8px;border-top:1px dashed var(--line);padding-top:6px;font-size:13.5px;color:var(--muted)}
77
+ details{margin:6px 0}summary{cursor:pointer}pre{background:#0f1320;border:1px solid var(--line);border-radius:8px;padding:10px;overflow-x:auto;font-size:12px;max-height:340px}
78
+ .run{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 14px;margin-top:10px;font-size:14px}
79
+ table{border-collapse:collapse;width:100%;margin-top:8px;font-size:13px}th,td{text-align:left;border-bottom:1px solid var(--line);padding:5px 8px;vertical-align:top}th{color:var(--dim);font-weight:600}
80
+ .flame{overflow-x:auto;background:#fff;border-radius:8px;margin-top:8px}.flame svg{display:block;max-width:100%;height:auto}
81
+ footer{margin-top:34px;color:var(--dim);font-size:12.5px;border-top:1px solid var(--line);padding-top:14px}
82
+ h2{font-size:17px;margin:26px 0 4px}
83
+ </style></head><body><div class="wrap">
84
+ <h1>Debug Anything report</h1>
85
+ <div class="meta">${[`${esc(t.kind)} <code>${esc(t.id)}</code>`, t.pid && String(t.pid) !== t.id ? `pid ${t.pid}` : "", t.comm ? esc(t.comm) : "", t.runtime && t.runtime !== t.comm ? esc(t.runtime) : "", `${esc(t.host)} (${esc(session.platform)})`, esc(session.created_at)].filter(Boolean).join(" \xB7 ")}</div>
86
+ <div class="badges"><span style="color:var(--high)">${counts.high ?? 0} high</span><span style="color:var(--warn)">${counts.warn ?? 0} warn</span><span style="color:var(--acc)">${counts.info ?? 0} info</span><span>${runs.length} runs</span></div>
87
+ <h2>Findings</h2>
88
+ ${findingCards || '<div class="dim">no findings recorded</div>'}
89
+ ${flameBlocks ? `<h2>Flamegraphs</h2>${flameBlocks}` : ""}
90
+ <h2>Runs</h2>
91
+ ${runRows}
92
+ <footer>Generated by <a href="https://debuganything.dev" style="color:var(--acc)">Debug Anything</a> v${esc(VERSION)} \xB7 session ${esc(session.id)} \xB7 every finding cites evidence ids; raw artifacts stay on the machine that ran Debug Anything. Provided "as is", no warranty \u2014 verify before acting.</footer>
93
+ </div></body></html>`;
94
+ }
95
+ export {
96
+ renderHtmlReport,
97
+ renderHtmlReportFromRuns
98
+ };
99
+ //# sourceMappingURL=report_html-2ENM7HLC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/report_html.ts"],"sourcesContent":["/**\n * Self-contained HTML session report: ranked findings with expandable\n * evidence, per-run detail, embedded flamegraphs. One file, no external\n * resources — made to be posted in a Slack thread or an issue.\n */\nimport { readFile } from \"node:fs/promises\";\nimport type { Session, ToolResult } from \"./contracts.js\";\nimport { redact } from \"./safety.js\";\nimport { VERSION } from \"./version.js\";\n\nconst esc = (s: unknown) => String(s).replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n\nexport async function renderHtmlReport(session: Session): Promise<string> {\n const runs: ToolResult[] = [];\n for (const r of session.runs) {\n try {\n runs.push(JSON.parse(await readFile(r.file, \"utf8\")) as ToolResult);\n } catch { /* skip */ }\n }\n const flames: Array<{ name: string; svg: string }> = [];\n for (const r of runs) {\n for (const a of r.artifacts ?? []) {\n if (a.kind === \"flamegraph_svg\" && flames.length < 3) {\n try {\n const svg = await readFile(a.path, \"utf8\");\n if (svg.includes(\"<svg\") && svg.length < 3_000_000) flames.push({ name: a.path.split(\"/\").pop()!, svg });\n } catch { /* skip */ }\n }\n }\n }\n return renderHtmlReportFromRuns(session, runs, flames);\n}\n\n/** Pure renderer, testable. */\nexport function renderHtmlReportFromRuns(session: Session, runs: ToolResult[], flames: Array<{ name: string; svg: string }> = []): string {\n const t = session.target;\n const all = runs.flatMap((r) => r.findings.map((f) => ({ run: r, f })));\n const order = { high: 0, warn: 1, info: 2 } as const;\n all.sort((a, b) => order[a.f.severity] - order[b.f.severity]);\n const evOf = (run: ToolResult, id: string) => run.evidence.find((e) => e.id === id);\n const counts = { high: 0, warn: 0, info: 0 } as Record<string, number>;\n for (const { f } of all) counts[f.severity] = (counts[f.severity] ?? 0) + 1;\n\n const findingCards = all.map(({ run, f }) => `\n <div class=\"finding ${f.severity}\">\n <div><span class=\"sev\">${f.severity}</span> ${esc(redact(f.summary))} <span class=\"dim\">· ${esc(f.confidence)} · ${esc(run.run_id ?? run.tool)}</span></div>\n ${f.detail ? `<div class=\"detail\">${esc(redact(f.detail))}</div>` : \"\"}\n <div class=\"ev\">${f.evidence_ids.map((id) => {\n const e = evOf(run, id);\n if (!e) return \"\";\n const payload = e.data !== undefined ? JSON.stringify(e.data, null, 2) : \"\";\n return `<details><summary><code>${esc(id)}</code> ${esc(redact(e.summary))}</summary>${payload ? `<pre>${esc(redact(payload).slice(0, 8000))}</pre>` : \"\"}${e.artifact ? `<div class=\"dim\">source: <code>${esc(e.artifact.split(\"/\").pop())}</code>${e.lines ? ` L${e.lines[0]}–${e.lines[1]}` : \"\"}</div>` : \"\"}</details>`;\n }).join(\"\")}</div>\n </div>`).join(\"\\n\");\n\n const runRows = runs.map((r) => `\n <details class=\"run\"><summary><b>${esc(r.run_id ?? r.tool)}</b> — ${r.ok ? \"ok\" : \"FAILED\"} · ${r.duration_ms} ms · ${r.evidence.length} evidence · ${r.findings.length} finding(s)</summary>\n ${r.error ? `<div class=\"detail\">error: ${esc(redact(r.error))}</div>` : \"\"}\n <table><tr><th>id</th><th>kind</th><th>summary</th></tr>\n ${r.evidence.map((e) => `<tr><td><code>${esc(e.id)}</code></td><td>${esc(e.kind)}</td><td>${esc(redact(e.summary))}</td></tr>`).join(\"\")}\n </table>\n ${r.limitations?.length ? `<div class=\"dim\">limitations: ${r.limitations.map((l) => esc(redact(l))).join(\" · \")}</div>` : \"\"}\n </details>`).join(\"\\n\");\n\n const flameBlocks = flames.map((f) => `<details open class=\"run\"><summary><b>flamegraph</b> — ${esc(f.name)}</summary><div class=\"flame\">${f.svg.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")}</div></details>`).join(\"\\n\");\n\n return `<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Debug Anything report — ${esc(t.kind)} ${esc(t.id)}</title>\n<style>\n:root{--bg:#0b0d12;--fg:#eef2f8;--muted:#9aa3b2;--dim:#5f6878;--acc:#7cc4ff;--warn:#ffb86b;--high:#ff7b7b;--card:#121521;--line:#1f2434;color-scheme:dark}\n*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.6 -apple-system,BlinkMacSystemFont,\"Segoe UI\",Inter,Roboto,sans-serif;padding:32px 20px}\n.wrap{max-width:920px;margin:0 auto}code,pre{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}\nh1{font-size:24px;margin:0 0 4px}.dim{color:var(--dim);font-size:13px}.meta{color:var(--muted);font-size:14px;margin-bottom:22px}\n.badges span{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:2px 10px;font-size:12.5px;margin-right:6px}\n.finding{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--dim);border-radius:10px;padding:12px 14px;margin-top:10px}\n.finding.high{border-left-color:var(--high)}.finding.warn{border-left-color:var(--warn)}.finding.info{border-left-color:var(--acc)}\n.sev{font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase}\n.finding.high .sev{color:var(--high)}.finding.warn .sev{color:var(--warn)}.finding.info .sev{color:var(--acc)}\n.detail{color:var(--muted);font-size:13.5px;margin-top:6px;white-space:pre-wrap}\n.ev{margin-top:8px;border-top:1px dashed var(--line);padding-top:6px;font-size:13.5px;color:var(--muted)}\ndetails{margin:6px 0}summary{cursor:pointer}pre{background:#0f1320;border:1px solid var(--line);border-radius:8px;padding:10px;overflow-x:auto;font-size:12px;max-height:340px}\n.run{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 14px;margin-top:10px;font-size:14px}\ntable{border-collapse:collapse;width:100%;margin-top:8px;font-size:13px}th,td{text-align:left;border-bottom:1px solid var(--line);padding:5px 8px;vertical-align:top}th{color:var(--dim);font-weight:600}\n.flame{overflow-x:auto;background:#fff;border-radius:8px;margin-top:8px}.flame svg{display:block;max-width:100%;height:auto}\nfooter{margin-top:34px;color:var(--dim);font-size:12.5px;border-top:1px solid var(--line);padding-top:14px}\nh2{font-size:17px;margin:26px 0 4px}\n</style></head><body><div class=\"wrap\">\n<h1>Debug Anything report</h1>\n<div class=\"meta\">${[`${esc(t.kind)} <code>${esc(t.id)}</code>`, t.pid && String(t.pid) !== t.id ? `pid ${t.pid}` : \"\", t.comm ? esc(t.comm) : \"\", t.runtime && t.runtime !== t.comm ? esc(t.runtime) : \"\", `${esc(t.host)} (${esc(session.platform)})`, esc(session.created_at)].filter(Boolean).join(\" · \")}</div>\n<div class=\"badges\"><span style=\"color:var(--high)\">${counts.high ?? 0} high</span><span style=\"color:var(--warn)\">${counts.warn ?? 0} warn</span><span style=\"color:var(--acc)\">${counts.info ?? 0} info</span><span>${runs.length} runs</span></div>\n<h2>Findings</h2>\n${findingCards || '<div class=\"dim\">no findings recorded</div>'}\n${flameBlocks ? `<h2>Flamegraphs</h2>${flameBlocks}` : \"\"}\n<h2>Runs</h2>\n${runRows}\n<footer>Generated by <a href=\"https://debuganything.dev\" style=\"color:var(--acc)\">Debug Anything</a> v${esc(VERSION)} · session ${esc(session.id)} · every finding cites evidence ids; raw artifacts stay on the machine that ran Debug Anything. Provided \"as is\", no warranty — verify before acting.</footer>\n</div></body></html>`;\n}\n"],"mappings":"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","names":[]}
package/dist/server.js ADDED
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ TOOL_DESCRIPTIONS,
4
+ runTool
5
+ } from "./chunk-VGYXHXTY.js";
6
+ import "./chunk-YY6M5RIJ.js";
7
+ import "./chunk-EMR42ZJQ.js";
8
+ import "./chunk-MLDOO673.js";
9
+ import "./chunk-NFL22T3H.js";
10
+ import "./chunk-5BXTDASF.js";
11
+ import "./chunk-5RAKTYW5.js";
12
+ import {
13
+ ToolArgs
14
+ } from "./chunk-D742WJPT.js";
15
+ import {
16
+ VERSION
17
+ } from "./chunk-32IDKAZK.js";
18
+ import {
19
+ killTrackedChildren
20
+ } from "./chunk-STFC7C5C.js";
21
+
22
+ // src/server.ts
23
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
24
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
25
+ import { z } from "zod";
26
+
27
+ // src/prompts/index.ts
28
+ var RULES = `Rules for this investigation:
29
+ 1. Call \`readiness\` first if you have not in this session. Respect tools_unavailable.
30
+ 2. Call \`attach\` before any other tool and \`detach\` when done. Use the returned session_id everywhere.
31
+ 3. Never state a root cause without citing an evidence id (e.g. "profile_cpu#1/e3") from a tool result. Unsupported ideas are hypotheses: say so and name the tool that would test them.
32
+ 4. Before passing \`consent: true\` (capture_traffic), ask the user explicitly.
33
+ 5. Prefer the tool's \`suggested_next\`. Stop when the evidence answers the question; do not run everything.
34
+ 6. End with \`report\` and summarize: findings (with evidence ids), limitations, and the next step \u2014 including a step-debugger handoff when a function/thread is localized.`;
35
+ var prompts = [
36
+ {
37
+ name: "dea_slow",
38
+ description: '"X is slow": profile CPU, trace syscalls (network/file), inspect sockets, report.',
39
+ args: [
40
+ { name: "target", description: "pid, container name, pod, or command", required: true },
41
+ { name: "symptom", description: "what the user observes (e.g. p99 latency 3s after 10 minutes)", required: false }
42
+ ],
43
+ render: (a) => `The user reports that ${a.target} is slow${a.symptom ? `: ${a.symptom}` : ""}. Find out why, with evidence.
44
+
45
+ Order:
46
+ 1. readiness
47
+ 2. attach { target: "${a.target}" }
48
+ 3. profile_cpu { session_id, duration_s: 15 } \u2014 look at top frames by self time and the hottest stack. CPU-bound if a few frames dominate; otherwise the time is spent waiting.
49
+ 4. trace_syscalls { session_id, duration_s: 10, categories: ["network","file"] } (Linux) \u2014 look at total time per syscall, the slowest individual calls, and blocked waits (futex/poll/epoll/nanosleep). Many slow read()/write() on sockets \u2192 downstream latency. Many open()/stat() \u2192 filesystem churn.
50
+ 5. inspect_sockets { session_id } \u2014 many connections to one remote, CLOSE_WAIT pileups, or fd count near ulimit.
51
+ 6. If a function is localized: suggest attaching a step debugger (e.g. mcp-debugger) at that file:function. If a remote host is localized: suggest capture_traffic with consent.
52
+ 7. report { session_id }, then detach.
53
+
54
+ ${RULES}`
55
+ },
56
+ {
57
+ name: "dea_leak",
58
+ description: '"memory keeps growing": snapshot memory twice around some load, diff, report.',
59
+ args: [
60
+ { name: "target", description: "pid, container name, pod, or command", required: true },
61
+ { name: "exercise", description: "how to generate load between snapshots (a command or instruction)", required: false }
62
+ ],
63
+ render: (a) => `The user reports that ${a.target} keeps growing in memory. Find what grows, with evidence.
64
+
65
+ Order:
66
+ 1. readiness
67
+ 2. attach { target: "${a.target}" }
68
+ 3. snapshot_memory { session_id } \u2014 baseline RSS and (Node) heap retainers.
69
+ 4. Exercise the target${a.exercise ? `: ${a.exercise}` : " (ask the user how, or send representative traffic yourself)"}. Wait at least 10 seconds.
70
+ 5. snapshot_memory { session_id } again.
71
+ 6. diff_runs { session_id, a: "snapshot_memory#1", b: "snapshot_memory#2" } \u2014 what grew in retained size, what appeared. The top grower is the suspect; name the constructor/closure and the retaining path if present.
72
+ 7. Optionally repeat 4\u20136 once to confirm the trend is monotonic, not a one-off.
73
+ 8. report { session_id }, then detach.
74
+
75
+ Note: RSS growth without heap growth points at native memory, buffers or fragmentation \u2014 say so instead of blaming JS/Python objects. Python targets get RSS series plus py-spy dump with locals, not heap retainers; state that limitation.
76
+
77
+ ${RULES}`
78
+ },
79
+ {
80
+ name: "dea_hang",
81
+ description: `"it's stuck": dump stacks, inspect sockets, short syscall trace, report.`,
82
+ args: [{ name: "target", description: "pid, container name, pod, or command", required: true }],
83
+ render: (a) => `The user reports that ${a.target} is hung or stuck. Find what it is waiting on, with evidence.
84
+
85
+ Order:
86
+ 1. readiness
87
+ 2. attach { target: "${a.target}" }
88
+ 3. dump_stacks { session_id } \u2014 look at every thread's top frames. Deadlock = two or more threads waiting on locks held by each other (the tool flags lock_wait evidence). Single thread blocked in a socket read = waiting on a remote. All threads idle = the process is not stuck, the caller is.
89
+ 4. inspect_sockets { session_id } \u2014 is there an ESTABLISHED connection to a remote with nothing happening? Which remote?
90
+ 5. trace_syscalls { session_id, duration_s: 5 } (Linux) \u2014 zero syscalls = spinning or deadlocked in user space; one blocked read/recvfrom/futex = waiting.
91
+ 6. If a thread/function is localized: suggest attaching a step debugger (e.g. mcp-debugger) there.
92
+ 7. report { session_id }, then detach.
93
+
94
+ ${RULES}`
95
+ },
96
+ {
97
+ name: "dea_crash",
98
+ description: '"it died": container state, OOM/exit codes, logs tail, core/dmesg hints, report.',
99
+ args: [{ name: "target", description: "container name or pid of the restarted process", required: true }],
100
+ render: (a) => `The user reports that ${a.target} crashed or died. Establish how it died, with evidence.
101
+
102
+ Order:
103
+ 1. readiness
104
+ 2. attach { target: "${a.target}" } (for a container that is down, attach still works for container_info)
105
+ 3. container_info { session_id } \u2014 OOMKilled, exit code (137 = SIGKILL/OOM, 139 = SIGSEGV, 143 = SIGTERM), restart count, cgroup memory limit vs usage, error lines in the log tail.
106
+ 4. If not a container: ask the user for the exit code / signal and check dmesg or journalctl for "Out of memory: Killed process <pid>" and segfault lines (Debug Anything does not read dmesg itself yet; say so).
107
+ 5. If a core file or crash log exists, suggest a step debugger / lldb on the core (handoff).
108
+ 6. If it restarted and is running now: snapshot_memory and profile_cpu to catch the lead-up.
109
+ 7. report { session_id }, then detach.
110
+
111
+ ${RULES}`
112
+ },
113
+ {
114
+ name: "dea_port_busy",
115
+ description: '"address already in use": find the process holding a port.',
116
+ args: [{ name: "port", description: "the TCP/UDP port that is busy", required: true }],
117
+ render: (a) => `The user cannot bind port ${a.port} (EADDRINUSE). Identify what holds it, with evidence.
118
+
119
+ Order:
120
+ 1. readiness
121
+ 2. list_processes { filter: "" } is not enough on its own \u2014 ports are per socket. Use the dedicated path: run \`debuganything port ${a.port}\` via the CLI if available, or:
122
+ 3. attach to the most likely owner (list_processes, then attach by pid) and call inspect_sockets { session_id } \u2014 the listening sockets evidence names the port and pid.
123
+ 4. If unsure which process, iterate: attach to candidates from list_processes and inspect_sockets each; a listening socket on :${a.port} is the answer.
124
+ 5. Report the pid, command line, user and whether it is a stale instance of the user's own app. Do NOT kill it; tell the user the exact pid so they can decide.
125
+ 6. detach.
126
+
127
+ ${RULES}`
128
+ }
129
+ ];
130
+
131
+ // src/server.ts
132
+ function createServer() {
133
+ const server = new McpServer(
134
+ { name: "debuganything", version: VERSION },
135
+ {
136
+ instructions: "DEA (Debug Anything) observes running processes, containers and pods with battle-tested local tools and returns structured evidence. Call readiness first, attach before anything else, detach at the end. Every finding cites evidence ids \u2014 never claim a root cause without one. capture_traffic requires consent: true; ask the user first. Read-only: Debug Anything never kills, signals or modifies the target. USE Debug Anything PROACTIVELY: when a command you ran hangs, a test times out, output shows EADDRINUSE / ECONNREFUSED / EMFILE / exit 137 / OOM / segfault, a server you started does not respond, or the user mentions slow, hang, leak, crash or a busy port \u2014 attach and measure (dump_stacks, inspect_sockets, profile_cpu, snapshot_memory, container_info) before proposing a theory, without waiting to be asked. After you change performance-sensitive code, re-measure and diff_runs to prove it."
137
+ }
138
+ );
139
+ for (const [name, schema] of Object.entries(ToolArgs)) {
140
+ server.registerTool(
141
+ name,
142
+ {
143
+ title: name,
144
+ description: TOOL_DESCRIPTIONS[name],
145
+ inputSchema: schema.shape,
146
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: name !== "attach", openWorldHint: false }
147
+ },
148
+ async (args) => {
149
+ const result = await runTool(name, args ?? {});
150
+ return {
151
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
152
+ structuredContent: result,
153
+ isError: !result.ok
154
+ };
155
+ }
156
+ );
157
+ }
158
+ for (const p of prompts) {
159
+ const argsSchema = {};
160
+ for (const a of p.args) argsSchema[a.name] = (a.required ? z.string() : z.string().optional()).describe(a.description);
161
+ server.registerPrompt(p.name, { title: p.name, description: p.description, argsSchema }, (args) => ({
162
+ messages: [{ role: "user", content: { type: "text", text: p.render(args) } }]
163
+ }));
164
+ }
165
+ return server;
166
+ }
167
+ async function serve() {
168
+ const server = createServer();
169
+ const transport = new StdioServerTransport();
170
+ const shutdown = () => {
171
+ killTrackedChildren();
172
+ process.exit(0);
173
+ };
174
+ process.on("SIGINT", shutdown);
175
+ process.on("SIGTERM", shutdown);
176
+ process.stdin.on("close", shutdown);
177
+ await server.connect(transport);
178
+ }
179
+ var invokedDirectly = process.argv[1] && /server\.(js|ts)$/.test(process.argv[1]);
180
+ if (invokedDirectly) {
181
+ serve().catch((err) => {
182
+ console.error(err);
183
+ process.exit(1);
184
+ });
185
+ }
186
+ export {
187
+ createServer,
188
+ serve
189
+ };
190
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../src/prompts/index.ts"],"sourcesContent":["/**\n * MCP server over stdio. Tools are registered 1:1 with the CLI.\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { ToolArgs } from \"./contracts.js\";\nimport { runTool, TOOL_DESCRIPTIONS } from \"./tools.js\";\nimport { prompts } from \"./prompts/index.js\";\nimport { killTrackedChildren } from \"./safety.js\";\nimport { VERSION } from \"./version.js\";\n\nexport function createServer(): McpServer {\n const server = new McpServer(\n { name: \"debuganything\", version: VERSION },\n {\n instructions:\n \"DEA (Debug Anything) observes running processes, containers and pods with battle-tested local tools and returns structured evidence. Call readiness first, attach before anything else, detach at the end. Every finding cites evidence ids — never claim a root cause without one. capture_traffic requires consent: true; ask the user first. Read-only: Debug Anything never kills, signals or modifies the target. USE Debug Anything PROACTIVELY: when a command you ran hangs, a test times out, output shows EADDRINUSE / ECONNREFUSED / EMFILE / exit 137 / OOM / segfault, a server you started does not respond, or the user mentions slow, hang, leak, crash or a busy port — attach and measure (dump_stacks, inspect_sockets, profile_cpu, snapshot_memory, container_info) before proposing a theory, without waiting to be asked. After you change performance-sensitive code, re-measure and diff_runs to prove it.\",\n },\n );\n\n for (const [name, schema] of Object.entries(ToolArgs)) {\n server.registerTool(\n name,\n {\n title: name,\n description: TOOL_DESCRIPTIONS[name as keyof typeof ToolArgs],\n inputSchema: schema.shape,\n annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: name !== \"attach\", openWorldHint: false },\n },\n async (args: Record<string, unknown>) => {\n const result = await runTool(name, args ?? {});\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: result as unknown as Record<string, unknown>,\n isError: !result.ok,\n };\n },\n );\n }\n\n for (const p of prompts) {\n const argsSchema: Record<string, z.ZodTypeAny> = {};\n for (const a of p.args) argsSchema[a.name] = (a.required ? z.string() : z.string().optional()).describe(a.description);\n server.registerPrompt(p.name, { title: p.name, description: p.description, argsSchema }, (args) => ({\n messages: [{ role: \"user\" as const, content: { type: \"text\" as const, text: p.render(args as Record<string, string | undefined>) } }],\n }));\n }\n\n return server;\n}\n\nexport async function serve(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n const shutdown = () => {\n killTrackedChildren();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n process.stdin.on(\"close\", shutdown);\n await server.connect(transport);\n}\n\n// Allow `node dist/server.js` directly.\nconst invokedDirectly = process.argv[1] && /server\\.(js|ts)$/.test(process.argv[1]);\nif (invokedDirectly) {\n serve().catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n","/**\n * MCP prompts: guided investigations. Each is a text template telling the\n * agent the order, what to look for, and to never state a cause without an\n * evidence id.\n */\nexport interface DeaPrompt {\n name: string;\n description: string;\n args: Array<{ name: string; description: string; required: boolean }>;\n render(args: Record<string, string | undefined>): string;\n}\n\nconst RULES = `Rules for this investigation:\n1. Call \\`readiness\\` first if you have not in this session. Respect tools_unavailable.\n2. Call \\`attach\\` before any other tool and \\`detach\\` when done. Use the returned session_id everywhere.\n3. Never state a root cause without citing an evidence id (e.g. \"profile_cpu#1/e3\") from a tool result. Unsupported ideas are hypotheses: say so and name the tool that would test them.\n4. Before passing \\`consent: true\\` (capture_traffic), ask the user explicitly.\n5. Prefer the tool's \\`suggested_next\\`. Stop when the evidence answers the question; do not run everything.\n6. End with \\`report\\` and summarize: findings (with evidence ids), limitations, and the next step — including a step-debugger handoff when a function/thread is localized.`;\n\nexport const prompts: DeaPrompt[] = [\n {\n name: \"dea_slow\",\n description: \"\\\"X is slow\\\": profile CPU, trace syscalls (network/file), inspect sockets, report.\",\n args: [\n { name: \"target\", description: \"pid, container name, pod, or command\", required: true },\n { name: \"symptom\", description: \"what the user observes (e.g. p99 latency 3s after 10 minutes)\", required: false },\n ],\n render: (a) => `The user reports that ${a.target} is slow${a.symptom ? `: ${a.symptom}` : \"\"}. Find out why, with evidence.\n\nOrder:\n1. readiness\n2. attach { target: \"${a.target}\" }\n3. profile_cpu { session_id, duration_s: 15 } — look at top frames by self time and the hottest stack. CPU-bound if a few frames dominate; otherwise the time is spent waiting.\n4. trace_syscalls { session_id, duration_s: 10, categories: [\"network\",\"file\"] } (Linux) — look at total time per syscall, the slowest individual calls, and blocked waits (futex/poll/epoll/nanosleep). Many slow read()/write() on sockets → downstream latency. Many open()/stat() → filesystem churn.\n5. inspect_sockets { session_id } — many connections to one remote, CLOSE_WAIT pileups, or fd count near ulimit.\n6. If a function is localized: suggest attaching a step debugger (e.g. mcp-debugger) at that file:function. If a remote host is localized: suggest capture_traffic with consent.\n7. report { session_id }, then detach.\n\n${RULES}`,\n },\n {\n name: \"dea_leak\",\n description: \"\\\"memory keeps growing\\\": snapshot memory twice around some load, diff, report.\",\n args: [\n { name: \"target\", description: \"pid, container name, pod, or command\", required: true },\n { name: \"exercise\", description: \"how to generate load between snapshots (a command or instruction)\", required: false },\n ],\n render: (a) => `The user reports that ${a.target} keeps growing in memory. Find what grows, with evidence.\n\nOrder:\n1. readiness\n2. attach { target: \"${a.target}\" }\n3. snapshot_memory { session_id } — baseline RSS and (Node) heap retainers.\n4. Exercise the target${a.exercise ? `: ${a.exercise}` : \" (ask the user how, or send representative traffic yourself)\"}. Wait at least 10 seconds.\n5. snapshot_memory { session_id } again.\n6. diff_runs { session_id, a: \"snapshot_memory#1\", b: \"snapshot_memory#2\" } — what grew in retained size, what appeared. The top grower is the suspect; name the constructor/closure and the retaining path if present.\n7. Optionally repeat 4–6 once to confirm the trend is monotonic, not a one-off.\n8. report { session_id }, then detach.\n\nNote: RSS growth without heap growth points at native memory, buffers or fragmentation — say so instead of blaming JS/Python objects. Python targets get RSS series plus py-spy dump with locals, not heap retainers; state that limitation.\n\n${RULES}`,\n },\n {\n name: \"dea_hang\",\n description: \"\\\"it's stuck\\\": dump stacks, inspect sockets, short syscall trace, report.\",\n args: [{ name: \"target\", description: \"pid, container name, pod, or command\", required: true }],\n render: (a) => `The user reports that ${a.target} is hung or stuck. Find what it is waiting on, with evidence.\n\nOrder:\n1. readiness\n2. attach { target: \"${a.target}\" }\n3. dump_stacks { session_id } — look at every thread's top frames. Deadlock = two or more threads waiting on locks held by each other (the tool flags lock_wait evidence). Single thread blocked in a socket read = waiting on a remote. All threads idle = the process is not stuck, the caller is.\n4. inspect_sockets { session_id } — is there an ESTABLISHED connection to a remote with nothing happening? Which remote?\n5. trace_syscalls { session_id, duration_s: 5 } (Linux) — zero syscalls = spinning or deadlocked in user space; one blocked read/recvfrom/futex = waiting.\n6. If a thread/function is localized: suggest attaching a step debugger (e.g. mcp-debugger) there.\n7. report { session_id }, then detach.\n\n${RULES}`,\n },\n {\n name: \"dea_crash\",\n description: \"\\\"it died\\\": container state, OOM/exit codes, logs tail, core/dmesg hints, report.\",\n args: [{ name: \"target\", description: \"container name or pid of the restarted process\", required: true }],\n render: (a) => `The user reports that ${a.target} crashed or died. Establish how it died, with evidence.\n\nOrder:\n1. readiness\n2. attach { target: \"${a.target}\" } (for a container that is down, attach still works for container_info)\n3. container_info { session_id } — OOMKilled, exit code (137 = SIGKILL/OOM, 139 = SIGSEGV, 143 = SIGTERM), restart count, cgroup memory limit vs usage, error lines in the log tail.\n4. If not a container: ask the user for the exit code / signal and check dmesg or journalctl for \"Out of memory: Killed process <pid>\" and segfault lines (Debug Anything does not read dmesg itself yet; say so).\n5. If a core file or crash log exists, suggest a step debugger / lldb on the core (handoff).\n6. If it restarted and is running now: snapshot_memory and profile_cpu to catch the lead-up.\n7. report { session_id }, then detach.\n\n${RULES}`,\n },\n {\n name: \"dea_port_busy\",\n description: \"\\\"address already in use\\\": find the process holding a port.\",\n args: [{ name: \"port\", description: \"the TCP/UDP port that is busy\", required: true }],\n render: (a) => `The user cannot bind port ${a.port} (EADDRINUSE). Identify what holds it, with evidence.\n\nOrder:\n1. readiness\n2. list_processes { filter: \"\" } is not enough on its own — ports are per socket. Use the dedicated path: run \\`debuganything port ${a.port}\\` via the CLI if available, or:\n3. attach to the most likely owner (list_processes, then attach by pid) and call inspect_sockets { session_id } — the listening sockets evidence names the port and pid.\n4. If unsure which process, iterate: attach to candidates from list_processes and inspect_sockets each; a listening socket on :${a.port} is the answer.\n5. Report the pid, command line, user and whether it is a stale instance of the user's own app. Do NOT kill it; tell the user the exact pid so they can decide.\n6. detach.\n\n${RULES}`,\n },\n];\n\nexport function getPrompt(name: string): DeaPrompt | undefined {\n return prompts.find((p) => p.name === name);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAGA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,SAAS,SAAS;;;ACOlB,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQP,IAAM,UAAuB;AAAA,EAClC;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,EAAE,MAAM,UAAU,aAAa,wCAAwC,UAAU,KAAK;AAAA,MACtF,EAAE,MAAM,WAAW,aAAa,iEAAiE,UAAU,MAAM;AAAA,IACnH;AAAA,IACA,QAAQ,CAAC,MAAM,yBAAyB,EAAE,MAAM,WAAW,EAAE,UAAU,KAAK,EAAE,OAAO,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA,uBAIzE,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,KAAK;AAAA,EACL;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,EAAE,MAAM,UAAU,aAAa,wCAAwC,UAAU,KAAK;AAAA,MACtF,EAAE,MAAM,YAAY,aAAa,qEAAqE,UAAU,MAAM;AAAA,IACxH;AAAA,IACA,QAAQ,CAAC,MAAM,yBAAyB,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA,uBAI7B,EAAE,MAAM;AAAA;AAAA,wBAEP,EAAE,WAAW,KAAK,EAAE,QAAQ,KAAK,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrH,KAAK;AAAA,EACL;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM,CAAC,EAAE,MAAM,UAAU,aAAa,wCAAwC,UAAU,KAAK,CAAC;AAAA,IAC9F,QAAQ,CAAC,MAAM,yBAAyB,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA,uBAI7B,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,KAAK;AAAA,EACL;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM,CAAC,EAAE,MAAM,UAAU,aAAa,kDAAkD,UAAU,KAAK,CAAC;AAAA,IACxG,QAAQ,CAAC,MAAM,yBAAyB,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA,uBAI7B,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,KAAK;AAAA,EACL;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM,CAAC,EAAE,MAAM,QAAQ,aAAa,iCAAiC,UAAU,KAAK,CAAC;AAAA,IACrF,QAAQ,CAAC,MAAM,6BAA6B,EAAE,IAAI;AAAA;AAAA;AAAA;AAAA,0IAI+E,EAAE,IAAI;AAAA;AAAA,iIAEV,EAAE,IAAI;AAAA;AAAA;AAAA;AAAA,EAIrI,KAAK;AAAA,EACL;AACF;;;ADtGO,SAAS,eAA0B;AACxC,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,iBAAiB,SAAS,QAAQ;AAAA,IAC1C;AAAA,MACE,cACE;AAAA,IACJ;AAAA,EACF;AAEA,aAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACrD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,aAAa,kBAAkB,IAA6B;AAAA,QAC5D,aAAa,OAAO;AAAA,QACpB,aAAa,EAAE,cAAc,MAAM,iBAAiB,OAAO,gBAAgB,SAAS,UAAU,eAAe,MAAM;AAAA,MACrH;AAAA,MACA,OAAO,SAAkC;AACvC,cAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC7C,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,UAC1E,mBAAmB;AAAA,UACnB,SAAS,CAAC,OAAO;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,aAAW,KAAK,SAAS;AACvB,UAAM,aAA2C,CAAC;AAClD,eAAW,KAAK,EAAE,KAAM,YAAW,EAAE,IAAI,KAAK,EAAE,WAAW,EAAE,OAAO,IAAI,EAAE,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,WAAW;AACrH,WAAO,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,aAAa,EAAE,aAAa,WAAW,GAAG,CAAC,UAAU;AAAA,MAClG,UAAU,CAAC,EAAE,MAAM,QAAiB,SAAS,EAAE,MAAM,QAAiB,MAAM,EAAE,OAAO,IAA0C,EAAE,EAAE,CAAC;AAAA,IACtI,EAAE;AAAA,EACJ;AAEA,SAAO;AACT;AAEA,eAAsB,QAAuB;AAC3C,QAAM,SAAS,aAAa;AAC5B,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,WAAW,MAAM;AACrB,wBAAoB;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAC9B,UAAQ,MAAM,GAAG,SAAS,QAAQ;AAClC,QAAM,OAAO,QAAQ,SAAS;AAChC;AAGA,IAAM,kBAAkB,QAAQ,KAAK,CAAC,KAAK,mBAAmB,KAAK,QAAQ,KAAK,CAAC,CAAC;AAClF,IAAI,iBAAiB;AACnB,QAAM,EAAE,MAAM,CAAC,QAAQ;AACrB,YAAQ,MAAM,GAAG;AACjB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}