@datasynx/agentic-ai-cartography 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1801,7 +1801,7 @@ if (process.env.CARTOGRAPHYY_DAEMON === "1") {
1801
1801
  function main() {
1802
1802
  const program = new Command();
1803
1803
  const CMD = "datasynx-cartography";
1804
- const VERSION = "0.2.1";
1804
+ const VERSION = "0.2.3";
1805
1805
  program.name(CMD).description("AI-powered Infrastructure Cartography & SOP Generation").version(VERSION);
1806
1806
  program.command("discover").description("Infrastruktur scannen und kartographieren").option("--entry <hosts...>", "Startpunkte", ["localhost"]).option("--depth <n>", "Max Tiefe", "8").option("--max-turns <n>", "Max Agent-Turns", "50").option("--model <m>", "Agent-Model", "claude-sonnet-4-5-20250929").option("--org <name>", "Organisation (f\xFCr Backstage)").option("-o, --output <dir>", "Output-Dir", "./datasynx-output").option("--db <path>", "DB-Pfad").option("-v, --verbose", "Agent-Reasoning anzeigen", false).action(async (opts) => {
1807
1807
  checkPrerequisites();
@@ -1844,7 +1844,7 @@ function main() {
1844
1844
  let nodeCount = 0;
1845
1845
  let edgeCount = 0;
1846
1846
  w("\n");
1847
- w(` ${bold("DISCOVERY")} ${dim(config.entryPoints.join(", "))}
1847
+ w(` ${bold("CARTOGRAPHY")} ${dim(config.entryPoints.join(", "))}
1848
1848
  `);
1849
1849
  w(` ${dim("Model: " + config.agentModel + " | MaxTurns: " + config.maxTurns)}
1850
1850
  `);
@@ -2460,7 +2460,7 @@ ${infraSummary.substring(0, 12e3)}`;
2460
2460
  out(dim(" AI-powered Infrastructure Cartography & SOP Generation\n"));
2461
2461
  out("\n");
2462
2462
  line();
2463
- out(b(cyan(" DISCOVERY\n")));
2463
+ out(b(cyan(" CARTOGRAPHY\n")));
2464
2464
  out("\n");
2465
2465
  out(` ${green("datasynx-cartography discover")}
2466
2466
  `);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/preflight.ts","../src/db.ts","../src/tools.ts","../src/safety.ts","../src/agent.ts","../src/daemon.ts","../src/ipc.ts","../src/notify.ts","../src/client.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { checkPrerequisites, checkPollInterval } from './preflight.js';\nimport { CartographyDB } from './db.js';\nimport { defaultConfig } from './types.js';\nimport { runDiscovery, generateSOPs } from './agent.js';\nimport type { DiscoveryEvent } from './agent.js';\nimport { exportAll } from './exporter.js';\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { createInterface } from 'readline';\nimport {\n forkDaemon, isDaemonRunning, stopDaemon, pauseDaemon, resumeDaemon, startDaemonProcess,\n} from './daemon.js';\nimport { ForegroundClient, AttachClient } from './client.js';\n\n// ── Shared color helpers ─────────────────────────────────────────────────────\nconst bold = (s: string) => `\\x1b[1m${s}\\x1b[0m`;\nconst dim = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\nconst cyan = (s: string) => `\\x1b[36m${s}\\x1b[0m`;\nconst green = (s: string) => `\\x1b[32m${s}\\x1b[0m`;\nconst yellow = (s: string) => `\\x1b[33m${s}\\x1b[0m`;\nconst magenta = (s: string) => `\\x1b[35m${s}\\x1b[0m`;\nconst red = (s: string) => `\\x1b[31m${s}\\x1b[0m`;\n\n// ── Daemon child-process entry ────────────────────────────────────────────────\nif (process.env.CARTOGRAPHYY_DAEMON === '1') {\n const config = JSON.parse(process.env.CARTOGRAPHYY_CONFIG ?? '{}') as ReturnType<typeof defaultConfig>;\n startDaemonProcess(config).catch((err) => {\n process.stderr.write(`Daemon fatal: ${err}\\n`);\n process.exitCode = 1;\n });\n} else {\n main();\n}\n\nfunction main(): void {\n const program = new Command();\n\n const CMD = 'datasynx-cartography';\n const VERSION = '0.2.1';\n\n program\n .name(CMD)\n .description('AI-powered Infrastructure Cartography & SOP Generation')\n .version(VERSION);\n\n // ── DISCOVERY ──────────────────────────────────────────────────────────────\n\n program\n .command('discover')\n .description('Infrastruktur scannen und kartographieren')\n .option('--entry <hosts...>', 'Startpunkte', ['localhost'])\n .option('--depth <n>', 'Max Tiefe', '8')\n .option('--max-turns <n>', 'Max Agent-Turns', '50')\n .option('--model <m>', 'Agent-Model', 'claude-sonnet-4-5-20250929')\n .option('--org <name>', 'Organisation (für Backstage)')\n .option('-o, --output <dir>', 'Output-Dir', './datasynx-output')\n .option('--db <path>', 'DB-Pfad')\n .option('-v, --verbose', 'Agent-Reasoning anzeigen', false)\n .action(async (opts) => {\n checkPrerequisites();\n\n const config = defaultConfig({\n mode: 'discover',\n entryPoints: opts.entry,\n maxDepth: parseInt(opts.depth, 10),\n maxTurns: parseInt(opts.maxTurns, 10),\n agentModel: opts.model,\n organization: opts.org,\n outputDir: opts.output,\n ...(opts.db ? { dbPath: opts.db } : {}),\n verbose: opts.verbose,\n });\n\n const db = new CartographyDB(config.dbPath);\n const sessionId = db.createSession('discover', config);\n\n const w = process.stderr.write.bind(process.stderr);\n\n const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n let spinIdx = 0;\n let spinnerTimer: ReturnType<typeof setInterval> | null = null;\n let spinnerMsg = '';\n\n const startSpinner = (msg: string) => {\n spinnerMsg = msg;\n if (spinnerTimer) clearInterval(spinnerTimer);\n spinnerTimer = setInterval(() => {\n const frame = cyan(SPINNER[spinIdx % SPINNER.length] ?? '⠋');\n w(`\\r ${frame} ${spinnerMsg}\\x1b[K`);\n spinIdx++;\n }, 80);\n };\n\n const stopSpinner = () => {\n if (spinnerTimer) { clearInterval(spinnerTimer); spinnerTimer = null; }\n w(`\\r\\x1b[K`);\n };\n\n const startTime = Date.now();\n let turnNum = 0;\n let nodeCount = 0;\n let edgeCount = 0;\n\n w('\\n');\n w(` ${bold('DISCOVERY')} ${dim(config.entryPoints.join(', '))}\\n`);\n w(` ${dim('Model: ' + config.agentModel + ' | MaxTurns: ' + config.maxTurns)}\\n`);\n w(dim(' ────────────────────────────────────────────────\\n'));\n w('\\n');\n\n const logLine = (icon: string, msg: string) => {\n stopSpinner();\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n w(` ${icon} ${msg} ${dim(elapsed + 's')}\\n`);\n };\n\n const handleEvent = (event: DiscoveryEvent) => {\n switch (event.kind) {\n case 'turn':\n turnNum = event.turn;\n startSpinner(`Turn ${turnNum}/${config.maxTurns} ${dim(`nodes:${nodeCount} edges:${edgeCount}`)}`);\n break;\n\n case 'thinking':\n if (config.verbose) {\n stopSpinner();\n const lines = event.text.split('\\n').slice(0, 3);\n for (const line of lines) {\n w(` ${dim(' ' + line.substring(0, 80))}\\n`);\n }\n }\n break;\n\n case 'tool_call': {\n const toolName = event.tool.replace('mcp__cartograph__', '');\n\n if (toolName === 'Bash') {\n const cmd = (event.input['command'] as string ?? '').substring(0, 70);\n startSpinner(`${yellow('$')} ${cmd}`);\n } else if (toolName === 'save_node') {\n const id = event.input['id'] as string ?? '?';\n const type = event.input['type'] as string ?? '?';\n nodeCount++;\n logLine(green('+'), `${bold('Node')} ${cyan(id)} ${dim('(' + type + ')')}`);\n startSpinner(`Turn ${turnNum}/${config.maxTurns} ${dim(`nodes:${nodeCount} edges:${edgeCount}`)}`);\n } else if (toolName === 'save_edge') {\n const src = event.input['sourceId'] as string ?? '?';\n const tgt = event.input['targetId'] as string ?? '?';\n const rel = event.input['relationship'] as string ?? '→';\n edgeCount++;\n logLine(magenta('~'), `${bold('Edge')} ${src} ${dim(rel)} ${cyan(tgt)}`);\n startSpinner(`Turn ${turnNum}/${config.maxTurns} ${dim(`nodes:${nodeCount} edges:${edgeCount}`)}`);\n } else if (toolName === 'get_catalog') {\n startSpinner(`Catalog-Check ${dim('(Duplikate vermeiden)')}`);\n } else if (toolName === 'scan_bookmarks') {\n logLine(cyan('🔖'), `Browser-Lesezeichen werden gescannt…`);\n startSpinner(`scan_bookmarks`);\n } else if (toolName === 'scan_installed_apps') {\n const sh = event.input['searchHint'] as string | undefined;\n logLine(cyan('🖥'), sh ? `Installierte Apps gesucht: ${bold(sh)}` : `Alle installierten Apps werden gescannt…`);\n startSpinner(`scan_installed_apps`);\n } else if (toolName === 'ask_user') {\n // Just display; actual interaction is handled by onAskUser below\n const q = (event.input['question'] as string ?? '').substring(0, 100);\n logLine(yellow('?'), `${bold('Agent fragt:')} ${q}`);\n } else {\n startSpinner(`${toolName}...`);\n }\n break;\n }\n\n case 'tool_result':\n // Spinner continues, no special output for results\n break;\n\n case 'done':\n stopSpinner();\n break;\n }\n };\n\n // Human-in-the-loop: Agent kann Rückfragen stellen\n const onAskUser = async (question: string, context?: string): Promise<string> => {\n stopSpinner();\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${yellow(bold('?'))} ${bold('Agent fragt:')} ${question}\\n`);\n if (context) w(` ${dim(context)}\\n`);\n\n if (!process.stdin.isTTY) {\n w(` ${dim('(Kein Terminal — Agent fährt ohne Antwort fort)')}\\n\\n`);\n return '(Kein interaktiver Modus — bitte ohne diese Information fortfahren)';\n }\n\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n const answer = await new Promise<string>(resolve => rl.question(` ${cyan('→')} `, resolve));\n rl.close();\n w('\\n');\n return answer || '(Keine Antwort — bitte fortfahren)';\n };\n\n try {\n await runDiscovery(config, db, sessionId, handleEvent, onAskUser, undefined);\n } catch (err) {\n stopSpinner();\n w(`\\n ${bold('\\x1b[31m✗\\x1b[0m')} Discovery fehlgeschlagen: ${err}\\n`);\n db.close();\n process.exitCode = 1;\n return;\n }\n\n stopSpinner();\n db.endSession(sessionId);\n const stats = db.getStats(sessionId);\n const totalSec = ((Date.now() - startTime) / 1000).toFixed(1);\n\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${green(bold('DONE'))} ${bold(String(stats.nodes))} nodes, ${bold(String(stats.edges))} edges ${dim('in ' + totalSec + 's')}\\n`);\n w('\\n');\n\n // ── Interactive Node Review ─────────────────────────────────────────────\n const allNodes = db.getNodes(sessionId);\n\n if (allNodes.length > 0 && process.stdin.isTTY) {\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${bold('REVIEW')} ${bold(String(allNodes.length))} entdeckte Nodes — zum Bereinigen\\n`);\n w(dim(' Gib Nummern ein um Nodes zu entfernen (z.B. \"1 3 5\"), Enter = alles behalten\\n'));\n w('\\n');\n\n const PAD_ID = 42;\n const PAD_TYPE = 16;\n allNodes.forEach((n, i) => {\n const num = String(i + 1).padStart(3);\n const id = n.id.padEnd(PAD_ID).substring(0, PAD_ID);\n const type = dim(`[${n.type}]`.padEnd(PAD_TYPE));\n const conf = dim(`${Math.round(n.confidence * 100)}%`);\n const src = dim(n.discoveredVia === 'bookmark' ? ' 🔖' : '');\n w(` ${dim(num)} ${cyan('●')} ${id} ${type} ${conf}${src}\\n`);\n });\n\n w('\\n');\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n const answer = await new Promise<string>(resolve =>\n rl.question(` ${yellow('?')} Entfernen (Nummern, leer = alle behalten): `, resolve)\n );\n rl.close();\n\n const toRemove = answer.trim().split(/[\\s,]+/).map(Number).filter(n => n >= 1 && n <= allNodes.length);\n if (toRemove.length > 0) {\n for (const idx of toRemove) {\n const node = allNodes[idx - 1];\n if (node) db.deleteNode(sessionId, node.id);\n }\n w(`\\n ${green('✓')} ${bold(String(toRemove.length))} Node(s) entfernt\\n`);\n } else {\n w(`\\n ${green('✓')} Alle Nodes behalten\\n`);\n }\n }\n\n // ── Export ─────────────────────────────────────────────────────────────\n exportAll(db, sessionId, config.outputDir);\n\n // ── Diagramm-Link ──────────────────────────────────────────────────────\n const osc8 = (url: string, label: string) => `\\x1b]8;;${url}\\x1b\\\\${label}\\x1b]8;;\\x1b\\\\`;\n const htmlPath = resolve(config.outputDir, 'topology.html');\n const topoPath = resolve(config.outputDir, 'topology.mermaid');\n\n w('\\n');\n if (existsSync(htmlPath)) {\n w(` ${green('→')} ${osc8(`file://${htmlPath}`, bold('topology.html öffnen'))}\\n`);\n }\n if (existsSync(topoPath)) {\n try {\n const code = readFileSync(topoPath, 'utf8');\n const b64 = Buffer.from(JSON.stringify({ code, mermaid: { theme: 'dark' } })).toString('base64');\n w(` ${cyan('→')} ${osc8(`https://mermaid.live/view#base64:${b64}`, bold('mermaid.live öffnen'))}\\n`);\n } catch { /* ignore */ }\n }\n w('\\n');\n\n // ── Human-in-the-Loop: Follow-up Discovery Chat ───────────────────────\n if (process.stdin.isTTY) {\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${bold('WEITERSUCHEN')} ${dim('Discovery interaktiv verfeinern')}\\n`);\n w(dim(' Gib Suchbegriffe ein (z.B. \"hubspot windsurf cursor\") oder Enter zum Beenden.\\n'));\n w('\\n');\n\n // Reset event counters for follow-up rounds\n nodeCount = 0;\n edgeCount = 0;\n\n let continueDiscovery = true;\n while (continueDiscovery) {\n const rlFollowup = createInterface({ input: process.stdin, output: process.stderr });\n const followupHint = await new Promise<string>(resolve =>\n rlFollowup.question(` ${yellow('→')} Suche nach (Enter = Beenden): `, resolve)\n );\n rlFollowup.close();\n\n if (!followupHint.trim()) {\n continueDiscovery = false;\n break;\n }\n\n const followupHintTrimmed = followupHint.trim();\n w('\\n');\n w(` ${cyan(bold('⟳'))} Suche nach: ${bold(followupHintTrimmed)}\\n`);\n w('\\n');\n\n try {\n await runDiscovery(config, db, sessionId, handleEvent, onAskUser, followupHintTrimmed);\n } catch (err) {\n stopSpinner();\n w(`\\n ${red('✗')} Fehler: ${err}\\n`);\n }\n\n stopSpinner();\n const followupStats = db.getStats(sessionId);\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${green(bold('✓'))} Gesamt jetzt: ${bold(String(followupStats.nodes))} nodes, ${bold(String(followupStats.edges))} edges\\n`);\n w('\\n');\n\n // Re-export with updated data\n exportAll(db, sessionId, config.outputDir);\n if (existsSync(htmlPath)) {\n w(` ${green('→')} ${osc8(`file://${htmlPath}`, bold('topology.html aktualisiert'))}\\n`);\n }\n w('\\n');\n }\n }\n\n db.close();\n });\n\n // ── SHADOW ────────────────────────────────────────────────────────────────\n\n const shadow = program.command('shadow').description('Shadow-Daemon verwalten');\n\n shadow\n .command('start')\n .description('Shadow-Daemon starten')\n .option('--interval <ms>', 'Poll-Intervall in ms', '30000')\n .option('--inactivity <ms>', 'Task-Grenze in ms', '300000')\n .option('--track-windows', 'Fenster-Focus tracken', false)\n .option('--auto-save', 'Nodes ohne Rückfrage speichern', false)\n .option('--no-notifications', 'Desktop-Notifications deaktivieren')\n .option('--model <m>', 'Analysis-Model', 'claude-haiku-4-5-20251001')\n .option('--foreground', 'Kein Daemon, im Terminal bleiben', false)\n .option('--db <path>', 'DB-Pfad')\n .option('--daemon-child', 'Internal: marks this as a daemon child process') // internal flag\n .action(async (opts) => {\n checkPrerequisites();\n\n const intervalMs = checkPollInterval(parseInt(opts.interval, 10));\n\n const config = defaultConfig({\n mode: 'shadow',\n shadowMode: opts.foreground ? 'foreground' : 'daemon',\n pollIntervalMs: intervalMs,\n inactivityTimeoutMs: parseInt(opts.inactivity, 10),\n trackWindowFocus: opts.trackWindows,\n autoSaveNodes: opts.autoSave,\n enableNotifications: opts.notifications !== false,\n shadowModel: opts.model,\n ...(opts.db ? { dbPath: opts.db } : {}),\n });\n\n // Check if already running\n const { running } = isDaemonRunning(config.pidFile);\n if (running) {\n process.stderr.write('❌ Shadow-Daemon läuft bereits. datasynx-cartography shadow status\\n');\n process.exitCode = 1;\n return;\n }\n\n if (opts.foreground) {\n const client = new ForegroundClient();\n await client.run(config);\n } else {\n const pid = forkDaemon(config);\n process.stderr.write(`👁 Shadow daemon started (PID ${pid})\\n`);\n process.stderr.write(` Intervall: ${intervalMs / 1000}s | Modell: ${config.shadowModel}\\n`);\n process.stderr.write(' datasynx-cartography shadow attach — ankoppeln\\n');\n process.stderr.write(' datasynx-cartography shadow stop — stoppen\\n\\n');\n }\n });\n\n shadow\n .command('stop')\n .description('Shadow-Daemon stoppen + SOP-Review')\n .option('-o, --output <dir>', 'Output-Dir für SOPs + Dashboard', './datasynx-output')\n .option('--no-review', 'SOP-Review überspringen')\n .action(async (opts) => {\n const config = defaultConfig({ outputDir: opts.output });\n const stopped = stopDaemon(config.pidFile);\n\n if (!stopped) {\n process.stderr.write('⚠ Kein laufender Shadow-Daemon gefunden\\n');\n return;\n }\n\n process.stderr.write('✓ Shadow-Daemon gestoppt\\n');\n\n if (opts.review === false) return;\n\n // Wait a moment for daemon to flush DB\n await new Promise(r => setTimeout(r, 500));\n\n // Generate SOPs + show review\n const db = new CartographyDB(config.dbPath);\n const session = db.getLatestSession('shadow');\n if (!session) {\n db.close();\n return;\n }\n\n const stats = db.getStats(session.id);\n const w = (s: string) => process.stderr.write(s);\n\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(bold(' Shadow-Session Review\\n'));\n w(dim(` Session: ${session.id}\\n`));\n w(dim(` Nodes: ${stats.nodes} | Events: ${stats.events} | Tasks: ${stats.tasks}\\n`));\n w(dim(' ────────────────────────────────────────────────\\n'));\n w('\\n');\n\n // Generate SOPs if tasks exist\n if (stats.tasks > 0) {\n try {\n w(' SOPs generieren...\\n');\n const count = await generateSOPs(db, session.id);\n w(` ${green('✓')} ${count} SOPs generiert\\n\\n`);\n } catch (err) {\n w(` ${red('✗')} SOP-Generierung fehlgeschlagen: ${err}\\n\\n`);\n }\n }\n\n // Show SOPs as markdown review\n const { exportSOPMarkdown, exportSOPDashboard } = await import('./exporter.js');\n const sops = db.getSOPs(session.id);\n\n if (sops.length > 0) {\n w(bold(' SOPs zur Überprüfung:\\n\\n'));\n for (const sop of sops) {\n const md = exportSOPMarkdown(sop);\n // Indent each line for terminal display\n for (const line of md.split('\\n')) {\n process.stdout.write(` ${line}\\n`);\n }\n process.stdout.write('\\n');\n w(dim(' ────────────────────────────────────────────────\\n\\n'));\n }\n\n // Export SOP dashboard HTML\n const { mkdirSync, writeFileSync } = await import('node:fs');\n const { join, resolve: resolvePath } = await import('node:path');\n\n mkdirSync(config.outputDir, { recursive: true });\n mkdirSync(join(config.outputDir, 'sops'), { recursive: true });\n\n // Write individual SOP markdown files\n for (const sop of sops) {\n const filename = sop.title.toLowerCase().replace(/[^a-z0-9]+/g, '-') + '.md';\n writeFileSync(join(config.outputDir, 'sops', filename), exportSOPMarkdown(sop));\n }\n\n // Write SOP dashboard HTML\n const allSOPs = db.getAllSOPs();\n const dashboardHtml = exportSOPDashboard(allSOPs);\n const dashboardPath = join(config.outputDir, 'sop-dashboard.html');\n writeFileSync(dashboardPath, dashboardHtml);\n\n const absPath = resolvePath(dashboardPath);\n w(` ${green('✓')} ${sops.length} SOP-Markdown-Dateien geschrieben\\n`);\n w(` ${green('✓')} SOP Dashboard: ${cyan(`file://${absPath}`)}\\n`);\n w('\\n');\n w(dim(` Öffne im Browser: ${bold(`file://${absPath}`)}\\n`));\n w('\\n');\n } else {\n w(dim(' Keine SOPs in dieser Session.\\n\\n'));\n }\n\n db.close();\n });\n\n shadow\n .command('pause')\n .description('Shadow-Daemon pausieren')\n .action(() => {\n const config = defaultConfig();\n const paused = pauseDaemon(config.pidFile);\n if (paused) {\n process.stderr.write('⏸ Shadow-Daemon pausiert\\n');\n } else {\n process.stderr.write('⚠ Kein laufender Shadow-Daemon gefunden\\n');\n }\n });\n\n shadow\n .command('resume')\n .description('Shadow-Daemon fortsetzen')\n .action(() => {\n const config = defaultConfig();\n const resumed = resumeDaemon(config.pidFile);\n if (resumed) {\n process.stderr.write('▶ Shadow-Daemon fortgesetzt\\n');\n } else {\n process.stderr.write('⚠ Kein laufender Shadow-Daemon gefunden\\n');\n }\n });\n\n shadow\n .command('status')\n .description('Shadow-Daemon Status anzeigen')\n .action(() => {\n const config = defaultConfig();\n const { running, pid } = isDaemonRunning(config.pidFile);\n if (running) {\n process.stdout.write(`✓ Shadow-Daemon läuft (PID ${pid})\\n`);\n process.stdout.write(` Socket: ${config.socketPath}\\n`);\n } else {\n process.stdout.write('✗ Shadow-Daemon gestoppt\\n');\n }\n });\n\n shadow\n .command('attach')\n .description('An laufenden Shadow-Daemon ankoppeln')\n .action(async () => {\n const config = defaultConfig();\n const client = new AttachClient();\n await client.attach(config.socketPath);\n });\n\n // ── ANALYSE & EXPORT ──────────────────────────────────────────────────────\n\n program\n .command('sops [session-id]')\n .description('SOPs aus beobachteten Workflows generieren')\n .action(async (sessionId?: string) => {\n checkPrerequisites();\n\n const config = defaultConfig();\n const db = new CartographyDB(config.dbPath);\n\n const session = sessionId\n ? db.getSession(sessionId)\n : db.getLatestSession('shadow');\n\n if (!session) {\n process.stderr.write('❌ Keine Shadow-Session gefunden. datasynx-cartography shadow start\\n');\n db.close();\n process.exitCode = 1;\n return;\n }\n\n process.stderr.write(`🔄 Generiere SOPs aus Session ${session.id}...\\n`);\n const count = await generateSOPs(db, session.id);\n process.stderr.write(`✓ ${count} SOPs generiert\\n`);\n\n db.close();\n });\n\n program\n .command('export [session-id]')\n .description('Alle Outputs generieren')\n .option('-o, --output <dir>', 'Output-Dir', './datasynx-output')\n .option('--format <fmt...>', 'Formate: mermaid,json,yaml,html,sops')\n .action((sessionId: string | undefined, opts) => {\n const config = defaultConfig({ outputDir: opts.output });\n const db = new CartographyDB(config.dbPath);\n\n const session = sessionId\n ? db.getSession(sessionId)\n : db.getLatestSession();\n\n if (!session) {\n process.stderr.write('❌ Keine Session gefunden\\n');\n db.close();\n process.exitCode = 1;\n return;\n }\n\n const formats = opts.format ?? ['mermaid', 'json', 'yaml', 'html', 'sops'];\n exportAll(db, session.id, opts.output, formats);\n process.stderr.write(`✓ Exported to: ${opts.output}\\n`);\n\n db.close();\n });\n\n program\n .command('show [session-id]')\n .description('Session-Details anzeigen')\n .action((sessionId?: string) => {\n const config = defaultConfig();\n const db = new CartographyDB(config.dbPath);\n\n const session = sessionId\n ? db.getSession(sessionId)\n : db.getLatestSession();\n\n if (!session) {\n process.stderr.write('❌ Keine Session gefunden\\n');\n db.close();\n process.exitCode = 1;\n return;\n }\n\n const stats = db.getStats(session.id);\n const nodes = db.getNodes(session.id);\n\n process.stdout.write(`\\nSession: ${session.id}\\n`);\n process.stdout.write(` Mode: ${session.mode}\\n`);\n process.stdout.write(` Started: ${session.startedAt}\\n`);\n if (session.completedAt) process.stdout.write(` Ended: ${session.completedAt}\\n`);\n process.stdout.write(` Nodes: ${stats.nodes}\\n`);\n process.stdout.write(` Edges: ${stats.edges}\\n`);\n process.stdout.write(` Events: ${stats.events}\\n`);\n process.stdout.write(` Tasks: ${stats.tasks}\\n`);\n\n if (nodes.length > 0) {\n process.stdout.write('\\n Discovered nodes:\\n');\n for (const node of nodes.slice(0, 20)) {\n process.stdout.write(` ${node.id} (${node.type}, confidence: ${node.confidence})\\n`);\n }\n if (nodes.length > 20) {\n process.stdout.write(` ... and ${nodes.length - 20} more\\n`);\n }\n }\n\n process.stdout.write('\\n');\n db.close();\n });\n\n program\n .command('sessions')\n .description('Alle Sessions auflisten')\n .action(() => {\n const config = defaultConfig();\n const db = new CartographyDB(config.dbPath);\n const sessions = db.getSessions();\n\n if (sessions.length === 0) {\n process.stdout.write('Keine Sessions gefunden\\n');\n db.close();\n return;\n }\n\n for (const session of sessions) {\n const stats = db.getStats(session.id);\n const status = session.completedAt ? '✓' : '●';\n process.stdout.write(\n `${status} ${session.id.substring(0, 8)} [${session.mode}] ` +\n `${session.startedAt.substring(0, 19)} ` +\n `nodes:${stats.nodes} edges:${stats.edges}\\n`\n );\n }\n\n db.close();\n });\n\n // ── OVERVIEW ──────────────────────────────────────────────────────────────\n\n program\n .command('overview')\n .description('Übersicht aller Cartographies + SOPs')\n .option('--db <path>', 'DB-Pfad')\n .action((opts) => {\n const config = defaultConfig();\n const db = new CartographyDB((opts as { db?: string }).db ?? config.dbPath);\n const sessions = db.getSessions();\n\n const b = bold, d = dim;\n const w = (s: string) => process.stdout.write(s);\n\n w('\\n');\n w(` ${b('CARTOGRAPHY OVERVIEW')}\\n`);\n w(d(' ─────────────────────────────────────────────────────\\n'));\n\n if (sessions.length === 0) {\n w(` ${d('Noch keine Sessions. Starte mit:')} ${green('datasynx-cartography discover')}\\n\\n`);\n db.close();\n return;\n }\n\n // Aggregate totals\n let totalNodes = 0, totalEdges = 0, totalSops = 0;\n for (const s of sessions) {\n const st = db.getStats(s.id);\n totalNodes += st.nodes; totalEdges += st.edges;\n totalSops += db.getSOPs(s.id).length;\n }\n\n w(` ${b(String(sessions.length))} Sessions · ${b(String(totalNodes))} Nodes · `);\n w(`${b(String(totalEdges))} Edges · ${b(String(totalSops))} SOPs\\n\\n`);\n\n for (const session of sessions) {\n const stats = db.getStats(session.id);\n const nodes = db.getNodes(session.id);\n const sops = db.getSOPs(session.id);\n const status = session.completedAt ? green('✓') : yellow('●');\n const age = session.startedAt.substring(0, 16).replace('T', ' ');\n const sid = cyan(session.id.substring(0, 8));\n\n w(` ${status} ${sid} ${b('[' + session.mode + ']')} ${d(age)}\\n`);\n w(` ${d('Nodes: ' + stats.nodes + ' Edges: ' + stats.edges + ' SOPs: ' + sops.length)}\\n`);\n\n // Node type breakdown\n const byType = new Map<string, number>();\n for (const n of nodes) byType.set(n.type, (byType.get(n.type) ?? 0) + 1);\n if (byType.size > 0) {\n const parts = [...byType.entries()].map(([t, c]) => `${t}:${c}`).join(' ');\n w(` ${d(parts)}\\n`);\n }\n\n // Top nodes\n const topNodes = nodes.slice(0, 5).map(n => n.id).join(', ');\n if (topNodes) w(` ${d('Nodes: ' + topNodes + (nodes.length > 5 ? ' …' : ''))}\\n`);\n\n // SOPs\n for (const sop of sops.slice(0, 3)) {\n w(` ${green('►')} ${sop.title} ${d('(' + sop.estimatedDuration + ')')}\\n`);\n }\n if (sops.length > 3) w(` ${d('… +' + (sops.length - 3) + ' weitere SOPs')}\\n`);\n\n w('\\n');\n }\n\n db.close();\n });\n\n // ── CHAT ──────────────────────────────────────────────────────────────────\n\n program\n .command('chat [session-id]')\n .description('Interaktiver Chat über die kartographierte Infrastruktur')\n .option('--db <path>', 'DB-Pfad')\n .option('--model <m>', 'Model', 'claude-sonnet-4-5-20250929')\n .action(async (sessionIdArg: string | undefined, opts) => {\n const config = defaultConfig();\n const db = new CartographyDB((opts as { db?: string }).db ?? config.dbPath);\n const sessions = db.getSessions();\n\n const session = sessionIdArg\n ? sessions.find(s => s.id.startsWith(sessionIdArg))\n : sessions.filter(s => s.completedAt).at(-1) ?? sessions.at(-1);\n\n if (!session) {\n process.stderr.write('Keine Session gefunden. Führe zuerst discover aus.\\n');\n db.close();\n return;\n }\n\n const nodes = db.getNodes(session.id);\n const edges = db.getEdges(session.id);\n const sops = db.getSOPs(session.id);\n\n const w = (s: string) => process.stdout.write(s);\n\n w('\\n');\n w(dim(` ─────────────────────────────────────────────────────\\n`));\n w(` ${bold('CARTOGRAPHY CHAT')} ${dim('Session ' + session.id.substring(0, 8))}\\n`);\n w(` ${dim(String(nodes.length) + ' Nodes · ' + edges.length + ' Edges · ' + sops.length + ' SOPs')}\\n`);\n w(dim(` ─────────────────────────────────────────────────────\\n`));\n w(` ${dim('Frage alles über deine Infrastruktur. exit = beenden.\\n\\n')}`);\n\n const Anthropic = (await import('@anthropic-ai/sdk')).default;\n const client = new Anthropic();\n\n // Build a compact infra summary for context (avoid token overflow)\n const infraSummary = JSON.stringify({\n nodes: nodes.map(n => ({\n id: n.id, name: n.name, type: n.type,\n confidence: n.confidence,\n metadata: n.metadata,\n tags: n.tags,\n })),\n edges: edges.map(e => ({ from: e.sourceId, to: e.targetId, rel: e.relationship, conf: e.confidence })),\n sops: sops.map(s => ({ title: s.title, description: s.description, steps: s.steps.length, duration: s.estimatedDuration })),\n });\n\n const systemPrompt = `Du bist ein Infrastruktur-Analyst für Cartography.\nDu hast Zugriff auf die vollständig kartographierte Infrastruktur dieser Session.\nBeantworte Fragen präzise und hilfreich. Nutze die Daten konkret.\nDu kannst SOPs erklären, Abhängigkeiten analysieren, Risiken benennen, Optimierungen vorschlagen.\n\nINFRASTRUKTUR-SNAPSHOT (${nodes.length} Nodes, ${edges.length} Edges, ${sops.length} SOPs):\n${infraSummary.substring(0, 12000)}`;\n\n // Multi-turn conversation history\n type MsgParam = { role: 'user' | 'assistant'; content: string };\n const history: MsgParam[] = [];\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n\n const ask = () => new Promise<string>(resolve => rl.question(` ${cyan('>')} `, resolve));\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let userInput: string;\n try { userInput = await ask(); } catch { break; }\n\n if (!userInput.trim()) continue;\n if (['exit', 'quit', ':q'].includes(userInput.trim().toLowerCase())) break;\n\n history.push({ role: 'user', content: userInput });\n\n try {\n const resp = await client.messages.create({\n model: (opts as { model: string }).model,\n max_tokens: 1024,\n system: systemPrompt,\n messages: history,\n });\n\n const reply = resp.content.find(b => b.type === 'text')?.text ?? '';\n history.push({ role: 'assistant', content: reply });\n\n w('\\n');\n // Word-wrap at 80 cols with indent\n for (const line of reply.split('\\n')) {\n w(` ${line}\\n`);\n }\n w('\\n');\n } catch (err) {\n w(` ${red('✗')} Fehler: ${err}\\n\\n`);\n }\n }\n\n rl.close();\n db.close();\n w(`\\n ${dim('Chat beendet.')}\\n\\n`);\n });\n\n // ── DOCS ──────────────────────────────────────────────────────────────────\n\n program\n .command('docs')\n .description('Alle Features und Befehle auf einen Blick')\n .action(() => {\n const out = process.stdout.write.bind(process.stdout);\n const b = bold;\n const line = () => out(dim('─'.repeat(60)) + '\\n');\n\n out('\\n');\n out(b(' DATASYNX CARTOGRAPHY') + ' ' + dim('v' + VERSION) + '\\n');\n out(dim(' AI-powered Infrastructure Cartography & SOP Generation\\n'));\n out('\\n');\n line();\n\n // ── DISCOVERY\n out(b(cyan(' DISCOVERY\\n')));\n out('\\n');\n out(` ${green('datasynx-cartography discover')}\\n`);\n out(` Scannt die lokale Infrastruktur (Claude Sonnet).\\n`);\n out(` Claude führt eigenständig ss, ps, curl, docker inspect, kubectl get\\n`);\n out(` aus und speichert alles in SQLite.\\n`);\n out('\\n');\n out(dim(' Optionen:\\n'));\n out(dim(' --entry <hosts...> Startpunkte (default: localhost)\\n'));\n out(dim(' --depth <n> Max Tiefe (default: 8)\\n'));\n out(dim(' --max-turns <n> Max Agent-Turns (default: 50)\\n'));\n out(dim(' --model <m> Model (default: claude-sonnet-4-5-...)\\n'));\n out(dim(' --org <name> Organisation für Backstage YAML\\n'));\n out(dim(' -o, --output <dir> Output-Verzeichnis (default: ./datasynx-output)\\n'));\n out(dim(' -v, --verbose Agent-Reasoning anzeigen\\n'));\n out('\\n');\n out(dim(' Output:\\n'));\n out(dim(' datasynx-output/\\n'));\n out(dim(' catalog.json Maschinenlesbarer Komplett-Dump\\n'));\n out(dim(' catalog-info.yaml Backstage Service-Katalog\\n'));\n out(dim(' topology.mermaid Infrastruktur-Topologie (graph TB)\\n'));\n out(dim(' dependencies.mermaid Service-Dependencies (graph LR)\\n'));\n out(dim(' topology.html Interaktiver D3.js Force-Graph\\n'));\n out(dim(' sops/ Generierte SOPs als Markdown\\n'));\n out(dim(' workflows/ Workflow-Flowcharts als Mermaid\\n'));\n out('\\n');\n line();\n\n // ── SHADOW\n out(b(cyan(' SHADOW DAEMON\\n')));\n out('\\n');\n out(` ${green('datasynx-cartography shadow start')}\\n`);\n out(` Startet einen Background-Daemon, der alle 30s einen System-Snapshot\\n`);\n out(` nimmt (ss + ps). Nur bei Änderung ruft er Claude Haiku auf.\\n`);\n out('\\n');\n out(dim(' Optionen:\\n'));\n out(dim(' --interval <ms> Poll-Intervall (default: 30000, min: 15000)\\n'));\n out(dim(' --inactivity <ms> Task-Grenze (default: 300000 = 5 min)\\n'));\n out(dim(' --model <m> Analysis-Model (default: claude-haiku-4-5-...)\\n'));\n out(dim(' --track-windows Fenster-Focus tracken (benötigt xdotool)\\n'));\n out(dim(' --auto-save Nodes ohne Rückfrage speichern\\n'));\n out(dim(' --no-notifications Desktop-Notifications deaktivieren\\n'));\n out(dim(' --foreground Kein Daemon, im Terminal bleiben\\n'));\n out('\\n');\n out(` ${green('datasynx-cartography shadow stop')} ${dim('Daemon per SIGTERM beenden')}\\n`);\n out(` ${green('datasynx-cartography shadow status')} ${dim('PID + Socket-Pfad anzeigen')}\\n`);\n out(` ${green('datasynx-cartography shadow attach')} ${dim('Live-Events im Terminal, Hotkeys: [T] [S] [D] [Q]')}\\n`);\n out('\\n');\n out(dim(' Hotkeys im Attach-Modus:\\n'));\n out(dim(' [T] Neuen Task starten (mit Beschreibung)\\n'));\n out(dim(' [S] Status-Dump anzeigen (Nodes, Events, Tasks, Cycles)\\n'));\n out(dim(' [D] Trennen — Daemon läuft weiter\\n'));\n out(dim(' [Q] Daemon stoppen und beenden\\n'));\n out('\\n');\n line();\n\n // ── ANALYSE & EXPORT\n out(b(cyan(' ANALYSE & EXPORT\\n')));\n out('\\n');\n out(` ${green('datasynx-cartography sops [session-id]')}\\n`);\n out(` Clustert abgeschlossene Tasks und generiert SOPs via Claude Sonnet.\\n`);\n out(` Nutzt die Anthropic Messages API (kein Agent-Loop, ein Request pro Cluster).\\n`);\n out('\\n');\n out(` ${green('datasynx-cartography export [session-id]')}\\n`);\n out(dim(' --format <fmt...> mermaid, json, yaml, html, sops (default: alle)\\n'));\n out(dim(' -o, --output <dir> Output-Verzeichnis\\n'));\n out('\\n');\n out(` ${green('datasynx-cartography show [session-id]')} ${dim('Session-Details + Node-Liste')}\\n`);\n out(` ${green('datasynx-cartography sessions')} ${dim('Alle Sessions tabellarisch auflisten')}\\n`);\n out('\\n');\n line();\n\n // ── KOSTEN\n out(b(cyan(' KOSTEN (Richtwerte)\\n')));\n out('\\n');\n out(yellow(' Modus Model Intervall pro Stunde pro 8h-Tag\\n'));\n out(dim(' ─────────────────────────────────────────────────────────────\\n'));\n out(` Discovery Sonnet einmalig $0.15–0.50 einmalig\\n`);\n out(` Shadow Haiku 30s $0.12–0.36 $0.96–2.88\\n`);\n out(` Shadow Haiku 60s $0.06–0.18 $0.48–1.44\\n`);\n out(` Shadow (ruhig) Haiku 30s ~$0.02 ~$0.16\\n`);\n out(` SOP-Gen Sonnet einmalig $0.01–0.03 einmalig\\n`);\n out('\\n');\n out(dim(' * \"ruhig\" = Diff-Check überspringt 90%+ Cycles, wenn System unverändert\\n'));\n out('\\n');\n line();\n\n // ── ARCHITEKTUR\n out(b(cyan(' ARCHITEKTUR\\n')));\n out('\\n');\n out(dim(' CLI (Commander)\\n'));\n out(dim(' └── Preflight: Claude CLI check + API key + Intervall-Validierung\\n'));\n out(dim(' └── Agent Orchestrator (agent.ts)\\n'));\n out(dim(' ├── runDiscovery() → Claude Sonnet + Bash + MCP Tools\\n'));\n out(dim(' ├── runShadowCycle() → Claude Haiku + nur MCP Tools (kein Bash!)\\n'));\n out(dim(' └── generateSOPs() → Anthropic Messages API (kein Agent-Loop)\\n'));\n out(dim(' └── Custom MCP Tools (tools.ts)\\n'));\n out(dim(' save_node, save_edge, save_event,\\n'));\n out(dim(' get_catalog, manage_task, save_sop\\n'));\n out(dim(' └── CartographyDB (SQLite WAL)\\n'));\n out(dim(' Shadow Daemon (daemon.ts)\\n'));\n out(dim(' ├── takeSnapshot() → ss + ps [kein Claude!]\\n'));\n out(dim(' ├── Diff-Check → nur bei Änderung: runShadowCycle()\\n'));\n out(dim(' ├── IPC Server (Unix Socket ~/.cartography/daemon.sock)\\n'));\n out(dim(' └── NotificationService (Desktop wenn kein Client attached)\\n'));\n out('\\n');\n line();\n\n // ── SETUP\n out(b(cyan(' SETUP\\n')));\n out('\\n');\n out(dim(' # 1. Claude CLI (Runtime-Dependency)\\n'));\n out(' npm install -g @anthropic-ai/claude-code\\n');\n out(' claude login\\n');\n out('\\n');\n out(dim(' # 2. API Key (falls nicht via claude login)\\n'));\n out(' export ANTHROPIC_API_KEY=sk-ant-...\\n');\n out('\\n');\n out(dim(' # 3. Los\\n'));\n out(' datasynx-cartography discover\\n');\n out(' datasynx-cartography shadow start\\n');\n out('\\n');\n out(dim(' Daten: ~/.cartography/cartography.db\\n'));\n out(dim(' Socket: ~/.cartography/daemon.sock\\n'));\n out(dim(' PID: ~/.cartography/daemon.pid\\n'));\n out('\\n');\n });\n\n // ── Bookmarks ──────────────────────────────────────────────────────────────\n\n program\n .command('bookmarks')\n .description('Alle Browser-Lesezeichen anzeigen (Chrome, Edge, Brave, Firefox)')\n .action(async () => {\n const { scanAllBookmarks } = await import('./bookmarks.js');\n const out = (s: string) => process.stdout.write(s);\n\n process.stderr.write(' Scanning bookmarks...\\n\\n');\n const hosts = await scanAllBookmarks();\n\n if (hosts.length === 0) {\n out(' (Keine Lesezeichen gefunden — Chrome, Edge, Brave und Firefox werden unterstützt)\\n\\n');\n return;\n }\n\n // Group by source browser\n const bySource = new Map<string, typeof hosts>();\n for (const h of hosts) {\n if (!bySource.has(h.source)) bySource.set(h.source, []);\n bySource.get(h.source)!.push(h);\n }\n\n for (const [source, entries] of bySource) {\n out(bold(cyan(` ${source.toUpperCase()}`)) + dim(` (${entries.length} Hosts)\\n`));\n out(dim(' ─────────────────────────────────────────\\n'));\n for (const h of entries) {\n const isDefault = (h.protocol === 'https' && h.port === 443) || (h.protocol === 'http' && h.port === 80);\n const portStr = isDefault ? '' : `:${h.port}`;\n out(` ${cyan(h.protocol + '://')}${h.hostname}${dim(portStr)}\\n`);\n }\n out('\\n');\n }\n\n out(dim(` Total: ${hosts.length} unique hosts\\n\\n`));\n out(dim(' Tipp: ') + 'datasynx-cartography discover' + dim(' — scannt + klassifiziert alle Lesezeichen automatisch\\n\\n'));\n });\n\n // ── Seed ───────────────────────────────────────────────────────────────────\n\n program\n .command('seed')\n .description('Bekannte Infrastruktur manuell eintragen (Tools, DBs, APIs, etc.)')\n .option('--file <path>', 'JSON-Datei mit Node-Definitionen einlesen')\n .option('--session <id>', 'In existierende Session eintragen (default: neue Session)')\n .option('--db <path>', 'DB-Pfad')\n .action(async (opts) => {\n const config = defaultConfig({ ...(opts.db ? { dbPath: opts.db } : {}) });\n const db = new CartographyDB(config.dbPath);\n const sessionId = opts.session ?? db.createSession('discover', config);\n\n const out = (s: string) => process.stdout.write(s);\n const w = (s: string) => process.stderr.write(s);\n\n // ── File mode ────────────────────────────────────────────────────────\n if (opts.file) {\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(resolve(opts.file), 'utf8'));\n } catch (e) {\n w(red(`\\n ✗ Datei konnte nicht gelesen werden: ${e}\\n\\n`));\n process.exitCode = 1;\n return;\n }\n\n if (!Array.isArray(raw)) {\n w(red('\\n ✗ JSON muss ein Array sein: [{ \"type\": \"...\", \"name\": \"...\", \"host\": \"...\" }]\\n\\n'));\n process.exitCode = 1;\n return;\n }\n\n let saved = 0;\n for (const entry of raw as Record<string, unknown>[]) {\n const type = entry['type'] as string;\n const name = entry['name'] as string;\n const host = entry['host'] as string | undefined;\n const port = entry['port'] as number | undefined;\n const tags = (entry['tags'] as string[] | undefined) ?? [];\n const metadata = (entry['metadata'] as Record<string, unknown> | undefined) ?? {};\n\n if (!type || !name) {\n w(yellow(` ⚠ Übersprungen (kein type/name): ${JSON.stringify(entry)}\\n`));\n continue;\n }\n\n const id = host\n ? `${type}:${host}${port ? ':' + port : ''}`\n : `${type}:${name.toLowerCase().replace(/\\s+/g, '-')}`;\n\n db.upsertNode(sessionId, {\n id,\n type: type as typeof import('./types.js').NODE_TYPES[number],\n name,\n discoveredVia: 'manual',\n confidence: 1.0,\n metadata: { ...metadata, ...(host ? { host } : {}), ...(port ? { port } : {}) },\n tags,\n });\n out(` ${green('+')} ${cyan(id)} ${dim('(' + type + ')')}\\n`);\n saved++;\n }\n\n db.endSession(sessionId);\n w(`\\n ${green(bold('DONE'))} ${saved} Nodes gespeichert ${dim('Session: ' + sessionId)}\\n\\n`);\n return;\n }\n\n // ── Interactive mode ─────────────────────────────────────────────────\n const { NODE_TYPES } = await import('./types.js');\n\n if (!process.stdin.isTTY) {\n w(red('\\n ✗ Interaktiver Modus benötigt ein Terminal (--file für nicht-interaktiven Betrieb)\\n\\n'));\n process.exitCode = 1;\n return;\n }\n\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(bold(' Bekannte Infrastruktur eintragen\\n'));\n w(dim(' Beispiele: Datenbanken, APIs, SaaS-Tools, Cloud-Services\\n'));\n w(dim(' ────────────────────────────────────────────────\\n'));\n w('\\n');\n\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n const ask = (q: string): Promise<string> => new Promise(res => rl.question(q, res));\n\n let saved = 0;\n\n const typeList = NODE_TYPES.map((t, i) => `${dim((i + 1).toString().padStart(2))} ${t}`).join('\\n ');\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n w('\\n');\n w(dim(' Node-Typen:\\n'));\n w(` ${typeList}\\n\\n`);\n\n const typeInput = (await ask(` ${cyan('Typ')} ${dim('[Nr. oder Name, Enter=abbrechen]')}: `)).trim();\n if (!typeInput) break;\n\n let nodeType: string;\n const asNum = parseInt(typeInput, 10);\n if (!isNaN(asNum) && asNum >= 1 && asNum <= NODE_TYPES.length) {\n nodeType = NODE_TYPES[asNum - 1] as string;\n } else if (NODE_TYPES.includes(typeInput as typeof NODE_TYPES[number])) {\n nodeType = typeInput;\n } else {\n w(yellow(` ⚠ Unbekannter Typ: \"${typeInput}\"\\n`));\n continue;\n }\n\n const name = (await ask(` ${cyan('Name')} ${dim('[z.B. \"Prod PostgreSQL\"]')}: `)).trim();\n if (!name) { w(dim(' (Abgebrochen)\\n')); continue; }\n\n const hostRaw = (await ask(` ${cyan('Host / IP')} ${dim('[optional, Enter=überspringen]')}: `)).trim();\n const portRaw = (await ask(` ${cyan('Port')} ${dim('[optional]')}: `)).trim();\n const tagsRaw = (await ask(` ${cyan('Tags')} ${dim('[komma-getrennt, optional]')}: `)).trim();\n\n const host = hostRaw || undefined;\n const port = portRaw ? parseInt(portRaw, 10) : undefined;\n const tags = tagsRaw ? tagsRaw.split(',').map(t => t.trim()).filter(Boolean) : [];\n\n const id = host\n ? `${nodeType}:${host}${port ? ':' + port : ''}`\n : `${nodeType}:${name.toLowerCase().replace(/\\s+/g, '-')}`;\n\n db.upsertNode(sessionId, {\n id,\n type: nodeType as typeof NODE_TYPES[number],\n name,\n discoveredVia: 'manual',\n confidence: 1.0,\n metadata: { ...(host ? { host } : {}), ...(port ? { port } : {}) },\n tags,\n });\n out(` ${green('+')} ${cyan(id)}\\n`);\n saved++;\n\n const again = (await ask(` ${dim('Weiteren Node hinzufügen? [Y/n]')}: `)).trim().toLowerCase();\n if (again === 'n' || again === 'nein') break;\n }\n\n rl.close();\n db.endSession(sessionId);\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${green(bold('DONE'))} ${saved} Node${saved !== 1 ? 's' : ''} gespeichert\\n`);\n w(` ${dim('Session: ' + sessionId)}\\n`);\n w(` ${dim('Tipp: datasynx-cartography show ' + sessionId)}\\n\\n`);\n });\n\n // ── Doctor ─────────────────────────────────────────────────────────────────\n\n program\n .command('doctor')\n .description('Prüft ob alle Voraussetzungen erfüllt sind')\n .action(async () => {\n const { execSync } = await import('node:child_process');\n const { existsSync, readFileSync } = await import('node:fs');\n const { join } = await import('node:path');\n const out = (s: string) => process.stdout.write(s);\n const ok = (msg: string) => out(` \\x1b[32m✓\\x1b[0m ${msg}\\n`);\n const err = (msg: string) => out(` \\x1b[31m✗\\x1b[0m ${msg}\\n`);\n const warn = (msg: string) => out(` \\x1b[33m⚠\\x1b[0m ${msg}\\n`);\n const dim = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\n let allGood = true;\n\n out('\\n \\x1b[1mDatasynx Cartography — Doctor\\x1b[0m\\n');\n out(dim(' ─────────────────────────────────\\n'));\n\n // 1. Node.js Version\n const nodeVer = process.versions.node;\n const [major] = nodeVer.split('.').map(Number);\n if ((major ?? 0) >= 18) {\n ok(`Node.js ${nodeVer}`);\n } else {\n err(`Node.js ${nodeVer} — benötigt >=18`);\n allGood = false;\n }\n\n // 2. Claude CLI\n try {\n const v = execSync('claude --version', { stdio: 'pipe' }).toString().trim();\n ok(`Claude CLI ${dim(v)}`);\n } catch {\n err('Claude CLI nicht gefunden — npm i -g @anthropic-ai/claude-code');\n allGood = false;\n }\n\n // 3. Auth\n const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY);\n const home = process.env.HOME ?? process.env.USERPROFILE ?? '/tmp';\n let hasOAuth = false;\n try {\n const creds = JSON.parse(readFileSync(join(home, '.claude', '.credentials.json'), 'utf8')) as Record<string, unknown>;\n const oauth = creds['claudeAiOauth'] as Record<string, unknown> | undefined;\n hasOAuth = typeof oauth?.['accessToken'] === 'string' && oauth['accessToken'].length > 0;\n } catch { /* no creds file */ }\n\n if (hasApiKey) {\n ok('ANTHROPIC_API_KEY gesetzt');\n } else if (hasOAuth) {\n ok('claude login (Subscription)');\n } else {\n err('Keine Authentifizierung — claude login oder export ANTHROPIC_API_KEY=sk-ant-...');\n allGood = false;\n }\n\n // 4. kubectl — wichtig für K8s Discovery\n try {\n const v = execSync('kubectl version --client --short 2>/dev/null || kubectl version --client', { stdio: 'pipe' }).toString().split('\\n')[0]?.trim() ?? '';\n ok(`kubectl ${dim(v || '(Client OK)')}`);\n } catch {\n warn(`kubectl nicht gefunden ${dim('— Installation: https://kubernetes.io/docs/tasks/tools/')}`);\n }\n\n // 5. Cloud CLIs (optional)\n const cloudClis: Array<[string, string, string]> = [\n ['aws', 'aws --version', 'AWS CLI — https://aws.amazon.com/cli/'],\n ['gcloud', 'gcloud --version', 'Google Cloud SDK — https://cloud.google.com/sdk/'],\n ['az', 'az --version', 'Azure CLI — https://aka.ms/installazurecliwindows'],\n ];\n for (const [name, cmd, hint] of cloudClis) {\n try {\n execSync(cmd, { stdio: 'pipe' });\n ok(`${name} ${dim('(Cloud-Scanning verfügbar)')}`);\n } catch {\n warn(`${name} nicht gefunden ${dim('— Cloud-Scan übersprungen | ' + hint)}`);\n }\n }\n\n // 6. Lokale Discovery-Tools\n const localTools: Array<[string, string]> = [\n ['docker', 'docker --version'],\n ['ss', 'ss --version'],\n ];\n for (const [name, cmd] of localTools) {\n try {\n execSync(cmd, { stdio: 'pipe' });\n ok(`${name} ${dim('(Discovery-Tool)')}`);\n } catch {\n warn(`${name} nicht gefunden ${dim('— Discovery ohne ' + name + ' eingeschränkt')}`);\n }\n }\n\n // 7. SQLite data dir\n const dbDir = join(home, '.cartography');\n if (existsSync(dbDir)) {\n ok(`~/.cartography ${dim('(Daten-Verzeichnis vorhanden)')}`);\n } else {\n warn('~/.cartography existiert noch nicht ' + dim('— wird beim ersten Start angelegt'));\n }\n\n out(dim(' ─────────────────────────────────\\n'));\n if (allGood) {\n out(' \\x1b[32m\\x1b[1mAlle Checks bestanden — datasynx-cartography discover\\x1b[0m\\n\\n');\n } else {\n out(' \\x1b[31m\\x1b[1mEinige Checks fehlgeschlagen. Bitte oben beheben.\\x1b[0m\\n\\n');\n process.exitCode = 1;\n }\n });\n\n // ── Banner (immer anzeigen) ───────────────────────────────────────────────\n\n const o = (s: string) => process.stderr.write(s);\n const _b = (s: string) => `\\x1b[1m${s}\\x1b[0m`;\n const _d = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\n const _c = (s: string) => `\\x1b[36m${s}\\x1b[0m`;\n const _g = (s: string) => `\\x1b[32m${s}\\x1b[0m`;\n const _m = (s: string) => `\\x1b[35m${s}\\x1b[0m`;\n\n o('\\n');\n o(_c(' ____ _ ____ ') + '\\n');\n o(_c(' | _ \\\\ __ _| |_ __ _/ ___| _ _ _ __ __ __') + '\\n');\n o(_c(' | | | |/ _` | __/ _` \\\\___ \\\\| | | | \\'_ \\\\\\\\ \\\\/ /') + '\\n');\n o(_c(' | |_| | (_| | || (_| |___) | |_| | | | |> < ') + '\\n');\n o(_c(' |____/ \\\\__,_|\\\\__\\\\__,_|____/ \\\\__, |_| |_/_/\\\\_\\\\') + '\\n');\n o(_c(' |___/ ') + '\\n');\n o('\\n');\n o(_b(' Cartography') + ' ' + _d('v' + VERSION) + '\\n');\n o(_d(' AI-powered Infrastructure Discovery & SOP Generation\\n'));\n o(_d(' Built on Claude Agent SDK\\n'));\n o('\\n');\n\n // ── Welcome Screen (no args → Befehlsübersicht) ─────────────────────────\n\n if (process.argv.length <= 2) {\n o(_d(' ────────────────────────────────────────────────\\n'));\n o('\\n');\n o(_b(' Commands:\\n'));\n o('\\n');\n o(` ${_g('discover')} ${_d('Infrastruktur scannen (Claude Sonnet)')}\\n`);\n o(` ${_g('seed')} ${_d('Bekannte Tools/DBs/APIs manuell eintragen')}\\n`);\n o(` ${_g('bookmarks')} ${_d('Browser-Lesezeichen anzeigen')}\\n`);\n o(` ${_g('shadow start')} ${_d('Background-Daemon starten (Claude Haiku)')}\\n`);\n o(` ${_g('shadow pause')} ${_d('Daemon pausieren')}\\n`);\n o(` ${_g('shadow resume')} ${_d('Daemon fortsetzen')}\\n`);\n o(` ${_g('shadow stop')} ${_d('Stoppen + SOP-Review + Dashboard')}\\n`);\n o(` ${_g('shadow status')} ${_d('Daemon-Status anzeigen')}\\n`);\n o(` ${_g('shadow attach')} ${_d('Live-Steuerung: [T] [S] [P] [D] [Q]')}\\n`);\n o(` ${_g('sops')} ${_d('[session]')} ${_d('SOPs aus Workflows generieren')}\\n`);\n o(` ${_g('export')} ${_d('[session]')} ${_d('Mermaid, JSON, YAML, HTML exportieren')}\\n`);\n o(` ${_g('show')} ${_d('[session]')} ${_d('Session-Details anzeigen')}\\n`);\n o(` ${_g('sessions')} ${_d('Alle Sessions auflisten')}\\n`);\n o(` ${_g('doctor')} ${_d('Installations-Check (kubectl, aws, gcloud, az)')}\\n`);\n o(` ${_g('docs')} ${_d('Vollständige Dokumentation')}\\n`);\n o('\\n');\n o(_d(' ────────────────────────────────────────────────\\n'));\n o('\\n');\n o(_b(' Quick Start:\\n'));\n o('\\n');\n o(` ${_m('$')} ${_b('datasynx-cartography doctor')} ${_d('Alles bereit?')}\\n`);\n o(` ${_m('$')} ${_b('datasynx-cartography seed')} ${_d('Bekannte Infra eintragen')}\\n`);\n o(` ${_m('$')} ${_b('datasynx-cartography discover')} ${_d('Einmal-Scan')}\\n`);\n o(` ${_m('$')} ${_b('datasynx-cartography shadow start')} ${_d('Dauerhaft beobachten')}\\n`);\n o('\\n');\n o(_d(' Doku: datasynx-cartography docs\\n'));\n o(_d(' Hilfe: datasynx-cartography --help\\n'));\n o(_d(' npm: @datasynx/agentic-ai-cartography\\n'));\n o('\\n');\n return;\n }\n\n o(_d(' ────────────────────────────────────────────────\\n'));\n o('\\n');\n\n // ── Parse ──────────────────────────────────────────────────────────────────\n\n program.exitOverride((err) => {\n if (err.code === 'commander.helpDisplayed') {\n process.exitCode = 0;\n } else {\n process.exitCode = 2;\n }\n });\n\n program.parse(process.argv);\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { MIN_POLL_INTERVAL_MS } from './types.js';\n\nfunction isOAuthLoggedIn(): boolean {\n // Claude CLI speichert OAuth-Tokens in ~/.claude/.credentials.json\n const home = process.env.HOME ?? process.env.USERPROFILE ?? '/tmp';\n const credFile = join(home, '.claude', '.credentials.json');\n if (!existsSync(credFile)) return false;\n try {\n const creds = JSON.parse(readFileSync(credFile, 'utf8')) as Record<string, unknown>;\n const oauth = creds['claudeAiOauth'] as Record<string, unknown> | undefined;\n return typeof oauth?.['accessToken'] === 'string' && oauth['accessToken'].length > 0;\n } catch {\n return false;\n }\n}\n\nexport function checkPrerequisites(): void {\n // Claude CLI vorhanden?\n try {\n execSync('claude --version', { stdio: 'pipe' });\n } catch {\n process.stderr.write(\n '\\n❌ Claude CLI nicht gefunden.\\n' +\n ' Datasynx Cartography braucht die Claude CLI als Runtime-Dependency.\\n\\n' +\n ' Installieren:\\n' +\n ' npm install -g @anthropic-ai/claude-code\\n' +\n ' # oder\\n' +\n ' curl -fsSL https://claude.ai/install.sh | bash\\n\\n' +\n ' Danach: claude login\\n\\n'\n );\n process.exitCode = 1;\n throw new Error('Claude CLI not found');\n }\n\n // Auth prüfen: API Key ODER OAuth-Login (claude.ai Subscription)\n const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOAuth = isOAuthLoggedIn();\n\n if (!hasApiKey && !hasOAuth) {\n process.stderr.write(\n '⚠ Keine Authentifizierung gefunden. Bitte eine der folgenden Optionen:\\n\\n' +\n ' Option A — claude.ai Subscription (empfohlen):\\n' +\n ' claude login\\n\\n' +\n ' Option B — API Key:\\n' +\n ' export ANTHROPIC_API_KEY=sk-ant-...\\n\\n'\n );\n } else if (hasOAuth && !hasApiKey) {\n process.stderr.write('✓ Eingeloggt via claude login (Subscription)\\n');\n }\n}\n\nexport function checkPollInterval(intervalMs: number): number {\n if (intervalMs < MIN_POLL_INTERVAL_MS) {\n process.stderr.write(\n `⚠ Minimum Shadow-Intervall: ${MIN_POLL_INTERVAL_MS / 1000} Sekunden (Agent SDK Overhead)\\n`\n );\n return MIN_POLL_INTERVAL_MS;\n }\n return intervalMs;\n}\n","import Database from 'better-sqlite3';\nimport { mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type {\n CartographyConfig, DiscoveryNode, DiscoveryEdge, ActivityEvent,\n NodeRow, EdgeRow, EventRow, TaskRow, WorkflowRow, SessionRow, SOP,\n} from './types.js';\n\nconst SCHEMA = `\nPRAGMA journal_mode = WAL;\nPRAGMA foreign_keys = ON;\nPRAGMA busy_timeout = 5000;\n\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n mode TEXT NOT NULL CHECK (mode IN ('discover','shadow')),\n started_at TEXT NOT NULL,\n completed_at TEXT,\n config TEXT NOT NULL DEFAULT '{}'\n);\n\nCREATE TABLE IF NOT EXISTS nodes (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n type TEXT NOT NULL,\n name TEXT NOT NULL,\n discovered_via TEXT,\n discovered_at TEXT NOT NULL,\n path_id TEXT,\n depth INTEGER DEFAULT 0,\n confidence REAL DEFAULT 0.5,\n metadata TEXT NOT NULL DEFAULT '{}',\n tags TEXT NOT NULL DEFAULT '[]',\n PRIMARY KEY (id, session_id)\n);\n\nCREATE TABLE IF NOT EXISTS edges (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n source_id TEXT NOT NULL,\n target_id TEXT NOT NULL,\n relationship TEXT NOT NULL,\n evidence TEXT,\n confidence REAL DEFAULT 0.5,\n discovered_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS activity_events (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n task_id TEXT,\n timestamp TEXT NOT NULL,\n event_type TEXT NOT NULL,\n process TEXT NOT NULL,\n pid INTEGER NOT NULL,\n target TEXT,\n target_type TEXT,\n port INTEGER,\n duration_ms INTEGER\n);\n\nCREATE TABLE IF NOT EXISTS tasks (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n description TEXT,\n started_at TEXT NOT NULL,\n completed_at TEXT,\n steps TEXT NOT NULL DEFAULT '[]',\n involved_services TEXT NOT NULL DEFAULT '[]',\n status TEXT DEFAULT 'active' CHECK (status IN ('active','completed','cancelled')),\n is_sop_candidate INTEGER DEFAULT 0\n);\n\nCREATE TABLE IF NOT EXISTS workflows (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n name TEXT,\n pattern TEXT NOT NULL,\n task_ids TEXT NOT NULL DEFAULT '[]',\n occurrences INTEGER DEFAULT 1,\n first_seen TEXT NOT NULL,\n last_seen TEXT NOT NULL,\n avg_duration_ms INTEGER,\n involved_services TEXT NOT NULL DEFAULT '[]'\n);\n\nCREATE TABLE IF NOT EXISTS sops (\n id TEXT PRIMARY KEY,\n workflow_id TEXT NOT NULL,\n title TEXT NOT NULL,\n description TEXT NOT NULL,\n steps TEXT NOT NULL,\n involved_systems TEXT NOT NULL DEFAULT '[]',\n estimated_duration TEXT,\n frequency TEXT,\n generated_at TEXT NOT NULL,\n confidence REAL DEFAULT 0.5\n);\n\nCREATE TABLE IF NOT EXISTS node_approvals (\n pattern TEXT PRIMARY KEY,\n action TEXT NOT NULL CHECK (action IN ('save','ignore','auto')),\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_nodes_session ON nodes(session_id);\nCREATE INDEX IF NOT EXISTS idx_edges_session ON edges(session_id);\nCREATE INDEX IF NOT EXISTS idx_events_session ON activity_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_events_task ON activity_events(task_id);\nCREATE INDEX IF NOT EXISTS idx_tasks_session ON tasks(session_id);\n`;\n\nexport class CartographyDB {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n mkdirSync(dirname(dbPath), { recursive: true });\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.db.pragma('busy_timeout = 5000');\n this.migrate();\n }\n\n private migrate(): void {\n const version = (this.db.pragma('user_version', { simple: true }) as number);\n if (version === 0) {\n this.db.exec(SCHEMA);\n this.db.pragma('user_version = 1');\n }\n }\n\n close(): void {\n this.db.pragma('optimize');\n this.db.close();\n }\n\n // ── Sessions ────────────────────────────\n\n createSession(mode: 'discover' | 'shadow', config: CartographyConfig): string {\n const id = crypto.randomUUID();\n this.db.prepare(\n 'INSERT INTO sessions (id, mode, started_at, config) VALUES (?, ?, ?, ?)'\n ).run(id, mode, new Date().toISOString(), JSON.stringify(config));\n return id;\n }\n\n endSession(id: string): void {\n this.db.prepare('UPDATE sessions SET completed_at = ? WHERE id = ?')\n .run(new Date().toISOString(), id);\n }\n\n getSession(id: string): SessionRow | undefined {\n const row = this.db.prepare('SELECT * FROM sessions WHERE id = ?').get(id) as Record<string, unknown> | undefined;\n return row ? this.mapSession(row) : undefined;\n }\n\n getLatestSession(mode?: string): SessionRow | undefined {\n const row = mode\n ? this.db.prepare('SELECT * FROM sessions WHERE mode = ? ORDER BY rowid DESC LIMIT 1').get(mode) as Record<string, unknown> | undefined\n : this.db.prepare('SELECT * FROM sessions ORDER BY rowid DESC LIMIT 1').get() as Record<string, unknown> | undefined;\n return row ? this.mapSession(row) : undefined;\n }\n\n getSessions(): SessionRow[] {\n const rows = this.db.prepare('SELECT * FROM sessions ORDER BY rowid DESC').all() as Record<string, unknown>[];\n return rows.map(r => this.mapSession(r));\n }\n\n private mapSession(r: Record<string, unknown>): SessionRow {\n return {\n id: r['id'] as string,\n mode: r['mode'] as 'discover' | 'shadow',\n startedAt: r['started_at'] as string,\n completedAt: (r['completed_at'] as string | null) ?? undefined,\n config: r['config'] as string,\n };\n }\n\n // ── Nodes ───────────────────────────────\n\n upsertNode(sessionId: string, node: DiscoveryNode, depth = 0): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO nodes\n (id, session_id, type, name, discovered_via, discovered_at, depth, confidence, metadata, tags)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n node.id, sessionId, node.type, node.name, node.discoveredVia,\n new Date().toISOString(), depth, node.confidence,\n JSON.stringify(node.metadata ?? {}),\n JSON.stringify(node.tags ?? []),\n );\n }\n\n getNodes(sessionId: string): NodeRow[] {\n const rows = this.db.prepare('SELECT * FROM nodes WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n type: r['type'] as NodeRow['type'],\n name: r['name'] as string,\n discoveredVia: r['discovered_via'] as string,\n discoveredAt: r['discovered_at'] as string,\n depth: r['depth'] as number,\n confidence: r['confidence'] as number,\n metadata: JSON.parse(r['metadata'] as string) as Record<string, unknown>,\n tags: JSON.parse(r['tags'] as string) as string[],\n pathId: r['path_id'] as string | undefined,\n }));\n }\n\n deleteNode(sessionId: string, nodeId: string): void {\n this.db.prepare('DELETE FROM nodes WHERE session_id = ? AND id = ?').run(sessionId, nodeId);\n // Remove orphaned edges\n this.db.prepare(\n 'DELETE FROM edges WHERE session_id = ? AND (source_id = ? OR target_id = ?)'\n ).run(sessionId, nodeId, nodeId);\n }\n\n // ── Edges ───────────────────────────────\n\n insertEdge(sessionId: string, edge: DiscoveryEdge): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT OR IGNORE INTO edges\n (id, session_id, source_id, target_id, relationship, evidence, confidence, discovered_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, edge.sourceId, edge.targetId,\n edge.relationship, edge.evidence, edge.confidence,\n new Date().toISOString(),\n );\n }\n\n getEdges(sessionId: string): EdgeRow[] {\n const rows = this.db.prepare('SELECT * FROM edges WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n sourceId: r['source_id'] as string,\n targetId: r['target_id'] as string,\n relationship: r['relationship'] as EdgeRow['relationship'],\n evidence: r['evidence'] as string,\n confidence: r['confidence'] as number,\n discoveredAt: r['discovered_at'] as string,\n }));\n }\n\n // ── Events ──────────────────────────────\n\n insertEvent(sessionId: string, event: ActivityEvent, taskId?: string): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO activity_events\n (id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, taskId ?? null, new Date().toISOString(),\n event.eventType, event.process, event.pid,\n event.target ?? null, event.targetType ?? null, event.port ?? null,\n );\n }\n\n getEvents(sessionId: string, since?: string): EventRow[] {\n const rows = since\n ? this.db.prepare('SELECT * FROM activity_events WHERE session_id = ? AND timestamp > ? ORDER BY timestamp').all(sessionId, since) as Record<string, unknown>[]\n : this.db.prepare('SELECT * FROM activity_events WHERE session_id = ? ORDER BY timestamp').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n taskId: r['task_id'] as string | undefined,\n timestamp: r['timestamp'] as string,\n eventType: r['event_type'] as EventRow['eventType'],\n process: r['process'] as string,\n pid: r['pid'] as number,\n target: r['target'] as string | undefined,\n targetType: r['target_type'] as EventRow['targetType'],\n port: r['port'] as number | undefined,\n durationMs: r['duration_ms'] as number | undefined,\n }));\n }\n\n // ── Tasks ───────────────────────────────\n\n startTask(sessionId: string, description?: string): string {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO tasks (id, session_id, description, started_at, steps, involved_services, status)\n VALUES (?, ?, ?, ?, '[]', '[]', 'active')\n `).run(id, sessionId, description ?? null, new Date().toISOString());\n return id;\n }\n\n endCurrentTask(sessionId: string): void {\n this.db.prepare(`\n UPDATE tasks SET status = 'completed', completed_at = ?\n WHERE session_id = ? AND status = 'active'\n `).run(new Date().toISOString(), sessionId);\n }\n\n updateTaskDescription(sessionId: string, description: string): void {\n this.db.prepare(`\n UPDATE tasks SET description = ?\n WHERE session_id = ? AND status = 'active'\n `).run(description, sessionId);\n }\n\n getActiveTask(sessionId: string): TaskRow | undefined {\n const row = this.db.prepare(\n \"SELECT * FROM tasks WHERE session_id = ? AND status = 'active' LIMIT 1\"\n ).get(sessionId) as Record<string, unknown> | undefined;\n return row ? this.mapTask(row) : undefined;\n }\n\n getTasks(sessionId: string): TaskRow[] {\n const rows = this.db.prepare('SELECT * FROM tasks WHERE session_id = ? ORDER BY started_at').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => this.mapTask(r));\n }\n\n private mapTask(r: Record<string, unknown>): TaskRow {\n return {\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n description: r['description'] as string | undefined,\n startedAt: r['started_at'] as string,\n completedAt: r['completed_at'] as string | undefined,\n steps: r['steps'] as string,\n involvedServices: r['involved_services'] as string,\n status: r['status'] as TaskRow['status'],\n isSOPCandidate: Boolean(r['is_sop_candidate']),\n };\n }\n\n // ── Workflows ───────────────────────────\n\n insertWorkflow(sessionId: string, data: Omit<WorkflowRow, 'id'>): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO workflows\n (id, session_id, name, pattern, task_ids, occurrences,\n first_seen, last_seen, avg_duration_ms, involved_services)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, data.name ?? null, data.pattern,\n data.taskIds, data.occurrences,\n data.firstSeen, data.lastSeen, data.avgDurationMs,\n data.involvedServices,\n );\n }\n\n getWorkflows(sessionId: string): WorkflowRow[] {\n const rows = this.db.prepare('SELECT * FROM workflows WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n name: r['name'] as string | undefined,\n pattern: r['pattern'] as string,\n taskIds: r['task_ids'] as string,\n occurrences: r['occurrences'] as number,\n firstSeen: r['first_seen'] as string,\n lastSeen: r['last_seen'] as string,\n avgDurationMs: r['avg_duration_ms'] as number,\n involvedServices: r['involved_services'] as string,\n }));\n }\n\n // ── SOPs ────────────────────────────────\n\n insertSOP(sop: { workflowId: string } & SOP): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO sops\n (id, workflow_id, title, description, steps, involved_systems,\n estimated_duration, frequency, generated_at, confidence)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sop.workflowId, sop.title, sop.description,\n JSON.stringify(sop.steps),\n JSON.stringify(sop.involvedSystems),\n sop.estimatedDuration, sop.frequency,\n new Date().toISOString(), sop.confidence,\n );\n }\n\n getSOPs(sessionId: string): Array<SOP & { id: string; workflowId: string }> {\n const rows = this.db.prepare(`\n SELECT s.* FROM sops s\n JOIN workflows w ON s.workflow_id = w.id\n WHERE w.session_id = ?\n `).all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n workflowId: r['workflow_id'] as string,\n title: r['title'] as string,\n description: r['description'] as string,\n steps: JSON.parse(r['steps'] as string) as SOP['steps'],\n involvedSystems: JSON.parse(r['involved_systems'] as string) as string[],\n estimatedDuration: r['estimated_duration'] as string,\n frequency: r['frequency'] as string,\n confidence: r['confidence'] as number,\n }));\n }\n\n markTaskAsSOPCandidate(taskId: string): void {\n this.db.prepare('UPDATE tasks SET is_sop_candidate = 1 WHERE id = ?').run(taskId);\n }\n\n getAllSOPs(): Array<SOP & { id: string; workflowId: string; generatedAt: string }> {\n const rows = this.db.prepare('SELECT * FROM sops ORDER BY generated_at DESC').all() as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n workflowId: r['workflow_id'] as string,\n title: r['title'] as string,\n description: r['description'] as string,\n steps: JSON.parse(r['steps'] as string) as SOP['steps'],\n involvedSystems: JSON.parse(r['involved_systems'] as string) as string[],\n estimatedDuration: r['estimated_duration'] as string,\n frequency: r['frequency'] as string,\n confidence: r['confidence'] as number,\n generatedAt: r['generated_at'] as string,\n }));\n }\n\n // ── Approvals ───────────────────────────\n\n setApproval(pattern: string, action: 'save' | 'ignore' | 'auto'): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO node_approvals (pattern, action, created_at) VALUES (?, ?, ?)\n `).run(pattern, action, new Date().toISOString());\n }\n\n getApproval(pattern: string): string | undefined {\n const row = this.db.prepare('SELECT action FROM node_approvals WHERE pattern = ?').get(pattern) as { action: string } | undefined;\n return row?.action;\n }\n\n // ── Stats ───────────────────────────────\n\n getStats(sessionId: string): { nodes: number; edges: number; events: number; tasks: number } {\n const nodes = (this.db.prepare('SELECT COUNT(*) as c FROM nodes WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const edges = (this.db.prepare('SELECT COUNT(*) as c FROM edges WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const events = (this.db.prepare('SELECT COUNT(*) as c FROM activity_events WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const tasks = (this.db.prepare('SELECT COUNT(*) as c FROM tasks WHERE session_id = ?').get(sessionId) as { c: number }).c;\n return { nodes, edges, events, tasks };\n }\n}\n","import { z } from 'zod';\nimport type { CartographyDB } from './db.js';\nimport { NODE_TYPES, EDGE_RELATIONSHIPS, EVENT_TYPES, SOPStepSchema } from './types.js';\nimport { scanAllBookmarks } from './bookmarks.js';\n\n// Lazy import to avoid hard-wiring SDK at module parse time\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype McpServer = any;\n\nexport interface CartographyToolsOptions {\n /** Called when the agent needs a human answer. Return the user's response. */\n onAskUser?: (question: string, context?: string) => Promise<string>;\n}\n\nexport function stripSensitive(target: string): string {\n try {\n const url = new URL(target.startsWith('http') ? target : `tcp://${target}`);\n return `${url.hostname}${url.port ? ':' + url.port : ''}`;\n } catch {\n return target\n .replace(/\\/.*$/, '')\n .replace(/\\?.*$/, '')\n .replace(/@.*:/, ':');\n }\n}\n\nexport async function createCartographyTools(\n db: CartographyDB,\n sessionId: string,\n opts: CartographyToolsOptions = {},\n): Promise<McpServer> {\n // Dynamically import the SDK so missing package doesn't crash at load time\n const sdk = await import('@anthropic-ai/claude-code');\n const { tool, createSdkMcpServer } = sdk as {\n tool: (name: string, description: string, schema: z.ZodRawShape, handler: (args: Record<string, unknown>) => Promise<{ content: Array<{ type: string; text: string }> }>) => unknown;\n createSdkMcpServer: (opts: { name: string; version: string; tools: unknown[] }) => McpServer;\n };\n\n const tools = [\n tool('save_node', 'Infrastructure-Node speichern', {\n id: z.string(),\n type: z.enum(NODE_TYPES),\n name: z.string(),\n discoveredVia: z.string(),\n confidence: z.number().min(0).max(1),\n metadata: z.record(z.unknown()).optional(),\n tags: z.array(z.string()).optional(),\n }, async (args) => {\n const node = {\n id: stripSensitive(args['id'] as string),\n type: args['type'] as typeof NODE_TYPES[number],\n name: args['name'] as string,\n discoveredVia: args['discoveredVia'] as string,\n confidence: args['confidence'] as number,\n metadata: (args['metadata'] as Record<string, unknown>) ?? {},\n tags: (args['tags'] as string[]) ?? [],\n };\n db.upsertNode(sessionId, node);\n return { content: [{ type: 'text', text: `✓ Node: ${node.id}` }] };\n }),\n\n tool('save_edge', 'Verbindung zwischen zwei Nodes speichern', {\n sourceId: z.string(),\n targetId: z.string(),\n relationship: z.enum(EDGE_RELATIONSHIPS),\n evidence: z.string(),\n confidence: z.number().min(0).max(1),\n }, async (args) => {\n db.insertEdge(sessionId, {\n sourceId: args['sourceId'] as string,\n targetId: args['targetId'] as string,\n relationship: args['relationship'] as typeof EDGE_RELATIONSHIPS[number],\n evidence: args['evidence'] as string,\n confidence: args['confidence'] as number,\n });\n return { content: [{ type: 'text', text: `✓ ${args['sourceId']}→${args['targetId']}` }] };\n }),\n\n tool('save_event', 'Activity-Event (Prozess/Verbindung) speichern', {\n eventType: z.enum(EVENT_TYPES),\n process: z.string(),\n pid: z.number(),\n target: z.string().optional(),\n targetType: z.enum(NODE_TYPES).optional(),\n port: z.number().optional(),\n }, async (args) => {\n db.insertEvent(sessionId, {\n eventType: args['eventType'] as typeof EVENT_TYPES[number],\n process: args['process'] as string,\n pid: args['pid'] as number,\n target: args['target'] ? stripSensitive(args['target'] as string) : undefined,\n targetType: args['targetType'] as typeof NODE_TYPES[number] | undefined,\n port: args['port'] as number | undefined,\n });\n return { content: [{ type: 'text', text: `✓ ${args['eventType']}` }] };\n }),\n\n tool('get_catalog', 'Aktuellen Katalog abrufen (Duplikat-Check)', {\n includeEdges: z.boolean().default(true),\n }, async (args) => {\n const nodes = db.getNodes(sessionId);\n const edges = (args['includeEdges'] as boolean) ? db.getEdges(sessionId) : [];\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n count: { nodes: nodes.length, edges: edges.length },\n nodeIds: nodes.map(n => n.id),\n }),\n }],\n };\n }),\n\n tool('manage_task', 'Task starten, beenden oder beschreiben', {\n action: z.enum(['start', 'end', 'describe']),\n description: z.string().optional(),\n }, async (args) => {\n const action = args['action'] as string;\n if (action === 'start') {\n const id = db.startTask(sessionId, args['description'] as string | undefined);\n return { content: [{ type: 'text', text: `✓ Task gestartet: ${id}` }] };\n }\n if (action === 'end') {\n db.endCurrentTask(sessionId);\n return { content: [{ type: 'text', text: '✓ Task beendet' }] };\n }\n db.updateTaskDescription(sessionId, args['description'] as string);\n return { content: [{ type: 'text', text: '✓ Beschreibung aktualisiert' }] };\n }),\n\n tool('ask_user', 'Rückfrage an den User stellen — bei Unklarheiten, fehlenden Credentials-Hinweisen oder wenn Kontext fehlt', {\n question: z.string().describe('Die Frage an den User (klar und konkret)'),\n context: z.string().optional().describe('Optionaler Zusatzkontext warum die Frage relevant ist'),\n }, async (args) => {\n const question = args['question'] as string;\n const context = args['context'] as string | undefined;\n\n if (opts.onAskUser) {\n const answer = await opts.onAskUser(question, context);\n return { content: [{ type: 'text', text: answer }] };\n }\n\n // Fallback when not interactive (piped input, daemon, etc.)\n return {\n content: [{ type: 'text', text: '(Kein interaktiver Modus — bitte ohne diese Information fortfahren)' }],\n };\n }),\n\n tool('scan_bookmarks', 'Alle Browser-Lesezeichen scannen — nur Hostnamen, keine persönlichen Daten', {\n minConfidence: z.number().min(0).max(1).default(0.5).optional(),\n }, async () => {\n const hosts = await scanAllBookmarks();\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n count: hosts.length,\n hosts: hosts.map(h => ({\n hostname: h.hostname,\n port: h.port,\n protocol: h.protocol,\n source: h.source,\n })),\n note: 'Nur Hostnamen — keine Pfade, keine persönlichen Daten. Entscheide selbst welche davon Business-Tools sind.',\n }),\n }],\n };\n }),\n\n tool('scan_k8s_resources', 'Kubernetes-Cluster via kubectl scannen — 100% readonly (get, describe)', {\n namespace: z.string().optional().describe('Namespace filtern — leer = alle Namespaces'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const ns = args['namespace'] as string | undefined;\n const nsFlag = ns ? `-n ${ns}` : '--all-namespaces';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 15_000, shell: '/bin/sh' }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['CONTEXT', 'kubectl config current-context 2>/dev/null || echo \"(kein Context gesetzt)\"'],\n ['NODES', 'kubectl get nodes -o wide'],\n ['NAMESPACES', 'kubectl get namespaces'],\n ['SERVICES', `kubectl get services ${nsFlag}`],\n ['DEPLOYMENTS', `kubectl get deployments ${nsFlag}`],\n ['STATEFULSETS', `kubectl get statefulsets ${nsFlag}`],\n ['INGRESSES', `kubectl get ingress ${nsFlag} 2>/dev/null || echo \"(keine)\"`],\n ['PODS_RUNNING', `kubectl get pods ${nsFlag} --field-selector=status.phase=Running 2>/dev/null | head -60`],\n ['CONFIGMAPS_SYSTEM', 'kubectl get configmaps -n kube-system 2>/dev/null | head -30'],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_aws_resources', 'AWS-Infrastruktur via AWS CLI scannen — 100% readonly (describe, list)', {\n region: z.string().optional().describe('AWS Region — default: AWS_DEFAULT_REGION oder Profil'),\n profile: z.string().optional().describe('AWS CLI Profil'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const region = args['region'] as string | undefined;\n const profile = args['profile'] as string | undefined;\n const env: NodeJS.ProcessEnv = { ...process.env };\n if (region) env['AWS_DEFAULT_REGION'] = region;\n const pf = profile ? `--profile ${profile}` : '';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 20_000, shell: '/bin/sh', env }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['IDENTITY', `aws sts get-caller-identity ${pf} --output json`],\n ['EC2', `aws ec2 describe-instances ${pf} --query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,PublicIpAddress,PrivateIpAddress,Tags[?Key==\\`Name\\`].Value|[0]]' --output table`],\n ['RDS', `aws rds describe-db-instances ${pf} --query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBInstanceStatus,Endpoint.Address,Endpoint.Port]' --output table`],\n ['ELB_V2', `aws elbv2 describe-load-balancers ${pf} --query 'LoadBalancers[*].[LoadBalancerName,DNSName,Type,State.Code]' --output table`],\n ['EKS', `aws eks list-clusters ${pf} --output json`],\n ['ELASTICACHE', `aws elasticache describe-cache-clusters ${pf} --query 'CacheClusters[*].[CacheClusterId,Engine,CacheClusterStatus]' --output table 2>/dev/null || echo \"(nicht verfügbar)\"`],\n ['S3', `aws s3 ls ${pf} 2>/dev/null || echo \"(nicht verfügbar)\"`],\n ['VPC', `aws ec2 describe-vpcs ${pf} --query 'Vpcs[*].[VpcId,CidrBlock,IsDefault,Tags[?Key==\\`Name\\`].Value|[0]]' --output table`],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_gcp_resources', 'Google Cloud Platform via gcloud CLI scannen — 100% readonly (list, describe)', {\n project: z.string().optional().describe('GCP Project ID — default: aktuelles gcloud-Projekt'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const project = args['project'] as string | undefined;\n const pf = project ? `--project ${project}` : '';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 20_000, shell: '/bin/sh' }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['IDENTITY', `gcloud config list account --format='value(core.account)' 2>/dev/null; gcloud config get-value project 2>/dev/null`],\n ['COMPUTE_INSTANCES', `gcloud compute instances list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['SQL_INSTANCES', `gcloud sql instances list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['GKE_CLUSTERS', `gcloud container clusters list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['CLOUD_RUN', `gcloud run services list ${pf} --platform managed 2>/dev/null || echo \"(error)\"`],\n ['CLOUD_FUNCTIONS', `gcloud functions list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['REDIS', `gcloud redis instances list ${pf} --regions=- 2>/dev/null || echo \"(error)\"`],\n ['PUBSUB', `gcloud pubsub topics list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['SPANNER', `gcloud spanner instances list ${pf} 2>/dev/null || echo \"(error)\"`],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_azure_resources', 'Azure-Infrastruktur via az CLI scannen — 100% readonly (list, show)', {\n subscription: z.string().optional().describe('Azure Subscription ID'),\n resourceGroup: z.string().optional().describe('Resource Group filtern'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const sub = args['subscription'] as string | undefined;\n const rg = args['resourceGroup'] as string | undefined;\n const sf = sub ? `--subscription ${sub}` : '';\n const rf = rg ? `--resource-group ${rg}` : '';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 20_000, shell: '/bin/sh' }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['IDENTITY', `az account show --output json ${sf} 2>/dev/null || echo \"(nicht eingeloggt — az login)\"`],\n ['VMS', `az vm list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['AKS', `az aks list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['SQL_SERVERS', `az sql server list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['POSTGRES', `az postgres server list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['REDIS', `az redis list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['WEBAPPS', `az webapp list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['CONTAINER_APPS', `az containerapp list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['FUNCTIONS', `az functionapp list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_installed_apps', 'Alle installierten Apps und Tools auf dem PC scannen — IDEs, Office, Dev-Tools, Business-Apps', {\n searchHint: z.string().optional().describe('Optionaler Suchbegriff um gezielt nach bestimmten Tools zu suchen (z.B. \"hubspot windsurf cursor\")'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const hint = args['searchHint'] as string | undefined;\n\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 15_000, shell: '/bin/sh' }).toString().trim();\n } catch {\n return '';\n }\n };\n\n const platform = process.platform;\n const results: Record<string, string> = {};\n\n if (platform === 'darwin') {\n // macOS: scan /Applications\n results['APPLICATIONS'] = run('ls /Applications/ 2>/dev/null | head -200') || '(leer)';\n results['USER_APPLICATIONS'] = run('ls ~/Applications/ 2>/dev/null | head -100') || '(leer)';\n // Homebrew\n results['BREW_CASKS'] = run('brew list --cask 2>/dev/null | head -100') || '(brew nicht installiert)';\n results['BREW_FORMULAE'] = run('brew list --formula 2>/dev/null | head -150') || '(brew nicht installiert)';\n // Spotlight — find .app bundles\n results['SPOTLIGHT_APPS'] = run('mdfind \"kMDItemKind == \\'Application\\'\" 2>/dev/null | grep -v \"^/System\" | grep -v \"^/Library/Apple\" | head -100') || '(Spotlight nicht verfügbar)';\n } else if (platform === 'linux') {\n // Linux: dpkg, snap, flatpak, .desktop files\n results['DPKG'] = run('dpkg --list 2>/dev/null | awk \\'{print $2}\\' | head -200') || '(dpkg nicht verfügbar)';\n results['SNAP'] = run('snap list 2>/dev/null | head -50') || '(snap nicht verfügbar)';\n results['FLATPAK'] = run('flatpak list 2>/dev/null | head -50') || '(flatpak nicht verfügbar)';\n results['DESKTOP_FILES'] = run('ls /usr/share/applications/*.desktop ~/.local/share/applications/*.desktop 2>/dev/null | xargs -I{} basename {} .desktop 2>/dev/null | head -100') || '(keine .desktop files)';\n results['RPM'] = run('rpm -qa 2>/dev/null | head -200') || '(rpm nicht verfügbar)';\n } else if (platform === 'win32') {\n results['WINGET'] = run('winget list 2>/dev/null | head -100') || '(winget nicht verfügbar)';\n results['PROGRAMS_x64'] = run('reg query \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\" /s /v DisplayName 2>/dev/null | findstr DisplayName | head -100') || '(nicht verfügbar)';\n }\n\n // Check known dev/business tools via `which`\n const knownTools = [\n // IDEs & Editors\n 'code', 'code-insiders', 'cursor', 'windsurf', 'zed', 'vim', 'nvim', 'emacs', 'nano', 'sublime_text', 'atom',\n 'idea', 'webstorm', 'pycharm', 'goland', 'datagrip', 'clion', 'rider', 'phpstorm', 'rubymine', 'appcode',\n // Dev Tools\n 'git', 'gh', 'docker', 'docker-compose', 'podman', 'kubectl', 'helm', 'terraform', 'ansible',\n 'node', 'npm', 'npx', 'yarn', 'pnpm', 'bun', 'deno',\n 'python', 'python3', 'pip', 'pip3', 'pipenv', 'poetry', 'conda',\n 'ruby', 'gem', 'bundler', 'rails',\n 'java', 'mvn', 'gradle', 'kotlin',\n 'go', 'cargo', 'rustc',\n 'php', 'composer',\n 'dotnet', 'dotnet-sdk',\n // Databases\n 'psql', 'mysql', 'mysqladmin', 'mongo', 'mongosh', 'redis-cli', 'sqlite3', 'clickhouse-client',\n // Cloud CLIs\n 'aws', 'gcloud', 'az', 'heroku', 'fly', 'vercel', 'netlify', 'wrangler',\n // Infra\n 'vagrant', 'packer', 'consul', 'vault', 'nomad',\n // Communication / SaaS\n 'slack', 'discord', 'zoom', 'teams', 'skype', 'telegram', 'signal',\n // Browsers\n 'google-chrome', 'chromium', 'firefox', 'safari', 'brave', 'opera', 'edge',\n // Monitoring / Analytics\n 'datadog-agent', 'newrelic-agent', 'prometheus', 'grafana-cli',\n // Other tools\n 'ngrok', 'stripe', 'supabase', 'neon',\n ];\n\n const found: string[] = [];\n const notFound: string[] = [];\n for (const t of knownTools) {\n const r = run(`which ${t} 2>/dev/null`);\n if (r) found.push(`${t}: ${r}`);\n else notFound.push(t);\n }\n results['WHICH_FOUND'] = found.join('\\n') || '(nichts gefunden)';\n results['WHICH_NOT_FOUND'] = notFound.join(', ');\n\n // Hint-based search: if user asks for specific tools, do targeted search\n if (hint) {\n const terms = hint.split(/[\\s,]+/).filter(Boolean);\n const hintResults: string[] = [];\n for (const term of terms) {\n const safe = term.replace(/[^a-zA-Z0-9._-]/g, '');\n if (!safe) continue;\n const r = run(`which ${safe} 2>/dev/null || find /Applications ~/Applications /usr/bin /usr/local/bin /opt/homebrew/bin ~/.local/bin 2>/dev/null -iname \"*${safe}*\" -maxdepth 3 2>/dev/null | head -5`);\n if (r) hintResults.push(`${term}: ${r}`);\n else hintResults.push(`${term}: (nicht gefunden)`);\n }\n results['HINT_SEARCH'] = hintResults.join('\\n');\n }\n\n const out = Object.entries(results)\n .map(([k, v]) => `=== ${k} ===\\n${v}`)\n .join('\\n\\n');\n\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('save_sop', 'Standard Operating Procedure speichern', {\n workflowId: z.string(),\n title: z.string(),\n description: z.string(),\n steps: z.array(SOPStepSchema),\n involvedSystems: z.array(z.string()),\n estimatedDuration: z.string(),\n frequency: z.string(),\n confidence: z.number().min(0).max(1),\n }, async (args) => {\n db.insertSOP({\n workflowId: args['workflowId'] as string,\n title: args['title'] as string,\n description: args['description'] as string,\n steps: args['steps'] as ReturnType<typeof SOPStepSchema.parse>[],\n involvedSystems: args['involvedSystems'] as string[],\n estimatedDuration: args['estimatedDuration'] as string,\n frequency: args['frequency'] as string,\n confidence: args['confidence'] as number,\n });\n return { content: [{ type: 'text', text: `✓ SOP: ${args['title']}` }] };\n }),\n ];\n\n return createSdkMcpServer({\n name: 'cartography',\n version: '0.1.0',\n tools,\n });\n}\n","// PreToolUse Safety Hook — enforces read-only policy on all Bash calls\n\nimport type { HookCallback } from '@anthropic-ai/claude-code';\n\n// Word-boundary matched dangerous commands\nconst BLOCKED_CMDS =\n /\\b(rm|mv|cp|dd|mkfs|chmod|chown|chgrp|kill|killall|pkill|reboot|shutdown|poweroff|halt|systemctl\\s+(start|stop|restart|enable|disable)|service\\s+(start|stop|restart)|docker\\s+(rm|rmi|stop|kill|exec|run|build|push)|kubectl\\s+(delete|apply|edit|exec|run|create|patch)|apt|yum|dnf|pacman|pip\\s+install|npm\\s+(install|uninstall)|curl\\s+.*-X\\s*(POST|PUT|DELETE|PATCH)|wget\\s+-O|tee\\s)\\b/i;\n// Redirect operators (no word boundary needed)\nconst BLOCKED_REDIRECTS = />>|>[^>]/;\n\nexport type { HookCallback };\n\nexport const safetyHook: HookCallback = async (input) => {\n // Only intercept PreToolUse events (other hook events don't have tool_name)\n if (!('tool_name' in input)) return {};\n if ((input as { tool_name: string }).tool_name !== 'Bash') return {};\n\n const cmd = ((input as { tool_input: { command?: string } }).tool_input)?.command ?? '';\n\n if (BLOCKED_CMDS.test(cmd) || BLOCKED_REDIRECTS.test(cmd)) {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: `BLOCKED: \"${cmd}\" — read-only policy`,\n },\n };\n }\n\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n },\n };\n};\n","import type { CartographyDB } from './db.js';\nimport { createCartographyTools } from './tools.js';\nimport { safetyHook } from './safety.js';\nimport type { CartographyConfig, TaskRow } from './types.js';\n\n// ── Discovery Event Types ────────────────────────────────────────────────────\n\nexport type DiscoveryEvent =\n | { kind: 'thinking'; text: string }\n | { kind: 'tool_call'; tool: string; input: Record<string, unknown> }\n | { kind: 'tool_result'; tool: string; output: string }\n | { kind: 'turn'; turn: number }\n | { kind: 'done' };\n\nexport type AskUserFn = (question: string, context?: string) => Promise<string>;\n\n// ── runDiscovery ─────────────────────────────────────────────────────────────\n\nexport async function runDiscovery(\n config: CartographyConfig,\n db: CartographyDB,\n sessionId: string,\n onEvent?: (event: DiscoveryEvent) => void,\n onAskUser?: AskUserFn,\n hint?: string,\n): Promise<void> {\n const { query } = await import('@anthropic-ai/claude-code');\n const tools = await createCartographyTools(db, sessionId, { onAskUser });\n\n const hintSection = hint\n ? `\\n⚡ USER-HINT (PRIORITÄT): Der User möchte gezielt nach folgenden Tools suchen: \"${hint}\"\\n → scan_installed_apps(searchHint: \"${hint}\") SOFORT ausführen und diese Tools als saas_tool oder config_file speichern!\\n`\n : '';\n\n const systemPrompt = `Du bist ein Infrastruktur-Discovery-Agent. Kartographiere die gesamte Systemlandschaft — lokale Services, SaaS-Tools UND alle installierten Apps/Tools des Users.\n${hintSection}\n━━ PFLICHT-REIHENFOLGE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nSCHRITT 1 — Browser-Lesezeichen (IMMER ZUERST):\n scan_bookmarks() aufrufen → jede zurückgegebene Domain klassifizieren:\n • Business-Tools (GitHub, Notion, Jira, Linear, Vercel, AWS, Datadog, etc.) → save_node als saas_tool\n • Interne Hosts (IPs, custom.company.com:PORT) → save_node als web_service\n • Persönliches (Social Media, News, Streaming, Shopping) → IGNORIEREN, NICHT speichern\n\nSCHRITT 2 — Installierte Apps & Tools (SEHR WICHTIG):\n scan_installed_apps() aufrufen → ALLE gefundenen Apps/Tools klassifizieren:\n • IDEs (VS Code, Cursor, Windsurf, JetBrains, etc.) → save_node als saas_tool mit category=\"ide\"\n • Office & Produktivität (Word, Excel, Notion, Obsidian, etc.) → save_node als saas_tool mit category=\"productivity\"\n • Dev-Tools (Docker, kubectl, git, Node, Python, etc.) → save_node als saas_tool mit category=\"dev-tool\"\n • Business-Apps (Slack, Zoom, HubSpot, Salesforce, etc.) → save_node als saas_tool mit category=\"business\"\n • Browser (Chrome, Firefox, Safari, etc.) → save_node als saas_tool mit category=\"browser\"\n • Design-Tools (Figma, Sketch, Adobe, etc.) → save_node als saas_tool mit category=\"design\"\n ALLE relevanten Tools speichern — auch wenn offline/lokal!\n\nSCHRITT 3 — Lokale Infrastruktur:\n ss -tlnp && ps aux → alle lauschenden Ports/Prozesse identifizieren\n Jeden Service vertiefen: DB→Schemas, API→Endpoints, Queue→Topics\n\nSCHRITT 4 — Cloud & Kubernetes (falls CLI vorhanden):\n scan_k8s_resources() → Nodes, Services, Pods, Deployments, Ingresses\n scan_aws_resources() → EC2, RDS, ELB, EKS, ElastiCache, S3 (falls AWS CLI + Credentials)\n scan_gcp_resources() → Compute, SQL, GKE, Cloud Run, Functions (falls gcloud + Auth)\n scan_azure_resources() → VMs, AKS, SQL, Redis, WebApps (falls az CLI + Login)\n Fehler / \"nicht verfügbar\" → ignorieren, weiter mit nächstem Tool\n\nSCHRITT 5 — Config-Files:\n .env, docker-compose.yml, application.yml, kubernetes/*.yml\n Nur Host:Port extrahieren — KEINE Credentials\n\nSCHRITT 6 — Rückfragen bei Unklarheit:\n ask_user() nutzen wenn: Dienst unklar ist, Kontext fehlt, oder User Input sinnvoll wäre\n Beispiele: \"Welche Umgebung ist das (dev/staging/prod)?\", \"Ist <host> ein internes Tool?\"\n\nSCHRITT 7 — Fertig wenn alle Spuren erschöpft.\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nPORT-MAPPING: 5432=postgres, 3306=mysql, 27017=mongodb, 6379=redis,\n9092=kafka, 5672=rabbitmq, 80/443/8080/3000=web_service,\n9090=prometheus, 8500=consul, 8200=vault, 2379=etcd\n\nREGELN:\n• Nur read-only (ss, ps, cat, head, curl -s, docker inspect, kubectl get)\n• Node IDs: \"type:host:port\" oder \"type:name\" — keine Pfade, keine Credentials\n• saas_tool IDs: \"saas_tool:github.com\", \"saas_tool:vscode\", \"saas_tool:cursor\"\n• Installed-App IDs: \"saas_tool:<appname>\" z.B. \"saas_tool:slack\", \"saas_tool:docker-desktop\"\n• Confidence: 0.9 direkt gesehen, 0.7 aus Config/Bookmarks/Apps, 0.5 Vermutung\n• metadata erlaubt: { description, category, port, version, path } — keine Passwörter\n• get_catalog vor save_node → Duplikate vermeiden\n• Edges speichern wenn Verbindungen klar erkennbar sind\n\nEntrypoints: ${config.entryPoints.join(', ')}`;\n\n const initialPrompt = hint\n ? `Starte Discovery mit USER-HINT: \"${hint}\".\nFühre SOFORT scan_installed_apps(searchHint: \"${hint}\") aus um nach diesen Tools zu suchen.\nDann scan_bookmarks, dann lokale Services.\nNutze ask_user wenn du Kontext vom User brauchst.`\n : `Starte Discovery jetzt.\nFühre SOFORT als erstes scan_bookmarks aus — noch bevor du ss oder ps verwendest.\nDanach scan_installed_apps() für alle installierten Apps und Tools.\nDann systematisch lokale Services, dann Config-Files.\nNutze ask_user wenn du Kontext vom User brauchst.`;\n\n let turnCount = 0;\n\n for await (const msg of query({\n prompt: initialPrompt,\n options: {\n model: config.agentModel,\n maxTurns: config.maxTurns,\n customSystemPrompt: systemPrompt,\n mcpServers: { cartography: tools },\n allowedTools: [\n 'Bash',\n 'mcp__cartograph__save_node',\n 'mcp__cartograph__save_edge',\n 'mcp__cartograph__get_catalog',\n 'mcp__cartograph__scan_bookmarks',\n 'mcp__cartograph__scan_installed_apps',\n 'mcp__cartograph__scan_k8s_resources',\n 'mcp__cartograph__scan_aws_resources',\n 'mcp__cartograph__scan_gcp_resources',\n 'mcp__cartograph__scan_azure_resources',\n 'mcp__cartograph__ask_user',\n ],\n hooks: {\n PreToolUse: [{ matcher: 'Bash', hooks: [safetyHook] }],\n },\n permissionMode: 'bypassPermissions',\n },\n })) {\n if (!onEvent) continue;\n\n if (msg.type === 'assistant') {\n turnCount++;\n onEvent({ kind: 'turn', turn: turnCount });\n\n for (const block of msg.message.content) {\n if (block.type === 'text') {\n onEvent({ kind: 'thinking', text: block.text });\n }\n if (block.type === 'tool_use') {\n onEvent({\n kind: 'tool_call',\n tool: block.name as string,\n input: block.input as Record<string, unknown>,\n });\n }\n }\n }\n\n if (msg.type === 'user') {\n const content = msg.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block && (block as { type: string }).type === 'tool_result') {\n const tb = block as { tool_use_id?: string; content?: unknown };\n const text = typeof tb.content === 'string' ? tb.content : '';\n onEvent({ kind: 'tool_result', tool: tb.tool_use_id ?? '', output: text });\n }\n }\n }\n }\n\n if (msg.type === 'result') {\n onEvent({ kind: 'done' });\n return;\n }\n }\n}\n\n// ── runShadowCycle ───────────────────────────────────────────────────────────\n\nexport async function runShadowCycle(\n config: CartographyConfig,\n db: CartographyDB,\n sessionId: string,\n prevSnapshot: string,\n currSnapshot: string,\n onOutput?: (msg: unknown) => void,\n): Promise<void> {\n const { query } = await import('@anthropic-ai/claude-code');\n const tools = await createCartographyTools(db, sessionId);\n\n const prompt = `Analysiere den Diff zwischen diesen beiden System-Snapshots.\nFinde:\n- Neue/geschlossene TCP-Verbindungen → save_event\n- Neue/beendete Prozesse → save_event\n- Bisher unbekannte Services → get_catalog prüfen, dann save_node\n- Task-Grenzen (Inaktivität, Tool-Wechsel) → manage_task\ntarget = NUR Host:Port. Kurz und effizient.\n\n=== VORHER ===\n${prevSnapshot}\n\n=== JETZT ===\n${currSnapshot}`;\n\n for await (const msg of query({\n prompt,\n options: {\n model: config.shadowModel,\n maxTurns: 5,\n mcpServers: { cartography: tools },\n allowedTools: [\n 'mcp__cartograph__save_event',\n 'mcp__cartograph__save_node',\n 'mcp__cartograph__save_edge',\n 'mcp__cartograph__get_catalog',\n 'mcp__cartograph__manage_task',\n ],\n permissionMode: 'bypassPermissions',\n },\n })) {\n if (onOutput) onOutput(msg);\n }\n}\n\n// ── generateSOPs ─────────────────────────────────────────────────────────────\n\nexport async function generateSOPs(db: CartographyDB, sessionId: string): Promise<number> {\n const Anthropic = (await import('@anthropic-ai/sdk')).default;\n const client = new Anthropic();\n\n const tasks = db.getTasks(sessionId).filter(t => t.status === 'completed');\n if (tasks.length === 0) return 0;\n\n // Cluster tasks by involved services\n const clusters = clusterTasks(tasks);\n let generated = 0;\n\n for (const cluster of clusters) {\n const workflowId = crypto.randomUUID();\n const involved = JSON.parse(cluster[0]?.involvedServices ?? '[]') as string[];\n\n const taskDescriptions = cluster\n .map((t, i) => `Task ${i + 1}: ${t.description ?? 'Unnamed'}\\nSteps: ${t.steps}`)\n .join('\\n\\n');\n\n const response = await client.messages.create({\n model: 'claude-sonnet-4-5-20250929',\n max_tokens: 2048,\n messages: [{\n role: 'user',\n content: `Generiere eine SOP (Standard Operating Procedure) für diesen wiederkehrenden Workflow.\nAntworte NUR mit validen JSON im Format:\n{\n \"title\": \"...\",\n \"description\": \"...\",\n \"steps\": [{\"order\": 1, \"instruction\": \"...\", \"tool\": \"...\", \"target\": \"...\", \"notes\": \"...\"}],\n \"involvedSystems\": [\"...\"],\n \"estimatedDuration\": \"~N Minuten\",\n \"frequency\": \"Xmal täglich\",\n \"confidence\": 0.8\n}\n\nTasks:\n${taskDescriptions}\n\nBeteiligte Services: ${involved.join(', ')}`,\n }],\n });\n\n const text = response.content[0]?.type === 'text' ? response.content[0].text : '';\n\n try {\n const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) continue;\n const parsed = JSON.parse(jsonMatch[0]) as {\n title: string;\n description: string;\n steps: Array<{ order: number; instruction: string; tool: string; target?: string; notes?: string }>;\n involvedSystems: string[];\n estimatedDuration: string;\n frequency: string;\n confidence: number;\n };\n\n db.insertSOP({ workflowId, ...parsed });\n generated++;\n } catch {\n // Skip malformed responses\n }\n }\n\n return generated;\n}\n\nfunction clusterTasks(tasks: TaskRow[]): TaskRow[][] {\n // Simple clustering: group by overlapping involved services\n const clusters: TaskRow[][] = [];\n const assigned = new Set<string>();\n\n for (const task of tasks) {\n if (assigned.has(task.id)) continue;\n\n const cluster = [task];\n assigned.add(task.id);\n\n const taskServices = new Set(JSON.parse(task.involvedServices ?? '[]') as string[]);\n\n for (const other of tasks) {\n if (assigned.has(other.id)) continue;\n const otherServices = new Set(JSON.parse(other.involvedServices ?? '[]') as string[]);\n // Check overlap\n const overlap = [...taskServices].filter(s => otherServices.has(s));\n if (overlap.length > 0) {\n cluster.push(other);\n assigned.add(other.id);\n }\n }\n\n clusters.push(cluster);\n }\n\n return clusters;\n}\n","import { execSync, spawn } from 'node:child_process';\nimport { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';\nimport { CartographyDB } from './db.js';\nimport { IPCServer, cleanStaleSocket } from './ipc.js';\nimport { NotificationService } from './notify.js';\nimport { runShadowCycle } from './agent.js';\nimport type { CartographyConfig, ShadowStatus, ClientMessage } from './types.js';\n\n// ── Snapshot ─────────────────────────────────────────────────────────────────\n\nexport function takeSnapshot(config: CartographyConfig): string {\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000 }).toString();\n } catch {\n return `(${cmd}: not available)`;\n }\n };\n\n const ss = run('ss -tnp 2>/dev/null || ss -tn 2>/dev/null || echo \"ss not available\"');\n const ps = run('ps aux --sort=-start_time 2>/dev/null | head -50');\n\n let win = '';\n if (config.trackWindowFocus) {\n try {\n win = execSync('xdotool getactivewindow getwindowname 2>/dev/null', {\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 2000,\n }).toString().trim();\n } catch {\n win = '';\n }\n }\n\n return `=== TCP ===\\n${ss}\\n=== PS ===\\n${ps}\\n=== Window ===\\n${win}`;\n}\n\n// ── ShadowDaemon ─────────────────────────────────────────────────────────────\n\nexport class ShadowDaemon {\n private running = false;\n private paused = false;\n private prevSnapshot = '';\n private cyclesRun = 0;\n private cyclesSkipped = 0;\n private lastTaskCount = 0;\n private sessionId = '';\n\n constructor(\n private config: CartographyConfig,\n private db: CartographyDB,\n private ipc: IPCServer,\n private notify: NotificationService,\n ) {}\n\n async run(): Promise<string> {\n this.running = true;\n this.sessionId = this.db.createSession('shadow', this.config);\n\n process.on('SIGTERM', () => this.stop());\n process.on('SIGINT', () => this.stop());\n process.on('SIGUSR1', () => this.pause());\n process.on('SIGUSR2', () => this.resume());\n\n // Handle IPC commands from attached clients\n this.ipc.on('message', (msg: ClientMessage) => {\n switch (msg.type) {\n case 'command':\n if (msg.command === 'pause') this.pause();\n else if (msg.command === 'resume') this.resume();\n else if (msg.command === 'stop') this.stop();\n else if (msg.command === 'status') {\n this.ipc.broadcast({ type: 'status', data: this.getStatus() });\n } else if (msg.command === 'new-task') {\n this.db.startTask(this.sessionId);\n this.ipc.broadcast({ type: 'info', message: 'Task gestartet' });\n } else if (msg.command === 'end-task') {\n this.db.endCurrentTask(this.sessionId);\n this.ipc.broadcast({ type: 'info', message: 'Task beendet' });\n }\n break;\n case 'task-description':\n this.db.updateTaskDescription(this.sessionId, msg.description);\n break;\n case 'prompt-response':\n // Handle SOP candidate response\n if (msg.id.startsWith('sop-suggest:')) {\n const taskId = msg.id.replace('sop-suggest:', '');\n if (msg.answer === 'ja' || msg.answer === 'yes' || msg.answer === 'Ja, als SOP speichern') {\n this.db.markTaskAsSOPCandidate(taskId);\n this.ipc.broadcast({ type: 'info', message: `Task als SOP-Kandidat markiert` });\n }\n }\n break;\n }\n });\n\n while (this.running) {\n if (this.paused) {\n // Still broadcast status while paused\n this.ipc.broadcast({ type: 'status', data: this.getStatus() });\n await sleep(this.config.pollIntervalMs);\n continue;\n }\n\n const snapshot = takeSnapshot(this.config);\n\n if (snapshot !== this.prevSnapshot) {\n try {\n await runShadowCycle(\n this.config,\n this.db,\n this.sessionId,\n this.prevSnapshot,\n snapshot,\n (msg) => {\n if (this.ipc.hasClients()) {\n this.ipc.broadcast({ type: 'agent-output', text: JSON.stringify(msg) });\n }\n },\n );\n this.cyclesRun++;\n } catch (err) {\n process.stderr.write(`⚠ Cycle error: ${err}\\n`);\n }\n this.prevSnapshot = snapshot;\n\n // Check for newly completed tasks → suggest as SOP\n this.checkForCompletedTasks();\n } else {\n this.cyclesSkipped++;\n }\n\n // Broadcast status\n this.ipc.broadcast({ type: 'status', data: this.getStatus() });\n\n // Desktop notification if no clients attached\n if (!this.ipc.hasClients()) {\n const stats = this.db.getStats(this.sessionId);\n if (stats.events > 0 && this.cyclesRun % 10 === 0) {\n this.notify.workflowDetected(stats.tasks, `${stats.events} events so far`);\n }\n }\n\n await sleep(this.config.pollIntervalMs);\n }\n\n this.db.endSession(this.sessionId);\n this.ipc.stop();\n cleanup(this.config);\n return this.sessionId;\n }\n\n pause(): void {\n if (!this.paused) {\n this.paused = true;\n this.ipc.broadcast({ type: 'info', message: '⏸ Shadow-Daemon pausiert' });\n }\n }\n\n resume(): void {\n if (this.paused) {\n this.paused = false;\n this.ipc.broadcast({ type: 'info', message: '▶ Shadow-Daemon fortgesetzt' });\n }\n }\n\n stop(): void {\n this.running = false;\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n private checkForCompletedTasks(): void {\n const tasks = this.db.getTasks(this.sessionId);\n const completedCount = tasks.filter(t => t.status === 'completed').length;\n\n if (completedCount > this.lastTaskCount) {\n // New task(s) completed — suggest as SOP candidate\n const newlyCompleted = tasks\n .filter(t => t.status === 'completed' && !t.isSOPCandidate)\n .slice(-1); // most recent\n\n for (const task of newlyCompleted) {\n const desc = task.description ?? `Task ${task.id.substring(0, 8)}`;\n if (this.ipc.hasClients()) {\n this.ipc.broadcast({\n type: 'prompt',\n id: `sop-suggest:${task.id}`,\n prompt: {\n kind: 'task-boundary',\n context: { taskId: task.id, description: desc },\n options: ['Ja, als SOP speichern', 'Nein, überspringen'],\n defaultAnswer: 'Ja, als SOP speichern',\n timeoutMs: 30_000,\n createdAt: new Date().toISOString(),\n },\n });\n } else {\n // Auto-mark as candidate when no client is attached\n this.db.markTaskAsSOPCandidate(task.id);\n }\n }\n this.lastTaskCount = completedCount;\n }\n }\n\n private getStatus(): ShadowStatus {\n const stats = this.db.getStats(this.sessionId);\n const sops = this.db.getSOPs(this.sessionId);\n return {\n pid: process.pid,\n uptime: process.uptime(),\n nodeCount: stats.nodes,\n eventCount: stats.events,\n taskCount: stats.tasks,\n sopCount: sops.length,\n pendingPrompts: 0,\n autoSave: this.config.autoSaveNodes,\n mode: this.config.shadowMode,\n agentActive: false,\n paused: this.paused,\n cyclesRun: this.cyclesRun,\n cyclesSkipped: this.cyclesSkipped,\n };\n }\n}\n\n// ── Daemon Lifecycle ──────────────────────────────────────────────────────────\n\nexport function forkDaemon(config: CartographyConfig): number {\n // The daemon entry is the same cli.ts but with --daemon flag via env\n const child = spawn(\n process.execPath,\n [process.argv[1] ?? 'datasynx-cartography', 'shadow', 'start', '--foreground', '--daemon-child'],\n {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n CARTOGRAPHYY_DAEMON: '1',\n CARTOGRAPHYY_CONFIG: JSON.stringify(config),\n },\n }\n );\n child.unref();\n\n const pid = child.pid;\n if (!pid) throw new Error('Failed to fork daemon');\n\n writeFileSync(config.pidFile, String(pid), 'utf8');\n return pid;\n}\n\nexport function isDaemonRunning(pidFile: string): { running: boolean; pid?: number } {\n if (!existsSync(pidFile)) return { running: false };\n\n try {\n const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);\n if (isNaN(pid)) return { running: false };\n\n process.kill(pid, 0); // throws if process doesn't exist\n return { running: true, pid };\n } catch {\n // Stale PID file\n try { unlinkSync(pidFile); } catch { /* already gone */ }\n return { running: false };\n }\n}\n\nexport function stopDaemon(pidFile: string): boolean {\n const { running, pid } = isDaemonRunning(pidFile);\n if (!running || !pid) return false;\n\n try {\n process.kill(pid, 'SIGTERM');\n try { unlinkSync(pidFile); } catch { /* already gone */ }\n return true;\n } catch {\n return false;\n }\n}\n\nexport function pauseDaemon(pidFile: string): boolean {\n const { running, pid } = isDaemonRunning(pidFile);\n if (!running || !pid) return false;\n try { process.kill(pid, 'SIGUSR1'); return true; } catch { return false; }\n}\n\nexport function resumeDaemon(pidFile: string): boolean {\n const { running, pid } = isDaemonRunning(pidFile);\n if (!running || !pid) return false;\n try { process.kill(pid, 'SIGUSR2'); return true; } catch { return false; }\n}\n\nfunction cleanup(config: CartographyConfig): void {\n try { unlinkSync(config.socketPath); } catch { /* already gone */ }\n try { unlinkSync(config.pidFile); } catch { /* already gone */ }\n}\n\n// ── startDaemonProcess ───────────────────────────────────────────────────────\n\nexport async function startDaemonProcess(config: CartographyConfig): Promise<void> {\n cleanStaleSocket(config.socketPath);\n\n const db = new CartographyDB(config.dbPath);\n const ipc = new IPCServer();\n const notify = new NotificationService(config.enableNotifications);\n\n ipc.start(config.socketPath);\n\n const daemon = new ShadowDaemon(config, db, ipc, notify);\n await daemon.run();\n\n db.close();\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","import net from 'node:net';\nimport { EventEmitter } from 'node:events';\nimport { chmodSync, existsSync, unlinkSync } from 'node:fs';\nimport type { DaemonMessage, ClientMessage } from './types.js';\n\n// ── IPCServer ────────────────────────────────────────────────────────────────\n\nexport class IPCServer extends EventEmitter {\n private server: net.Server | null = null;\n private clients: Set<net.Socket> = new Set();\n\n start(socketPath: string): void {\n this.server = net.createServer((socket) => {\n this.clients.add(socket);\n this.emit('client-connect', socket);\n\n let buf = '';\n socket.on('data', (chunk) => {\n buf += chunk.toString();\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line) as ClientMessage;\n this.emit('message', msg, socket);\n } catch {\n // Ignore malformed JSON\n }\n }\n });\n\n socket.on('close', () => {\n this.clients.delete(socket);\n this.emit('client-disconnect', socket);\n });\n\n socket.on('error', () => {\n this.clients.delete(socket);\n });\n });\n\n this.server.listen(socketPath, () => {\n try {\n chmodSync(socketPath, 0o600);\n } catch {\n // chmod may fail in some environments — non-fatal\n }\n });\n }\n\n broadcast(msg: DaemonMessage): void {\n const line = JSON.stringify(msg) + '\\n';\n for (const socket of this.clients) {\n try {\n socket.write(line);\n } catch {\n this.clients.delete(socket);\n }\n }\n }\n\n hasClients(): boolean {\n return this.clients.size > 0;\n }\n\n stop(): void {\n for (const socket of this.clients) {\n socket.destroy();\n }\n this.clients.clear();\n this.server?.close();\n this.server = null;\n }\n}\n\n// ── IPCClient ────────────────────────────────────────────────────────────────\n\nexport class IPCClient extends EventEmitter {\n private socket: net.Socket | null = null;\n\n connect(socketPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const socket = net.createConnection(socketPath, () => {\n resolve();\n });\n\n socket.on('error', (err) => {\n reject(err);\n });\n\n let buf = '';\n socket.on('data', (chunk) => {\n buf += chunk.toString();\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line) as DaemonMessage;\n this.emit('message', msg);\n } catch {\n // Ignore malformed JSON\n }\n }\n });\n\n socket.on('close', () => {\n this.emit('disconnect');\n });\n\n this.socket = socket;\n });\n }\n\n send(msg: ClientMessage): void {\n if (!this.socket) return;\n try {\n this.socket.write(JSON.stringify(msg) + '\\n');\n } catch {\n // Socket may have closed\n }\n }\n\n disconnect(): void {\n this.socket?.destroy();\n this.socket = null;\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function cleanStaleSocket(socketPath: string): void {\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Already gone\n }\n }\n}\n","import notifier from 'node-notifier';\n\nexport class NotificationService {\n constructor(private enabled: boolean) {}\n\n nodeDiscovered(nodeId: string, via: string): void {\n this.send(`📍 Node entdeckt: ${nodeId}`, `Via: ${via}`);\n }\n\n workflowDetected(count: number, desc: string): void {\n this.send(`🔄 ${count} Workflow(s) erkannt`, desc);\n }\n\n taskBoundary(gapMinutes: number): void {\n this.send('⏸ Task-Grenze erkannt', `${gapMinutes} Minuten Inaktivität`);\n }\n\n private send(title: string, message: string): void {\n if (!this.enabled) return;\n\n try {\n notifier.notify({ title, message, sound: false });\n } catch {\n // Notifications not available — silently skip\n }\n }\n}\n","import { IPCClient } from './ipc.js';\nimport { startDaemonProcess } from './daemon.js';\nimport type { CartographyConfig, DaemonMessage, ShadowStatus } from './types.js';\n\n// ── ForegroundClient ─────────────────────────────────────────────────────────\n// Runs daemon + terminal UI in the same process (no fork)\n\nexport class ForegroundClient {\n async run(config: CartographyConfig): Promise<void> {\n process.stderr.write('👁 Datasynx Cartography Shadow (foreground) gestartet\\n');\n process.stderr.write(` Intervall: ${config.pollIntervalMs / 1000}s | Modell: ${config.shadowModel}\\n`);\n process.stderr.write(' Ctrl+C zum Beenden\\n\\n');\n\n // Run daemon inline (blocks until SIGINT/SIGTERM)\n await startDaemonProcess({ ...config, shadowMode: 'foreground' });\n }\n}\n\n// ── AttachClient ─────────────────────────────────────────────────────────────\n// Connects to a running daemon via Unix socket and provides terminal UI\n\nexport class AttachClient {\n private isPaused = false;\n\n async attach(socketPath: string): Promise<void> {\n const client = new IPCClient();\n\n try {\n await client.connect(socketPath);\n } catch {\n process.stderr.write(`❌ Kann nicht an Daemon ankoppeln: ${socketPath}\\n`);\n process.stderr.write(' Ist der Daemon gestartet? datasynx-cartography shadow status\\n');\n process.exitCode = 1;\n return;\n }\n\n process.stderr.write('📡 Verbunden mit Shadow-Daemon\\n');\n process.stderr.write(' [T] Neuer Task [S] Status [P] Pause/Resume [D] Trennen [Q] Stoppen\\n\\n');\n\n // Set raw mode for hotkeys\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n process.stdin.resume();\n process.stdin.setEncoding('utf8');\n\n process.stdin.on('data', (key: string) => {\n const k = key.toLowerCase();\n\n if (k === 't') {\n process.stdout.write('\\nTask-Beschreibung: ');\n process.stdin.once('data', (desc: string) => {\n client.send({ type: 'task-description', description: desc.trim() });\n client.send({ type: 'command', command: 'new-task' });\n process.stdout.write(`\\n✓ Neuer Task gestartet: ${desc.trim()}\\n`);\n });\n return;\n }\n\n if (k === 's') {\n client.send({ type: 'command', command: 'status' });\n return;\n }\n\n if (k === 'p') {\n if (this.isPaused) {\n client.send({ type: 'command', command: 'resume' });\n process.stderr.write('\\n▶ Resume gesendet\\n');\n } else {\n client.send({ type: 'command', command: 'pause' });\n process.stderr.write('\\n⏸ Pause gesendet\\n');\n }\n this.isPaused = !this.isPaused;\n return;\n }\n\n if (k === 'd' || k === '\\u0003') {\n process.stderr.write('\\n📡 Getrennt. Daemon läuft weiter.\\n');\n client.disconnect();\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n return;\n }\n\n if (k === 'q') {\n client.send({ type: 'command', command: 'stop' });\n process.stderr.write('\\n🛑 Daemon wird gestoppt...\\n');\n setTimeout(() => {\n client.disconnect();\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n }, 1000);\n return;\n }\n });\n\n client.on('message', (msg: DaemonMessage) => {\n switch (msg.type) {\n case 'status':\n this.isPaused = msg.data.paused;\n renderStatus(msg.data);\n break;\n case 'event':\n process.stdout.write(\n ` [${new Date(msg.data.timestamp).toLocaleTimeString()}] ` +\n `${msg.data.eventType} ${msg.data.process}` +\n (msg.data.target ? ` → ${msg.data.target}` : '') + '\\n'\n );\n break;\n case 'agent-output':\n if (msg.text) process.stdout.write(` 🤖 ${msg.text}\\n`);\n break;\n case 'info':\n process.stdout.write(` ℹ ${msg.message}\\n`);\n break;\n case 'prompt':\n renderPrompt(msg.id, msg.prompt.kind, msg.prompt.context, msg.prompt.options, (answer) => {\n client.send({ type: 'prompt-response', id: msg.id, answer });\n });\n break;\n }\n });\n\n client.on('disconnect', () => {\n process.stderr.write('\\n⚠ Verbindung zum Daemon verloren\\n');\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n });\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction renderStatus(status: ShadowStatus): void {\n const state = status.paused ? '\\x1b[33m⏸ PAUSED\\x1b[0m' : '\\x1b[32m● RUNNING\\x1b[0m';\n process.stdout.write(\n `\\n── Shadow Status ───────────────────────────────\\n` +\n ` ${state} PID: ${status.pid} | Uptime: ${Math.round(status.uptime)}s\\n` +\n ` Nodes: ${status.nodeCount} | Events: ${status.eventCount} | Tasks: ${status.taskCount} | SOPs: ${status.sopCount}\\n` +\n ` Cycles: ${status.cyclesRun} run, ${status.cyclesSkipped} skipped\\n` +\n `────────────────────────────────────────────────\\n`\n );\n}\n\nfunction renderPrompt(\n id: string,\n kind: string,\n context: Record<string, unknown>,\n options: string[],\n callback: (answer: string) => void,\n): void {\n if (id.startsWith('sop-suggest:')) {\n const desc = context['description'] as string ?? 'Unbenannter Task';\n process.stdout.write(`\\n 📋 Task abgeschlossen: \"${desc}\"\\n`);\n process.stdout.write(` Als SOP speichern?\\n`);\n options.forEach((opt, i) => process.stdout.write(` [${i + 1}] ${opt}\\n`));\n process.stdout.write(' → ');\n process.stdin.once('data', (data: string) => {\n const idx = parseInt(data.trim(), 10) - 1;\n callback(options[idx] ?? options[0] ?? '');\n });\n return;\n }\n\n process.stdout.write(`\\n❓ ${kind}\\n`);\n options.forEach((opt, i) => process.stdout.write(` [${i + 1}] ${opt}\\n`));\n process.stdout.write('Antwort: ');\n process.stdin.once('data', (data: string) => {\n const idx = parseInt(data.trim(), 10) - 1;\n callback(options[idx] ?? options[0] ?? '');\n });\n}\n"],"mappings":"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","names":["execSync","readFileSync","existsSync","execSync","existsSync","readFileSync","unlinkSync","existsSync","resolve","execSync","existsSync","readFileSync","unlinkSync","resolve","resolve","existsSync","readFileSync","mkdirSync","writeFileSync","join","scanAllBookmarks","saved","NODE_TYPES","execSync","dim"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/preflight.ts","../src/db.ts","../src/tools.ts","../src/safety.ts","../src/agent.ts","../src/daemon.ts","../src/ipc.ts","../src/notify.ts","../src/client.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { checkPrerequisites, checkPollInterval } from './preflight.js';\nimport { CartographyDB } from './db.js';\nimport { defaultConfig } from './types.js';\nimport { runDiscovery, generateSOPs } from './agent.js';\nimport type { DiscoveryEvent } from './agent.js';\nimport { exportAll } from './exporter.js';\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { createInterface } from 'readline';\nimport {\n forkDaemon, isDaemonRunning, stopDaemon, pauseDaemon, resumeDaemon, startDaemonProcess,\n} from './daemon.js';\nimport { ForegroundClient, AttachClient } from './client.js';\n\n// ── Shared color helpers ─────────────────────────────────────────────────────\nconst bold = (s: string) => `\\x1b[1m${s}\\x1b[0m`;\nconst dim = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\nconst cyan = (s: string) => `\\x1b[36m${s}\\x1b[0m`;\nconst green = (s: string) => `\\x1b[32m${s}\\x1b[0m`;\nconst yellow = (s: string) => `\\x1b[33m${s}\\x1b[0m`;\nconst magenta = (s: string) => `\\x1b[35m${s}\\x1b[0m`;\nconst red = (s: string) => `\\x1b[31m${s}\\x1b[0m`;\n\n// ── Daemon child-process entry ────────────────────────────────────────────────\nif (process.env.CARTOGRAPHYY_DAEMON === '1') {\n const config = JSON.parse(process.env.CARTOGRAPHYY_CONFIG ?? '{}') as ReturnType<typeof defaultConfig>;\n startDaemonProcess(config).catch((err) => {\n process.stderr.write(`Daemon fatal: ${err}\\n`);\n process.exitCode = 1;\n });\n} else {\n main();\n}\n\nfunction main(): void {\n const program = new Command();\n\n const CMD = 'datasynx-cartography';\n const VERSION = '0.2.3';\n\n program\n .name(CMD)\n .description('AI-powered Infrastructure Cartography & SOP Generation')\n .version(VERSION);\n\n // ── DISCOVERY ──────────────────────────────────────────────────────────────\n\n program\n .command('discover')\n .description('Infrastruktur scannen und kartographieren')\n .option('--entry <hosts...>', 'Startpunkte', ['localhost'])\n .option('--depth <n>', 'Max Tiefe', '8')\n .option('--max-turns <n>', 'Max Agent-Turns', '50')\n .option('--model <m>', 'Agent-Model', 'claude-sonnet-4-5-20250929')\n .option('--org <name>', 'Organisation (für Backstage)')\n .option('-o, --output <dir>', 'Output-Dir', './datasynx-output')\n .option('--db <path>', 'DB-Pfad')\n .option('-v, --verbose', 'Agent-Reasoning anzeigen', false)\n .action(async (opts) => {\n checkPrerequisites();\n\n const config = defaultConfig({\n mode: 'discover',\n entryPoints: opts.entry,\n maxDepth: parseInt(opts.depth, 10),\n maxTurns: parseInt(opts.maxTurns, 10),\n agentModel: opts.model,\n organization: opts.org,\n outputDir: opts.output,\n ...(opts.db ? { dbPath: opts.db } : {}),\n verbose: opts.verbose,\n });\n\n const db = new CartographyDB(config.dbPath);\n const sessionId = db.createSession('discover', config);\n\n const w = process.stderr.write.bind(process.stderr);\n\n const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n let spinIdx = 0;\n let spinnerTimer: ReturnType<typeof setInterval> | null = null;\n let spinnerMsg = '';\n\n const startSpinner = (msg: string) => {\n spinnerMsg = msg;\n if (spinnerTimer) clearInterval(spinnerTimer);\n spinnerTimer = setInterval(() => {\n const frame = cyan(SPINNER[spinIdx % SPINNER.length] ?? '⠋');\n w(`\\r ${frame} ${spinnerMsg}\\x1b[K`);\n spinIdx++;\n }, 80);\n };\n\n const stopSpinner = () => {\n if (spinnerTimer) { clearInterval(spinnerTimer); spinnerTimer = null; }\n w(`\\r\\x1b[K`);\n };\n\n const startTime = Date.now();\n let turnNum = 0;\n let nodeCount = 0;\n let edgeCount = 0;\n\n w('\\n');\n w(` ${bold('CARTOGRAPHY')} ${dim(config.entryPoints.join(', '))}\\n`);\n w(` ${dim('Model: ' + config.agentModel + ' | MaxTurns: ' + config.maxTurns)}\\n`);\n w(dim(' ────────────────────────────────────────────────\\n'));\n w('\\n');\n\n const logLine = (icon: string, msg: string) => {\n stopSpinner();\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n w(` ${icon} ${msg} ${dim(elapsed + 's')}\\n`);\n };\n\n const handleEvent = (event: DiscoveryEvent) => {\n switch (event.kind) {\n case 'turn':\n turnNum = event.turn;\n startSpinner(`Turn ${turnNum}/${config.maxTurns} ${dim(`nodes:${nodeCount} edges:${edgeCount}`)}`);\n break;\n\n case 'thinking':\n if (config.verbose) {\n stopSpinner();\n const lines = event.text.split('\\n').slice(0, 3);\n for (const line of lines) {\n w(` ${dim(' ' + line.substring(0, 80))}\\n`);\n }\n }\n break;\n\n case 'tool_call': {\n const toolName = event.tool.replace('mcp__cartograph__', '');\n\n if (toolName === 'Bash') {\n const cmd = (event.input['command'] as string ?? '').substring(0, 70);\n startSpinner(`${yellow('$')} ${cmd}`);\n } else if (toolName === 'save_node') {\n const id = event.input['id'] as string ?? '?';\n const type = event.input['type'] as string ?? '?';\n nodeCount++;\n logLine(green('+'), `${bold('Node')} ${cyan(id)} ${dim('(' + type + ')')}`);\n startSpinner(`Turn ${turnNum}/${config.maxTurns} ${dim(`nodes:${nodeCount} edges:${edgeCount}`)}`);\n } else if (toolName === 'save_edge') {\n const src = event.input['sourceId'] as string ?? '?';\n const tgt = event.input['targetId'] as string ?? '?';\n const rel = event.input['relationship'] as string ?? '→';\n edgeCount++;\n logLine(magenta('~'), `${bold('Edge')} ${src} ${dim(rel)} ${cyan(tgt)}`);\n startSpinner(`Turn ${turnNum}/${config.maxTurns} ${dim(`nodes:${nodeCount} edges:${edgeCount}`)}`);\n } else if (toolName === 'get_catalog') {\n startSpinner(`Catalog-Check ${dim('(Duplikate vermeiden)')}`);\n } else if (toolName === 'scan_bookmarks') {\n logLine(cyan('🔖'), `Browser-Lesezeichen werden gescannt…`);\n startSpinner(`scan_bookmarks`);\n } else if (toolName === 'scan_installed_apps') {\n const sh = event.input['searchHint'] as string | undefined;\n logLine(cyan('🖥'), sh ? `Installierte Apps gesucht: ${bold(sh)}` : `Alle installierten Apps werden gescannt…`);\n startSpinner(`scan_installed_apps`);\n } else if (toolName === 'ask_user') {\n // Just display; actual interaction is handled by onAskUser below\n const q = (event.input['question'] as string ?? '').substring(0, 100);\n logLine(yellow('?'), `${bold('Agent fragt:')} ${q}`);\n } else {\n startSpinner(`${toolName}...`);\n }\n break;\n }\n\n case 'tool_result':\n // Spinner continues, no special output for results\n break;\n\n case 'done':\n stopSpinner();\n break;\n }\n };\n\n // Human-in-the-loop: Agent kann Rückfragen stellen\n const onAskUser = async (question: string, context?: string): Promise<string> => {\n stopSpinner();\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${yellow(bold('?'))} ${bold('Agent fragt:')} ${question}\\n`);\n if (context) w(` ${dim(context)}\\n`);\n\n if (!process.stdin.isTTY) {\n w(` ${dim('(Kein Terminal — Agent fährt ohne Antwort fort)')}\\n\\n`);\n return '(Kein interaktiver Modus — bitte ohne diese Information fortfahren)';\n }\n\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n const answer = await new Promise<string>(resolve => rl.question(` ${cyan('→')} `, resolve));\n rl.close();\n w('\\n');\n return answer || '(Keine Antwort — bitte fortfahren)';\n };\n\n try {\n await runDiscovery(config, db, sessionId, handleEvent, onAskUser, undefined);\n } catch (err) {\n stopSpinner();\n w(`\\n ${bold('\\x1b[31m✗\\x1b[0m')} Discovery fehlgeschlagen: ${err}\\n`);\n db.close();\n process.exitCode = 1;\n return;\n }\n\n stopSpinner();\n db.endSession(sessionId);\n const stats = db.getStats(sessionId);\n const totalSec = ((Date.now() - startTime) / 1000).toFixed(1);\n\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${green(bold('DONE'))} ${bold(String(stats.nodes))} nodes, ${bold(String(stats.edges))} edges ${dim('in ' + totalSec + 's')}\\n`);\n w('\\n');\n\n // ── Interactive Node Review ─────────────────────────────────────────────\n const allNodes = db.getNodes(sessionId);\n\n if (allNodes.length > 0 && process.stdin.isTTY) {\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${bold('REVIEW')} ${bold(String(allNodes.length))} entdeckte Nodes — zum Bereinigen\\n`);\n w(dim(' Gib Nummern ein um Nodes zu entfernen (z.B. \"1 3 5\"), Enter = alles behalten\\n'));\n w('\\n');\n\n const PAD_ID = 42;\n const PAD_TYPE = 16;\n allNodes.forEach((n, i) => {\n const num = String(i + 1).padStart(3);\n const id = n.id.padEnd(PAD_ID).substring(0, PAD_ID);\n const type = dim(`[${n.type}]`.padEnd(PAD_TYPE));\n const conf = dim(`${Math.round(n.confidence * 100)}%`);\n const src = dim(n.discoveredVia === 'bookmark' ? ' 🔖' : '');\n w(` ${dim(num)} ${cyan('●')} ${id} ${type} ${conf}${src}\\n`);\n });\n\n w('\\n');\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n const answer = await new Promise<string>(resolve =>\n rl.question(` ${yellow('?')} Entfernen (Nummern, leer = alle behalten): `, resolve)\n );\n rl.close();\n\n const toRemove = answer.trim().split(/[\\s,]+/).map(Number).filter(n => n >= 1 && n <= allNodes.length);\n if (toRemove.length > 0) {\n for (const idx of toRemove) {\n const node = allNodes[idx - 1];\n if (node) db.deleteNode(sessionId, node.id);\n }\n w(`\\n ${green('✓')} ${bold(String(toRemove.length))} Node(s) entfernt\\n`);\n } else {\n w(`\\n ${green('✓')} Alle Nodes behalten\\n`);\n }\n }\n\n // ── Export ─────────────────────────────────────────────────────────────\n exportAll(db, sessionId, config.outputDir);\n\n // ── Diagramm-Link ──────────────────────────────────────────────────────\n const osc8 = (url: string, label: string) => `\\x1b]8;;${url}\\x1b\\\\${label}\\x1b]8;;\\x1b\\\\`;\n const htmlPath = resolve(config.outputDir, 'topology.html');\n const topoPath = resolve(config.outputDir, 'topology.mermaid');\n\n w('\\n');\n if (existsSync(htmlPath)) {\n w(` ${green('→')} ${osc8(`file://${htmlPath}`, bold('topology.html öffnen'))}\\n`);\n }\n if (existsSync(topoPath)) {\n try {\n const code = readFileSync(topoPath, 'utf8');\n const b64 = Buffer.from(JSON.stringify({ code, mermaid: { theme: 'dark' } })).toString('base64');\n w(` ${cyan('→')} ${osc8(`https://mermaid.live/view#base64:${b64}`, bold('mermaid.live öffnen'))}\\n`);\n } catch { /* ignore */ }\n }\n w('\\n');\n\n // ── Human-in-the-Loop: Follow-up Discovery Chat ───────────────────────\n if (process.stdin.isTTY) {\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${bold('WEITERSUCHEN')} ${dim('Discovery interaktiv verfeinern')}\\n`);\n w(dim(' Gib Suchbegriffe ein (z.B. \"hubspot windsurf cursor\") oder Enter zum Beenden.\\n'));\n w('\\n');\n\n // Reset event counters for follow-up rounds\n nodeCount = 0;\n edgeCount = 0;\n\n let continueDiscovery = true;\n while (continueDiscovery) {\n const rlFollowup = createInterface({ input: process.stdin, output: process.stderr });\n const followupHint = await new Promise<string>(resolve =>\n rlFollowup.question(` ${yellow('→')} Suche nach (Enter = Beenden): `, resolve)\n );\n rlFollowup.close();\n\n if (!followupHint.trim()) {\n continueDiscovery = false;\n break;\n }\n\n const followupHintTrimmed = followupHint.trim();\n w('\\n');\n w(` ${cyan(bold('⟳'))} Suche nach: ${bold(followupHintTrimmed)}\\n`);\n w('\\n');\n\n try {\n await runDiscovery(config, db, sessionId, handleEvent, onAskUser, followupHintTrimmed);\n } catch (err) {\n stopSpinner();\n w(`\\n ${red('✗')} Fehler: ${err}\\n`);\n }\n\n stopSpinner();\n const followupStats = db.getStats(sessionId);\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${green(bold('✓'))} Gesamt jetzt: ${bold(String(followupStats.nodes))} nodes, ${bold(String(followupStats.edges))} edges\\n`);\n w('\\n');\n\n // Re-export with updated data\n exportAll(db, sessionId, config.outputDir);\n if (existsSync(htmlPath)) {\n w(` ${green('→')} ${osc8(`file://${htmlPath}`, bold('topology.html aktualisiert'))}\\n`);\n }\n w('\\n');\n }\n }\n\n db.close();\n });\n\n // ── SHADOW ────────────────────────────────────────────────────────────────\n\n const shadow = program.command('shadow').description('Shadow-Daemon verwalten');\n\n shadow\n .command('start')\n .description('Shadow-Daemon starten')\n .option('--interval <ms>', 'Poll-Intervall in ms', '30000')\n .option('--inactivity <ms>', 'Task-Grenze in ms', '300000')\n .option('--track-windows', 'Fenster-Focus tracken', false)\n .option('--auto-save', 'Nodes ohne Rückfrage speichern', false)\n .option('--no-notifications', 'Desktop-Notifications deaktivieren')\n .option('--model <m>', 'Analysis-Model', 'claude-haiku-4-5-20251001')\n .option('--foreground', 'Kein Daemon, im Terminal bleiben', false)\n .option('--db <path>', 'DB-Pfad')\n .option('--daemon-child', 'Internal: marks this as a daemon child process') // internal flag\n .action(async (opts) => {\n checkPrerequisites();\n\n const intervalMs = checkPollInterval(parseInt(opts.interval, 10));\n\n const config = defaultConfig({\n mode: 'shadow',\n shadowMode: opts.foreground ? 'foreground' : 'daemon',\n pollIntervalMs: intervalMs,\n inactivityTimeoutMs: parseInt(opts.inactivity, 10),\n trackWindowFocus: opts.trackWindows,\n autoSaveNodes: opts.autoSave,\n enableNotifications: opts.notifications !== false,\n shadowModel: opts.model,\n ...(opts.db ? { dbPath: opts.db } : {}),\n });\n\n // Check if already running\n const { running } = isDaemonRunning(config.pidFile);\n if (running) {\n process.stderr.write('❌ Shadow-Daemon läuft bereits. datasynx-cartography shadow status\\n');\n process.exitCode = 1;\n return;\n }\n\n if (opts.foreground) {\n const client = new ForegroundClient();\n await client.run(config);\n } else {\n const pid = forkDaemon(config);\n process.stderr.write(`👁 Shadow daemon started (PID ${pid})\\n`);\n process.stderr.write(` Intervall: ${intervalMs / 1000}s | Modell: ${config.shadowModel}\\n`);\n process.stderr.write(' datasynx-cartography shadow attach — ankoppeln\\n');\n process.stderr.write(' datasynx-cartography shadow stop — stoppen\\n\\n');\n }\n });\n\n shadow\n .command('stop')\n .description('Shadow-Daemon stoppen + SOP-Review')\n .option('-o, --output <dir>', 'Output-Dir für SOPs + Dashboard', './datasynx-output')\n .option('--no-review', 'SOP-Review überspringen')\n .action(async (opts) => {\n const config = defaultConfig({ outputDir: opts.output });\n const stopped = stopDaemon(config.pidFile);\n\n if (!stopped) {\n process.stderr.write('⚠ Kein laufender Shadow-Daemon gefunden\\n');\n return;\n }\n\n process.stderr.write('✓ Shadow-Daemon gestoppt\\n');\n\n if (opts.review === false) return;\n\n // Wait a moment for daemon to flush DB\n await new Promise(r => setTimeout(r, 500));\n\n // Generate SOPs + show review\n const db = new CartographyDB(config.dbPath);\n const session = db.getLatestSession('shadow');\n if (!session) {\n db.close();\n return;\n }\n\n const stats = db.getStats(session.id);\n const w = (s: string) => process.stderr.write(s);\n\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(bold(' Shadow-Session Review\\n'));\n w(dim(` Session: ${session.id}\\n`));\n w(dim(` Nodes: ${stats.nodes} | Events: ${stats.events} | Tasks: ${stats.tasks}\\n`));\n w(dim(' ────────────────────────────────────────────────\\n'));\n w('\\n');\n\n // Generate SOPs if tasks exist\n if (stats.tasks > 0) {\n try {\n w(' SOPs generieren...\\n');\n const count = await generateSOPs(db, session.id);\n w(` ${green('✓')} ${count} SOPs generiert\\n\\n`);\n } catch (err) {\n w(` ${red('✗')} SOP-Generierung fehlgeschlagen: ${err}\\n\\n`);\n }\n }\n\n // Show SOPs as markdown review\n const { exportSOPMarkdown, exportSOPDashboard } = await import('./exporter.js');\n const sops = db.getSOPs(session.id);\n\n if (sops.length > 0) {\n w(bold(' SOPs zur Überprüfung:\\n\\n'));\n for (const sop of sops) {\n const md = exportSOPMarkdown(sop);\n // Indent each line for terminal display\n for (const line of md.split('\\n')) {\n process.stdout.write(` ${line}\\n`);\n }\n process.stdout.write('\\n');\n w(dim(' ────────────────────────────────────────────────\\n\\n'));\n }\n\n // Export SOP dashboard HTML\n const { mkdirSync, writeFileSync } = await import('node:fs');\n const { join, resolve: resolvePath } = await import('node:path');\n\n mkdirSync(config.outputDir, { recursive: true });\n mkdirSync(join(config.outputDir, 'sops'), { recursive: true });\n\n // Write individual SOP markdown files\n for (const sop of sops) {\n const filename = sop.title.toLowerCase().replace(/[^a-z0-9]+/g, '-') + '.md';\n writeFileSync(join(config.outputDir, 'sops', filename), exportSOPMarkdown(sop));\n }\n\n // Write SOP dashboard HTML\n const allSOPs = db.getAllSOPs();\n const dashboardHtml = exportSOPDashboard(allSOPs);\n const dashboardPath = join(config.outputDir, 'sop-dashboard.html');\n writeFileSync(dashboardPath, dashboardHtml);\n\n const absPath = resolvePath(dashboardPath);\n w(` ${green('✓')} ${sops.length} SOP-Markdown-Dateien geschrieben\\n`);\n w(` ${green('✓')} SOP Dashboard: ${cyan(`file://${absPath}`)}\\n`);\n w('\\n');\n w(dim(` Öffne im Browser: ${bold(`file://${absPath}`)}\\n`));\n w('\\n');\n } else {\n w(dim(' Keine SOPs in dieser Session.\\n\\n'));\n }\n\n db.close();\n });\n\n shadow\n .command('pause')\n .description('Shadow-Daemon pausieren')\n .action(() => {\n const config = defaultConfig();\n const paused = pauseDaemon(config.pidFile);\n if (paused) {\n process.stderr.write('⏸ Shadow-Daemon pausiert\\n');\n } else {\n process.stderr.write('⚠ Kein laufender Shadow-Daemon gefunden\\n');\n }\n });\n\n shadow\n .command('resume')\n .description('Shadow-Daemon fortsetzen')\n .action(() => {\n const config = defaultConfig();\n const resumed = resumeDaemon(config.pidFile);\n if (resumed) {\n process.stderr.write('▶ Shadow-Daemon fortgesetzt\\n');\n } else {\n process.stderr.write('⚠ Kein laufender Shadow-Daemon gefunden\\n');\n }\n });\n\n shadow\n .command('status')\n .description('Shadow-Daemon Status anzeigen')\n .action(() => {\n const config = defaultConfig();\n const { running, pid } = isDaemonRunning(config.pidFile);\n if (running) {\n process.stdout.write(`✓ Shadow-Daemon läuft (PID ${pid})\\n`);\n process.stdout.write(` Socket: ${config.socketPath}\\n`);\n } else {\n process.stdout.write('✗ Shadow-Daemon gestoppt\\n');\n }\n });\n\n shadow\n .command('attach')\n .description('An laufenden Shadow-Daemon ankoppeln')\n .action(async () => {\n const config = defaultConfig();\n const client = new AttachClient();\n await client.attach(config.socketPath);\n });\n\n // ── ANALYSE & EXPORT ──────────────────────────────────────────────────────\n\n program\n .command('sops [session-id]')\n .description('SOPs aus beobachteten Workflows generieren')\n .action(async (sessionId?: string) => {\n checkPrerequisites();\n\n const config = defaultConfig();\n const db = new CartographyDB(config.dbPath);\n\n const session = sessionId\n ? db.getSession(sessionId)\n : db.getLatestSession('shadow');\n\n if (!session) {\n process.stderr.write('❌ Keine Shadow-Session gefunden. datasynx-cartography shadow start\\n');\n db.close();\n process.exitCode = 1;\n return;\n }\n\n process.stderr.write(`🔄 Generiere SOPs aus Session ${session.id}...\\n`);\n const count = await generateSOPs(db, session.id);\n process.stderr.write(`✓ ${count} SOPs generiert\\n`);\n\n db.close();\n });\n\n program\n .command('export [session-id]')\n .description('Alle Outputs generieren')\n .option('-o, --output <dir>', 'Output-Dir', './datasynx-output')\n .option('--format <fmt...>', 'Formate: mermaid,json,yaml,html,sops')\n .action((sessionId: string | undefined, opts) => {\n const config = defaultConfig({ outputDir: opts.output });\n const db = new CartographyDB(config.dbPath);\n\n const session = sessionId\n ? db.getSession(sessionId)\n : db.getLatestSession();\n\n if (!session) {\n process.stderr.write('❌ Keine Session gefunden\\n');\n db.close();\n process.exitCode = 1;\n return;\n }\n\n const formats = opts.format ?? ['mermaid', 'json', 'yaml', 'html', 'sops'];\n exportAll(db, session.id, opts.output, formats);\n process.stderr.write(`✓ Exported to: ${opts.output}\\n`);\n\n db.close();\n });\n\n program\n .command('show [session-id]')\n .description('Session-Details anzeigen')\n .action((sessionId?: string) => {\n const config = defaultConfig();\n const db = new CartographyDB(config.dbPath);\n\n const session = sessionId\n ? db.getSession(sessionId)\n : db.getLatestSession();\n\n if (!session) {\n process.stderr.write('❌ Keine Session gefunden\\n');\n db.close();\n process.exitCode = 1;\n return;\n }\n\n const stats = db.getStats(session.id);\n const nodes = db.getNodes(session.id);\n\n process.stdout.write(`\\nSession: ${session.id}\\n`);\n process.stdout.write(` Mode: ${session.mode}\\n`);\n process.stdout.write(` Started: ${session.startedAt}\\n`);\n if (session.completedAt) process.stdout.write(` Ended: ${session.completedAt}\\n`);\n process.stdout.write(` Nodes: ${stats.nodes}\\n`);\n process.stdout.write(` Edges: ${stats.edges}\\n`);\n process.stdout.write(` Events: ${stats.events}\\n`);\n process.stdout.write(` Tasks: ${stats.tasks}\\n`);\n\n if (nodes.length > 0) {\n process.stdout.write('\\n Discovered nodes:\\n');\n for (const node of nodes.slice(0, 20)) {\n process.stdout.write(` ${node.id} (${node.type}, confidence: ${node.confidence})\\n`);\n }\n if (nodes.length > 20) {\n process.stdout.write(` ... and ${nodes.length - 20} more\\n`);\n }\n }\n\n process.stdout.write('\\n');\n db.close();\n });\n\n program\n .command('sessions')\n .description('Alle Sessions auflisten')\n .action(() => {\n const config = defaultConfig();\n const db = new CartographyDB(config.dbPath);\n const sessions = db.getSessions();\n\n if (sessions.length === 0) {\n process.stdout.write('Keine Sessions gefunden\\n');\n db.close();\n return;\n }\n\n for (const session of sessions) {\n const stats = db.getStats(session.id);\n const status = session.completedAt ? '✓' : '●';\n process.stdout.write(\n `${status} ${session.id.substring(0, 8)} [${session.mode}] ` +\n `${session.startedAt.substring(0, 19)} ` +\n `nodes:${stats.nodes} edges:${stats.edges}\\n`\n );\n }\n\n db.close();\n });\n\n // ── OVERVIEW ──────────────────────────────────────────────────────────────\n\n program\n .command('overview')\n .description('Übersicht aller Cartographies + SOPs')\n .option('--db <path>', 'DB-Pfad')\n .action((opts) => {\n const config = defaultConfig();\n const db = new CartographyDB((opts as { db?: string }).db ?? config.dbPath);\n const sessions = db.getSessions();\n\n const b = bold, d = dim;\n const w = (s: string) => process.stdout.write(s);\n\n w('\\n');\n w(` ${b('CARTOGRAPHY OVERVIEW')}\\n`);\n w(d(' ─────────────────────────────────────────────────────\\n'));\n\n if (sessions.length === 0) {\n w(` ${d('Noch keine Sessions. Starte mit:')} ${green('datasynx-cartography discover')}\\n\\n`);\n db.close();\n return;\n }\n\n // Aggregate totals\n let totalNodes = 0, totalEdges = 0, totalSops = 0;\n for (const s of sessions) {\n const st = db.getStats(s.id);\n totalNodes += st.nodes; totalEdges += st.edges;\n totalSops += db.getSOPs(s.id).length;\n }\n\n w(` ${b(String(sessions.length))} Sessions · ${b(String(totalNodes))} Nodes · `);\n w(`${b(String(totalEdges))} Edges · ${b(String(totalSops))} SOPs\\n\\n`);\n\n for (const session of sessions) {\n const stats = db.getStats(session.id);\n const nodes = db.getNodes(session.id);\n const sops = db.getSOPs(session.id);\n const status = session.completedAt ? green('✓') : yellow('●');\n const age = session.startedAt.substring(0, 16).replace('T', ' ');\n const sid = cyan(session.id.substring(0, 8));\n\n w(` ${status} ${sid} ${b('[' + session.mode + ']')} ${d(age)}\\n`);\n w(` ${d('Nodes: ' + stats.nodes + ' Edges: ' + stats.edges + ' SOPs: ' + sops.length)}\\n`);\n\n // Node type breakdown\n const byType = new Map<string, number>();\n for (const n of nodes) byType.set(n.type, (byType.get(n.type) ?? 0) + 1);\n if (byType.size > 0) {\n const parts = [...byType.entries()].map(([t, c]) => `${t}:${c}`).join(' ');\n w(` ${d(parts)}\\n`);\n }\n\n // Top nodes\n const topNodes = nodes.slice(0, 5).map(n => n.id).join(', ');\n if (topNodes) w(` ${d('Nodes: ' + topNodes + (nodes.length > 5 ? ' …' : ''))}\\n`);\n\n // SOPs\n for (const sop of sops.slice(0, 3)) {\n w(` ${green('►')} ${sop.title} ${d('(' + sop.estimatedDuration + ')')}\\n`);\n }\n if (sops.length > 3) w(` ${d('… +' + (sops.length - 3) + ' weitere SOPs')}\\n`);\n\n w('\\n');\n }\n\n db.close();\n });\n\n // ── CHAT ──────────────────────────────────────────────────────────────────\n\n program\n .command('chat [session-id]')\n .description('Interaktiver Chat über die kartographierte Infrastruktur')\n .option('--db <path>', 'DB-Pfad')\n .option('--model <m>', 'Model', 'claude-sonnet-4-5-20250929')\n .action(async (sessionIdArg: string | undefined, opts) => {\n const config = defaultConfig();\n const db = new CartographyDB((opts as { db?: string }).db ?? config.dbPath);\n const sessions = db.getSessions();\n\n const session = sessionIdArg\n ? sessions.find(s => s.id.startsWith(sessionIdArg))\n : sessions.filter(s => s.completedAt).at(-1) ?? sessions.at(-1);\n\n if (!session) {\n process.stderr.write('Keine Session gefunden. Führe zuerst discover aus.\\n');\n db.close();\n return;\n }\n\n const nodes = db.getNodes(session.id);\n const edges = db.getEdges(session.id);\n const sops = db.getSOPs(session.id);\n\n const w = (s: string) => process.stdout.write(s);\n\n w('\\n');\n w(dim(` ─────────────────────────────────────────────────────\\n`));\n w(` ${bold('CARTOGRAPHY CHAT')} ${dim('Session ' + session.id.substring(0, 8))}\\n`);\n w(` ${dim(String(nodes.length) + ' Nodes · ' + edges.length + ' Edges · ' + sops.length + ' SOPs')}\\n`);\n w(dim(` ─────────────────────────────────────────────────────\\n`));\n w(` ${dim('Frage alles über deine Infrastruktur. exit = beenden.\\n\\n')}`);\n\n const Anthropic = (await import('@anthropic-ai/sdk')).default;\n const client = new Anthropic();\n\n // Build a compact infra summary for context (avoid token overflow)\n const infraSummary = JSON.stringify({\n nodes: nodes.map(n => ({\n id: n.id, name: n.name, type: n.type,\n confidence: n.confidence,\n metadata: n.metadata,\n tags: n.tags,\n })),\n edges: edges.map(e => ({ from: e.sourceId, to: e.targetId, rel: e.relationship, conf: e.confidence })),\n sops: sops.map(s => ({ title: s.title, description: s.description, steps: s.steps.length, duration: s.estimatedDuration })),\n });\n\n const systemPrompt = `Du bist ein Infrastruktur-Analyst für Cartography.\nDu hast Zugriff auf die vollständig kartographierte Infrastruktur dieser Session.\nBeantworte Fragen präzise und hilfreich. Nutze die Daten konkret.\nDu kannst SOPs erklären, Abhängigkeiten analysieren, Risiken benennen, Optimierungen vorschlagen.\n\nINFRASTRUKTUR-SNAPSHOT (${nodes.length} Nodes, ${edges.length} Edges, ${sops.length} SOPs):\n${infraSummary.substring(0, 12000)}`;\n\n // Multi-turn conversation history\n type MsgParam = { role: 'user' | 'assistant'; content: string };\n const history: MsgParam[] = [];\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n\n const ask = () => new Promise<string>(resolve => rl.question(` ${cyan('>')} `, resolve));\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let userInput: string;\n try { userInput = await ask(); } catch { break; }\n\n if (!userInput.trim()) continue;\n if (['exit', 'quit', ':q'].includes(userInput.trim().toLowerCase())) break;\n\n history.push({ role: 'user', content: userInput });\n\n try {\n const resp = await client.messages.create({\n model: (opts as { model: string }).model,\n max_tokens: 1024,\n system: systemPrompt,\n messages: history,\n });\n\n const reply = resp.content.find(b => b.type === 'text')?.text ?? '';\n history.push({ role: 'assistant', content: reply });\n\n w('\\n');\n // Word-wrap at 80 cols with indent\n for (const line of reply.split('\\n')) {\n w(` ${line}\\n`);\n }\n w('\\n');\n } catch (err) {\n w(` ${red('✗')} Fehler: ${err}\\n\\n`);\n }\n }\n\n rl.close();\n db.close();\n w(`\\n ${dim('Chat beendet.')}\\n\\n`);\n });\n\n // ── DOCS ──────────────────────────────────────────────────────────────────\n\n program\n .command('docs')\n .description('Alle Features und Befehle auf einen Blick')\n .action(() => {\n const out = process.stdout.write.bind(process.stdout);\n const b = bold;\n const line = () => out(dim('─'.repeat(60)) + '\\n');\n\n out('\\n');\n out(b(' DATASYNX CARTOGRAPHY') + ' ' + dim('v' + VERSION) + '\\n');\n out(dim(' AI-powered Infrastructure Cartography & SOP Generation\\n'));\n out('\\n');\n line();\n\n // ── CARTOGRAPHY\n out(b(cyan(' CARTOGRAPHY\\n')));\n out('\\n');\n out(` ${green('datasynx-cartography discover')}\\n`);\n out(` Scannt die lokale Infrastruktur (Claude Sonnet).\\n`);\n out(` Claude führt eigenständig ss, ps, curl, docker inspect, kubectl get\\n`);\n out(` aus und speichert alles in SQLite.\\n`);\n out('\\n');\n out(dim(' Optionen:\\n'));\n out(dim(' --entry <hosts...> Startpunkte (default: localhost)\\n'));\n out(dim(' --depth <n> Max Tiefe (default: 8)\\n'));\n out(dim(' --max-turns <n> Max Agent-Turns (default: 50)\\n'));\n out(dim(' --model <m> Model (default: claude-sonnet-4-5-...)\\n'));\n out(dim(' --org <name> Organisation für Backstage YAML\\n'));\n out(dim(' -o, --output <dir> Output-Verzeichnis (default: ./datasynx-output)\\n'));\n out(dim(' -v, --verbose Agent-Reasoning anzeigen\\n'));\n out('\\n');\n out(dim(' Output:\\n'));\n out(dim(' datasynx-output/\\n'));\n out(dim(' catalog.json Maschinenlesbarer Komplett-Dump\\n'));\n out(dim(' catalog-info.yaml Backstage Service-Katalog\\n'));\n out(dim(' topology.mermaid Infrastruktur-Topologie (graph TB)\\n'));\n out(dim(' dependencies.mermaid Service-Dependencies (graph LR)\\n'));\n out(dim(' topology.html Interaktiver D3.js Force-Graph\\n'));\n out(dim(' sops/ Generierte SOPs als Markdown\\n'));\n out(dim(' workflows/ Workflow-Flowcharts als Mermaid\\n'));\n out('\\n');\n line();\n\n // ── SHADOW\n out(b(cyan(' SHADOW DAEMON\\n')));\n out('\\n');\n out(` ${green('datasynx-cartography shadow start')}\\n`);\n out(` Startet einen Background-Daemon, der alle 30s einen System-Snapshot\\n`);\n out(` nimmt (ss + ps). Nur bei Änderung ruft er Claude Haiku auf.\\n`);\n out('\\n');\n out(dim(' Optionen:\\n'));\n out(dim(' --interval <ms> Poll-Intervall (default: 30000, min: 15000)\\n'));\n out(dim(' --inactivity <ms> Task-Grenze (default: 300000 = 5 min)\\n'));\n out(dim(' --model <m> Analysis-Model (default: claude-haiku-4-5-...)\\n'));\n out(dim(' --track-windows Fenster-Focus tracken (benötigt xdotool)\\n'));\n out(dim(' --auto-save Nodes ohne Rückfrage speichern\\n'));\n out(dim(' --no-notifications Desktop-Notifications deaktivieren\\n'));\n out(dim(' --foreground Kein Daemon, im Terminal bleiben\\n'));\n out('\\n');\n out(` ${green('datasynx-cartography shadow stop')} ${dim('Daemon per SIGTERM beenden')}\\n`);\n out(` ${green('datasynx-cartography shadow status')} ${dim('PID + Socket-Pfad anzeigen')}\\n`);\n out(` ${green('datasynx-cartography shadow attach')} ${dim('Live-Events im Terminal, Hotkeys: [T] [S] [D] [Q]')}\\n`);\n out('\\n');\n out(dim(' Hotkeys im Attach-Modus:\\n'));\n out(dim(' [T] Neuen Task starten (mit Beschreibung)\\n'));\n out(dim(' [S] Status-Dump anzeigen (Nodes, Events, Tasks, Cycles)\\n'));\n out(dim(' [D] Trennen — Daemon läuft weiter\\n'));\n out(dim(' [Q] Daemon stoppen und beenden\\n'));\n out('\\n');\n line();\n\n // ── ANALYSE & EXPORT\n out(b(cyan(' ANALYSE & EXPORT\\n')));\n out('\\n');\n out(` ${green('datasynx-cartography sops [session-id]')}\\n`);\n out(` Clustert abgeschlossene Tasks und generiert SOPs via Claude Sonnet.\\n`);\n out(` Nutzt die Anthropic Messages API (kein Agent-Loop, ein Request pro Cluster).\\n`);\n out('\\n');\n out(` ${green('datasynx-cartography export [session-id]')}\\n`);\n out(dim(' --format <fmt...> mermaid, json, yaml, html, sops (default: alle)\\n'));\n out(dim(' -o, --output <dir> Output-Verzeichnis\\n'));\n out('\\n');\n out(` ${green('datasynx-cartography show [session-id]')} ${dim('Session-Details + Node-Liste')}\\n`);\n out(` ${green('datasynx-cartography sessions')} ${dim('Alle Sessions tabellarisch auflisten')}\\n`);\n out('\\n');\n line();\n\n // ── KOSTEN\n out(b(cyan(' KOSTEN (Richtwerte)\\n')));\n out('\\n');\n out(yellow(' Modus Model Intervall pro Stunde pro 8h-Tag\\n'));\n out(dim(' ─────────────────────────────────────────────────────────────\\n'));\n out(` Discovery Sonnet einmalig $0.15–0.50 einmalig\\n`);\n out(` Shadow Haiku 30s $0.12–0.36 $0.96–2.88\\n`);\n out(` Shadow Haiku 60s $0.06–0.18 $0.48–1.44\\n`);\n out(` Shadow (ruhig) Haiku 30s ~$0.02 ~$0.16\\n`);\n out(` SOP-Gen Sonnet einmalig $0.01–0.03 einmalig\\n`);\n out('\\n');\n out(dim(' * \"ruhig\" = Diff-Check überspringt 90%+ Cycles, wenn System unverändert\\n'));\n out('\\n');\n line();\n\n // ── ARCHITEKTUR\n out(b(cyan(' ARCHITEKTUR\\n')));\n out('\\n');\n out(dim(' CLI (Commander)\\n'));\n out(dim(' └── Preflight: Claude CLI check + API key + Intervall-Validierung\\n'));\n out(dim(' └── Agent Orchestrator (agent.ts)\\n'));\n out(dim(' ├── runDiscovery() → Claude Sonnet + Bash + MCP Tools\\n'));\n out(dim(' ├── runShadowCycle() → Claude Haiku + nur MCP Tools (kein Bash!)\\n'));\n out(dim(' └── generateSOPs() → Anthropic Messages API (kein Agent-Loop)\\n'));\n out(dim(' └── Custom MCP Tools (tools.ts)\\n'));\n out(dim(' save_node, save_edge, save_event,\\n'));\n out(dim(' get_catalog, manage_task, save_sop\\n'));\n out(dim(' └── CartographyDB (SQLite WAL)\\n'));\n out(dim(' Shadow Daemon (daemon.ts)\\n'));\n out(dim(' ├── takeSnapshot() → ss + ps [kein Claude!]\\n'));\n out(dim(' ├── Diff-Check → nur bei Änderung: runShadowCycle()\\n'));\n out(dim(' ├── IPC Server (Unix Socket ~/.cartography/daemon.sock)\\n'));\n out(dim(' └── NotificationService (Desktop wenn kein Client attached)\\n'));\n out('\\n');\n line();\n\n // ── SETUP\n out(b(cyan(' SETUP\\n')));\n out('\\n');\n out(dim(' # 1. Claude CLI (Runtime-Dependency)\\n'));\n out(' npm install -g @anthropic-ai/claude-code\\n');\n out(' claude login\\n');\n out('\\n');\n out(dim(' # 2. API Key (falls nicht via claude login)\\n'));\n out(' export ANTHROPIC_API_KEY=sk-ant-...\\n');\n out('\\n');\n out(dim(' # 3. Los\\n'));\n out(' datasynx-cartography discover\\n');\n out(' datasynx-cartography shadow start\\n');\n out('\\n');\n out(dim(' Daten: ~/.cartography/cartography.db\\n'));\n out(dim(' Socket: ~/.cartography/daemon.sock\\n'));\n out(dim(' PID: ~/.cartography/daemon.pid\\n'));\n out('\\n');\n });\n\n // ── Bookmarks ──────────────────────────────────────────────────────────────\n\n program\n .command('bookmarks')\n .description('Alle Browser-Lesezeichen anzeigen (Chrome, Edge, Brave, Firefox)')\n .action(async () => {\n const { scanAllBookmarks } = await import('./bookmarks.js');\n const out = (s: string) => process.stdout.write(s);\n\n process.stderr.write(' Scanning bookmarks...\\n\\n');\n const hosts = await scanAllBookmarks();\n\n if (hosts.length === 0) {\n out(' (Keine Lesezeichen gefunden — Chrome, Edge, Brave und Firefox werden unterstützt)\\n\\n');\n return;\n }\n\n // Group by source browser\n const bySource = new Map<string, typeof hosts>();\n for (const h of hosts) {\n if (!bySource.has(h.source)) bySource.set(h.source, []);\n bySource.get(h.source)!.push(h);\n }\n\n for (const [source, entries] of bySource) {\n out(bold(cyan(` ${source.toUpperCase()}`)) + dim(` (${entries.length} Hosts)\\n`));\n out(dim(' ─────────────────────────────────────────\\n'));\n for (const h of entries) {\n const isDefault = (h.protocol === 'https' && h.port === 443) || (h.protocol === 'http' && h.port === 80);\n const portStr = isDefault ? '' : `:${h.port}`;\n out(` ${cyan(h.protocol + '://')}${h.hostname}${dim(portStr)}\\n`);\n }\n out('\\n');\n }\n\n out(dim(` Total: ${hosts.length} unique hosts\\n\\n`));\n out(dim(' Tipp: ') + 'datasynx-cartography discover' + dim(' — scannt + klassifiziert alle Lesezeichen automatisch\\n\\n'));\n });\n\n // ── Seed ───────────────────────────────────────────────────────────────────\n\n program\n .command('seed')\n .description('Bekannte Infrastruktur manuell eintragen (Tools, DBs, APIs, etc.)')\n .option('--file <path>', 'JSON-Datei mit Node-Definitionen einlesen')\n .option('--session <id>', 'In existierende Session eintragen (default: neue Session)')\n .option('--db <path>', 'DB-Pfad')\n .action(async (opts) => {\n const config = defaultConfig({ ...(opts.db ? { dbPath: opts.db } : {}) });\n const db = new CartographyDB(config.dbPath);\n const sessionId = opts.session ?? db.createSession('discover', config);\n\n const out = (s: string) => process.stdout.write(s);\n const w = (s: string) => process.stderr.write(s);\n\n // ── File mode ────────────────────────────────────────────────────────\n if (opts.file) {\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(resolve(opts.file), 'utf8'));\n } catch (e) {\n w(red(`\\n ✗ Datei konnte nicht gelesen werden: ${e}\\n\\n`));\n process.exitCode = 1;\n return;\n }\n\n if (!Array.isArray(raw)) {\n w(red('\\n ✗ JSON muss ein Array sein: [{ \"type\": \"...\", \"name\": \"...\", \"host\": \"...\" }]\\n\\n'));\n process.exitCode = 1;\n return;\n }\n\n let saved = 0;\n for (const entry of raw as Record<string, unknown>[]) {\n const type = entry['type'] as string;\n const name = entry['name'] as string;\n const host = entry['host'] as string | undefined;\n const port = entry['port'] as number | undefined;\n const tags = (entry['tags'] as string[] | undefined) ?? [];\n const metadata = (entry['metadata'] as Record<string, unknown> | undefined) ?? {};\n\n if (!type || !name) {\n w(yellow(` ⚠ Übersprungen (kein type/name): ${JSON.stringify(entry)}\\n`));\n continue;\n }\n\n const id = host\n ? `${type}:${host}${port ? ':' + port : ''}`\n : `${type}:${name.toLowerCase().replace(/\\s+/g, '-')}`;\n\n db.upsertNode(sessionId, {\n id,\n type: type as typeof import('./types.js').NODE_TYPES[number],\n name,\n discoveredVia: 'manual',\n confidence: 1.0,\n metadata: { ...metadata, ...(host ? { host } : {}), ...(port ? { port } : {}) },\n tags,\n });\n out(` ${green('+')} ${cyan(id)} ${dim('(' + type + ')')}\\n`);\n saved++;\n }\n\n db.endSession(sessionId);\n w(`\\n ${green(bold('DONE'))} ${saved} Nodes gespeichert ${dim('Session: ' + sessionId)}\\n\\n`);\n return;\n }\n\n // ── Interactive mode ─────────────────────────────────────────────────\n const { NODE_TYPES } = await import('./types.js');\n\n if (!process.stdin.isTTY) {\n w(red('\\n ✗ Interaktiver Modus benötigt ein Terminal (--file für nicht-interaktiven Betrieb)\\n\\n'));\n process.exitCode = 1;\n return;\n }\n\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(bold(' Bekannte Infrastruktur eintragen\\n'));\n w(dim(' Beispiele: Datenbanken, APIs, SaaS-Tools, Cloud-Services\\n'));\n w(dim(' ────────────────────────────────────────────────\\n'));\n w('\\n');\n\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n const ask = (q: string): Promise<string> => new Promise(res => rl.question(q, res));\n\n let saved = 0;\n\n const typeList = NODE_TYPES.map((t, i) => `${dim((i + 1).toString().padStart(2))} ${t}`).join('\\n ');\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n w('\\n');\n w(dim(' Node-Typen:\\n'));\n w(` ${typeList}\\n\\n`);\n\n const typeInput = (await ask(` ${cyan('Typ')} ${dim('[Nr. oder Name, Enter=abbrechen]')}: `)).trim();\n if (!typeInput) break;\n\n let nodeType: string;\n const asNum = parseInt(typeInput, 10);\n if (!isNaN(asNum) && asNum >= 1 && asNum <= NODE_TYPES.length) {\n nodeType = NODE_TYPES[asNum - 1] as string;\n } else if (NODE_TYPES.includes(typeInput as typeof NODE_TYPES[number])) {\n nodeType = typeInput;\n } else {\n w(yellow(` ⚠ Unbekannter Typ: \"${typeInput}\"\\n`));\n continue;\n }\n\n const name = (await ask(` ${cyan('Name')} ${dim('[z.B. \"Prod PostgreSQL\"]')}: `)).trim();\n if (!name) { w(dim(' (Abgebrochen)\\n')); continue; }\n\n const hostRaw = (await ask(` ${cyan('Host / IP')} ${dim('[optional, Enter=überspringen]')}: `)).trim();\n const portRaw = (await ask(` ${cyan('Port')} ${dim('[optional]')}: `)).trim();\n const tagsRaw = (await ask(` ${cyan('Tags')} ${dim('[komma-getrennt, optional]')}: `)).trim();\n\n const host = hostRaw || undefined;\n const port = portRaw ? parseInt(portRaw, 10) : undefined;\n const tags = tagsRaw ? tagsRaw.split(',').map(t => t.trim()).filter(Boolean) : [];\n\n const id = host\n ? `${nodeType}:${host}${port ? ':' + port : ''}`\n : `${nodeType}:${name.toLowerCase().replace(/\\s+/g, '-')}`;\n\n db.upsertNode(sessionId, {\n id,\n type: nodeType as typeof NODE_TYPES[number],\n name,\n discoveredVia: 'manual',\n confidence: 1.0,\n metadata: { ...(host ? { host } : {}), ...(port ? { port } : {}) },\n tags,\n });\n out(` ${green('+')} ${cyan(id)}\\n`);\n saved++;\n\n const again = (await ask(` ${dim('Weiteren Node hinzufügen? [Y/n]')}: `)).trim().toLowerCase();\n if (again === 'n' || again === 'nein') break;\n }\n\n rl.close();\n db.endSession(sessionId);\n w('\\n');\n w(dim(' ────────────────────────────────────────────────\\n'));\n w(` ${green(bold('DONE'))} ${saved} Node${saved !== 1 ? 's' : ''} gespeichert\\n`);\n w(` ${dim('Session: ' + sessionId)}\\n`);\n w(` ${dim('Tipp: datasynx-cartography show ' + sessionId)}\\n\\n`);\n });\n\n // ── Doctor ─────────────────────────────────────────────────────────────────\n\n program\n .command('doctor')\n .description('Prüft ob alle Voraussetzungen erfüllt sind')\n .action(async () => {\n const { execSync } = await import('node:child_process');\n const { existsSync, readFileSync } = await import('node:fs');\n const { join } = await import('node:path');\n const out = (s: string) => process.stdout.write(s);\n const ok = (msg: string) => out(` \\x1b[32m✓\\x1b[0m ${msg}\\n`);\n const err = (msg: string) => out(` \\x1b[31m✗\\x1b[0m ${msg}\\n`);\n const warn = (msg: string) => out(` \\x1b[33m⚠\\x1b[0m ${msg}\\n`);\n const dim = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\n let allGood = true;\n\n out('\\n \\x1b[1mDatasynx Cartography — Doctor\\x1b[0m\\n');\n out(dim(' ─────────────────────────────────\\n'));\n\n // 1. Node.js Version\n const nodeVer = process.versions.node;\n const [major] = nodeVer.split('.').map(Number);\n if ((major ?? 0) >= 18) {\n ok(`Node.js ${nodeVer}`);\n } else {\n err(`Node.js ${nodeVer} — benötigt >=18`);\n allGood = false;\n }\n\n // 2. Claude CLI\n try {\n const v = execSync('claude --version', { stdio: 'pipe' }).toString().trim();\n ok(`Claude CLI ${dim(v)}`);\n } catch {\n err('Claude CLI nicht gefunden — npm i -g @anthropic-ai/claude-code');\n allGood = false;\n }\n\n // 3. Auth\n const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY);\n const home = process.env.HOME ?? process.env.USERPROFILE ?? '/tmp';\n let hasOAuth = false;\n try {\n const creds = JSON.parse(readFileSync(join(home, '.claude', '.credentials.json'), 'utf8')) as Record<string, unknown>;\n const oauth = creds['claudeAiOauth'] as Record<string, unknown> | undefined;\n hasOAuth = typeof oauth?.['accessToken'] === 'string' && oauth['accessToken'].length > 0;\n } catch { /* no creds file */ }\n\n if (hasApiKey) {\n ok('ANTHROPIC_API_KEY gesetzt');\n } else if (hasOAuth) {\n ok('claude login (Subscription)');\n } else {\n err('Keine Authentifizierung — claude login oder export ANTHROPIC_API_KEY=sk-ant-...');\n allGood = false;\n }\n\n // 4. kubectl — wichtig für K8s Discovery\n try {\n const v = execSync('kubectl version --client --short 2>/dev/null || kubectl version --client', { stdio: 'pipe' }).toString().split('\\n')[0]?.trim() ?? '';\n ok(`kubectl ${dim(v || '(Client OK)')}`);\n } catch {\n warn(`kubectl nicht gefunden ${dim('— Installation: https://kubernetes.io/docs/tasks/tools/')}`);\n }\n\n // 5. Cloud CLIs (optional)\n const cloudClis: Array<[string, string, string]> = [\n ['aws', 'aws --version', 'AWS CLI — https://aws.amazon.com/cli/'],\n ['gcloud', 'gcloud --version', 'Google Cloud SDK — https://cloud.google.com/sdk/'],\n ['az', 'az --version', 'Azure CLI — https://aka.ms/installazurecliwindows'],\n ];\n for (const [name, cmd, hint] of cloudClis) {\n try {\n execSync(cmd, { stdio: 'pipe' });\n ok(`${name} ${dim('(Cloud-Scanning verfügbar)')}`);\n } catch {\n warn(`${name} nicht gefunden ${dim('— Cloud-Scan übersprungen | ' + hint)}`);\n }\n }\n\n // 6. Lokale Discovery-Tools\n const localTools: Array<[string, string]> = [\n ['docker', 'docker --version'],\n ['ss', 'ss --version'],\n ];\n for (const [name, cmd] of localTools) {\n try {\n execSync(cmd, { stdio: 'pipe' });\n ok(`${name} ${dim('(Discovery-Tool)')}`);\n } catch {\n warn(`${name} nicht gefunden ${dim('— Discovery ohne ' + name + ' eingeschränkt')}`);\n }\n }\n\n // 7. SQLite data dir\n const dbDir = join(home, '.cartography');\n if (existsSync(dbDir)) {\n ok(`~/.cartography ${dim('(Daten-Verzeichnis vorhanden)')}`);\n } else {\n warn('~/.cartography existiert noch nicht ' + dim('— wird beim ersten Start angelegt'));\n }\n\n out(dim(' ─────────────────────────────────\\n'));\n if (allGood) {\n out(' \\x1b[32m\\x1b[1mAlle Checks bestanden — datasynx-cartography discover\\x1b[0m\\n\\n');\n } else {\n out(' \\x1b[31m\\x1b[1mEinige Checks fehlgeschlagen. Bitte oben beheben.\\x1b[0m\\n\\n');\n process.exitCode = 1;\n }\n });\n\n // ── Banner (immer anzeigen) ───────────────────────────────────────────────\n\n const o = (s: string) => process.stderr.write(s);\n const _b = (s: string) => `\\x1b[1m${s}\\x1b[0m`;\n const _d = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\n const _c = (s: string) => `\\x1b[36m${s}\\x1b[0m`;\n const _g = (s: string) => `\\x1b[32m${s}\\x1b[0m`;\n const _m = (s: string) => `\\x1b[35m${s}\\x1b[0m`;\n\n o('\\n');\n o(_c(' ____ _ ____ ') + '\\n');\n o(_c(' | _ \\\\ __ _| |_ __ _/ ___| _ _ _ __ __ __') + '\\n');\n o(_c(' | | | |/ _` | __/ _` \\\\___ \\\\| | | | \\'_ \\\\\\\\ \\\\/ /') + '\\n');\n o(_c(' | |_| | (_| | || (_| |___) | |_| | | | |> < ') + '\\n');\n o(_c(' |____/ \\\\__,_|\\\\__\\\\__,_|____/ \\\\__, |_| |_/_/\\\\_\\\\') + '\\n');\n o(_c(' |___/ ') + '\\n');\n o('\\n');\n o(_b(' Cartography') + ' ' + _d('v' + VERSION) + '\\n');\n o(_d(' AI-powered Infrastructure Discovery & SOP Generation\\n'));\n o(_d(' Built on Claude Agent SDK\\n'));\n o('\\n');\n\n // ── Welcome Screen (no args → Befehlsübersicht) ─────────────────────────\n\n if (process.argv.length <= 2) {\n o(_d(' ────────────────────────────────────────────────\\n'));\n o('\\n');\n o(_b(' Commands:\\n'));\n o('\\n');\n o(` ${_g('discover')} ${_d('Infrastruktur scannen (Claude Sonnet)')}\\n`);\n o(` ${_g('seed')} ${_d('Bekannte Tools/DBs/APIs manuell eintragen')}\\n`);\n o(` ${_g('bookmarks')} ${_d('Browser-Lesezeichen anzeigen')}\\n`);\n o(` ${_g('shadow start')} ${_d('Background-Daemon starten (Claude Haiku)')}\\n`);\n o(` ${_g('shadow pause')} ${_d('Daemon pausieren')}\\n`);\n o(` ${_g('shadow resume')} ${_d('Daemon fortsetzen')}\\n`);\n o(` ${_g('shadow stop')} ${_d('Stoppen + SOP-Review + Dashboard')}\\n`);\n o(` ${_g('shadow status')} ${_d('Daemon-Status anzeigen')}\\n`);\n o(` ${_g('shadow attach')} ${_d('Live-Steuerung: [T] [S] [P] [D] [Q]')}\\n`);\n o(` ${_g('sops')} ${_d('[session]')} ${_d('SOPs aus Workflows generieren')}\\n`);\n o(` ${_g('export')} ${_d('[session]')} ${_d('Mermaid, JSON, YAML, HTML exportieren')}\\n`);\n o(` ${_g('show')} ${_d('[session]')} ${_d('Session-Details anzeigen')}\\n`);\n o(` ${_g('sessions')} ${_d('Alle Sessions auflisten')}\\n`);\n o(` ${_g('doctor')} ${_d('Installations-Check (kubectl, aws, gcloud, az)')}\\n`);\n o(` ${_g('docs')} ${_d('Vollständige Dokumentation')}\\n`);\n o('\\n');\n o(_d(' ────────────────────────────────────────────────\\n'));\n o('\\n');\n o(_b(' Quick Start:\\n'));\n o('\\n');\n o(` ${_m('$')} ${_b('datasynx-cartography doctor')} ${_d('Alles bereit?')}\\n`);\n o(` ${_m('$')} ${_b('datasynx-cartography seed')} ${_d('Bekannte Infra eintragen')}\\n`);\n o(` ${_m('$')} ${_b('datasynx-cartography discover')} ${_d('Einmal-Scan')}\\n`);\n o(` ${_m('$')} ${_b('datasynx-cartography shadow start')} ${_d('Dauerhaft beobachten')}\\n`);\n o('\\n');\n o(_d(' Doku: datasynx-cartography docs\\n'));\n o(_d(' Hilfe: datasynx-cartography --help\\n'));\n o(_d(' npm: @datasynx/agentic-ai-cartography\\n'));\n o('\\n');\n return;\n }\n\n o(_d(' ────────────────────────────────────────────────\\n'));\n o('\\n');\n\n // ── Parse ──────────────────────────────────────────────────────────────────\n\n program.exitOverride((err) => {\n if (err.code === 'commander.helpDisplayed') {\n process.exitCode = 0;\n } else {\n process.exitCode = 2;\n }\n });\n\n program.parse(process.argv);\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { MIN_POLL_INTERVAL_MS } from './types.js';\n\nfunction isOAuthLoggedIn(): boolean {\n // Claude CLI speichert OAuth-Tokens in ~/.claude/.credentials.json\n const home = process.env.HOME ?? process.env.USERPROFILE ?? '/tmp';\n const credFile = join(home, '.claude', '.credentials.json');\n if (!existsSync(credFile)) return false;\n try {\n const creds = JSON.parse(readFileSync(credFile, 'utf8')) as Record<string, unknown>;\n const oauth = creds['claudeAiOauth'] as Record<string, unknown> | undefined;\n return typeof oauth?.['accessToken'] === 'string' && oauth['accessToken'].length > 0;\n } catch {\n return false;\n }\n}\n\nexport function checkPrerequisites(): void {\n // Claude CLI vorhanden?\n try {\n execSync('claude --version', { stdio: 'pipe' });\n } catch {\n process.stderr.write(\n '\\n❌ Claude CLI nicht gefunden.\\n' +\n ' Datasynx Cartography braucht die Claude CLI als Runtime-Dependency.\\n\\n' +\n ' Installieren:\\n' +\n ' npm install -g @anthropic-ai/claude-code\\n' +\n ' # oder\\n' +\n ' curl -fsSL https://claude.ai/install.sh | bash\\n\\n' +\n ' Danach: claude login\\n\\n'\n );\n process.exitCode = 1;\n throw new Error('Claude CLI not found');\n }\n\n // Auth prüfen: API Key ODER OAuth-Login (claude.ai Subscription)\n const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOAuth = isOAuthLoggedIn();\n\n if (!hasApiKey && !hasOAuth) {\n process.stderr.write(\n '⚠ Keine Authentifizierung gefunden. Bitte eine der folgenden Optionen:\\n\\n' +\n ' Option A — claude.ai Subscription (empfohlen):\\n' +\n ' claude login\\n\\n' +\n ' Option B — API Key:\\n' +\n ' export ANTHROPIC_API_KEY=sk-ant-...\\n\\n'\n );\n } else if (hasOAuth && !hasApiKey) {\n process.stderr.write('✓ Eingeloggt via claude login (Subscription)\\n');\n }\n}\n\nexport function checkPollInterval(intervalMs: number): number {\n if (intervalMs < MIN_POLL_INTERVAL_MS) {\n process.stderr.write(\n `⚠ Minimum Shadow-Intervall: ${MIN_POLL_INTERVAL_MS / 1000} Sekunden (Agent SDK Overhead)\\n`\n );\n return MIN_POLL_INTERVAL_MS;\n }\n return intervalMs;\n}\n","import Database from 'better-sqlite3';\nimport { mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type {\n CartographyConfig, DiscoveryNode, DiscoveryEdge, ActivityEvent,\n NodeRow, EdgeRow, EventRow, TaskRow, WorkflowRow, SessionRow, SOP,\n} from './types.js';\n\nconst SCHEMA = `\nPRAGMA journal_mode = WAL;\nPRAGMA foreign_keys = ON;\nPRAGMA busy_timeout = 5000;\n\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n mode TEXT NOT NULL CHECK (mode IN ('discover','shadow')),\n started_at TEXT NOT NULL,\n completed_at TEXT,\n config TEXT NOT NULL DEFAULT '{}'\n);\n\nCREATE TABLE IF NOT EXISTS nodes (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n type TEXT NOT NULL,\n name TEXT NOT NULL,\n discovered_via TEXT,\n discovered_at TEXT NOT NULL,\n path_id TEXT,\n depth INTEGER DEFAULT 0,\n confidence REAL DEFAULT 0.5,\n metadata TEXT NOT NULL DEFAULT '{}',\n tags TEXT NOT NULL DEFAULT '[]',\n PRIMARY KEY (id, session_id)\n);\n\nCREATE TABLE IF NOT EXISTS edges (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n source_id TEXT NOT NULL,\n target_id TEXT NOT NULL,\n relationship TEXT NOT NULL,\n evidence TEXT,\n confidence REAL DEFAULT 0.5,\n discovered_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS activity_events (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n task_id TEXT,\n timestamp TEXT NOT NULL,\n event_type TEXT NOT NULL,\n process TEXT NOT NULL,\n pid INTEGER NOT NULL,\n target TEXT,\n target_type TEXT,\n port INTEGER,\n duration_ms INTEGER\n);\n\nCREATE TABLE IF NOT EXISTS tasks (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n description TEXT,\n started_at TEXT NOT NULL,\n completed_at TEXT,\n steps TEXT NOT NULL DEFAULT '[]',\n involved_services TEXT NOT NULL DEFAULT '[]',\n status TEXT DEFAULT 'active' CHECK (status IN ('active','completed','cancelled')),\n is_sop_candidate INTEGER DEFAULT 0\n);\n\nCREATE TABLE IF NOT EXISTS workflows (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n name TEXT,\n pattern TEXT NOT NULL,\n task_ids TEXT NOT NULL DEFAULT '[]',\n occurrences INTEGER DEFAULT 1,\n first_seen TEXT NOT NULL,\n last_seen TEXT NOT NULL,\n avg_duration_ms INTEGER,\n involved_services TEXT NOT NULL DEFAULT '[]'\n);\n\nCREATE TABLE IF NOT EXISTS sops (\n id TEXT PRIMARY KEY,\n workflow_id TEXT NOT NULL,\n title TEXT NOT NULL,\n description TEXT NOT NULL,\n steps TEXT NOT NULL,\n involved_systems TEXT NOT NULL DEFAULT '[]',\n estimated_duration TEXT,\n frequency TEXT,\n generated_at TEXT NOT NULL,\n confidence REAL DEFAULT 0.5\n);\n\nCREATE TABLE IF NOT EXISTS node_approvals (\n pattern TEXT PRIMARY KEY,\n action TEXT NOT NULL CHECK (action IN ('save','ignore','auto')),\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_nodes_session ON nodes(session_id);\nCREATE INDEX IF NOT EXISTS idx_edges_session ON edges(session_id);\nCREATE INDEX IF NOT EXISTS idx_events_session ON activity_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_events_task ON activity_events(task_id);\nCREATE INDEX IF NOT EXISTS idx_tasks_session ON tasks(session_id);\n`;\n\nexport class CartographyDB {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n mkdirSync(dirname(dbPath), { recursive: true });\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.db.pragma('busy_timeout = 5000');\n this.migrate();\n }\n\n private migrate(): void {\n const version = (this.db.pragma('user_version', { simple: true }) as number);\n if (version === 0) {\n this.db.exec(SCHEMA);\n this.db.pragma('user_version = 1');\n }\n }\n\n close(): void {\n this.db.pragma('optimize');\n this.db.close();\n }\n\n // ── Sessions ────────────────────────────\n\n createSession(mode: 'discover' | 'shadow', config: CartographyConfig): string {\n const id = crypto.randomUUID();\n this.db.prepare(\n 'INSERT INTO sessions (id, mode, started_at, config) VALUES (?, ?, ?, ?)'\n ).run(id, mode, new Date().toISOString(), JSON.stringify(config));\n return id;\n }\n\n endSession(id: string): void {\n this.db.prepare('UPDATE sessions SET completed_at = ? WHERE id = ?')\n .run(new Date().toISOString(), id);\n }\n\n getSession(id: string): SessionRow | undefined {\n const row = this.db.prepare('SELECT * FROM sessions WHERE id = ?').get(id) as Record<string, unknown> | undefined;\n return row ? this.mapSession(row) : undefined;\n }\n\n getLatestSession(mode?: string): SessionRow | undefined {\n const row = mode\n ? this.db.prepare('SELECT * FROM sessions WHERE mode = ? ORDER BY rowid DESC LIMIT 1').get(mode) as Record<string, unknown> | undefined\n : this.db.prepare('SELECT * FROM sessions ORDER BY rowid DESC LIMIT 1').get() as Record<string, unknown> | undefined;\n return row ? this.mapSession(row) : undefined;\n }\n\n getSessions(): SessionRow[] {\n const rows = this.db.prepare('SELECT * FROM sessions ORDER BY rowid DESC').all() as Record<string, unknown>[];\n return rows.map(r => this.mapSession(r));\n }\n\n private mapSession(r: Record<string, unknown>): SessionRow {\n return {\n id: r['id'] as string,\n mode: r['mode'] as 'discover' | 'shadow',\n startedAt: r['started_at'] as string,\n completedAt: (r['completed_at'] as string | null) ?? undefined,\n config: r['config'] as string,\n };\n }\n\n // ── Nodes ───────────────────────────────\n\n upsertNode(sessionId: string, node: DiscoveryNode, depth = 0): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO nodes\n (id, session_id, type, name, discovered_via, discovered_at, depth, confidence, metadata, tags)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n node.id, sessionId, node.type, node.name, node.discoveredVia,\n new Date().toISOString(), depth, node.confidence,\n JSON.stringify(node.metadata ?? {}),\n JSON.stringify(node.tags ?? []),\n );\n }\n\n getNodes(sessionId: string): NodeRow[] {\n const rows = this.db.prepare('SELECT * FROM nodes WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n type: r['type'] as NodeRow['type'],\n name: r['name'] as string,\n discoveredVia: r['discovered_via'] as string,\n discoveredAt: r['discovered_at'] as string,\n depth: r['depth'] as number,\n confidence: r['confidence'] as number,\n metadata: JSON.parse(r['metadata'] as string) as Record<string, unknown>,\n tags: JSON.parse(r['tags'] as string) as string[],\n pathId: r['path_id'] as string | undefined,\n }));\n }\n\n deleteNode(sessionId: string, nodeId: string): void {\n this.db.prepare('DELETE FROM nodes WHERE session_id = ? AND id = ?').run(sessionId, nodeId);\n // Remove orphaned edges\n this.db.prepare(\n 'DELETE FROM edges WHERE session_id = ? AND (source_id = ? OR target_id = ?)'\n ).run(sessionId, nodeId, nodeId);\n }\n\n // ── Edges ───────────────────────────────\n\n insertEdge(sessionId: string, edge: DiscoveryEdge): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT OR IGNORE INTO edges\n (id, session_id, source_id, target_id, relationship, evidence, confidence, discovered_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, edge.sourceId, edge.targetId,\n edge.relationship, edge.evidence, edge.confidence,\n new Date().toISOString(),\n );\n }\n\n getEdges(sessionId: string): EdgeRow[] {\n const rows = this.db.prepare('SELECT * FROM edges WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n sourceId: r['source_id'] as string,\n targetId: r['target_id'] as string,\n relationship: r['relationship'] as EdgeRow['relationship'],\n evidence: r['evidence'] as string,\n confidence: r['confidence'] as number,\n discoveredAt: r['discovered_at'] as string,\n }));\n }\n\n // ── Events ──────────────────────────────\n\n insertEvent(sessionId: string, event: ActivityEvent, taskId?: string): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO activity_events\n (id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, taskId ?? null, new Date().toISOString(),\n event.eventType, event.process, event.pid,\n event.target ?? null, event.targetType ?? null, event.port ?? null,\n );\n }\n\n getEvents(sessionId: string, since?: string): EventRow[] {\n const rows = since\n ? this.db.prepare('SELECT * FROM activity_events WHERE session_id = ? AND timestamp > ? ORDER BY timestamp').all(sessionId, since) as Record<string, unknown>[]\n : this.db.prepare('SELECT * FROM activity_events WHERE session_id = ? ORDER BY timestamp').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n taskId: r['task_id'] as string | undefined,\n timestamp: r['timestamp'] as string,\n eventType: r['event_type'] as EventRow['eventType'],\n process: r['process'] as string,\n pid: r['pid'] as number,\n target: r['target'] as string | undefined,\n targetType: r['target_type'] as EventRow['targetType'],\n port: r['port'] as number | undefined,\n durationMs: r['duration_ms'] as number | undefined,\n }));\n }\n\n // ── Tasks ───────────────────────────────\n\n startTask(sessionId: string, description?: string): string {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO tasks (id, session_id, description, started_at, steps, involved_services, status)\n VALUES (?, ?, ?, ?, '[]', '[]', 'active')\n `).run(id, sessionId, description ?? null, new Date().toISOString());\n return id;\n }\n\n endCurrentTask(sessionId: string): void {\n this.db.prepare(`\n UPDATE tasks SET status = 'completed', completed_at = ?\n WHERE session_id = ? AND status = 'active'\n `).run(new Date().toISOString(), sessionId);\n }\n\n updateTaskDescription(sessionId: string, description: string): void {\n this.db.prepare(`\n UPDATE tasks SET description = ?\n WHERE session_id = ? AND status = 'active'\n `).run(description, sessionId);\n }\n\n getActiveTask(sessionId: string): TaskRow | undefined {\n const row = this.db.prepare(\n \"SELECT * FROM tasks WHERE session_id = ? AND status = 'active' LIMIT 1\"\n ).get(sessionId) as Record<string, unknown> | undefined;\n return row ? this.mapTask(row) : undefined;\n }\n\n getTasks(sessionId: string): TaskRow[] {\n const rows = this.db.prepare('SELECT * FROM tasks WHERE session_id = ? ORDER BY started_at').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => this.mapTask(r));\n }\n\n private mapTask(r: Record<string, unknown>): TaskRow {\n return {\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n description: r['description'] as string | undefined,\n startedAt: r['started_at'] as string,\n completedAt: r['completed_at'] as string | undefined,\n steps: r['steps'] as string,\n involvedServices: r['involved_services'] as string,\n status: r['status'] as TaskRow['status'],\n isSOPCandidate: Boolean(r['is_sop_candidate']),\n };\n }\n\n // ── Workflows ───────────────────────────\n\n insertWorkflow(sessionId: string, data: Omit<WorkflowRow, 'id'>): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO workflows\n (id, session_id, name, pattern, task_ids, occurrences,\n first_seen, last_seen, avg_duration_ms, involved_services)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, data.name ?? null, data.pattern,\n data.taskIds, data.occurrences,\n data.firstSeen, data.lastSeen, data.avgDurationMs,\n data.involvedServices,\n );\n }\n\n getWorkflows(sessionId: string): WorkflowRow[] {\n const rows = this.db.prepare('SELECT * FROM workflows WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n sessionId: r['session_id'] as string,\n name: r['name'] as string | undefined,\n pattern: r['pattern'] as string,\n taskIds: r['task_ids'] as string,\n occurrences: r['occurrences'] as number,\n firstSeen: r['first_seen'] as string,\n lastSeen: r['last_seen'] as string,\n avgDurationMs: r['avg_duration_ms'] as number,\n involvedServices: r['involved_services'] as string,\n }));\n }\n\n // ── SOPs ────────────────────────────────\n\n insertSOP(sop: { workflowId: string } & SOP): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO sops\n (id, workflow_id, title, description, steps, involved_systems,\n estimated_duration, frequency, generated_at, confidence)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sop.workflowId, sop.title, sop.description,\n JSON.stringify(sop.steps),\n JSON.stringify(sop.involvedSystems),\n sop.estimatedDuration, sop.frequency,\n new Date().toISOString(), sop.confidence,\n );\n }\n\n getSOPs(sessionId: string): Array<SOP & { id: string; workflowId: string }> {\n const rows = this.db.prepare(`\n SELECT s.* FROM sops s\n JOIN workflows w ON s.workflow_id = w.id\n WHERE w.session_id = ?\n `).all(sessionId) as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n workflowId: r['workflow_id'] as string,\n title: r['title'] as string,\n description: r['description'] as string,\n steps: JSON.parse(r['steps'] as string) as SOP['steps'],\n involvedSystems: JSON.parse(r['involved_systems'] as string) as string[],\n estimatedDuration: r['estimated_duration'] as string,\n frequency: r['frequency'] as string,\n confidence: r['confidence'] as number,\n }));\n }\n\n markTaskAsSOPCandidate(taskId: string): void {\n this.db.prepare('UPDATE tasks SET is_sop_candidate = 1 WHERE id = ?').run(taskId);\n }\n\n getAllSOPs(): Array<SOP & { id: string; workflowId: string; generatedAt: string }> {\n const rows = this.db.prepare('SELECT * FROM sops ORDER BY generated_at DESC').all() as Record<string, unknown>[];\n return rows.map(r => ({\n id: r['id'] as string,\n workflowId: r['workflow_id'] as string,\n title: r['title'] as string,\n description: r['description'] as string,\n steps: JSON.parse(r['steps'] as string) as SOP['steps'],\n involvedSystems: JSON.parse(r['involved_systems'] as string) as string[],\n estimatedDuration: r['estimated_duration'] as string,\n frequency: r['frequency'] as string,\n confidence: r['confidence'] as number,\n generatedAt: r['generated_at'] as string,\n }));\n }\n\n // ── Approvals ───────────────────────────\n\n setApproval(pattern: string, action: 'save' | 'ignore' | 'auto'): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO node_approvals (pattern, action, created_at) VALUES (?, ?, ?)\n `).run(pattern, action, new Date().toISOString());\n }\n\n getApproval(pattern: string): string | undefined {\n const row = this.db.prepare('SELECT action FROM node_approvals WHERE pattern = ?').get(pattern) as { action: string } | undefined;\n return row?.action;\n }\n\n // ── Stats ───────────────────────────────\n\n getStats(sessionId: string): { nodes: number; edges: number; events: number; tasks: number } {\n const nodes = (this.db.prepare('SELECT COUNT(*) as c FROM nodes WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const edges = (this.db.prepare('SELECT COUNT(*) as c FROM edges WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const events = (this.db.prepare('SELECT COUNT(*) as c FROM activity_events WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const tasks = (this.db.prepare('SELECT COUNT(*) as c FROM tasks WHERE session_id = ?').get(sessionId) as { c: number }).c;\n return { nodes, edges, events, tasks };\n }\n}\n","import { z } from 'zod';\nimport type { CartographyDB } from './db.js';\nimport { NODE_TYPES, EDGE_RELATIONSHIPS, EVENT_TYPES, SOPStepSchema } from './types.js';\nimport { scanAllBookmarks } from './bookmarks.js';\n\n// Lazy import to avoid hard-wiring SDK at module parse time\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype McpServer = any;\n\nexport interface CartographyToolsOptions {\n /** Called when the agent needs a human answer. Return the user's response. */\n onAskUser?: (question: string, context?: string) => Promise<string>;\n}\n\nexport function stripSensitive(target: string): string {\n try {\n const url = new URL(target.startsWith('http') ? target : `tcp://${target}`);\n return `${url.hostname}${url.port ? ':' + url.port : ''}`;\n } catch {\n return target\n .replace(/\\/.*$/, '')\n .replace(/\\?.*$/, '')\n .replace(/@.*:/, ':');\n }\n}\n\nexport async function createCartographyTools(\n db: CartographyDB,\n sessionId: string,\n opts: CartographyToolsOptions = {},\n): Promise<McpServer> {\n // Dynamically import the SDK so missing package doesn't crash at load time\n const sdk = await import('@anthropic-ai/claude-code');\n const { tool, createSdkMcpServer } = sdk as {\n tool: (name: string, description: string, schema: z.ZodRawShape, handler: (args: Record<string, unknown>) => Promise<{ content: Array<{ type: string; text: string }> }>) => unknown;\n createSdkMcpServer: (opts: { name: string; version: string; tools: unknown[] }) => McpServer;\n };\n\n const tools = [\n tool('save_node', 'Infrastructure-Node speichern', {\n id: z.string(),\n type: z.enum(NODE_TYPES),\n name: z.string(),\n discoveredVia: z.string(),\n confidence: z.number().min(0).max(1),\n metadata: z.record(z.unknown()).optional(),\n tags: z.array(z.string()).optional(),\n }, async (args) => {\n const node = {\n id: stripSensitive(args['id'] as string),\n type: args['type'] as typeof NODE_TYPES[number],\n name: args['name'] as string,\n discoveredVia: args['discoveredVia'] as string,\n confidence: args['confidence'] as number,\n metadata: (args['metadata'] as Record<string, unknown>) ?? {},\n tags: (args['tags'] as string[]) ?? [],\n };\n db.upsertNode(sessionId, node);\n return { content: [{ type: 'text', text: `✓ Node: ${node.id}` }] };\n }),\n\n tool('save_edge', 'Verbindung zwischen zwei Nodes speichern', {\n sourceId: z.string(),\n targetId: z.string(),\n relationship: z.enum(EDGE_RELATIONSHIPS),\n evidence: z.string(),\n confidence: z.number().min(0).max(1),\n }, async (args) => {\n db.insertEdge(sessionId, {\n sourceId: args['sourceId'] as string,\n targetId: args['targetId'] as string,\n relationship: args['relationship'] as typeof EDGE_RELATIONSHIPS[number],\n evidence: args['evidence'] as string,\n confidence: args['confidence'] as number,\n });\n return { content: [{ type: 'text', text: `✓ ${args['sourceId']}→${args['targetId']}` }] };\n }),\n\n tool('save_event', 'Activity-Event (Prozess/Verbindung) speichern', {\n eventType: z.enum(EVENT_TYPES),\n process: z.string(),\n pid: z.number(),\n target: z.string().optional(),\n targetType: z.enum(NODE_TYPES).optional(),\n port: z.number().optional(),\n }, async (args) => {\n db.insertEvent(sessionId, {\n eventType: args['eventType'] as typeof EVENT_TYPES[number],\n process: args['process'] as string,\n pid: args['pid'] as number,\n target: args['target'] ? stripSensitive(args['target'] as string) : undefined,\n targetType: args['targetType'] as typeof NODE_TYPES[number] | undefined,\n port: args['port'] as number | undefined,\n });\n return { content: [{ type: 'text', text: `✓ ${args['eventType']}` }] };\n }),\n\n tool('get_catalog', 'Aktuellen Katalog abrufen (Duplikat-Check)', {\n includeEdges: z.boolean().default(true),\n }, async (args) => {\n const nodes = db.getNodes(sessionId);\n const edges = (args['includeEdges'] as boolean) ? db.getEdges(sessionId) : [];\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n count: { nodes: nodes.length, edges: edges.length },\n nodeIds: nodes.map(n => n.id),\n }),\n }],\n };\n }),\n\n tool('manage_task', 'Task starten, beenden oder beschreiben', {\n action: z.enum(['start', 'end', 'describe']),\n description: z.string().optional(),\n }, async (args) => {\n const action = args['action'] as string;\n if (action === 'start') {\n const id = db.startTask(sessionId, args['description'] as string | undefined);\n return { content: [{ type: 'text', text: `✓ Task gestartet: ${id}` }] };\n }\n if (action === 'end') {\n db.endCurrentTask(sessionId);\n return { content: [{ type: 'text', text: '✓ Task beendet' }] };\n }\n db.updateTaskDescription(sessionId, args['description'] as string);\n return { content: [{ type: 'text', text: '✓ Beschreibung aktualisiert' }] };\n }),\n\n tool('ask_user', 'Rückfrage an den User stellen — bei Unklarheiten, fehlenden Credentials-Hinweisen oder wenn Kontext fehlt', {\n question: z.string().describe('Die Frage an den User (klar und konkret)'),\n context: z.string().optional().describe('Optionaler Zusatzkontext warum die Frage relevant ist'),\n }, async (args) => {\n const question = args['question'] as string;\n const context = args['context'] as string | undefined;\n\n if (opts.onAskUser) {\n const answer = await opts.onAskUser(question, context);\n return { content: [{ type: 'text', text: answer }] };\n }\n\n // Fallback when not interactive (piped input, daemon, etc.)\n return {\n content: [{ type: 'text', text: '(Kein interaktiver Modus — bitte ohne diese Information fortfahren)' }],\n };\n }),\n\n tool('scan_bookmarks', 'Alle Browser-Lesezeichen scannen — nur Hostnamen, keine persönlichen Daten', {\n minConfidence: z.number().min(0).max(1).default(0.5).optional(),\n }, async () => {\n const hosts = await scanAllBookmarks();\n return {\n content: [{\n type: 'text',\n text: JSON.stringify({\n count: hosts.length,\n hosts: hosts.map(h => ({\n hostname: h.hostname,\n port: h.port,\n protocol: h.protocol,\n source: h.source,\n })),\n note: 'Nur Hostnamen — keine Pfade, keine persönlichen Daten. Entscheide selbst welche davon Business-Tools sind.',\n }),\n }],\n };\n }),\n\n tool('scan_k8s_resources', 'Kubernetes-Cluster via kubectl scannen — 100% readonly (get, describe)', {\n namespace: z.string().optional().describe('Namespace filtern — leer = alle Namespaces'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const ns = args['namespace'] as string | undefined;\n const nsFlag = ns ? `-n ${ns}` : '--all-namespaces';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 15_000, shell: '/bin/sh' }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['CONTEXT', 'kubectl config current-context 2>/dev/null || echo \"(kein Context gesetzt)\"'],\n ['NODES', 'kubectl get nodes -o wide'],\n ['NAMESPACES', 'kubectl get namespaces'],\n ['SERVICES', `kubectl get services ${nsFlag}`],\n ['DEPLOYMENTS', `kubectl get deployments ${nsFlag}`],\n ['STATEFULSETS', `kubectl get statefulsets ${nsFlag}`],\n ['INGRESSES', `kubectl get ingress ${nsFlag} 2>/dev/null || echo \"(keine)\"`],\n ['PODS_RUNNING', `kubectl get pods ${nsFlag} --field-selector=status.phase=Running 2>/dev/null | head -60`],\n ['CONFIGMAPS_SYSTEM', 'kubectl get configmaps -n kube-system 2>/dev/null | head -30'],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_aws_resources', 'AWS-Infrastruktur via AWS CLI scannen — 100% readonly (describe, list)', {\n region: z.string().optional().describe('AWS Region — default: AWS_DEFAULT_REGION oder Profil'),\n profile: z.string().optional().describe('AWS CLI Profil'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const region = args['region'] as string | undefined;\n const profile = args['profile'] as string | undefined;\n const env: NodeJS.ProcessEnv = { ...process.env };\n if (region) env['AWS_DEFAULT_REGION'] = region;\n const pf = profile ? `--profile ${profile}` : '';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 20_000, shell: '/bin/sh', env }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['IDENTITY', `aws sts get-caller-identity ${pf} --output json`],\n ['EC2', `aws ec2 describe-instances ${pf} --query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,PublicIpAddress,PrivateIpAddress,Tags[?Key==\\`Name\\`].Value|[0]]' --output table`],\n ['RDS', `aws rds describe-db-instances ${pf} --query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBInstanceStatus,Endpoint.Address,Endpoint.Port]' --output table`],\n ['ELB_V2', `aws elbv2 describe-load-balancers ${pf} --query 'LoadBalancers[*].[LoadBalancerName,DNSName,Type,State.Code]' --output table`],\n ['EKS', `aws eks list-clusters ${pf} --output json`],\n ['ELASTICACHE', `aws elasticache describe-cache-clusters ${pf} --query 'CacheClusters[*].[CacheClusterId,Engine,CacheClusterStatus]' --output table 2>/dev/null || echo \"(nicht verfügbar)\"`],\n ['S3', `aws s3 ls ${pf} 2>/dev/null || echo \"(nicht verfügbar)\"`],\n ['VPC', `aws ec2 describe-vpcs ${pf} --query 'Vpcs[*].[VpcId,CidrBlock,IsDefault,Tags[?Key==\\`Name\\`].Value|[0]]' --output table`],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_gcp_resources', 'Google Cloud Platform via gcloud CLI scannen — 100% readonly (list, describe)', {\n project: z.string().optional().describe('GCP Project ID — default: aktuelles gcloud-Projekt'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const project = args['project'] as string | undefined;\n const pf = project ? `--project ${project}` : '';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 20_000, shell: '/bin/sh' }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['IDENTITY', `gcloud config list account --format='value(core.account)' 2>/dev/null; gcloud config get-value project 2>/dev/null`],\n ['COMPUTE_INSTANCES', `gcloud compute instances list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['SQL_INSTANCES', `gcloud sql instances list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['GKE_CLUSTERS', `gcloud container clusters list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['CLOUD_RUN', `gcloud run services list ${pf} --platform managed 2>/dev/null || echo \"(error)\"`],\n ['CLOUD_FUNCTIONS', `gcloud functions list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['REDIS', `gcloud redis instances list ${pf} --regions=- 2>/dev/null || echo \"(error)\"`],\n ['PUBSUB', `gcloud pubsub topics list ${pf} 2>/dev/null || echo \"(error)\"`],\n ['SPANNER', `gcloud spanner instances list ${pf} 2>/dev/null || echo \"(error)\"`],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_azure_resources', 'Azure-Infrastruktur via az CLI scannen — 100% readonly (list, show)', {\n subscription: z.string().optional().describe('Azure Subscription ID'),\n resourceGroup: z.string().optional().describe('Resource Group filtern'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const sub = args['subscription'] as string | undefined;\n const rg = args['resourceGroup'] as string | undefined;\n const sf = sub ? `--subscription ${sub}` : '';\n const rf = rg ? `--resource-group ${rg}` : '';\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 20_000, shell: '/bin/sh' }).toString().trim();\n } catch (e) {\n return `(error: ${e instanceof Error ? e.message.split('\\n')[0] : String(e)})`;\n }\n };\n const sections: [string, string][] = [\n ['IDENTITY', `az account show --output json ${sf} 2>/dev/null || echo \"(nicht eingeloggt — az login)\"`],\n ['VMS', `az vm list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['AKS', `az aks list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['SQL_SERVERS', `az sql server list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['POSTGRES', `az postgres server list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['REDIS', `az redis list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['WEBAPPS', `az webapp list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['CONTAINER_APPS', `az containerapp list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ['FUNCTIONS', `az functionapp list ${sf} ${rf} --output table 2>/dev/null || echo \"(error)\"`],\n ];\n const out = sections.map(([l, c]) => `=== ${l} ===\\n${run(c)}`).join('\\n\\n');\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('scan_installed_apps', 'Alle installierten Apps und Tools auf dem PC scannen — IDEs, Office, Dev-Tools, Business-Apps', {\n searchHint: z.string().optional().describe('Optionaler Suchbegriff um gezielt nach bestimmten Tools zu suchen (z.B. \"hubspot windsurf cursor\")'),\n }, async (args) => {\n const { execSync } = await import('node:child_process');\n const hint = args['searchHint'] as string | undefined;\n\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: 'pipe', timeout: 15_000, shell: '/bin/sh' }).toString().trim();\n } catch {\n return '';\n }\n };\n\n const platform = process.platform;\n const results: Record<string, string> = {};\n\n if (platform === 'darwin') {\n // macOS: scan /Applications\n results['APPLICATIONS'] = run('ls /Applications/ 2>/dev/null | head -200') || '(leer)';\n results['USER_APPLICATIONS'] = run('ls ~/Applications/ 2>/dev/null | head -100') || '(leer)';\n // Homebrew\n results['BREW_CASKS'] = run('brew list --cask 2>/dev/null | head -100') || '(brew nicht installiert)';\n results['BREW_FORMULAE'] = run('brew list --formula 2>/dev/null | head -150') || '(brew nicht installiert)';\n // Spotlight — find .app bundles\n results['SPOTLIGHT_APPS'] = run('mdfind \"kMDItemKind == \\'Application\\'\" 2>/dev/null | grep -v \"^/System\" | grep -v \"^/Library/Apple\" | head -100') || '(Spotlight nicht verfügbar)';\n } else if (platform === 'linux') {\n // Linux: dpkg, snap, flatpak, .desktop files\n results['DPKG'] = run('dpkg --list 2>/dev/null | awk \\'{print $2}\\' | head -200') || '(dpkg nicht verfügbar)';\n results['SNAP'] = run('snap list 2>/dev/null | head -50') || '(snap nicht verfügbar)';\n results['FLATPAK'] = run('flatpak list 2>/dev/null | head -50') || '(flatpak nicht verfügbar)';\n results['DESKTOP_FILES'] = run('ls /usr/share/applications/*.desktop ~/.local/share/applications/*.desktop 2>/dev/null | xargs -I{} basename {} .desktop 2>/dev/null | head -100') || '(keine .desktop files)';\n results['RPM'] = run('rpm -qa 2>/dev/null | head -200') || '(rpm nicht verfügbar)';\n } else if (platform === 'win32') {\n results['WINGET'] = run('winget list 2>/dev/null | head -100') || '(winget nicht verfügbar)';\n results['PROGRAMS_x64'] = run('reg query \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\" /s /v DisplayName 2>/dev/null | findstr DisplayName | head -100') || '(nicht verfügbar)';\n }\n\n // Check known dev/business tools via `which`\n const knownTools = [\n // IDEs & Editors\n 'code', 'code-insiders', 'cursor', 'windsurf', 'zed', 'vim', 'nvim', 'emacs', 'nano', 'sublime_text', 'atom',\n 'idea', 'webstorm', 'pycharm', 'goland', 'datagrip', 'clion', 'rider', 'phpstorm', 'rubymine', 'appcode',\n // Dev Tools\n 'git', 'gh', 'docker', 'docker-compose', 'podman', 'kubectl', 'helm', 'terraform', 'ansible',\n 'node', 'npm', 'npx', 'yarn', 'pnpm', 'bun', 'deno',\n 'python', 'python3', 'pip', 'pip3', 'pipenv', 'poetry', 'conda',\n 'ruby', 'gem', 'bundler', 'rails',\n 'java', 'mvn', 'gradle', 'kotlin',\n 'go', 'cargo', 'rustc',\n 'php', 'composer',\n 'dotnet', 'dotnet-sdk',\n // Databases\n 'psql', 'mysql', 'mysqladmin', 'mongo', 'mongosh', 'redis-cli', 'sqlite3', 'clickhouse-client',\n // Cloud CLIs\n 'aws', 'gcloud', 'az', 'heroku', 'fly', 'vercel', 'netlify', 'wrangler',\n // Infra\n 'vagrant', 'packer', 'consul', 'vault', 'nomad',\n // Communication / SaaS\n 'slack', 'discord', 'zoom', 'teams', 'skype', 'telegram', 'signal',\n // Browsers\n 'google-chrome', 'chromium', 'firefox', 'safari', 'brave', 'opera', 'edge',\n // Monitoring / Analytics\n 'datadog-agent', 'newrelic-agent', 'prometheus', 'grafana-cli',\n // Other tools\n 'ngrok', 'stripe', 'supabase', 'neon',\n ];\n\n const found: string[] = [];\n const notFound: string[] = [];\n for (const t of knownTools) {\n const r = run(`which ${t} 2>/dev/null`);\n if (r) found.push(`${t}: ${r}`);\n else notFound.push(t);\n }\n results['WHICH_FOUND'] = found.join('\\n') || '(nichts gefunden)';\n results['WHICH_NOT_FOUND'] = notFound.join(', ');\n\n // Hint-based search: if user asks for specific tools, do targeted search\n if (hint) {\n const terms = hint.split(/[\\s,]+/).filter(Boolean);\n const hintResults: string[] = [];\n for (const term of terms) {\n const safe = term.replace(/[^a-zA-Z0-9._-]/g, '');\n if (!safe) continue;\n const r = run(`which ${safe} 2>/dev/null || find /Applications ~/Applications /usr/bin /usr/local/bin /opt/homebrew/bin ~/.local/bin 2>/dev/null -iname \"*${safe}*\" -maxdepth 3 2>/dev/null | head -5`);\n if (r) hintResults.push(`${term}: ${r}`);\n else hintResults.push(`${term}: (nicht gefunden)`);\n }\n results['HINT_SEARCH'] = hintResults.join('\\n');\n }\n\n const out = Object.entries(results)\n .map(([k, v]) => `=== ${k} ===\\n${v}`)\n .join('\\n\\n');\n\n return { content: [{ type: 'text', text: out }] };\n }),\n\n tool('save_sop', 'Standard Operating Procedure speichern', {\n workflowId: z.string(),\n title: z.string(),\n description: z.string(),\n steps: z.array(SOPStepSchema),\n involvedSystems: z.array(z.string()),\n estimatedDuration: z.string(),\n frequency: z.string(),\n confidence: z.number().min(0).max(1),\n }, async (args) => {\n db.insertSOP({\n workflowId: args['workflowId'] as string,\n title: args['title'] as string,\n description: args['description'] as string,\n steps: args['steps'] as ReturnType<typeof SOPStepSchema.parse>[],\n involvedSystems: args['involvedSystems'] as string[],\n estimatedDuration: args['estimatedDuration'] as string,\n frequency: args['frequency'] as string,\n confidence: args['confidence'] as number,\n });\n return { content: [{ type: 'text', text: `✓ SOP: ${args['title']}` }] };\n }),\n ];\n\n return createSdkMcpServer({\n name: 'cartography',\n version: '0.1.0',\n tools,\n });\n}\n","// PreToolUse Safety Hook — enforces read-only policy on all Bash calls\n\nimport type { HookCallback } from '@anthropic-ai/claude-code';\n\n// Word-boundary matched dangerous commands\nconst BLOCKED_CMDS =\n /\\b(rm|mv|cp|dd|mkfs|chmod|chown|chgrp|kill|killall|pkill|reboot|shutdown|poweroff|halt|systemctl\\s+(start|stop|restart|enable|disable)|service\\s+(start|stop|restart)|docker\\s+(rm|rmi|stop|kill|exec|run|build|push)|kubectl\\s+(delete|apply|edit|exec|run|create|patch)|apt|yum|dnf|pacman|pip\\s+install|npm\\s+(install|uninstall)|curl\\s+.*-X\\s*(POST|PUT|DELETE|PATCH)|wget\\s+-O|tee\\s)\\b/i;\n// Redirect operators (no word boundary needed)\nconst BLOCKED_REDIRECTS = />>|>[^>]/;\n\nexport type { HookCallback };\n\nexport const safetyHook: HookCallback = async (input) => {\n // Only intercept PreToolUse events (other hook events don't have tool_name)\n if (!('tool_name' in input)) return {};\n if ((input as { tool_name: string }).tool_name !== 'Bash') return {};\n\n const cmd = ((input as { tool_input: { command?: string } }).tool_input)?.command ?? '';\n\n if (BLOCKED_CMDS.test(cmd) || BLOCKED_REDIRECTS.test(cmd)) {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: `BLOCKED: \"${cmd}\" — read-only policy`,\n },\n };\n }\n\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n },\n };\n};\n","import type { CartographyDB } from './db.js';\nimport { createCartographyTools } from './tools.js';\nimport { safetyHook } from './safety.js';\nimport type { CartographyConfig, TaskRow } from './types.js';\n\n// ── Discovery Event Types ────────────────────────────────────────────────────\n\nexport type DiscoveryEvent =\n | { kind: 'thinking'; text: string }\n | { kind: 'tool_call'; tool: string; input: Record<string, unknown> }\n | { kind: 'tool_result'; tool: string; output: string }\n | { kind: 'turn'; turn: number }\n | { kind: 'done' };\n\nexport type AskUserFn = (question: string, context?: string) => Promise<string>;\n\n// ── runDiscovery ─────────────────────────────────────────────────────────────\n\nexport async function runDiscovery(\n config: CartographyConfig,\n db: CartographyDB,\n sessionId: string,\n onEvent?: (event: DiscoveryEvent) => void,\n onAskUser?: AskUserFn,\n hint?: string,\n): Promise<void> {\n const { query } = await import('@anthropic-ai/claude-code');\n const tools = await createCartographyTools(db, sessionId, { onAskUser });\n\n const hintSection = hint\n ? `\\n⚡ USER-HINT (PRIORITÄT): Der User möchte gezielt nach folgenden Tools suchen: \"${hint}\"\\n → scan_installed_apps(searchHint: \"${hint}\") SOFORT ausführen und diese Tools als saas_tool oder config_file speichern!\\n`\n : '';\n\n const systemPrompt = `Du bist ein Infrastruktur-Discovery-Agent. Kartographiere die gesamte Systemlandschaft — lokale Services, SaaS-Tools UND alle installierten Apps/Tools des Users.\n${hintSection}\n━━ PFLICHT-REIHENFOLGE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nSCHRITT 1 — Browser-Lesezeichen (IMMER ZUERST):\n scan_bookmarks() aufrufen → jede zurückgegebene Domain klassifizieren:\n • Business-Tools (GitHub, Notion, Jira, Linear, Vercel, AWS, Datadog, etc.) → save_node als saas_tool\n • Interne Hosts (IPs, custom.company.com:PORT) → save_node als web_service\n • Persönliches (Social Media, News, Streaming, Shopping) → IGNORIEREN, NICHT speichern\n\nSCHRITT 2 — Installierte Apps & Tools (SEHR WICHTIG):\n scan_installed_apps() aufrufen → ALLE gefundenen Apps/Tools klassifizieren:\n • IDEs (VS Code, Cursor, Windsurf, JetBrains, etc.) → save_node als saas_tool mit category=\"ide\"\n • Office & Produktivität (Word, Excel, Notion, Obsidian, etc.) → save_node als saas_tool mit category=\"productivity\"\n • Dev-Tools (Docker, kubectl, git, Node, Python, etc.) → save_node als saas_tool mit category=\"dev-tool\"\n • Business-Apps (Slack, Zoom, HubSpot, Salesforce, etc.) → save_node als saas_tool mit category=\"business\"\n • Browser (Chrome, Firefox, Safari, etc.) → save_node als saas_tool mit category=\"browser\"\n • Design-Tools (Figma, Sketch, Adobe, etc.) → save_node als saas_tool mit category=\"design\"\n ALLE relevanten Tools speichern — auch wenn offline/lokal!\n\nSCHRITT 3 — Lokale Infrastruktur:\n ss -tlnp && ps aux → alle lauschenden Ports/Prozesse identifizieren\n Jeden Service vertiefen: DB→Schemas, API→Endpoints, Queue→Topics\n\nSCHRITT 4 — Cloud & Kubernetes (falls CLI vorhanden):\n scan_k8s_resources() → Nodes, Services, Pods, Deployments, Ingresses\n scan_aws_resources() → EC2, RDS, ELB, EKS, ElastiCache, S3 (falls AWS CLI + Credentials)\n scan_gcp_resources() → Compute, SQL, GKE, Cloud Run, Functions (falls gcloud + Auth)\n scan_azure_resources() → VMs, AKS, SQL, Redis, WebApps (falls az CLI + Login)\n Fehler / \"nicht verfügbar\" → ignorieren, weiter mit nächstem Tool\n\nSCHRITT 5 — Config-Files:\n .env, docker-compose.yml, application.yml, kubernetes/*.yml\n Nur Host:Port extrahieren — KEINE Credentials\n\nSCHRITT 6 — Rückfragen bei Unklarheit:\n ask_user() nutzen wenn: Dienst unklar ist, Kontext fehlt, oder User Input sinnvoll wäre\n Beispiele: \"Welche Umgebung ist das (dev/staging/prod)?\", \"Ist <host> ein internes Tool?\"\n\nSCHRITT 7 — Fertig wenn alle Spuren erschöpft.\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nPORT-MAPPING: 5432=postgres, 3306=mysql, 27017=mongodb, 6379=redis,\n9092=kafka, 5672=rabbitmq, 80/443/8080/3000=web_service,\n9090=prometheus, 8500=consul, 8200=vault, 2379=etcd\n\nREGELN:\n• Nur read-only (ss, ps, cat, head, curl -s, docker inspect, kubectl get)\n• Node IDs: \"type:host:port\" oder \"type:name\" — keine Pfade, keine Credentials\n• saas_tool IDs: \"saas_tool:github.com\", \"saas_tool:vscode\", \"saas_tool:cursor\"\n• Installed-App IDs: \"saas_tool:<appname>\" z.B. \"saas_tool:slack\", \"saas_tool:docker-desktop\"\n• Confidence: 0.9 direkt gesehen, 0.7 aus Config/Bookmarks/Apps, 0.5 Vermutung\n• metadata erlaubt: { description, category, port, version, path } — keine Passwörter\n• get_catalog vor save_node → Duplikate vermeiden\n• Edges speichern wenn Verbindungen klar erkennbar sind\n\nEntrypoints: ${config.entryPoints.join(', ')}`;\n\n const initialPrompt = hint\n ? `Starte Discovery mit USER-HINT: \"${hint}\".\nFühre SOFORT scan_installed_apps(searchHint: \"${hint}\") aus um nach diesen Tools zu suchen.\nDann scan_bookmarks, dann lokale Services.\nNutze ask_user wenn du Kontext vom User brauchst.`\n : `Starte Discovery jetzt.\nFühre SOFORT als erstes scan_bookmarks aus — noch bevor du ss oder ps verwendest.\nDanach scan_installed_apps() für alle installierten Apps und Tools.\nDann systematisch lokale Services, dann Config-Files.\nNutze ask_user wenn du Kontext vom User brauchst.`;\n\n let turnCount = 0;\n\n for await (const msg of query({\n prompt: initialPrompt,\n options: {\n model: config.agentModel,\n maxTurns: config.maxTurns,\n customSystemPrompt: systemPrompt,\n mcpServers: { cartography: tools },\n allowedTools: [\n 'Bash',\n 'mcp__cartograph__save_node',\n 'mcp__cartograph__save_edge',\n 'mcp__cartograph__get_catalog',\n 'mcp__cartograph__scan_bookmarks',\n 'mcp__cartograph__scan_installed_apps',\n 'mcp__cartograph__scan_k8s_resources',\n 'mcp__cartograph__scan_aws_resources',\n 'mcp__cartograph__scan_gcp_resources',\n 'mcp__cartograph__scan_azure_resources',\n 'mcp__cartograph__ask_user',\n ],\n hooks: {\n PreToolUse: [{ matcher: 'Bash', hooks: [safetyHook] }],\n },\n permissionMode: 'bypassPermissions',\n },\n })) {\n if (!onEvent) continue;\n\n if (msg.type === 'assistant') {\n turnCount++;\n onEvent({ kind: 'turn', turn: turnCount });\n\n for (const block of msg.message.content) {\n if (block.type === 'text') {\n onEvent({ kind: 'thinking', text: block.text });\n }\n if (block.type === 'tool_use') {\n onEvent({\n kind: 'tool_call',\n tool: block.name as string,\n input: block.input as Record<string, unknown>,\n });\n }\n }\n }\n\n if (msg.type === 'user') {\n const content = msg.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block && (block as { type: string }).type === 'tool_result') {\n const tb = block as { tool_use_id?: string; content?: unknown };\n const text = typeof tb.content === 'string' ? tb.content : '';\n onEvent({ kind: 'tool_result', tool: tb.tool_use_id ?? '', output: text });\n }\n }\n }\n }\n\n if (msg.type === 'result') {\n onEvent({ kind: 'done' });\n return;\n }\n }\n}\n\n// ── runShadowCycle ───────────────────────────────────────────────────────────\n\nexport async function runShadowCycle(\n config: CartographyConfig,\n db: CartographyDB,\n sessionId: string,\n prevSnapshot: string,\n currSnapshot: string,\n onOutput?: (msg: unknown) => void,\n): Promise<void> {\n const { query } = await import('@anthropic-ai/claude-code');\n const tools = await createCartographyTools(db, sessionId);\n\n const prompt = `Analysiere den Diff zwischen diesen beiden System-Snapshots.\nFinde:\n- Neue/geschlossene TCP-Verbindungen → save_event\n- Neue/beendete Prozesse → save_event\n- Bisher unbekannte Services → get_catalog prüfen, dann save_node\n- Task-Grenzen (Inaktivität, Tool-Wechsel) → manage_task\ntarget = NUR Host:Port. Kurz und effizient.\n\n=== VORHER ===\n${prevSnapshot}\n\n=== JETZT ===\n${currSnapshot}`;\n\n for await (const msg of query({\n prompt,\n options: {\n model: config.shadowModel,\n maxTurns: 5,\n mcpServers: { cartography: tools },\n allowedTools: [\n 'mcp__cartograph__save_event',\n 'mcp__cartograph__save_node',\n 'mcp__cartograph__save_edge',\n 'mcp__cartograph__get_catalog',\n 'mcp__cartograph__manage_task',\n ],\n permissionMode: 'bypassPermissions',\n },\n })) {\n if (onOutput) onOutput(msg);\n }\n}\n\n// ── generateSOPs ─────────────────────────────────────────────────────────────\n\nexport async function generateSOPs(db: CartographyDB, sessionId: string): Promise<number> {\n const Anthropic = (await import('@anthropic-ai/sdk')).default;\n const client = new Anthropic();\n\n const tasks = db.getTasks(sessionId).filter(t => t.status === 'completed');\n if (tasks.length === 0) return 0;\n\n // Cluster tasks by involved services\n const clusters = clusterTasks(tasks);\n let generated = 0;\n\n for (const cluster of clusters) {\n const workflowId = crypto.randomUUID();\n const involved = JSON.parse(cluster[0]?.involvedServices ?? '[]') as string[];\n\n const taskDescriptions = cluster\n .map((t, i) => `Task ${i + 1}: ${t.description ?? 'Unnamed'}\\nSteps: ${t.steps}`)\n .join('\\n\\n');\n\n const response = await client.messages.create({\n model: 'claude-sonnet-4-5-20250929',\n max_tokens: 2048,\n messages: [{\n role: 'user',\n content: `Generiere eine SOP (Standard Operating Procedure) für diesen wiederkehrenden Workflow.\nAntworte NUR mit validen JSON im Format:\n{\n \"title\": \"...\",\n \"description\": \"...\",\n \"steps\": [{\"order\": 1, \"instruction\": \"...\", \"tool\": \"...\", \"target\": \"...\", \"notes\": \"...\"}],\n \"involvedSystems\": [\"...\"],\n \"estimatedDuration\": \"~N Minuten\",\n \"frequency\": \"Xmal täglich\",\n \"confidence\": 0.8\n}\n\nTasks:\n${taskDescriptions}\n\nBeteiligte Services: ${involved.join(', ')}`,\n }],\n });\n\n const text = response.content[0]?.type === 'text' ? response.content[0].text : '';\n\n try {\n const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) continue;\n const parsed = JSON.parse(jsonMatch[0]) as {\n title: string;\n description: string;\n steps: Array<{ order: number; instruction: string; tool: string; target?: string; notes?: string }>;\n involvedSystems: string[];\n estimatedDuration: string;\n frequency: string;\n confidence: number;\n };\n\n db.insertSOP({ workflowId, ...parsed });\n generated++;\n } catch {\n // Skip malformed responses\n }\n }\n\n return generated;\n}\n\nfunction clusterTasks(tasks: TaskRow[]): TaskRow[][] {\n // Simple clustering: group by overlapping involved services\n const clusters: TaskRow[][] = [];\n const assigned = new Set<string>();\n\n for (const task of tasks) {\n if (assigned.has(task.id)) continue;\n\n const cluster = [task];\n assigned.add(task.id);\n\n const taskServices = new Set(JSON.parse(task.involvedServices ?? '[]') as string[]);\n\n for (const other of tasks) {\n if (assigned.has(other.id)) continue;\n const otherServices = new Set(JSON.parse(other.involvedServices ?? '[]') as string[]);\n // Check overlap\n const overlap = [...taskServices].filter(s => otherServices.has(s));\n if (overlap.length > 0) {\n cluster.push(other);\n assigned.add(other.id);\n }\n }\n\n clusters.push(cluster);\n }\n\n return clusters;\n}\n","import { execSync, spawn } from 'node:child_process';\nimport { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';\nimport { CartographyDB } from './db.js';\nimport { IPCServer, cleanStaleSocket } from './ipc.js';\nimport { NotificationService } from './notify.js';\nimport { runShadowCycle } from './agent.js';\nimport type { CartographyConfig, ShadowStatus, ClientMessage } from './types.js';\n\n// ── Snapshot ─────────────────────────────────────────────────────────────────\n\nexport function takeSnapshot(config: CartographyConfig): string {\n const run = (cmd: string): string => {\n try {\n return execSync(cmd, { stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000 }).toString();\n } catch {\n return `(${cmd}: not available)`;\n }\n };\n\n const ss = run('ss -tnp 2>/dev/null || ss -tn 2>/dev/null || echo \"ss not available\"');\n const ps = run('ps aux --sort=-start_time 2>/dev/null | head -50');\n\n let win = '';\n if (config.trackWindowFocus) {\n try {\n win = execSync('xdotool getactivewindow getwindowname 2>/dev/null', {\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 2000,\n }).toString().trim();\n } catch {\n win = '';\n }\n }\n\n return `=== TCP ===\\n${ss}\\n=== PS ===\\n${ps}\\n=== Window ===\\n${win}`;\n}\n\n// ── ShadowDaemon ─────────────────────────────────────────────────────────────\n\nexport class ShadowDaemon {\n private running = false;\n private paused = false;\n private prevSnapshot = '';\n private cyclesRun = 0;\n private cyclesSkipped = 0;\n private lastTaskCount = 0;\n private sessionId = '';\n\n constructor(\n private config: CartographyConfig,\n private db: CartographyDB,\n private ipc: IPCServer,\n private notify: NotificationService,\n ) {}\n\n async run(): Promise<string> {\n this.running = true;\n this.sessionId = this.db.createSession('shadow', this.config);\n\n process.on('SIGTERM', () => this.stop());\n process.on('SIGINT', () => this.stop());\n process.on('SIGUSR1', () => this.pause());\n process.on('SIGUSR2', () => this.resume());\n\n // Handle IPC commands from attached clients\n this.ipc.on('message', (msg: ClientMessage) => {\n switch (msg.type) {\n case 'command':\n if (msg.command === 'pause') this.pause();\n else if (msg.command === 'resume') this.resume();\n else if (msg.command === 'stop') this.stop();\n else if (msg.command === 'status') {\n this.ipc.broadcast({ type: 'status', data: this.getStatus() });\n } else if (msg.command === 'new-task') {\n this.db.startTask(this.sessionId);\n this.ipc.broadcast({ type: 'info', message: 'Task gestartet' });\n } else if (msg.command === 'end-task') {\n this.db.endCurrentTask(this.sessionId);\n this.ipc.broadcast({ type: 'info', message: 'Task beendet' });\n }\n break;\n case 'task-description':\n this.db.updateTaskDescription(this.sessionId, msg.description);\n break;\n case 'prompt-response':\n // Handle SOP candidate response\n if (msg.id.startsWith('sop-suggest:')) {\n const taskId = msg.id.replace('sop-suggest:', '');\n if (msg.answer === 'ja' || msg.answer === 'yes' || msg.answer === 'Ja, als SOP speichern') {\n this.db.markTaskAsSOPCandidate(taskId);\n this.ipc.broadcast({ type: 'info', message: `Task als SOP-Kandidat markiert` });\n }\n }\n break;\n }\n });\n\n while (this.running) {\n if (this.paused) {\n // Still broadcast status while paused\n this.ipc.broadcast({ type: 'status', data: this.getStatus() });\n await sleep(this.config.pollIntervalMs);\n continue;\n }\n\n const snapshot = takeSnapshot(this.config);\n\n if (snapshot !== this.prevSnapshot) {\n try {\n await runShadowCycle(\n this.config,\n this.db,\n this.sessionId,\n this.prevSnapshot,\n snapshot,\n (msg) => {\n if (this.ipc.hasClients()) {\n this.ipc.broadcast({ type: 'agent-output', text: JSON.stringify(msg) });\n }\n },\n );\n this.cyclesRun++;\n } catch (err) {\n process.stderr.write(`⚠ Cycle error: ${err}\\n`);\n }\n this.prevSnapshot = snapshot;\n\n // Check for newly completed tasks → suggest as SOP\n this.checkForCompletedTasks();\n } else {\n this.cyclesSkipped++;\n }\n\n // Broadcast status\n this.ipc.broadcast({ type: 'status', data: this.getStatus() });\n\n // Desktop notification if no clients attached\n if (!this.ipc.hasClients()) {\n const stats = this.db.getStats(this.sessionId);\n if (stats.events > 0 && this.cyclesRun % 10 === 0) {\n this.notify.workflowDetected(stats.tasks, `${stats.events} events so far`);\n }\n }\n\n await sleep(this.config.pollIntervalMs);\n }\n\n this.db.endSession(this.sessionId);\n this.ipc.stop();\n cleanup(this.config);\n return this.sessionId;\n }\n\n pause(): void {\n if (!this.paused) {\n this.paused = true;\n this.ipc.broadcast({ type: 'info', message: '⏸ Shadow-Daemon pausiert' });\n }\n }\n\n resume(): void {\n if (this.paused) {\n this.paused = false;\n this.ipc.broadcast({ type: 'info', message: '▶ Shadow-Daemon fortgesetzt' });\n }\n }\n\n stop(): void {\n this.running = false;\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n private checkForCompletedTasks(): void {\n const tasks = this.db.getTasks(this.sessionId);\n const completedCount = tasks.filter(t => t.status === 'completed').length;\n\n if (completedCount > this.lastTaskCount) {\n // New task(s) completed — suggest as SOP candidate\n const newlyCompleted = tasks\n .filter(t => t.status === 'completed' && !t.isSOPCandidate)\n .slice(-1); // most recent\n\n for (const task of newlyCompleted) {\n const desc = task.description ?? `Task ${task.id.substring(0, 8)}`;\n if (this.ipc.hasClients()) {\n this.ipc.broadcast({\n type: 'prompt',\n id: `sop-suggest:${task.id}`,\n prompt: {\n kind: 'task-boundary',\n context: { taskId: task.id, description: desc },\n options: ['Ja, als SOP speichern', 'Nein, überspringen'],\n defaultAnswer: 'Ja, als SOP speichern',\n timeoutMs: 30_000,\n createdAt: new Date().toISOString(),\n },\n });\n } else {\n // Auto-mark as candidate when no client is attached\n this.db.markTaskAsSOPCandidate(task.id);\n }\n }\n this.lastTaskCount = completedCount;\n }\n }\n\n private getStatus(): ShadowStatus {\n const stats = this.db.getStats(this.sessionId);\n const sops = this.db.getSOPs(this.sessionId);\n return {\n pid: process.pid,\n uptime: process.uptime(),\n nodeCount: stats.nodes,\n eventCount: stats.events,\n taskCount: stats.tasks,\n sopCount: sops.length,\n pendingPrompts: 0,\n autoSave: this.config.autoSaveNodes,\n mode: this.config.shadowMode,\n agentActive: false,\n paused: this.paused,\n cyclesRun: this.cyclesRun,\n cyclesSkipped: this.cyclesSkipped,\n };\n }\n}\n\n// ── Daemon Lifecycle ──────────────────────────────────────────────────────────\n\nexport function forkDaemon(config: CartographyConfig): number {\n // The daemon entry is the same cli.ts but with --daemon flag via env\n const child = spawn(\n process.execPath,\n [process.argv[1] ?? 'datasynx-cartography', 'shadow', 'start', '--foreground', '--daemon-child'],\n {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n CARTOGRAPHYY_DAEMON: '1',\n CARTOGRAPHYY_CONFIG: JSON.stringify(config),\n },\n }\n );\n child.unref();\n\n const pid = child.pid;\n if (!pid) throw new Error('Failed to fork daemon');\n\n writeFileSync(config.pidFile, String(pid), 'utf8');\n return pid;\n}\n\nexport function isDaemonRunning(pidFile: string): { running: boolean; pid?: number } {\n if (!existsSync(pidFile)) return { running: false };\n\n try {\n const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);\n if (isNaN(pid)) return { running: false };\n\n process.kill(pid, 0); // throws if process doesn't exist\n return { running: true, pid };\n } catch {\n // Stale PID file\n try { unlinkSync(pidFile); } catch { /* already gone */ }\n return { running: false };\n }\n}\n\nexport function stopDaemon(pidFile: string): boolean {\n const { running, pid } = isDaemonRunning(pidFile);\n if (!running || !pid) return false;\n\n try {\n process.kill(pid, 'SIGTERM');\n try { unlinkSync(pidFile); } catch { /* already gone */ }\n return true;\n } catch {\n return false;\n }\n}\n\nexport function pauseDaemon(pidFile: string): boolean {\n const { running, pid } = isDaemonRunning(pidFile);\n if (!running || !pid) return false;\n try { process.kill(pid, 'SIGUSR1'); return true; } catch { return false; }\n}\n\nexport function resumeDaemon(pidFile: string): boolean {\n const { running, pid } = isDaemonRunning(pidFile);\n if (!running || !pid) return false;\n try { process.kill(pid, 'SIGUSR2'); return true; } catch { return false; }\n}\n\nfunction cleanup(config: CartographyConfig): void {\n try { unlinkSync(config.socketPath); } catch { /* already gone */ }\n try { unlinkSync(config.pidFile); } catch { /* already gone */ }\n}\n\n// ── startDaemonProcess ───────────────────────────────────────────────────────\n\nexport async function startDaemonProcess(config: CartographyConfig): Promise<void> {\n cleanStaleSocket(config.socketPath);\n\n const db = new CartographyDB(config.dbPath);\n const ipc = new IPCServer();\n const notify = new NotificationService(config.enableNotifications);\n\n ipc.start(config.socketPath);\n\n const daemon = new ShadowDaemon(config, db, ipc, notify);\n await daemon.run();\n\n db.close();\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","import net from 'node:net';\nimport { EventEmitter } from 'node:events';\nimport { chmodSync, existsSync, unlinkSync } from 'node:fs';\nimport type { DaemonMessage, ClientMessage } from './types.js';\n\n// ── IPCServer ────────────────────────────────────────────────────────────────\n\nexport class IPCServer extends EventEmitter {\n private server: net.Server | null = null;\n private clients: Set<net.Socket> = new Set();\n\n start(socketPath: string): void {\n this.server = net.createServer((socket) => {\n this.clients.add(socket);\n this.emit('client-connect', socket);\n\n let buf = '';\n socket.on('data', (chunk) => {\n buf += chunk.toString();\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line) as ClientMessage;\n this.emit('message', msg, socket);\n } catch {\n // Ignore malformed JSON\n }\n }\n });\n\n socket.on('close', () => {\n this.clients.delete(socket);\n this.emit('client-disconnect', socket);\n });\n\n socket.on('error', () => {\n this.clients.delete(socket);\n });\n });\n\n this.server.listen(socketPath, () => {\n try {\n chmodSync(socketPath, 0o600);\n } catch {\n // chmod may fail in some environments — non-fatal\n }\n });\n }\n\n broadcast(msg: DaemonMessage): void {\n const line = JSON.stringify(msg) + '\\n';\n for (const socket of this.clients) {\n try {\n socket.write(line);\n } catch {\n this.clients.delete(socket);\n }\n }\n }\n\n hasClients(): boolean {\n return this.clients.size > 0;\n }\n\n stop(): void {\n for (const socket of this.clients) {\n socket.destroy();\n }\n this.clients.clear();\n this.server?.close();\n this.server = null;\n }\n}\n\n// ── IPCClient ────────────────────────────────────────────────────────────────\n\nexport class IPCClient extends EventEmitter {\n private socket: net.Socket | null = null;\n\n connect(socketPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const socket = net.createConnection(socketPath, () => {\n resolve();\n });\n\n socket.on('error', (err) => {\n reject(err);\n });\n\n let buf = '';\n socket.on('data', (chunk) => {\n buf += chunk.toString();\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line) as DaemonMessage;\n this.emit('message', msg);\n } catch {\n // Ignore malformed JSON\n }\n }\n });\n\n socket.on('close', () => {\n this.emit('disconnect');\n });\n\n this.socket = socket;\n });\n }\n\n send(msg: ClientMessage): void {\n if (!this.socket) return;\n try {\n this.socket.write(JSON.stringify(msg) + '\\n');\n } catch {\n // Socket may have closed\n }\n }\n\n disconnect(): void {\n this.socket?.destroy();\n this.socket = null;\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function cleanStaleSocket(socketPath: string): void {\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Already gone\n }\n }\n}\n","import notifier from 'node-notifier';\n\nexport class NotificationService {\n constructor(private enabled: boolean) {}\n\n nodeDiscovered(nodeId: string, via: string): void {\n this.send(`📍 Node entdeckt: ${nodeId}`, `Via: ${via}`);\n }\n\n workflowDetected(count: number, desc: string): void {\n this.send(`🔄 ${count} Workflow(s) erkannt`, desc);\n }\n\n taskBoundary(gapMinutes: number): void {\n this.send('⏸ Task-Grenze erkannt', `${gapMinutes} Minuten Inaktivität`);\n }\n\n private send(title: string, message: string): void {\n if (!this.enabled) return;\n\n try {\n notifier.notify({ title, message, sound: false });\n } catch {\n // Notifications not available — silently skip\n }\n }\n}\n","import { IPCClient } from './ipc.js';\nimport { startDaemonProcess } from './daemon.js';\nimport type { CartographyConfig, DaemonMessage, ShadowStatus } from './types.js';\n\n// ── ForegroundClient ─────────────────────────────────────────────────────────\n// Runs daemon + terminal UI in the same process (no fork)\n\nexport class ForegroundClient {\n async run(config: CartographyConfig): Promise<void> {\n process.stderr.write('👁 Datasynx Cartography Shadow (foreground) gestartet\\n');\n process.stderr.write(` Intervall: ${config.pollIntervalMs / 1000}s | Modell: ${config.shadowModel}\\n`);\n process.stderr.write(' Ctrl+C zum Beenden\\n\\n');\n\n // Run daemon inline (blocks until SIGINT/SIGTERM)\n await startDaemonProcess({ ...config, shadowMode: 'foreground' });\n }\n}\n\n// ── AttachClient ─────────────────────────────────────────────────────────────\n// Connects to a running daemon via Unix socket and provides terminal UI\n\nexport class AttachClient {\n private isPaused = false;\n\n async attach(socketPath: string): Promise<void> {\n const client = new IPCClient();\n\n try {\n await client.connect(socketPath);\n } catch {\n process.stderr.write(`❌ Kann nicht an Daemon ankoppeln: ${socketPath}\\n`);\n process.stderr.write(' Ist der Daemon gestartet? datasynx-cartography shadow status\\n');\n process.exitCode = 1;\n return;\n }\n\n process.stderr.write('📡 Verbunden mit Shadow-Daemon\\n');\n process.stderr.write(' [T] Neuer Task [S] Status [P] Pause/Resume [D] Trennen [Q] Stoppen\\n\\n');\n\n // Set raw mode for hotkeys\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n process.stdin.resume();\n process.stdin.setEncoding('utf8');\n\n process.stdin.on('data', (key: string) => {\n const k = key.toLowerCase();\n\n if (k === 't') {\n process.stdout.write('\\nTask-Beschreibung: ');\n process.stdin.once('data', (desc: string) => {\n client.send({ type: 'task-description', description: desc.trim() });\n client.send({ type: 'command', command: 'new-task' });\n process.stdout.write(`\\n✓ Neuer Task gestartet: ${desc.trim()}\\n`);\n });\n return;\n }\n\n if (k === 's') {\n client.send({ type: 'command', command: 'status' });\n return;\n }\n\n if (k === 'p') {\n if (this.isPaused) {\n client.send({ type: 'command', command: 'resume' });\n process.stderr.write('\\n▶ Resume gesendet\\n');\n } else {\n client.send({ type: 'command', command: 'pause' });\n process.stderr.write('\\n⏸ Pause gesendet\\n');\n }\n this.isPaused = !this.isPaused;\n return;\n }\n\n if (k === 'd' || k === '\\u0003') {\n process.stderr.write('\\n📡 Getrennt. Daemon läuft weiter.\\n');\n client.disconnect();\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n return;\n }\n\n if (k === 'q') {\n client.send({ type: 'command', command: 'stop' });\n process.stderr.write('\\n🛑 Daemon wird gestoppt...\\n');\n setTimeout(() => {\n client.disconnect();\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n }, 1000);\n return;\n }\n });\n\n client.on('message', (msg: DaemonMessage) => {\n switch (msg.type) {\n case 'status':\n this.isPaused = msg.data.paused;\n renderStatus(msg.data);\n break;\n case 'event':\n process.stdout.write(\n ` [${new Date(msg.data.timestamp).toLocaleTimeString()}] ` +\n `${msg.data.eventType} ${msg.data.process}` +\n (msg.data.target ? ` → ${msg.data.target}` : '') + '\\n'\n );\n break;\n case 'agent-output':\n if (msg.text) process.stdout.write(` 🤖 ${msg.text}\\n`);\n break;\n case 'info':\n process.stdout.write(` ℹ ${msg.message}\\n`);\n break;\n case 'prompt':\n renderPrompt(msg.id, msg.prompt.kind, msg.prompt.context, msg.prompt.options, (answer) => {\n client.send({ type: 'prompt-response', id: msg.id, answer });\n });\n break;\n }\n });\n\n client.on('disconnect', () => {\n process.stderr.write('\\n⚠ Verbindung zum Daemon verloren\\n');\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n });\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction renderStatus(status: ShadowStatus): void {\n const state = status.paused ? '\\x1b[33m⏸ PAUSED\\x1b[0m' : '\\x1b[32m● RUNNING\\x1b[0m';\n process.stdout.write(\n `\\n── Shadow Status ───────────────────────────────\\n` +\n ` ${state} PID: ${status.pid} | Uptime: ${Math.round(status.uptime)}s\\n` +\n ` Nodes: ${status.nodeCount} | Events: ${status.eventCount} | Tasks: ${status.taskCount} | SOPs: ${status.sopCount}\\n` +\n ` Cycles: ${status.cyclesRun} run, ${status.cyclesSkipped} skipped\\n` +\n `────────────────────────────────────────────────\\n`\n );\n}\n\nfunction renderPrompt(\n id: string,\n kind: string,\n context: Record<string, unknown>,\n options: string[],\n callback: (answer: string) => void,\n): void {\n if (id.startsWith('sop-suggest:')) {\n const desc = context['description'] as string ?? 'Unbenannter Task';\n process.stdout.write(`\\n 📋 Task abgeschlossen: \"${desc}\"\\n`);\n process.stdout.write(` Als SOP speichern?\\n`);\n options.forEach((opt, i) => process.stdout.write(` [${i + 1}] ${opt}\\n`));\n process.stdout.write(' → ');\n process.stdin.once('data', (data: string) => {\n const idx = parseInt(data.trim(), 10) - 1;\n callback(options[idx] ?? options[0] ?? '');\n });\n return;\n }\n\n process.stdout.write(`\\n❓ ${kind}\\n`);\n options.forEach((opt, i) => process.stdout.write(` [${i + 1}] ${opt}\\n`));\n process.stdout.write('Antwort: ');\n process.stdin.once('data', (data: string) => {\n const idx = parseInt(data.trim(), 10) - 1;\n callback(options[idx] ?? options[0] ?? '');\n });\n}\n"],"mappings":"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","names":["execSync","readFileSync","existsSync","execSync","existsSync","readFileSync","unlinkSync","existsSync","resolve","execSync","existsSync","readFileSync","unlinkSync","resolve","resolve","existsSync","readFileSync","mkdirSync","writeFileSync","join","scanAllBookmarks","saved","NODE_TYPES","execSync","dim"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datasynx/agentic-ai-cartography",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "AI-powered infrastructure cartography & SOP generation CLI — built on Claude Agent SDK",
5
5
  "type": "module",
6
6
  "bin": {
@@ -44,15 +44,15 @@
44
44
  ],
45
45
  "author": {
46
46
  "name": "Datasynx AI",
47
- "url": "https://github.com/datasynx-ai"
47
+ "url": "https://github.com/datasynx"
48
48
  },
49
49
  "repository": {
50
50
  "type": "git",
51
- "url": "https://github.com/datasynx-ai/agentic-ai-discovery.git"
51
+ "url": "https://github.com/datasynx/agentic-ai-cartography.git"
52
52
  },
53
- "homepage": "https://github.com/datasynx-ai/agentic-ai-discovery#readme",
53
+ "homepage": "https://github.com/datasynx/agentic-ai-cartography#readme",
54
54
  "bugs": {
55
- "url": "https://github.com/datasynx-ai/agentic-ai-discovery/issues"
55
+ "url": "https://github.com/datasynx/agentic-ai-cartography/issues"
56
56
  },
57
57
  "license": "MIT",
58
58
  "dependencies": {