@datasynx/agentic-ai-cartography 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +197 -33
  2. package/dist/bookmarks-VS56KVCO.js +25 -0
  3. package/dist/chunk-CJ2PITFA.js +785 -0
  4. package/dist/chunk-CJ2PITFA.js.map +1 -0
  5. package/dist/chunk-D6SRSLBF.js +48 -0
  6. package/dist/{chunk-WJR63RWY.js → chunk-J6FDZ6HZ.js} +11 -2
  7. package/dist/chunk-J6FDZ6HZ.js.map +1 -0
  8. package/dist/chunk-UGSNG3QJ.js +49 -0
  9. package/dist/chunk-UGSNG3QJ.js.map +1 -0
  10. package/dist/chunk-W7YE6AAH.js +1516 -0
  11. package/dist/chunk-W7YE6AAH.js.map +1 -0
  12. package/dist/cli.js +133 -664
  13. package/dist/cli.js.map +1 -1
  14. package/dist/index.cjs +60115 -0
  15. package/dist/index.cjs.map +1 -0
  16. package/dist/index.d.cts +734 -0
  17. package/dist/index.d.ts +363 -7
  18. package/dist/index.js +1462 -161
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp-bin.js +33 -0
  21. package/dist/mcp-bin.js.map +1 -0
  22. package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
  23. package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
  24. package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
  25. package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
  26. package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
  27. package/dist/sdk-A6NLO3DJ.js +12294 -0
  28. package/dist/sdk-A6NLO3DJ.js.map +1 -0
  29. package/dist/sdk-G5D4WQZ4.js +12293 -0
  30. package/dist/sdk-G5D4WQZ4.js.map +1 -0
  31. package/dist/sdk-QSTAREST.js +4869 -0
  32. package/dist/sdk-QSTAREST.js.map +1 -0
  33. package/dist/sqlite-vec-EZN67B2V.js +40 -0
  34. package/dist/sqlite-vec-EZN67B2V.js.map +1 -0
  35. package/dist/sqlite-vec-UK5YYE5T.js +39 -0
  36. package/dist/sqlite-vec-UK5YYE5T.js.map +1 -0
  37. package/dist/transformers.node-BTYUTJK5.js +42884 -0
  38. package/dist/transformers.node-BTYUTJK5.js.map +1 -0
  39. package/dist/transformers.node-J6PRTTOX.js +42883 -0
  40. package/dist/transformers.node-J6PRTTOX.js.map +1 -0
  41. package/dist/{types-54623ALF.js → types-JG27FR3E.js} +5 -2
  42. package/dist/types-JG27FR3E.js.map +1 -0
  43. package/package.json +51 -16
  44. package/server.json +28 -0
  45. package/dist/bookmarks-BWNVQGPG.js +0 -14
  46. package/dist/chunk-QKNYI3SU.js +0 -459
  47. package/dist/chunk-QKNYI3SU.js.map +0 -1
  48. package/dist/chunk-WJR63RWY.js.map +0 -1
  49. /package/dist/{bookmarks-BWNVQGPG.js.map → bookmarks-VS56KVCO.js.map} +0 -0
  50. /package/dist/{types-54623ALF.js.map → chunk-D6SRSLBF.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,27 +1,39 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ CartographyDB,
4
+ startMcp
5
+ } from "./chunk-W7YE6AAH.js";
2
6
  import {
3
7
  DOMAIN_COLORS,
4
8
  DOMAIN_PALETTE,
5
9
  EDGE_RELATIONSHIPS,
6
10
  NODE_TYPES,
11
+ NODE_TYPE_GROUPS,
7
12
  defaultConfig
8
- } from "./chunk-WJR63RWY.js";
13
+ } from "./chunk-J6FDZ6HZ.js";
9
14
  import {
10
15
  HOME,
11
16
  IS_LINUX,
12
17
  IS_MAC,
13
18
  IS_WIN,
14
19
  PLATFORM,
20
+ checkReadOnly,
15
21
  cleanupTempFiles,
16
22
  commandExists,
17
23
  dbScanDirs,
18
24
  findFiles,
25
+ logDebug,
26
+ logError,
27
+ logInfo,
28
+ logWarn,
19
29
  run,
20
30
  scanAllBookmarks,
21
31
  scanAllHistory,
22
32
  scanWindowsDbServices,
23
- scanWindowsPrograms
24
- } from "./chunk-QKNYI3SU.js";
33
+ scanWindowsPrograms,
34
+ setVerbose
35
+ } from "./chunk-CJ2PITFA.js";
36
+ import "./chunk-UGSNG3QJ.js";
25
37
 
26
38
  // src/cli.ts
27
39
  import { Command } from "commander";
