claude-eidetic 0.1.0 → 0.1.2

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 (96) hide show
  1. package/README.md +333 -0
  2. package/dist/config.d.ts +25 -0
  3. package/dist/config.js +29 -14
  4. package/dist/core/cleanup.d.ts +8 -0
  5. package/dist/core/cleanup.js +41 -0
  6. package/dist/core/doc-indexer.d.ts +13 -0
  7. package/dist/core/doc-indexer.js +76 -0
  8. package/dist/core/doc-searcher.d.ts +13 -0
  9. package/dist/core/doc-searcher.js +65 -0
  10. package/dist/core/file-category.d.ts +7 -0
  11. package/dist/core/file-category.js +75 -0
  12. package/dist/core/indexer.js +12 -4
  13. package/dist/core/preview.d.ts +1 -2
  14. package/dist/core/preview.js +2 -5
  15. package/dist/core/repo-map.d.ts +33 -0
  16. package/dist/core/repo-map.js +144 -0
  17. package/dist/core/searcher.d.ts +1 -13
  18. package/dist/core/searcher.js +20 -24
  19. package/dist/core/snapshot-io.js +2 -2
  20. package/dist/core/sync.d.ts +5 -25
  21. package/dist/core/sync.js +90 -65
  22. package/dist/core/targeted-indexer.d.ts +19 -0
  23. package/dist/core/targeted-indexer.js +127 -0
  24. package/dist/embedding/factory.d.ts +0 -13
  25. package/dist/embedding/factory.js +0 -17
  26. package/dist/embedding/openai.d.ts +2 -14
  27. package/dist/embedding/openai.js +7 -20
  28. package/dist/errors.d.ts +2 -0
  29. package/dist/errors.js +2 -0
  30. package/dist/format.d.ts +12 -0
  31. package/dist/format.js +160 -31
  32. package/dist/hooks/post-tool-use.d.ts +13 -0
  33. package/dist/hooks/post-tool-use.js +113 -0
  34. package/dist/hooks/stop-hook.d.ts +11 -0
  35. package/dist/hooks/stop-hook.js +121 -0
  36. package/dist/hooks/targeted-runner.d.ts +11 -0
  37. package/dist/hooks/targeted-runner.js +66 -0
  38. package/dist/index.js +102 -24
  39. package/dist/infra/qdrant-bootstrap.js +14 -12
  40. package/dist/memory/history.d.ts +19 -0
  41. package/dist/memory/history.js +40 -0
  42. package/dist/memory/llm.d.ts +2 -0
  43. package/dist/memory/llm.js +56 -0
  44. package/dist/memory/prompts.d.ts +5 -0
  45. package/dist/memory/prompts.js +36 -0
  46. package/dist/memory/reconciler.d.ts +12 -0
  47. package/dist/memory/reconciler.js +36 -0
  48. package/dist/memory/store.d.ts +20 -0
  49. package/dist/memory/store.js +206 -0
  50. package/dist/memory/types.d.ts +28 -0
  51. package/dist/memory/types.js +2 -0
  52. package/dist/paths.d.ts +3 -4
  53. package/dist/paths.js +14 -4
  54. package/dist/precompact/hook.d.ts +9 -0
  55. package/dist/precompact/hook.js +170 -0
  56. package/dist/precompact/index-runner.d.ts +9 -0
  57. package/dist/precompact/index-runner.js +52 -0
  58. package/dist/precompact/note-writer.d.ts +15 -0
  59. package/dist/precompact/note-writer.js +109 -0
  60. package/dist/precompact/session-indexer.d.ts +13 -0
  61. package/dist/precompact/session-indexer.js +31 -0
  62. package/dist/precompact/tier0-inject.d.ts +16 -0
  63. package/dist/precompact/tier0-inject.js +88 -0
  64. package/dist/precompact/tier0-writer.d.ts +16 -0
  65. package/dist/precompact/tier0-writer.js +74 -0
  66. package/dist/precompact/transcript-parser.d.ts +10 -0
  67. package/dist/precompact/transcript-parser.js +148 -0
  68. package/dist/precompact/types.d.ts +93 -0
  69. package/dist/precompact/types.js +5 -0
  70. package/dist/precompact/utils.d.ts +29 -0
  71. package/dist/precompact/utils.js +95 -0
  72. package/dist/setup-message.d.ts +3 -0
  73. package/dist/setup-message.js +42 -0
  74. package/dist/splitter/ast.js +84 -22
  75. package/dist/splitter/line.d.ts +0 -4
  76. package/dist/splitter/line.js +1 -7
  77. package/dist/splitter/symbol-extract.d.ts +16 -0
  78. package/dist/splitter/symbol-extract.js +61 -0
  79. package/dist/splitter/types.d.ts +5 -0
  80. package/dist/splitter/types.js +1 -1
  81. package/dist/state/doc-metadata.d.ts +18 -0
  82. package/dist/state/doc-metadata.js +59 -0
  83. package/dist/state/registry.d.ts +1 -3
  84. package/dist/state/snapshot.d.ts +0 -1
  85. package/dist/state/snapshot.js +3 -19
  86. package/dist/tool-schemas.d.ts +251 -1
  87. package/dist/tool-schemas.js +307 -0
  88. package/dist/tools.d.ts +69 -0
  89. package/dist/tools.js +286 -17
  90. package/dist/vectordb/milvus.d.ts +7 -5
  91. package/dist/vectordb/milvus.js +116 -19
  92. package/dist/vectordb/qdrant.d.ts +8 -10
  93. package/dist/vectordb/qdrant.js +105 -33
  94. package/dist/vectordb/types.d.ts +20 -0
  95. package/messages.yaml +50 -0
  96. package/package.json +31 -6