@@ -47,7 +59,7 @@ function checkPrerequisites() {
47
59
  execSync("claude --version", { stdio: "pipe" });
48
60
  } catch {
49
61
  process.stderr.write(
50
- "\n\u274C Claude CLI nicht gefunden.\n Datasynx Cartography braucht die Claude CLI als Runtime-Dependency.\n\n Installieren:\n npm install -g @anthropic-ai/claude-code\n # oder\n curl -fsSL https://claude.ai/install.sh | bash\n\n Danach: claude login\n\n"
62
+ "\n\u274C Claude CLI not found.\n Datasynx Cartography requires the Claude CLI as a runtime dependency.\n\n Install:\n npm install -g @anthropic-ai/claude-code\n # or\n curl -fsSL https://claude.ai/install.sh | bash\n\n Then: claude login\n\n"
51
63
  );
52
64
  process.exitCode = 1;
53
65
  throw new Error("Claude CLI not found");
@@ -56,562 +68,31 @@ function checkPrerequisites() {
56
68
  const hasOAuth = isOAuthLoggedIn();
57
69
  if (!hasApiKey && !hasOAuth) {
58
70
  process.stderr.write(
59
- "\u26A0 Keine Authentifizierung gefunden. Bitte eine der folgenden Optionen:\n\n Option A \u2014 claude.ai Subscription (empfohlen):\n claude login\n\n Option B \u2014 API Key:\n export ANTHROPIC_API_KEY=sk-ant-...\n\n"
71
+ "\u26A0 No authentication found. Please choose one of the following options:\n\n Option A \u2014 claude.ai Subscription (recommended):\n claude login\n\n Option B \u2014 API Key:\n export ANTHROPIC_API_KEY=sk-ant-...\n\n"
60
72
  );
61
73
  } else if (hasOAuth && !hasApiKey) {
62
- process.stderr.write("\u2713 Eingeloggt via claude login (Subscription)\n");
74
+ process.stderr.write("\u2713 Logged in via claude login (Subscription)\n");
63
75
  }
64
76
  }
65
77
 
66
- // src/db.ts
67
- import Database from "better-sqlite3";
68
- import { mkdirSync } from "fs";
69
- import { dirname } from "path";
70
- import { z } from "zod";
71
- var SessionRowSchema = z.object({
72
- id: z.string(),
73
- mode: z.literal("discover"),
74
- started_at: z.string(),
75
- completed_at: z.string().nullable().optional(),
76
- config: z.string()
77
- });
78
- var NodeRowSchema = z.object({
79
- id: z.string(),
80
- session_id: z.string(),
81
- type: z.enum(NODE_TYPES),
82
- name: z.string(),
83
- discovered_via: z.string().nullable().optional(),
84
- discovered_at: z.string(),
85
- path_id: z.string().nullable().optional(),
86
- depth: z.number().default(0),
87
- confidence: z.number().default(0.5),
88
- metadata: z.string().default("{}"),
89
- tags: z.string().default("[]"),
90
- domain: z.string().nullable().optional(),
91
- sub_domain: z.string().nullable().optional(),
92
- quality_score: z.number().nullable().optional()
93
- });
94
- var EdgeRowSchema = z.object({
95
- id: z.string(),
96
- session_id: z.string(),
97
- source_id: z.string(),
98
- target_id: z.string(),
99
- relationship: z.enum(EDGE_RELATIONSHIPS),
100
- evidence: z.string().nullable().optional(),
101
- confidence: z.number().default(0.5),
102
- discovered_at: z.string()
103
- });
104
- var EventRowSchema = z.object({
105
- id: z.string(),
106
- session_id: z.string(),
107
- task_id: z.string().nullable().optional(),
108
- timestamp: z.string(),
109
- event_type: z.string(),
110
- process: z.string(),
111
- pid: z.number(),
112
- target: z.string().nullable().optional(),
113
- target_type: z.string().nullable().optional(),
114
- port: z.number().nullable().optional(),
115
- duration_ms: z.number().nullable().optional()
116
- });
117
- var TaskRowSchema = z.object({
118
- id: z.string(),
119
- session_id: z.string(),
120
- description: z.string().nullable().optional(),
121
- started_at: z.string(),
122
- completed_at: z.string().nullable().optional(),
123
- steps: z.string().default("[]"),
124
- involved_services: z.string().default("[]"),
125
- status: z.enum(["active", "completed", "cancelled"])
126
- });
127
- var WorkflowRowSchema = z.object({
128
- id: z.string(),
129
- session_id: z.string(),
130
- name: z.string().nullable().optional(),
131
- pattern: z.string(),
132
- task_ids: z.string().default("[]"),
133
- occurrences: z.number().default(1),
134
- first_seen: z.string(),
135
- last_seen: z.string(),
136
- avg_duration_ms: z.number().nullable().optional(),
137
- involved_services: z.string().default("[]")
138
- });
139
- var ConnectionRowSchema = z.object({
140
- id: z.string(),
141
- session_id: z.string(),
142
- source_asset_id: z.string(),
143
- target_asset_id: z.string(),
144
- type: z.string().nullable().optional(),
145
- created_at: z.string()
146
- });
147
- var SCHEMA = `
148
- PRAGMA journal_mode = WAL;
149
- PRAGMA foreign_keys = ON;
150
- PRAGMA busy_timeout = 5000;
151
-
152
- CREATE TABLE IF NOT EXISTS sessions (
153
- id TEXT PRIMARY KEY,
154
- mode TEXT NOT NULL CHECK (mode IN ('discover')),
155
- started_at TEXT NOT NULL,
156
- completed_at TEXT,
157
- config TEXT NOT NULL DEFAULT '{}'
158
- );
159
-
160
- CREATE TABLE IF NOT EXISTS nodes (
161
- id TEXT NOT NULL,
162
- session_id TEXT NOT NULL REFERENCES sessions(id),
163
- type TEXT NOT NULL,
164
- name TEXT NOT NULL,
165
- discovered_via TEXT,
166
- discovered_at TEXT NOT NULL,
167
- path_id TEXT,
168
- depth INTEGER DEFAULT 0,
169
- confidence REAL DEFAULT 0.5,
170
- metadata TEXT NOT NULL DEFAULT '{}',
171
- tags TEXT NOT NULL DEFAULT '[]',
172
- domain TEXT,
173
- sub_domain TEXT,
174
- quality_score REAL,
175
- PRIMARY KEY (id, session_id)
176
- );
177
-
178
- CREATE TABLE IF NOT EXISTS connections (
179
- id TEXT PRIMARY KEY,
180
- session_id TEXT NOT NULL REFERENCES sessions(id),
181
- source_asset_id TEXT NOT NULL,
182
- target_asset_id TEXT NOT NULL,
183
- type TEXT,
184
- created_at TEXT NOT NULL
185
- );
186
-
187
- CREATE TABLE IF NOT EXISTS edges (
188
- id TEXT PRIMARY KEY,
189
- session_id TEXT NOT NULL REFERENCES sessions(id),
190
- source_id TEXT NOT NULL,
191
- target_id TEXT NOT NULL,
192
- relationship TEXT NOT NULL,
193
- evidence TEXT,
194
- confidence REAL DEFAULT 0.5,
195
- discovered_at TEXT NOT NULL
196
- );
197
-
198
- CREATE TABLE IF NOT EXISTS activity_events (
199
- id TEXT PRIMARY KEY,
200
- session_id TEXT NOT NULL REFERENCES sessions(id),
201
- task_id TEXT,
202
- timestamp TEXT NOT NULL,
203
- event_type TEXT NOT NULL,
204
- process TEXT NOT NULL,
205
- pid INTEGER NOT NULL,
206
- target TEXT,
207
- target_type TEXT,
208
- port INTEGER,
209
- duration_ms INTEGER
210
- );
211
-
212
- CREATE TABLE IF NOT EXISTS tasks (
213
- id TEXT PRIMARY KEY,
214
- session_id TEXT NOT NULL REFERENCES sessions(id),
215
- description TEXT,
216
- started_at TEXT NOT NULL,
217
- completed_at TEXT,
218
- steps TEXT NOT NULL DEFAULT '[]',
219
- involved_services TEXT NOT NULL DEFAULT '[]',
220
- status TEXT DEFAULT 'active' CHECK (status IN ('active','completed','cancelled'))
221
- );
222
-
223
- CREATE TABLE IF NOT EXISTS workflows (
224
- id TEXT PRIMARY KEY,
225
- session_id TEXT NOT NULL REFERENCES sessions(id),
226
- name TEXT,
227
- pattern TEXT NOT NULL,
228
- task_ids TEXT NOT NULL DEFAULT '[]',
229
- occurrences INTEGER DEFAULT 1,
230
- first_seen TEXT NOT NULL,
231
- last_seen TEXT NOT NULL,
232
- avg_duration_ms INTEGER,
233
- involved_services TEXT NOT NULL DEFAULT '[]'
234
- );
235
-
236
- CREATE TABLE IF NOT EXISTS node_approvals (
237
- pattern TEXT PRIMARY KEY,
238
- action TEXT NOT NULL CHECK (action IN ('save','ignore','auto')),
239
- created_at TEXT NOT NULL
240
- );
241
-
242
- CREATE INDEX IF NOT EXISTS idx_nodes_session ON nodes(session_id);
243
- CREATE INDEX IF NOT EXISTS idx_edges_session ON edges(session_id);
244
- CREATE INDEX IF NOT EXISTS idx_events_session ON activity_events(session_id);
245
- CREATE INDEX IF NOT EXISTS idx_events_task ON activity_events(task_id);
246
- CREATE INDEX IF NOT EXISTS idx_tasks_session ON tasks(session_id);
247
- CREATE INDEX IF NOT EXISTS idx_connections_session ON connections(session_id);
248
- `;
249
- var CartographyDB = class {
250
- db;
251
- constructor(dbPath) {
252
- mkdirSync(dirname(dbPath), { recursive: true });
253
- this.db = new Database(dbPath);
254
- this.db.pragma("journal_mode = WAL");
255
- this.db.pragma("foreign_keys = ON");
256
- this.db.pragma("busy_timeout = 5000");
257
- this.migrate();
258
- }
259
- migrate() {
260
- const version = this.db.pragma("user_version", { simple: true });
261
- if (version === 0) {
262
- this.db.exec(SCHEMA);
263
- this.db.pragma("user_version = 2");
264
- } else if (version === 1) {
265
- const cols = this.db.prepare("PRAGMA table_info(nodes)").all().map((c) => c.name);
266
- if (!cols.includes("domain")) this.db.exec("ALTER TABLE nodes ADD COLUMN domain TEXT");
267
- if (!cols.includes("sub_domain")) this.db.exec("ALTER TABLE nodes ADD COLUMN sub_domain TEXT");
268
- if (!cols.includes("quality_score")) this.db.exec("ALTER TABLE nodes ADD COLUMN quality_score REAL");
269
- this.db.exec(`
270
- CREATE TABLE IF NOT EXISTS connections (
271
- id TEXT PRIMARY KEY,
272
- session_id TEXT NOT NULL REFERENCES sessions(id),
273
- source_asset_id TEXT NOT NULL,
274
- target_asset_id TEXT NOT NULL,
275
- type TEXT,
276
- created_at TEXT NOT NULL
277
- );
278
- CREATE INDEX IF NOT EXISTS idx_connections_session ON connections(session_id);
279
- `);
280
- this.db.pragma("user_version = 2");
281
- }
282
- }
283
- close() {
284
- this.db.pragma("optimize");
285
- this.db.close();
286
- }
287
- // ── Sessions ────────────────────────────
288
- createSession(mode, config) {
289
- const id = crypto.randomUUID();
290
- this.db.prepare(
291
- "INSERT INTO sessions (id, mode, started_at, config) VALUES (?, ?, ?, ?)"
292
- ).run(id, mode, (/* @__PURE__ */ new Date()).toISOString(), JSON.stringify(config));
293
- return id;
294
- }
295
- endSession(id) {
296
- this.db.prepare("UPDATE sessions SET completed_at = ? WHERE id = ?").run((/* @__PURE__ */ new Date()).toISOString(), id);
297
- }
298
- getSession(id) {
299
- const row = this.db.prepare("SELECT * FROM sessions WHERE id = ?").get(id);
300
- return row ? this.mapSession(row) : void 0;
301
- }
302
- getLatestSession(mode) {
303
- const row = mode ? this.db.prepare("SELECT * FROM sessions WHERE mode = ? ORDER BY rowid DESC LIMIT 1").get(mode) : this.db.prepare("SELECT * FROM sessions ORDER BY rowid DESC LIMIT 1").get();
304
- return row ? this.mapSession(row) : void 0;
305
- }
306
- getSessions() {
307
- const rows = this.db.prepare("SELECT * FROM sessions ORDER BY rowid DESC").all();
308
- return rows.map((r) => this.mapSession(r));
309
- }
310
- mapSession(r) {
311
- const v = SessionRowSchema.parse(r);
312
- return {
313
- id: v.id,
314
- mode: v.mode,
315
- startedAt: v.started_at,
316
- completedAt: v.completed_at ?? void 0,
317
- config: v.config
318
- };
319
- }
320
- // ── Nodes ───────────────────────────────
321
- upsertNode(sessionId, node, depth = 0) {
322
- this.db.prepare(`
323
- INSERT OR REPLACE INTO nodes
324
- (id, session_id, type, name, discovered_via, discovered_at, depth, confidence, metadata, tags,
325
- domain, sub_domain, quality_score)
326
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
327
- `).run(
328
- node.id,
329
- sessionId,
330
- node.type,
331
- node.name,
332
- node.discoveredVia,
333
- (/* @__PURE__ */ new Date()).toISOString(),
334
- depth,
335
- node.confidence,
336
- JSON.stringify(node.metadata ?? {}),
337
- JSON.stringify(node.tags ?? []),
338
- node.domain ?? null,
339
- node.subDomain ?? null,
340
- node.qualityScore ?? null
341
- );
342
- }
343
- getNodes(sessionId) {
344
- const rows = this.db.prepare("SELECT * FROM nodes WHERE session_id = ?").all(sessionId);
345
- return rows.map((r) => this.mapNode(r));
346
- }
347
- mapNode(r) {
348
- const v = NodeRowSchema.parse(r);
349
- return {
350
- id: v.id,
351
- sessionId: v.session_id,
352
- type: v.type,
353
- name: v.name,
354
- discoveredVia: v.discovered_via ?? "",
355
- discoveredAt: v.discovered_at,
356
- depth: v.depth,
357
- confidence: v.confidence,
358
- metadata: JSON.parse(v.metadata),
359
- tags: JSON.parse(v.tags),
360
- pathId: v.path_id ?? void 0,
361
- domain: v.domain ?? void 0,
362
- subDomain: v.sub_domain ?? void 0,
363
- qualityScore: v.quality_score ?? void 0
364
- };
365
- }
366
- deleteNode(sessionId, nodeId) {
367
- this.db.prepare("DELETE FROM nodes WHERE session_id = ? AND id = ?").run(sessionId, nodeId);
368
- this.db.prepare(
369
- "DELETE FROM edges WHERE session_id = ? AND (source_id = ? OR target_id = ?)"
370
- ).run(sessionId, nodeId, nodeId);
371
- }
372
- // ── Edges ───────────────────────────────
373
- insertEdge(sessionId, edge) {
374
- const id = crypto.randomUUID();
375
- this.db.prepare(`
376
- INSERT OR IGNORE INTO edges
377
- (id, session_id, source_id, target_id, relationship, evidence, confidence, discovered_at)
378
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
379
- `).run(
380
- id,
381
- sessionId,
382
- edge.sourceId,
383
- edge.targetId,
384
- edge.relationship,
385
- edge.evidence,
386
- edge.confidence,
387
- (/* @__PURE__ */ new Date()).toISOString()
388
- );
389
- }
390
- getEdges(sessionId) {
391
- const rows = this.db.prepare("SELECT * FROM edges WHERE session_id = ?").all(sessionId);
392
- return rows.map((r) => {
393
- const v = EdgeRowSchema.parse(r);
394
- return {
395
- id: v.id,
396
- sessionId: v.session_id,
397
- sourceId: v.source_id,
398
- targetId: v.target_id,
399
- relationship: v.relationship,
400
- evidence: v.evidence ?? "",
401
- confidence: v.confidence,
402
- discoveredAt: v.discovered_at
403
- };
404
- });
405
- }
406
- // ── Events ──────────────────────────────
407
- insertEvent(sessionId, event, taskId) {
408
- const id = crypto.randomUUID();
409
- this.db.prepare(`
410
- INSERT INTO activity_events
411
- (id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port)
412
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
413
- `).run(
414
- id,
415
- sessionId,
416
- taskId ?? null,
417
- (/* @__PURE__ */ new Date()).toISOString(),
418
- event.eventType,
419
- event.process,
420
- event.pid,
421
- event.target ?? null,
422
- event.targetType ?? null,
423
- event.port ?? null
424
- );
425
- }
426
- getEvents(sessionId, since) {
427
- const rows = since ? this.db.prepare("SELECT * FROM activity_events WHERE session_id = ? AND timestamp > ? ORDER BY timestamp").all(sessionId, since) : this.db.prepare("SELECT * FROM activity_events WHERE session_id = ? ORDER BY timestamp").all(sessionId);
428
- return rows.map((r) => {
429
- const v = EventRowSchema.parse(r);
430
- return {
431
- id: v.id,
432
- sessionId: v.session_id,
433
- taskId: v.task_id ?? void 0,
434
- timestamp: v.timestamp,
435
- eventType: v.event_type,
436
- process: v.process,
437
- pid: v.pid,
438
- target: v.target ?? void 0,
439
- targetType: v.target_type ?? void 0,
440
- port: v.port ?? void 0,
441
- durationMs: v.duration_ms ?? void 0
442
- };
443
- });
444
- }
445
- // ── Tasks ───────────────────────────────
446
- startTask(sessionId, description) {
447
- const id = crypto.randomUUID();
448
- this.db.prepare(`
449
- INSERT INTO tasks (id, session_id, description, started_at, steps, involved_services, status)
450
- VALUES (?, ?, ?, ?, '[]', '[]', 'active')
451
- `).run(id, sessionId, description ?? null, (/* @__PURE__ */ new Date()).toISOString());
452
- return id;
453
- }
454
- endCurrentTask(sessionId) {
455
- this.db.prepare(`
456
- UPDATE tasks SET status = 'completed', completed_at = ?
457
- WHERE session_id = ? AND status = 'active'
458
- `).run((/* @__PURE__ */ new Date()).toISOString(), sessionId);
459
- }
460
- updateTaskDescription(sessionId, description) {
461
- this.db.prepare(`
462
- UPDATE tasks SET description = ?
463
- WHERE session_id = ? AND status = 'active'
464
- `).run(description, sessionId);
465
- }
466
- getActiveTask(sessionId) {
467
- const row = this.db.prepare(
468
- "SELECT * FROM tasks WHERE session_id = ? AND status = 'active' LIMIT 1"
469
- ).get(sessionId);
470
- return row ? this.mapTask(row) : void 0;
471
- }
472
- getTasks(sessionId) {
473
- const rows = this.db.prepare("SELECT * FROM tasks WHERE session_id = ? ORDER BY started_at").all(sessionId);
474
- return rows.map((r) => this.mapTask(r));
475
- }
476
- mapTask(r) {
477
- const v = TaskRowSchema.parse(r);
478
- return {
479
- id: v.id,
480
- sessionId: v.session_id,
481
- description: v.description ?? void 0,
482
- startedAt: v.started_at,
483
- completedAt: v.completed_at ?? void 0,
484
- steps: v.steps,
485
- involvedServices: v.involved_services,
486
- status: v.status
487
- };
488
- }
489
- // ── Workflows ───────────────────────────
490
- insertWorkflow(sessionId, data) {
491
- const id = crypto.randomUUID();
492
- this.db.prepare(`
493
- INSERT INTO workflows
494
- (id, session_id, name, pattern, task_ids, occurrences,
495
- first_seen, last_seen, avg_duration_ms, involved_services)
496
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
497
- `).run(
498
- id,
499
- sessionId,
500
- data.name ?? null,
501
- data.pattern,
502
- data.taskIds,
503
- data.occurrences,
504
- data.firstSeen,
505
- data.lastSeen,
506
- data.avgDurationMs,
507
- data.involvedServices
508
- );
509
- }
510
- getWorkflows(sessionId) {
511
- const rows = this.db.prepare("SELECT * FROM workflows WHERE session_id = ?").all(sessionId);
512
- return rows.map((r) => {
513
- const v = WorkflowRowSchema.parse(r);
514
- return {
515
- id: v.id,
516
- sessionId: v.session_id,
517
- name: v.name ?? void 0,
518
- pattern: v.pattern,
519
- taskIds: v.task_ids,
520
- occurrences: v.occurrences,
521
- firstSeen: v.first_seen,
522
- lastSeen: v.last_seen,
523
- avgDurationMs: v.avg_duration_ms ?? 0,
524
- involvedServices: v.involved_services
525
- };
526
- });
527
- }
528
- // ── Connections (user-created hex map links) ─────────────────────────────
529
- upsertConnection(sessionId, conn) {
530
- const existing = this.db.prepare(
531
- "SELECT id FROM connections WHERE session_id = ? AND source_asset_id = ? AND target_asset_id = ?"
532
- ).get(sessionId, conn.sourceAssetId, conn.targetAssetId);
533
- if (existing) return existing.id;
534
- const id = crypto.randomUUID();
535
- this.db.prepare(`
536
- INSERT INTO connections (id, session_id, source_asset_id, target_asset_id, type, created_at)
537
- VALUES (?, ?, ?, ?, ?, ?)
538
- `).run(id, sessionId, conn.sourceAssetId, conn.targetAssetId, conn.type ?? null, (/* @__PURE__ */ new Date()).toISOString());
539
- return id;
540
- }
541
- getConnections(sessionId) {
542
- const rows = this.db.prepare("SELECT * FROM connections WHERE session_id = ?").all(sessionId);
543
- return rows.map((r) => {
544
- const v = ConnectionRowSchema.parse(r);
545
- return {
546
- id: v.id,
547
- sessionId: v.session_id,
548
- sourceAssetId: v.source_asset_id,
549
- targetAssetId: v.target_asset_id,
550
- type: v.type ?? void 0,
551
- createdAt: v.created_at
552
- };
553
- });
554
- }
555
- deleteConnection(sessionId, connectionId) {
556
- this.db.prepare("DELETE FROM connections WHERE session_id = ? AND id = ?").run(sessionId, connectionId);
557
- }
558
- // ── Approvals ───────────────────────────
559
- setApproval(pattern, action) {
560
- this.db.prepare(`
561
- INSERT OR REPLACE INTO node_approvals (pattern, action, created_at) VALUES (?, ?, ?)
562
- `).run(pattern, action, (/* @__PURE__ */ new Date()).toISOString());
563
- }
564
- getApproval(pattern) {
565
- const row = this.db.prepare("SELECT action FROM node_approvals WHERE pattern = ?").get(pattern);
566
- return row?.action;
567
- }
568
- // ── Pruning ──────────────────────────────
569
- /**
570
- * Delete a session and all its associated data (nodes, edges, events, tasks, workflows, connections).
571
- */
572
- deleteSession(sessionId) {
573
- this.db.prepare("DELETE FROM connections WHERE session_id = ?").run(sessionId);
574
- this.db.prepare("DELETE FROM workflows WHERE session_id = ?").run(sessionId);
575
- this.db.prepare("DELETE FROM activity_events WHERE session_id = ?").run(sessionId);
576
- this.db.prepare("DELETE FROM tasks WHERE session_id = ?").run(sessionId);
577
- this.db.prepare("DELETE FROM edges WHERE session_id = ?").run(sessionId);
578
- this.db.prepare("DELETE FROM nodes WHERE session_id = ?").run(sessionId);
579
- this.db.prepare("DELETE FROM sessions WHERE id = ?").run(sessionId);
580
- }
581
- /**
582
- * Prune sessions older than the given ISO date string. Returns count of deleted sessions.
583
- */
584
- pruneSessions(olderThan) {
585
- const rows = this.db.prepare(
586
- "SELECT id FROM sessions WHERE started_at < ?"
587
- ).all(olderThan);
588
- for (const row of rows) {
589
- this.deleteSession(row.id);
590
- }
591
- return rows.length;
592
- }
593
- // ── Stats ───────────────────────────────
594
- getStats(sessionId) {
595
- const nodes = this.db.prepare("SELECT COUNT(*) as c FROM nodes WHERE session_id = ?").get(sessionId).c;
596
- const edges = this.db.prepare("SELECT COUNT(*) as c FROM edges WHERE session_id = ?").get(sessionId).c;
597
- const events = this.db.prepare("SELECT COUNT(*) as c FROM activity_events WHERE session_id = ?").get(sessionId).c;
598
- const tasks = this.db.prepare("SELECT COUNT(*) as c FROM tasks WHERE session_id = ?").get(sessionId).c;
599
- return { nodes, edges, events, tasks };
600
- }
601
- };
602
-
603
78
  // src/tools.ts
604
- import { z as z2 } from "zod";
79
+ import { z } from "zod";
605
80
  function createScanRunner(runFn, opts = {}) {
606
81
  const threshold = opts.threshold ?? 3;
607
82
  let consecutiveFailures = 0;
608
83
  let tripped = false;
609
84
  return (cmd) => {
610
- if (tripped) return "(skipped \u2014 circuit breaker: too many consecutive failures)";
85
+ if (tripped) {
86
+ logDebug(`Circuit breaker: skipping "${cmd}" (${consecutiveFailures} consecutive failures)`);
87
+ return "(skipped \u2014 circuit breaker: too many consecutive failures)";
88
+ }
611
89
  const result = runFn(cmd, { timeout: opts.timeout ?? 2e4, env: opts.env });
612
90
  if (!result) {
613
91
  consecutiveFailures++;
614
- if (consecutiveFailures >= threshold) tripped = true;
92
+ if (consecutiveFailures >= threshold) {
93
+ tripped = true;
94
+ logDebug(`Circuit breaker tripped after ${threshold} failures, last command: "${cmd}"`);
95
+ }
615
96
  return "(error or not available)";
616
97
  }
617
98
  consecutiveFailures = 0;
@@ -619,27 +100,31 @@ function createScanRunner(runFn, opts = {}) {
619
100
  };
620
101
  }
621
102
  function stripSensitive(target) {
103
+ const raw = target.trim();
104
+ if (!raw) return raw;
622
105
  try {
623
- const url = new URL(target.startsWith("http") ? target : `tcp://${target}`);
624
- return `${url.hostname}${url.port ? ":" + url.port : ""}`;
106
+ const url = new URL(raw.startsWith("http") ? raw : `tcp://${raw}`);
107
+ const stripped = `${url.hostname}${url.port ? ":" + url.port : ""}`;
108
+ return stripped || raw;
625
109
  } catch {
626
- return target.replace(/\/.*$/, "").replace(/\?.*$/, "").replace(/@.*:/, ":");
110
+ const stripped = raw.replace(/\/.*$/, "").replace(/\?.*$/, "").replace(/@.*:/, ":");
111
+ return stripped || raw;
627
112
  }
628
113
  }
629
114
  async function createCartographyTools(db, sessionId, opts = {}) {
630
- const { tool, createSdkMcpServer } = await import("@anthropic-ai/claude-agent-sdk");
115
+ const { tool, createSdkMcpServer } = await import("./sdk-A6NLO3DJ.js");
631
116
  const tools = [
632
117
  tool("save_node", "Save an infrastructure node to the catalog", {
633
- id: z2.string(),
634
- type: z2.enum(NODE_TYPES),
635
- name: z2.string(),
636
- discoveredVia: z2.string(),
637
- confidence: z2.number().min(0).max(1),
638
- metadata: z2.record(z2.string(), z2.unknown()).optional(),
639
- tags: z2.array(z2.string()).optional(),
640
- domain: z2.string().optional().describe('Business domain, e.g. "Marketing", "Finance"'),
641
- subDomain: z2.string().optional().describe('Sub-domain, e.g. "Forecast client orders"'),
642
- qualityScore: z2.number().min(0).max(100).optional().describe("Data quality score 0\u2013100")
118
+ id: z.string(),
119
+ type: z.enum(NODE_TYPES),
120
+ name: z.string(),
121
+ discoveredVia: z.string(),
122
+ confidence: z.number().min(0).max(1),
123
+ metadata: z.record(z.string(), z.unknown()).optional(),
124
+ tags: z.array(z.string()).optional(),
125
+ domain: z.string().optional().describe('Business domain, e.g. "Marketing", "Finance"'),
126
+ subDomain: z.string().optional().describe('Sub-domain, e.g. "Forecast client orders"'),
127
+ qualityScore: z.number().min(0).max(100).optional().describe("Data quality score 0\u2013100")
643
128
  }, async (args) => {
644
129
  const node = {
645
130
  id: stripSensitive(args["id"]),
@@ -657,11 +142,11 @@ async function createCartographyTools(db, sessionId, opts = {}) {
657
142
  return { content: [{ type: "text", text: `\u2713 Node: ${node.id}` }] };
658
143
  }),
659
144
  tool("save_edge", "Save a relationship (edge) between two nodes \u2014 ALWAYS save edges when connections are clear", {
660
- sourceId: z2.string(),
661
- targetId: z2.string(),
662
- relationship: z2.enum(EDGE_RELATIONSHIPS),
663
- evidence: z2.string(),
664
- confidence: z2.number().min(0).max(1)
145
+ sourceId: z.string(),
146
+ targetId: z.string(),
147
+ relationship: z.enum(EDGE_RELATIONSHIPS),
148
+ evidence: z.string(),
149
+ confidence: z.number().min(0).max(1)
665
150
  }, async (args) => {
666
151
  db.insertEdge(sessionId, {
667
152
  sourceId: args["sourceId"],
@@ -673,7 +158,7 @@ async function createCartographyTools(db, sessionId, opts = {}) {
673
158
  return { content: [{ type: "text", text: `\u2713 ${args["sourceId"]}\u2192${args["targetId"]}` }] };
674
159
  }),
675
160
  tool("get_catalog", "Get the current catalog \u2014 use before save_node to avoid duplicates", {
676
- includeEdges: z2.boolean().default(true)
161
+ includeEdges: z.boolean().default(true)
677
162
  }, async (args) => {
678
163
  const nodes = db.getNodes(sessionId);
679
164
  const edges = args["includeEdges"] ? db.getEdges(sessionId) : [];
@@ -688,8 +173,8 @@ async function createCartographyTools(db, sessionId, opts = {}) {
688
173
  };
689
174
  }),
690
175
  tool("ask_user", "Ask the user a question \u2014 for clarifications, missing context, or consent (e.g. before scanning browser history)", {
691
- question: z2.string().describe("The question for the user (clear and specific)"),
692
- context: z2.string().optional().describe("Optional context explaining why this is relevant")
176
+ question: z.string().describe("The question for the user (clear and specific)"),
177
+ context: z.string().optional().describe("Optional context explaining why this is relevant")
693
178
  }, async (args) => {
694
179
  const question = args["question"];
695
180
  const context = args["context"];
@@ -702,7 +187,7 @@ async function createCartographyTools(db, sessionId, opts = {}) {
702
187
  };
703
188
  }),
704
189
  tool("scan_bookmarks", "Scan all browser bookmarks \u2014 hostnames only, no personal data (Chrome, Chromium, Edge, Brave, Vivaldi, Opera, Firefox)", {
705
- minConfidence: z2.number().min(0).max(1).default(0.5).optional()
190
+ minConfidence: z.number().min(0).max(1).default(0.5).optional()
706
191
  }, async () => {
707
192
  const hosts = await scanAllBookmarks();
708
193
  return {
@@ -722,7 +207,7 @@ async function createCartographyTools(db, sessionId, opts = {}) {
722
207
  };
723
208
  }),
724
209
  tool("scan_browser_history", "Scan browser history \u2014 anonymized hostnames + visit frequency. ALWAYS call ask_user for consent before using this tool.", {
725
- minVisits: z2.number().min(1).default(3).optional().describe("Minimum visit count to include a host (filters rarely-visited sites)")
210
+ minVisits: z.number().min(1).default(3).optional().describe("Minimum visit count to include a host (filters rarely-visited sites)")
726
211
  }, async (args) => {
727
212
  const minVisits = args["minVisits"] ?? 3;
728
213
  const hosts = await scanAllHistory();
@@ -744,7 +229,7 @@ async function createCartographyTools(db, sessionId, opts = {}) {
744
229
  };
745
230
  }),
746
231
  tool("scan_local_databases", "Scan for local database files and running DB servers \u2014 PostgreSQL databases, MySQL, SQLite files from installed apps", {
747
- deep: z2.boolean().default(false).optional().describe("Also search home directory recursively for SQLite/DB files (slower)")
232
+ deep: z.boolean().default(false).optional().describe("Also search home directory recursively for SQLite/DB files (slower)")
748
233
  }, async (args) => {
749
234
  const deep = args["deep"] ?? false;
750
235
  const results = {};
@@ -816,7 +301,7 @@ ${v}`).join("\n\n");
816
301
  return { content: [{ type: "text", text: out }] };
817
302
  }),
818
303
  tool("scan_k8s_resources", "Scan Kubernetes cluster via kubectl \u2014 100% readonly (get, describe)", {
819
- namespace: z2.string().optional().describe("Filter by namespace \u2014 empty = all namespaces")
304
+ namespace: z.string().optional().describe("Filter by namespace \u2014 empty = all namespaces")
820
305
  }, async (args) => {
821
306
  const ns = args["namespace"];
822
307
  const nsFlag = ns ? `-n ${ns}` : "--all-namespaces";
@@ -847,8 +332,8 @@ ${runK(c)}`).join("\n\n");
847
332
  return { content: [{ type: "text", text: out }] };
848
333
  }),
849
334
  tool("scan_aws_resources", "Scan AWS infrastructure via AWS CLI \u2014 100% readonly (describe, list)", {
850
- region: z2.string().optional().describe("AWS Region \u2014 default: AWS_DEFAULT_REGION or profile"),
851
- profile: z2.string().optional().describe("AWS CLI profile")
335
+ region: z.string().optional().describe("AWS Region \u2014 default: AWS_DEFAULT_REGION or profile"),
336
+ profile: z.string().optional().describe("AWS CLI profile")
852
337
  }, async (args) => {
853
338
  const region = args["region"];
854
339
  const profile = args["profile"];
@@ -871,7 +356,7 @@ ${runAws(c)}`).join("\n\n");
871
356
  return { content: [{ type: "text", text: out }] };
872
357
  }),
873
358
  tool("scan_gcp_resources", "Scan Google Cloud Platform via gcloud CLI \u2014 100% readonly (list, describe)", {
874
- project: z2.string().optional().describe("GCP Project ID \u2014 default: current gcloud project")
359
+ project: z.string().optional().describe("GCP Project ID \u2014 default: current gcloud project")
875
360
  }, async (args) => {
876
361
  const project = args["project"];
877
362
  const pf = project ? `--project ${project}` : "";
@@ -892,8 +377,8 @@ ${runGcp(c)}`).join("\n\n");
892
377
  return { content: [{ type: "text", text: out }] };
893
378
  }),
894
379
  tool("scan_azure_resources", "Scan Azure infrastructure via az CLI \u2014 100% readonly (list, show)", {
895
- subscription: z2.string().optional().describe("Azure Subscription ID"),
896
- resourceGroup: z2.string().optional().describe("Filter by resource group")
380
+ subscription: z.string().optional().describe("Azure Subscription ID"),
381
+ resourceGroup: z.string().optional().describe("Filter by resource group")
897
382
  }, async (args) => {
898
383
  const sub = args["subscription"];
899
384
  const rg = args["resourceGroup"];
@@ -916,7 +401,7 @@ ${runAz(c)}`).join("\n\n");
916
401
  return { content: [{ type: "text", text: out }] };
917
402
  }),
918
403
  tool("scan_installed_apps", "Scan all installed apps and tools \u2014 IDEs, office, dev tools, business apps, databases", {
919
- searchHint: z2.string().optional().describe('Optional search term to find specific tools (e.g. "hubspot windsurf cursor")')
404
+ searchHint: z.string().optional().describe('Optional search term to find specific tools (e.g. "hubspot windsurf cursor")')
920
405
  }, async (args) => {
921
406
  const hint = args["searchHint"];
922
407
  const results = {};
@@ -1101,18 +586,20 @@ ${v}`).join("\n\n");
1101
586
  }
1102
587
 
1103
588
  // src/safety.ts
1104
- var BLOCKED_CMDS = /\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|Remove-Item|Move-Item|Copy-Item|Stop-Process|Stop-Service|Restart-Service|Start-Service|Set-Service|Invoke-WebRequest\s+.*-Method\s+(POST|PUT|DELETE|PATCH)|del\s|rmdir\s|Format-Volume|Clear-Disk|Stop-Computer|Restart-Computer|Uninstall-Package|Install-Package|Install-Module)\b/i;
1105
- var BLOCKED_REDIRECTS = />>|>[^>]|Out-File|Set-Content|Add-Content/;
1106
589
  var safetyHook = async (input, _toolUseID, _options) => {
1107
590
  if (!("tool_name" in input)) return {};
1108
591
  if (input.tool_name !== "Bash") return {};
1109
- const cmd = input.tool_input?.command ?? "";
1110
- if (BLOCKED_CMDS.test(cmd) || BLOCKED_REDIRECTS.test(cmd)) {
592
+ const cmd = (input.tool_input?.command ?? "").trim();
593
+ if (!cmd) {
594
+ return { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow" } };
595
+ }
596
+ const decision = checkReadOnly(cmd);
597
+ if (!decision.allowed) {
1111
598
  return {
1112
599
  hookSpecificOutput: {
1113
600
  hookEventName: "PreToolUse",
1114
601
  permissionDecision: "deny",
1115
- permissionDecisionReason: `BLOCKED: "${cmd}" \u2014 read-only policy`
602
+ permissionDecisionReason: `BLOCKED: ${decision.reason} \u2014 read-only allowlist policy`
1116
603
  }
1117
604
  };
1118
605
  }
@@ -1126,7 +613,7 @@ var safetyHook = async (input, _toolUseID, _options) => {
1126
613
 
1127
614
  // src/agent.ts
1128
615
  async function runDiscovery(config, db, sessionId, onEvent, onAskUser, hint) {
1129
- const { query } = await import("@anthropic-ai/claude-agent-sdk");
616
+ const { query } = await import("./sdk-A6NLO3DJ.js");
1130
617
  const tools = await createCartographyTools(db, sessionId, { onAskUser });
1131
618
  const hintSection = hint ? `
1132
619
  \u26A1 USER HINT (HIGH PRIORITY): The user wants to find these specific tools: "${hint}"
@@ -1319,7 +806,7 @@ Use ask_user when you need context from the user.`;
1319
806
  }
1320
807
 
1321
808
  // src/exporter.ts
1322
- import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
809
+ import { mkdirSync, writeFileSync } from "fs";
1323
810
  import { join as join2 } from "path";
1324
811
 
1325
812
  // src/hex.ts
@@ -1427,6 +914,11 @@ function layoutClusters(groups, hexSize) {
1427
914
  }
1428
915
  function findFreeOrigin(occupied, count, gap) {
1429
916
  const key = (q, r) => `${q},${r}`;
917
+ const parsedOccupied = [];
918
+ for (const oKey of occupied) {
919
+ const [oq, or] = oKey.split(",").map(Number);
920
+ parsedOccupied.push({ q: oq, r: or });
921
+ }
1430
922
  for (let searchRadius = 1; searchRadius < 100; searchRadius++) {
1431
923
  const candidates = hexSpiral({ q: 0, r: 0 }, 1 + 6 * searchRadius * (searchRadius + 1) / 2);
1432
924
  for (const candidate of candidates) {
@@ -1437,9 +929,8 @@ function findFreeOrigin(occupied, count, gap) {
1437
929
  fits = false;
1438
930
  break;
1439
931
  }
1440
- for (const oKey of occupied) {
1441
- const [oq, or] = oKey.split(",").map(Number);
1442
- if (hexDistance(tp, { q: oq, r: or }) < gap) {
932
+ for (const oc of parsedOccupied) {
933
+ if (hexDistance(tp, oc) < gap) {
1443
934
  fits = false;
1444
935
  break;
1445
936
  }
@@ -1537,12 +1028,9 @@ function buildMapData(nodes, edges, options) {
1537
1028
 
1538
1029
  // src/exporter.ts
1539
1030
  function nodeLayer(type) {
1540
- if (type === "saas_tool") return "saas";
1541
- if (["web_service", "api_endpoint"].includes(type)) return "web";
1542
- if (["database_server", "database", "table", "cache_server"].includes(type)) return "data";
1543
- if (["message_broker", "queue", "topic"].includes(type)) return "messaging";
1544
- if (["host", "container", "pod", "k8s_cluster"].includes(type)) return "infra";
1545
- if (type === "config_file") return "config";
1031
+ for (const [layer, types] of Object.entries(NODE_TYPE_GROUPS)) {
1032
+ if (types.includes(type)) return layer;
1033
+ }
1546
1034
  return "other";
1547
1035
  }
1548
1036
  var LAYER_LABELS = {
@@ -2824,7 +2312,7 @@ function exportJGF(nodes, edges) {
2824
2312
  return JSON.stringify(jgf, null, 2);
2825
2313
  }
2826
2314
  function exportAll(db, sessionId, outputDir, formats = ["mermaid", "json", "yaml", "html", "map", "discovery"]) {
2827
- mkdirSync2(outputDir, { recursive: true });
2315
+ mkdirSync(outputDir, { recursive: true });
2828
2316
  const nodes = db.getNodes(sessionId);
2829
2317
  const edges = db.getEdges(sessionId);
2830
2318
  const jgfPath = join2(outputDir, "cartography-graph.jgf.json");
@@ -2846,35 +2334,9 @@ function exportAll(db, sessionId, outputDir, formats = ["mermaid", "json", "yaml
2846
2334
 
2847
2335
  // src/cli.ts
2848
2336
  import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
2849
- import { resolve } from "path";
2337
+ import { resolve, dirname } from "path";
2338
+ import { fileURLToPath } from "url";
2850
2339
  import { createInterface } from "readline";
2851
-
2852
- // src/logger.ts
2853
- var verboseMode = false;
2854
- function setVerbose(v) {
2855
- verboseMode = v;
2856
- }
2857
- function log(level, message, context) {
2858
- if (level === "DEBUG" && !verboseMode) return;
2859
- const entry = {
2860
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2861
- level,
2862
- message,
2863
- ...context && Object.keys(context).length > 0 ? { context } : {}
2864
- };
2865
- process.stderr.write(JSON.stringify(entry) + "\n");
2866
- }
2867
- function logInfo(message, context) {
2868
- log("INFO", message, context);
2869
- }
2870
- function logWarn(message, context) {
2871
- log("WARN", message, context);
2872
- }
2873
- function logError(message, context) {
2874
- log("ERROR", message, context);
2875
- }
2876
-
2877
- // src/cli.ts
2878
2340
  var bold = (s) => `\x1B[1m${s}\x1B[0m`;
2879
2341
  var dim = (s) => `\x1B[2m${s}\x1B[0m`;
2880
2342
  var cyan = (s) => `\x1B[36m${s}\x1B[0m`;
@@ -2901,7 +2363,8 @@ function main() {
2901
2363
  cleanupTempFiles();
2902
2364
  const program = new Command();
2903
2365
  const CMD = "datasynx-cartography";
2904
- const VERSION = "1.0.1";
2366
+ const __dirname = import.meta.dirname ?? dirname(fileURLToPath(import.meta.url));
2367
+ const { version: VERSION } = JSON.parse(readFileSync2(resolve(__dirname, "..", "package.json"), "utf-8"));
2905
2368
  program.name(CMD).description("AI-powered Infrastructure Discovery & Agentic AI Cartography").version(VERSION);
2906
2369
  program.command("discover").description("Scan and map your infrastructure").option("--entry <hosts...>", "Entry points", ["localhost"]).option("--depth <n>", "Max crawl depth", "8").option("--max-turns <n>", "Max agent turns", "50").option("--model <m>", "Agent model", "claude-sonnet-4-5-20250929").option("--org <name>", "Organization name (for Backstage)").option("-o, --output <dir>", "Output directory", "./datasynx-output").option("--db <path>", "DB path").option("-v, --verbose", "Show agent reasoning", false).action(async (opts) => {
2907
2370
  checkPrerequisites();
@@ -3065,7 +2528,8 @@ function main() {
3065
2528
  await runDiscovery(config, db, sessionId, handleEvent, onAskUser, void 0);
3066
2529
  } catch (err) {
3067
2530
  stopSpinner();
3068
- const errMsg = err instanceof Error ? err.message : String(err);
2531
+ const rawMsg = err instanceof Error ? err.message : String(err);
2532
+ const errMsg = rawMsg.replace(/https?:\/\/[^\s]+/g, (u) => stripSensitive(u));
3069
2533
  logError("Discovery failed", { sessionId, error: errMsg });
3070
2534
  w(`
3071
2535
  ${bold("\x1B[31m\u2717\x1B[0m")} Discovery failed: ${errMsg}
@@ -3277,7 +2741,7 @@ Session: ${session.id}
3277
2741
  }
3278
2742
  db.close();
3279
2743
  });
3280
- program.command("overview").description("Overview of all cartography sessions").option("--db <path>", "DB-Pfad").action((opts) => {
2744
+ program.command("overview").description("Overview of all cartography sessions").option("--db <path>", "DB path").action((opts) => {
3281
2745
  const config = defaultConfig();
3282
2746
  const db = new CartographyDB(opts.db ?? config.dbPath);
3283
2747
  const sessions = db.getSessions();
@@ -3328,7 +2792,7 @@ Session: ${session.id}
3328
2792
  }
3329
2793
  db.close();
3330
2794
  });
3331
- program.command("chat [session-id]").description("Interactive chat about your mapped infrastructure").option("--db <path>", "DB-Pfad").option("--model <m>", "Model", "claude-sonnet-4-5-20250929").action(async (sessionIdArg, opts) => {
2795
+ program.command("chat [session-id]").description("Interactive chat about your mapped infrastructure").option("--db <path>", "DB path").option("--model <m>", "Model", "claude-sonnet-4-5-20250929").action(async (sessionIdArg, opts) => {
3332
2796
  const config = defaultConfig();
3333
2797
  const db = new CartographyDB(opts.db ?? config.dbPath);
3334
2798
  const sessions = db.getSessions();
@@ -3351,7 +2815,7 @@ Session: ${session.id}
3351
2815
  w(dim(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
3352
2816
  `));
3353
2817
  w(` ${dim("Ask anything about your infrastructure. exit = quit.\n\n")}`);
3354
- const Anthropic = (await import("@anthropic-ai/sdk")).default;
2818
+ const Anthropic = (await import("./sdk-QSTAREST.js")).default;
3355
2819
  const client = new Anthropic();
3356
2820
  const infraSummary = JSON.stringify({
3357
2821
  nodes: nodes.map((n) => ({
@@ -3541,7 +3005,7 @@ ${infraSummary.substring(0, 12e3)}`;
3541
3005
  out("\n");
3542
3006
  });
3543
3007
  program.command("bookmarks").description("View all browser bookmarks (Chrome, Chromium, Edge, Brave, Vivaldi, Opera, Firefox)").action(async () => {
3544
- const { scanAllBookmarks: scanAllBookmarks2 } = await import("./bookmarks-BWNVQGPG.js");
3008
+ const { scanAllBookmarks: scanAllBookmarks2 } = await import("./bookmarks-VS56KVCO.js");
3545
3009
  const out = (s) => process.stdout.write(s);
3546
3010
  process.stderr.write(" Scanning bookmarks...\n\n");
3547
3011
  const hosts = await scanAllBookmarks2();
@@ -3628,7 +3092,7 @@ ${infraSummary.substring(0, 12e3)}`;
3628
3092
  `);
3629
3093
  return;
3630
3094
  }
3631
- const { NODE_TYPES: NODE_TYPES2 } = await import("./types-54623ALF.js");
3095
+ const { NODE_TYPES: NODE_TYPES2 } = await import("./types-JG27FR3E.js");
3632
3096
  if (!process.stdin.isTTY) {
3633
3097
  w(red("\n \u2717 Interactive mode requires a terminal (use --file for non-interactive)\n\n"));
3634
3098
  process.exitCode = 1;
@@ -3722,7 +3186,7 @@ ${infraSummary.substring(0, 12e3)}`;
3722
3186
  if ((major ?? 0) >= 18) {
3723
3187
  ok(`Node.js ${nodeVer}`);
3724
3188
  } else {
3725
- err(`Node.js ${nodeVer} \u2014 ben\xF6tigt >=18`);
3189
+ err(`Node.js ${nodeVer} \u2014 requires >=18`);
3726
3190
  allGood = false;
3727
3191
  }
3728
3192
  try {
@@ -3834,64 +3298,69 @@ ${infraSummary.substring(0, 12e3)}`;
3834
3298
  }
3835
3299
  db.close();
3836
3300
  });
3301
+ program.command("mcp").description("Run the Model Context Protocol server (stdio by default) \u2014 the primary interface for AI agents").option("--http", "Use Streamable HTTP transport instead of stdio", false).option("--port <n>", "HTTP port", "3737").option("--host <h>", "HTTP host", "127.0.0.1").option("--db <path>", "DB path").option("--session <id>", 'Session to serve (id or "latest")', "latest").option("--no-semantic", "Disable semantic (vector) search").action(async (opts) => {
3302
+ await startMcp({
3303
+ transport: opts.http ? "http" : "stdio",
3304
+ port: parseInt(opts.port, 10),
3305
+ host: opts.host,
3306
+ dbPath: opts.db,
3307
+ session: opts.session,
3308
+ semantic: opts.semantic
3309
+ });
3310
+ });
3837
3311
  const o = (s) => process.stderr.write(s);
3838
- const _b = (s) => `\x1B[1m${s}\x1B[0m`;
3839
- const _d = (s) => `\x1B[2m${s}\x1B[0m`;
3840
- const _c = (s) => `\x1B[36m${s}\x1B[0m`;
3841
- const _g = (s) => `\x1B[32m${s}\x1B[0m`;
3842
- const _m = (s) => `\x1B[35m${s}\x1B[0m`;
3843
3312
  o("\n");
3844
- o(_c(" ____ _ ____ ") + "\n");
3845
- o(_c(" | _ \\ __ _| |_ __ _/ ___| _ _ _ __ __ __") + "\n");
3846
- o(_c(" | | | |/ _` | __/ _` \\___ \\| | | | '_ \\\\ \\/ /") + "\n");
3847
- o(_c(" | |_| | (_| | || (_| |___) | |_| | | | |> < ") + "\n");
3848
- o(_c(" |____/ \\__,_|\\__\\__,_|____/ \\__, |_| |_/_/\\_\\") + "\n");
3849
- o(_c(" |___/ ") + "\n");
3313
+ o(cyan(" ____ _ ____ ") + "\n");
3314
+ o(cyan(" | _ \\ __ _| |_ __ _/ ___| _ _ _ __ __ __") + "\n");
3315
+ o(cyan(" | | | |/ _` | __/ _` \\___ \\| | | | '_ \\\\ \\/ /") + "\n");
3316
+ o(cyan(" | |_| | (_| | || (_| |___) | |_| | | | |> < ") + "\n");
3317
+ o(cyan(" |____/ \\__,_|\\__\\__,_|____/ \\__, |_| |_/_/\\_\\") + "\n");
3318
+ o(cyan(" |___/ ") + "\n");
3850
3319
  o("\n");
3851
- o(_b(" Cartography") + " " + _d("v" + VERSION) + "\n");
3852
- o(_d(" AI-powered Infrastructure Discovery & Agentic AI Cartography\n"));
3853
- o(_d(" Built on Claude Agent SDK\n"));
3320
+ o(bold(" Cartography") + " " + dim("v" + VERSION) + "\n");
3321
+ o(dim(" AI-powered Infrastructure Discovery & Agentic AI Cartography\n"));
3322
+ o(dim(" Autonomous infrastructure discovery \u2014 zero-config, provider-agnostic\n"));
3854
3323
  o("\n");
3855
3324
  if (process.argv.length <= 2) {
3856
- o(_d(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3325
+ o(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3857
3326
  o("\n");
3858
- o(_b(" Commands:\n"));
3327
+ o(bold(" Commands:\n"));
3859
3328
  o("\n");
3860
- o(` ${_g("discover")} ${_d("Scan infrastructure (Claude Sonnet)")}
3329
+ o(` ${green("discover")} ${dim("Scan infrastructure (Claude Sonnet)")}
3861
3330
  `);
3862
- o(` ${_g("seed")} ${_d("Manually add known tools/DBs/APIs")}
3331
+ o(` ${green("seed")} ${dim("Manually add known tools/DBs/APIs")}
3863
3332
  `);
3864
- o(` ${_g("bookmarks")} ${_d("View browser bookmarks")}
3333
+ o(` ${green("bookmarks")} ${dim("View browser bookmarks")}
3865
3334
  `);
3866
- o(` ${_g("export")} ${_d("[session]")} ${_d("Export Mermaid, JSON, YAML, HTML")}
3335
+ o(` ${green("export")} ${dim("[session]")} ${dim("Export Mermaid, JSON, YAML, HTML")}
3867
3336
  `);
3868
- o(` ${_g("show")} ${_d("[session]")} ${_d("Show session details")}
3337
+ o(` ${green("show")} ${dim("[session]")} ${dim("Show session details")}
3869
3338
  `);
3870
- o(` ${_g("sessions")} ${_d("List all sessions")}
3339
+ o(` ${green("sessions")} ${dim("List all sessions")}
3871
3340
  `);
3872
- o(` ${_g("doctor")} ${_d("Check requirements (kubectl, aws, gcloud, az)")}
3341
+ o(` ${green("doctor")} ${dim("Check requirements (kubectl, aws, gcloud, az)")}
3873
3342
  `);
3874
- o(` ${_g("docs")} ${_d("Full feature reference")}
3343
+ o(` ${green("docs")} ${dim("Full feature reference")}
3875
3344
  `);
3876
3345
  o("\n");
3877
- o(_d(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3346
+ o(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3878
3347
  o("\n");
3879
- o(_b(" Quick Start:\n"));
3348
+ o(bold(" Quick Start:\n"));
3880
3349
  o("\n");
3881
- o(` ${_m("$")} ${_b("datasynx-cartography doctor")} ${_d("Check requirements")}
3350
+ o(` ${magenta("$")} ${bold("datasynx-cartography doctor")} ${dim("Check requirements")}
3882
3351
  `);
3883
- o(` ${_m("$")} ${_b("datasynx-cartography seed")} ${_d("Add known infrastructure")}
3352
+ o(` ${magenta("$")} ${bold("datasynx-cartography seed")} ${dim("Add known infrastructure")}
3884
3353
  `);
3885
- o(` ${_m("$")} ${_b("datasynx-cartography discover")} ${_d("One-time scan")}
3354
+ o(` ${magenta("$")} ${bold("datasynx-cartography discover")} ${dim("One-time scan")}
3886
3355
  `);
3887
3356
  o("\n");
3888
- o(_d(" Docs: datasynx-cartography docs\n"));
3889
- o(_d(" Help: datasynx-cartography --help\n"));
3890
- o(_d(" npm: @datasynx/agentic-ai-cartography\n"));
3357
+ o(dim(" Docs: datasynx-cartography docs\n"));
3358
+ o(dim(" Help: datasynx-cartography --help\n"));
3359
+ o(dim(" npm: @datasynx/agentic-ai-cartography\n"));
3891
3360
  o("\n");
3892
3361
  return;
3893
3362
  }
3894
- o(_d(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3363
+ o(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3895
3364
  o("\n");
3896
3365
  program.exitOverride((err) => {
3897
3366
  if (err.code === "commander.helpDisplayed") {