@@ -1,4 +1,6 @@
1
1
  import { createRequire } from 'node:module';
2
+ import { MAX_CHUNK_CHARS } from './types.js';
3
+ import { extractSymbolInfo, isContainerType } from './symbol-extract.js';
2
4
  // tree-sitter and language parsers are native CommonJS modules
3
5
  const require = createRequire(import.meta.url);
4
6
  const Parser = require('tree-sitter');
@@ -23,29 +25,67 @@ const languageParsers = {
23
25
  };
24
26
  // AST node types that represent logical code units per language
25
27
  const SPLITTABLE_TYPES = {
26
- javascript: ['function_declaration', 'arrow_function', 'class_declaration', 'method_definition', 'export_statement'],
27
- typescript: ['function_declaration', 'arrow_function', 'class_declaration', 'method_definition', 'export_statement', 'interface_declaration', 'type_alias_declaration'],
28
- tsx: ['function_declaration', 'arrow_function', 'class_declaration', 'method_definition', 'export_statement', 'interface_declaration', 'type_alias_declaration'],
29
- python: ['function_definition', 'class_definition', 'decorated_definition', 'async_function_definition'],
30
- java: ['method_declaration', 'class_declaration', 'interface_declaration', 'constructor_declaration'],
28
+ javascript: ['function_declaration', 'arrow_function', 'class_declaration', 'method_definition'],
29
+ typescript: [
30
+ 'function_declaration',
31
+ 'arrow_function',
32
+ 'class_declaration',
33
+ 'method_definition',
34
+ 'interface_declaration',
35
+ 'type_alias_declaration',
36
+ ],
37
+ tsx: [
38
+ 'function_declaration',
39
+ 'arrow_function',
40
+ 'class_declaration',
41
+ 'method_definition',
42
+ 'interface_declaration',
43
+ 'type_alias_declaration',
44
+ ],
45
+ python: [
46
+ 'function_definition',
47
+ 'class_definition',
48
+ 'decorated_definition',
49
+ 'async_function_definition',
50
+ ],
51
+ java: [
52
+ 'method_declaration',
53
+ 'class_declaration',
54
+ 'interface_declaration',
55
+ 'constructor_declaration',
56
+ ],
31
57
  cpp: ['function_definition', 'class_specifier', 'namespace_definition', 'declaration'],
32
- go: ['function_declaration', 'method_declaration', 'type_declaration', 'var_declaration', 'const_declaration'],
58
+ go: [
59
+ 'function_declaration',
60
+ 'method_declaration',
61
+ 'type_declaration',
62
+ 'var_declaration',
63
+ 'const_declaration',
64
+ ],
33
65
  rust: ['function_item', 'impl_item', 'struct_item', 'enum_item', 'trait_item', 'mod_item'],
34
- csharp: ['method_declaration', 'class_declaration', 'interface_declaration', 'struct_declaration', 'enum_declaration'],
66
+ csharp: [
67
+ 'method_declaration',
68
+ 'class_declaration',
69
+ 'interface_declaration',
70
+ 'struct_declaration',
71
+ 'enum_declaration',
72
+ ],
35
73
  };
36
- // Map aliases to canonical language names for node type lookup
37
74
  const LANG_CANONICAL = {
38
- js: 'javascript', ts: 'typescript', py: 'python',
39
- rs: 'rust', 'c++': 'cpp', c: 'cpp', cs: 'csharp',
75
+ js: 'javascript',
76
+ ts: 'typescript',
77
+ py: 'python',
78
+ rs: 'rust',
79
+ 'c++': 'cpp',
80
+ c: 'cpp',
81
+ cs: 'csharp',
40
82
  };
41
- const MAX_CHUNK_CHARS = 2500;
42
83
  export class AstSplitter {
43
84
  parser = new Parser();
44
85
  currentLang = '';
45
86
  // Shared across all AstSplitter instances — one cache per process
46
87
  static langCache = new Map();
47
88
  static resolveLanguage(lang) {
48
- // Resolve alias to canonical name first — prevents duplicate cache entries
49
89
  const canonical = LANG_CANONICAL[lang] ?? lang;
50
90
  const cached = AstSplitter.langCache.get(canonical);
51
91
  if (cached)
@@ -59,7 +99,7 @@ export class AstSplitter {
59
99
  return mod;
60
100
  }
61
101
  catch (err) {
62
- console.warn(`Failed to load tree-sitter parser for "${lang}": ${err}`);
102
+ console.warn(`Failed to load tree-sitter parser for "${lang}":`, err);
63
103
  return null;
64
104
  }
65
105
  }
@@ -68,10 +108,9 @@ export class AstSplitter {
68
108
  const canonical = LANG_CANONICAL[lang] ?? lang;
69
109
  const langModule = AstSplitter.resolveLanguage(lang);
70
110
  if (!langModule) {
71
- return []; // Caller should fall back to line splitter
111
+ return [];
72
112
  }
73
113
  try {
74
- // Skip setLanguage() if parser is already configured for this language
75
114
  if (canonical !== this.currentLang) {
76
115
  this.parser.setLanguage(langModule);
77
116
  this.currentLang = canonical;
@@ -81,14 +120,13 @@ export class AstSplitter {
81
120
  return [];
82
121
  const nodeTypes = SPLITTABLE_TYPES[canonical] ?? [];
83
122
  const rawChunks = this.extractChunks(tree.rootNode, code, nodeTypes, language, filePath);
84
- // If no meaningful chunks found, return empty (caller will use line splitter)
85
123
  if (rawChunks.length === 0)
86
124
  return [];
87
125
  return this.refineChunks(rawChunks);
88
126
  }
89
127
  catch (err) {
90
- console.warn(`AST parse failed for "${filePath}" (${language}): ${err}`);
91
- return []; // Caller should fall back to line splitter
128
+ console.warn(`AST parse failed for "${filePath}" (${language}):`, err);
129
+ return [];
92
130
  }
93
131
  }
94
132
  static isSupported(language) {
@@ -96,21 +134,37 @@ export class AstSplitter {
96
134
  }
97
135
  extractChunks(node, code, splittableTypes, language, filePath) {
98
136
  const chunks = [];
99
- const traverse = (current) => {
137
+ const traverse = (current, parentName) => {
100
138
  if (splittableTypes.includes(current.type)) {
101
139
  const text = code.slice(current.startIndex, current.endIndex);
102
140
  if (text.trim().length > 0) {
103
- chunks.push({
141
+ const symbolInfo = extractSymbolInfo(current, code, parentName);
142
+ const chunk = {
104
143
  content: text,
105
144
  startLine: current.startPosition.row + 1,
106
145
  endLine: current.endPosition.row + 1,
107
146
  language,
108
147
  filePath,
109
- });
148
+ };
149
+ if (symbolInfo) {
150
+ chunk.symbolName = symbolInfo.name;
151
+ chunk.symbolKind = symbolInfo.kind;
152
+ chunk.symbolSignature = symbolInfo.signature;
153
+ if (parentName)
154
+ chunk.parentSymbol = parentName;
155
+ }
156
+ chunks.push(chunk);
157
+ // If this is a container, pass its name as parentName to children
158
+ if (isContainerType(current.type) && symbolInfo?.name) {
159
+ for (const child of current.children) {
160
+ traverse(child, symbolInfo.name);
161
+ }
162
+ return;
163
+ }
110
164
  }
111
165
  }
112
166
  for (const child of current.children) {
113
- traverse(child);
167
+ traverse(child, parentName);
114
168
  }
115
169
  };
116
170
  traverse(node);
@@ -144,6 +198,10 @@ export class AstSplitter {
144
198
  endLine: startLine + lineCount - 1,
145
199
  language: chunk.language,
146
200
  filePath: chunk.filePath,
201
+ symbolName: chunk.symbolName,
202
+ symbolKind: chunk.symbolKind,
203
+ symbolSignature: chunk.symbolSignature,
204
+ parentSymbol: chunk.parentSymbol,
147
205
  });
148
206
  current = addition;
149
207
  startLine = chunk.startLine + i;
@@ -161,6 +219,10 @@ export class AstSplitter {
161
219
  endLine: startLine + lineCount - 1,
162
220
  language: chunk.language,
163
221
  filePath: chunk.filePath,
222
+ symbolName: chunk.symbolName,
223
+ symbolKind: chunk.symbolKind,
224
+ symbolSignature: chunk.symbolSignature,
225
+ parentSymbol: chunk.parentSymbol,
164
226
  });
165
227
  }
166
228
  return subChunks;
@@ -1,8 +1,4 @@
1
1
  import type { Splitter, CodeChunk } from './types.js';
2
- /**
3
- * Simple line-based splitter. Used as fallback when tree-sitter
4
- * doesn't support the language or fails to parse.
5
- */
6
2
  export declare class LineSplitter implements Splitter {
7
3
  private chunkLines;
8
4
  private overlapLines;
@@ -1,10 +1,6 @@
1
+ import { MAX_CHUNK_CHARS } from './types.js';
1
2
  const DEFAULT_CHUNK_LINES = 60;
2
3
  const OVERLAP_LINES = 5;
3
- const MAX_CHUNK_CHARS = 2500;
4
- /**
5
- * Simple line-based splitter. Used as fallback when tree-sitter
6
- * doesn't support the language or fails to parse.
7
- */
8
4
  export class LineSplitter {
9
5
  chunkLines;
10
6
  overlapLines;
@@ -72,9 +68,7 @@ export class LineSplitter {
72
68
  startLine = chunk.startLine + i;
73
69
  lineCount = 0;
74
70
  }
75
- // If a single line exceeds the limit, hard-split it by characters
76
71
  if (addition.length > MAX_CHUNK_CHARS) {
77
- // Flush anything accumulated before this line
78
72
  if (current.length > 0) {
79
73
  flush();
80
74
  current = '';
@@ -0,0 +1,16 @@
1
+ export interface SymbolInfo {
2
+ name: string;
3
+ kind: string;
4
+ signature: string;
5
+ }
6
+ interface AstNode {
7
+ type: string;
8
+ startIndex: number;
9
+ endIndex: number;
10
+ children: AstNode[];
11
+ text?: string;
12
+ }
13
+ export declare function extractSymbolInfo(node: AstNode, code: string, parentName?: string): SymbolInfo | undefined;
14
+ export declare function isContainerType(nodeType: string): boolean;
15
+ export {};
16
+ //# sourceMappingURL=symbol-extract.d.ts.map
@@ -0,0 +1,61 @@
1
+ const CONTAINER_TYPES = new Set(['class_declaration', 'class_definition', 'interface_declaration']);
2
+ const KIND_MAP = {
3
+ function_declaration: 'function',
4
+ arrow_function: 'function',
5
+ async_function_definition: 'function',
6
+ function_definition: 'function',
7
+ class_declaration: 'class',
8
+ class_definition: 'class',
9
+ interface_declaration: 'interface',
10
+ method_definition: 'method',
11
+ method_declaration: 'method',
12
+ type_alias_declaration: 'type',
13
+ enum_declaration: 'enum',
14
+ // Java
15
+ constructor_declaration: 'constructor',
16
+ // Rust
17
+ function_item: 'function',
18
+ impl_item: 'impl',
19
+ struct_item: 'struct',
20
+ enum_item: 'enum',
21
+ trait_item: 'trait',
22
+ // C#
23
+ struct_declaration: 'struct',
24
+ };
25
+ function getIdentifier(node, code) {
26
+ const identChild = node.children.find((c) => c.type === 'identifier' || c.type === 'type_identifier' || c.type === 'name');
27
+ if (identChild)
28
+ return code.slice(identChild.startIndex, identChild.endIndex);
29
+ return undefined;
30
+ }
31
+ function extractSignature(node, code) {
32
+ const text = code.slice(node.startIndex, node.endIndex);
33
+ // Take first line up to opening brace or end of line
34
+ const firstLine = text.split('\n')[0];
35
+ const upToBrace = firstLine.split('{')[0].trimEnd();
36
+ const sig = upToBrace || firstLine;
37
+ return sig.length > 200 ? sig.slice(0, 200) + '…' : sig;
38
+ }
39
+ export function extractSymbolInfo(node, code, parentName) {
40
+ const nodeType = node.type;
41
+ // Handle export_statement: recurse into declaration child
42
+ if (nodeType === 'export_statement') {
43
+ const declChild = node.children.find((c) => c.type !== 'export' && c.type !== 'default' && c.type !== ';' && c.type !== 'identifier');
44
+ if (declChild)
45
+ return extractSymbolInfo(declChild, code, parentName);
46
+ return undefined;
47
+ }
48
+ const kind = KIND_MAP[nodeType];
49
+ if (!kind)
50
+ return undefined;
51
+ const name = getIdentifier(node, code);
52
+ if (!name)
53
+ return undefined;
54
+ const signature = extractSignature(node, code);
55
+ void parentName; // consumed by caller to set chunk.parentSymbol
56
+ return { name, kind, signature };
57
+ }
58
+ export function isContainerType(nodeType) {
59
+ return CONTAINER_TYPES.has(nodeType);
60
+ }
61
+ //# sourceMappingURL=symbol-extract.js.map
@@ -1,9 +1,14 @@
1
+ export declare const MAX_CHUNK_CHARS = 2500;
1
2
  export interface CodeChunk {
2
3
  content: string;
3
4
  startLine: number;
4
5
  endLine: number;
5
6
  language: string;
6
7
  filePath: string;
8
+ symbolName?: string;
9
+ symbolKind?: string;
10
+ symbolSignature?: string;
11
+ parentSymbol?: string;
7
12
  }
8
13
  export interface Splitter {
9
14
  split(code: string, language: string, filePath: string): CodeChunk[];
@@ -1,2 +1,2 @@
1
- export {};
1
+ export const MAX_CHUNK_CHARS = 2500;
2
2
  //# sourceMappingURL=types.js.map
@@ -0,0 +1,18 @@
1
+ export interface DocEntry {
2
+ library: string;
3
+ topic: string;
4
+ source: string;
5
+ collectionName: string;
6
+ indexedAt: string;
7
+ ttlDays: number;
8
+ totalChunks: number;
9
+ }
10
+ export type DocMetadata = Record<string, DocEntry>;
11
+ export declare function loadDocMetadata(): DocMetadata;
12
+ export declare function saveDocMetadata(metadata: DocMetadata): void;
13
+ export declare function upsertDocEntry(entry: DocEntry): void;
14
+ export declare function removeDocEntry(library: string, topic: string): boolean;
15
+ export declare function findDocEntries(library: string): DocEntry[];
16
+ export declare function isStale(entry: DocEntry): boolean;
17
+ export declare function listDocLibraries(): string[];
18
+ //# sourceMappingURL=doc-metadata.d.ts.map
@@ -0,0 +1,59 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { getDocMetadataPath } from '../paths.js';
4
+ function metadataKey(library, topic) {
5
+ return `${library.toLowerCase()}::${topic.toLowerCase()}`;
6
+ }
7
+ export function loadDocMetadata() {
8
+ const metadataPath = getDocMetadataPath();
9
+ try {
10
+ const data = fs.readFileSync(metadataPath, 'utf-8');
11
+ return JSON.parse(data);
12
+ }
13
+ catch {
14
+ return {};
15
+ }
16
+ }
17
+ export function saveDocMetadata(metadata) {
18
+ const metadataPath = getDocMetadataPath();
19
+ const dir = path.dirname(metadataPath);
20
+ fs.mkdirSync(dir, { recursive: true });
21
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2) + '\n', 'utf-8');
22
+ }
23
+ export function upsertDocEntry(entry) {
24
+ const metadata = loadDocMetadata();
25
+ const key = metadataKey(entry.library, entry.topic);
26
+ metadata[key] = entry;
27
+ saveDocMetadata(metadata);
28
+ }
29
+ export function removeDocEntry(library, topic) {
30
+ const metadata = loadDocMetadata();
31
+ const key = metadataKey(library, topic);
32
+ if (!(key in metadata))
33
+ return false;
34
+ Reflect.deleteProperty(metadata, key);
35
+ saveDocMetadata(metadata);
36
+ return true;
37
+ }
38
+ export function findDocEntries(library) {
39
+ const metadata = loadDocMetadata();
40
+ const prefix = `${library.toLowerCase()}::`;
41
+ return Object.entries(metadata)
42
+ .filter(([key]) => key.startsWith(prefix))
43
+ .map(([, entry]) => entry);
44
+ }
45
+ export function isStale(entry) {
46
+ const indexedAt = new Date(entry.indexedAt).getTime();
47
+ const now = Date.now();
48
+ const ttlMs = entry.ttlDays * 24 * 60 * 60 * 1000;
49
+ return now - indexedAt > ttlMs;
50
+ }
51
+ export function listDocLibraries() {
52
+ const metadata = loadDocMetadata();
53
+ const libs = new Set();
54
+ for (const entry of Object.values(metadata)) {
55
+ libs.add(entry.library);
56
+ }
57
+ return [...libs].sort();
58
+ }
59
+ //# sourceMappingURL=doc-metadata.js.map
@@ -1,6 +1,4 @@
1
- interface Registry {
2
- [project: string]: string;
3
- }
1
+ type Registry = Record<string, string>;
4
2
  export declare function registerProject(absolutePath: string): void;
5
3
  export declare function resolveProject(project: string): string | undefined;
6
4
  export declare function listProjects(): Registry;
@@ -20,7 +20,6 @@ export declare class StateManager {
20
20
  setIndexed(normalizedPath: string, totalFiles: number, totalChunks: number): void;
21
21
  setError(normalizedPath: string, error: string): void;
22
22
  remove(normalizedPath: string): void;
23
- markExisting(normalizedPath: string, collectionName: string): void;
24
23
  }
25
24
  export declare function cleanupOrphanedSnapshots(vectordb: VectorDB): Promise<number>;
26
25
  //# sourceMappingURL=snapshot.d.ts.map
@@ -46,14 +46,6 @@ export class StateManager {
46
46
  remove(normalizedPath) {
47
47
  this.states.delete(normalizedPath);
48
48
  }
49
- markExisting(normalizedPath, collectionName) {
50
- this.states.set(normalizedPath, {
51
- path: normalizedPath,
52
- collectionName,
53
- status: 'indexed',
54
- lastIndexed: 'unknown (pre-existing)',
55
- });
56
- }
57
49
  }
58
50
  export async function cleanupOrphanedSnapshots(vectordb) {
59
51
  const snapshotDir = getSnapshotDir();
@@ -61,16 +53,10 @@ export async function cleanupOrphanedSnapshots(vectordb) {
61
53
  try {
62
54
  if (!fs.existsSync(snapshotDir))
63
55
  return 0;
64
- const files = fs.readdirSync(snapshotDir).filter(f => f.endsWith('.json'));
56
+ const files = fs.readdirSync(snapshotDir).filter((f) => f.endsWith('.json'));
65
57
  if (files.length === 0)
66
58
  return 0;
67
- // Connectivity probe: use a name unlikely to exist. If hasCollection throws
68
- // or the vector DB is unreachable (Qdrant's hasCollection returns false on
69
- // network error), we must not proceed -- deleting snapshots when we cannot
70
- // confirm collection absence would destroy valid state.
71
59
  const probeResult = await vectordb.hasCollection('__eidetic_connectivity_probe__');
72
- // If the probe returns true for a name that should never exist, something is
73
- // wrong -- skip cleanup to be safe.
74
60
  if (probeResult) {
75
61
  console.warn('Orphan cleanup skipped: connectivity probe returned unexpected result.');
76
62
  return 0;
@@ -87,14 +73,12 @@ export async function cleanupOrphanedSnapshots(vectordb) {
87
73
  }
88
74
  }
89
75
  catch (err) {
90
- // Network error for this specific check -- skip rather than risk deletion
91
- console.warn(`Skipping orphan check for ${collectionName}: ${err}`);
76
+ console.warn(`Skipping orphan check for ${collectionName}:`, err);
92
77
  }
93
78
  }
94
79
  }
95
80
  catch (err) {
96
- // Connectivity probe failure or filesystem error -- skip cleanup entirely
97
- console.warn(`Orphan cleanup skipped: ${err}`);
81
+ console.warn('Orphan cleanup skipped:', err);
98
82
  }
99
83
  return cleaned;
100
84
  }