@sashabogi/foundation 2.2.0 → 3.0.1

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 (43) hide show
  1. package/dist/cli.js +3 -3
  2. package/dist/cli.js.map +1 -1
  3. package/dist/tools/demerzel/engine.d.ts +3 -2
  4. package/dist/tools/demerzel/engine.d.ts.map +1 -1
  5. package/dist/tools/demerzel/engine.js +7 -7
  6. package/dist/tools/demerzel/engine.js.map +1 -1
  7. package/dist/tools/demerzel/enhanced-snapshot.d.ts +10 -2
  8. package/dist/tools/demerzel/enhanced-snapshot.d.ts.map +1 -1
  9. package/dist/tools/demerzel/enhanced-snapshot.js +156 -77
  10. package/dist/tools/demerzel/enhanced-snapshot.js.map +1 -1
  11. package/dist/tools/demerzel/index.d.ts +1 -1
  12. package/dist/tools/demerzel/index.d.ts.map +1 -1
  13. package/dist/tools/demerzel/index.js +53 -36
  14. package/dist/tools/demerzel/index.js.map +1 -1
  15. package/dist/tools/demerzel/semantic-search.d.ts +2 -2
  16. package/dist/tools/demerzel/semantic-search.d.ts.map +1 -1
  17. package/dist/tools/demerzel/semantic-search.js +4 -3
  18. package/dist/tools/demerzel/semantic-search.js.map +1 -1
  19. package/dist/tools/demerzel/snapshot.d.ts +34 -1
  20. package/dist/tools/demerzel/snapshot.d.ts.map +1 -1
  21. package/dist/tools/demerzel/snapshot.js +70 -34
  22. package/dist/tools/demerzel/snapshot.js.map +1 -1
  23. package/dist/tools/demerzel/zstd-io.d.ts +40 -0
  24. package/dist/tools/demerzel/zstd-io.d.ts.map +1 -0
  25. package/dist/tools/demerzel/zstd-io.js +69 -0
  26. package/dist/tools/demerzel/zstd-io.js.map +1 -0
  27. package/dist/tools/gaia/index.d.ts +5 -4
  28. package/dist/tools/gaia/index.d.ts.map +1 -1
  29. package/dist/tools/gaia/index.js +155 -8
  30. package/dist/tools/gaia/index.js.map +1 -1
  31. package/dist/tools/gaia/storage.d.ts +29 -2
  32. package/dist/tools/gaia/storage.d.ts.map +1 -1
  33. package/dist/tools/gaia/storage.js +100 -7
  34. package/dist/tools/gaia/storage.js.map +1 -1
  35. package/dist/tools/gaia/transcript-ingester.d.ts +81 -0
  36. package/dist/tools/gaia/transcript-ingester.d.ts.map +1 -0
  37. package/dist/tools/gaia/transcript-ingester.js +418 -0
  38. package/dist/tools/gaia/transcript-ingester.js.map +1 -0
  39. package/dist/vault/sync.d.ts.map +1 -1
  40. package/dist/vault/sync.js +24 -12
  41. package/dist/vault/sync.js.map +1 -1
  42. package/package.json +2 -1
  43. package/docs/foundation +0 -0
@@ -6,8 +6,9 @@
6
6
  *
7
7
  * Ported from Argus to Foundation.
8
8
  */
9
- import { existsSync, readFileSync, readdirSync, statSync, writeFileSync, mkdirSync } from 'fs';
9
+ import { existsSync, readFileSync, readdirSync, statSync, mkdirSync } from 'fs';
10
10
  import { join, relative, extname, dirname } from 'path';
11
+ import { writeCompressed, compressedPath } from './zstd-io.js';
11
12
  export const DEFAULT_EXTENSIONS = [
12
13
  'ts', 'tsx', 'js', 'jsx', 'rs', 'py', 'go', 'java', 'rb', 'php',
13
14
  'swift', 'kt', 'scala', 'c', 'cpp', 'h', 'hpp', 'cs', 'md', 'json'
@@ -34,6 +35,7 @@ const DEFAULT_OPTIONS = {
34
35
  excludePatterns: DEFAULT_EXCLUDE_PATTERNS,
35
36
  maxFileSize: 1024 * 1024, // 1MB
36
37
  includeHidden: false,
38
+ mode: 'full',
37
39
  };
38
40
  function shouldExclude(filePath, patterns) {
39
41
  const normalizedPath = filePath.replace(/\\/g, '/');
@@ -96,11 +98,39 @@ function collectFiles(dir, options, baseDir = dir) {
96
98
  }
97
99
  return files.sort();
98
100
  }
99
- export function createSnapshot(projectPath, outputPath, options = {}) {
101
+ /**
102
+ * Build the standard snapshot header lines, shared across all modes.
103
+ */
104
+ export function buildSnapshotHeader(projectPath, fileCount, extensions, mode) {
105
+ return [
106
+ '================================================================================',
107
+ 'CODEBASE SNAPSHOT',
108
+ `Project: ${projectPath}`,
109
+ `Generated: ${new Date().toISOString()}`,
110
+ `Extensions: ${extensions.join(', ')}`,
111
+ `Files: ${fileCount}`,
112
+ `Mode: ${mode}`,
113
+ '================================================================================',
114
+ '',
115
+ ];
116
+ }
117
+ /**
118
+ * Create a basic codebase snapshot.
119
+ *
120
+ * Writes a compressed `.zst` file to disk. The `outputPath` parameter is the
121
+ * canonical (uncompressed) path; the actual on-disk file is `outputPath + ".zst"`.
122
+ *
123
+ * Mode behaviour:
124
+ * - `"full"` — includes all file bodies (default, preserves existing behaviour)
125
+ * - `"graph"` / `"index"` — writes header + file tree only; `createEnhancedSnapshot`
126
+ * appends the relevant structural metadata on top of this base
127
+ */
128
+ export async function createSnapshot(projectPath, outputPath, options = {}) {
100
129
  const mergedOptions = {
101
130
  ...DEFAULT_OPTIONS,
102
131
  ...options,
103
132
  };
133
+ const mode = mergedOptions.mode;
104
134
  if (!existsSync(projectPath)) {
105
135
  throw new Error(`Project path does not exist: ${projectPath}`);
106
136
  }
@@ -108,7 +138,7 @@ export function createSnapshot(projectPath, outputPath, options = {}) {
108
138
  if (!stats.isDirectory()) {
109
139
  throw new Error(`Project path is not a directory: ${projectPath}`);
110
140
  }
111
- // Ensure output directory exists
141
+ // Ensure output directory exists (for the .zst file)
112
142
  const outputDir = dirname(outputPath);
113
143
  if (!existsSync(outputDir)) {
114
144
  mkdirSync(outputDir, { recursive: true });
@@ -116,54 +146,60 @@ export function createSnapshot(projectPath, outputPath, options = {}) {
116
146
  // Collect all files
117
147
  const files = collectFiles(projectPath, mergedOptions);
118
148
  // Build snapshot content
119
- const lines = [];
120
- // Header
121
- lines.push('================================================================================');
122
- lines.push('CODEBASE SNAPSHOT');
123
- lines.push(`Project: ${projectPath}`);
124
- lines.push(`Generated: ${new Date().toISOString()}`);
125
- lines.push(`Extensions: ${mergedOptions.extensions.join(', ')}`);
126
- lines.push(`Files: ${files.length}`);
127
- lines.push('================================================================================');
128
- lines.push('');
129
- // Process each file
130
- for (const filePath of files) {
131
- const relativePath = relative(projectPath, filePath);
132
- lines.push('');
149
+ const lines = buildSnapshotHeader(projectPath, files.length, mergedOptions.extensions, mode);
150
+ if (mode === 'full') {
151
+ // Full mode: include every file body
152
+ for (const filePath of files) {
153
+ const relativePath = relative(projectPath, filePath);
154
+ lines.push('');
155
+ lines.push('================================================================================');
156
+ lines.push(`FILE: ./${relativePath}`);
157
+ lines.push('================================================================================');
158
+ try {
159
+ const content = readFileSync(filePath, 'utf-8');
160
+ lines.push(content);
161
+ }
162
+ catch {
163
+ lines.push('[Unable to read file]');
164
+ }
165
+ }
166
+ }
167
+ else {
168
+ // graph / index modes: emit file tree only (no bodies).
169
+ // createEnhancedSnapshot will append the relevant structural sections.
133
170
  lines.push('================================================================================');
134
- lines.push(`FILE: ./${relativePath}`);
171
+ lines.push('FILE TREE');
135
172
  lines.push('================================================================================');
136
- try {
137
- const content = readFileSync(filePath, 'utf-8');
138
- lines.push(content);
139
- }
140
- catch {
141
- lines.push('[Unable to read file]');
173
+ for (const filePath of files) {
174
+ lines.push(`./${relative(projectPath, filePath)}`);
142
175
  }
143
176
  }
144
- // Write snapshot
145
177
  const content = lines.join('\n');
146
- writeFileSync(outputPath, content);
178
+ const diskPath = await writeCompressed(outputPath, content);
147
179
  const totalLines = content.split('\n').length;
148
180
  const totalSize = Buffer.byteLength(content, 'utf-8');
149
181
  return {
150
182
  outputPath,
183
+ diskPath,
151
184
  fileCount: files.length,
152
185
  totalLines,
153
186
  totalSize,
154
187
  files: files.map(f => relative(projectPath, f)),
188
+ mode,
155
189
  };
156
190
  }
191
+ /**
192
+ * Return disk-level stats for an existing snapshot.
193
+ * Accepts the canonical (uncompressed) path; transparently resolves to `.zst`.
194
+ */
157
195
  export function getSnapshotStats(snapshotPath) {
158
- if (!existsSync(snapshotPath)) {
196
+ const zstPath = compressedPath(snapshotPath);
197
+ const actualPath = existsSync(zstPath) ? zstPath : snapshotPath;
198
+ if (!existsSync(actualPath)) {
159
199
  throw new Error(`Snapshot file does not exist: ${snapshotPath}`);
160
200
  }
161
- const content = readFileSync(snapshotPath, 'utf-8');
162
- const totalLines = content.split('\n').length;
163
- const totalSize = Buffer.byteLength(content, 'utf-8');
164
- // Count FILE: markers
165
- const fileMatches = content.match(/^FILE: /gm);
166
- const fileCount = fileMatches ? fileMatches.length : 0;
167
- return { fileCount, totalLines, totalSize };
201
+ // Return disk size; for full line/file counts callers should decompress
202
+ const diskSize = statSync(actualPath).size;
203
+ return { fileCount: 0, totalLines: 0, totalSize: diskSize };
168
204
  }
169
205
  //# sourceMappingURL=snapshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/tools/demerzel/snapshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/tools/demerzel/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Demerzel zstd I/O helpers
3
+ *
4
+ * Wraps @mongodb-js/zstd for snapshot read/write.
5
+ * Write path: always produces <outputPath>.zst
6
+ * Read path: tries <path>.zst first; falls back to legacy <path> (plain text)
7
+ */
8
+ /** The `.zst` extension suffix appended to snapshot paths on disk. */
9
+ export declare const ZST_SUFFIX = ".zst";
10
+ /**
11
+ * Given a canonical snapshot path (e.g. `.foundation/snapshot.txt`), returns
12
+ * the on-disk compressed path (`.foundation/snapshot.txt.zst`).
13
+ */
14
+ export declare function compressedPath(snapshotPath: string): string;
15
+ /**
16
+ * Write `content` to `<snapshotPath>.zst`.
17
+ * The uncompressed `.txt` file is NOT written — only the compressed form.
18
+ *
19
+ * @returns The actual path written to disk (i.e. `snapshotPath + ".zst"`).
20
+ */
21
+ export declare function writeCompressed(snapshotPath: string, content: string): Promise<string>;
22
+ /**
23
+ * Read a snapshot, transparently handling both compressed and legacy formats.
24
+ *
25
+ * Resolution order:
26
+ * 1. `<snapshotPath>.zst` — decompress and return UTF-8 string
27
+ * 2. `<snapshotPath>` (legacy plain text) — read directly
28
+ * 3. Throws if neither exists
29
+ */
30
+ export declare function readSnapshotContent(snapshotPath: string): Promise<string>;
31
+ /**
32
+ * Check whether a snapshot exists on disk (either compressed or legacy).
33
+ */
34
+ export declare function snapshotExists(snapshotPath: string): boolean;
35
+ /**
36
+ * Return the actual on-disk path for a snapshot (compressed if present,
37
+ * otherwise legacy), or `null` if neither exists.
38
+ */
39
+ export declare function resolveSnapshotPath(snapshotPath: string): string | null;
40
+ //# sourceMappingURL=zstd-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zstd-io.d.ts","sourceRoot":"","sources":["../../../src/tools/demerzel/zstd-io.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,sEAAsE;AACtE,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK5F;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAc/E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvE"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Demerzel zstd I/O helpers
3
+ *
4
+ * Wraps @mongodb-js/zstd for snapshot read/write.
5
+ * Write path: always produces <outputPath>.zst
6
+ * Read path: tries <path>.zst first; falls back to legacy <path> (plain text)
7
+ */
8
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
9
+ import { compress, decompress } from '@mongodb-js/zstd';
10
+ /** The `.zst` extension suffix appended to snapshot paths on disk. */
11
+ export const ZST_SUFFIX = '.zst';
12
+ /**
13
+ * Given a canonical snapshot path (e.g. `.foundation/snapshot.txt`), returns
14
+ * the on-disk compressed path (`.foundation/snapshot.txt.zst`).
15
+ */
16
+ export function compressedPath(snapshotPath) {
17
+ return snapshotPath + ZST_SUFFIX;
18
+ }
19
+ /**
20
+ * Write `content` to `<snapshotPath>.zst`.
21
+ * The uncompressed `.txt` file is NOT written — only the compressed form.
22
+ *
23
+ * @returns The actual path written to disk (i.e. `snapshotPath + ".zst"`).
24
+ */
25
+ export async function writeCompressed(snapshotPath, content) {
26
+ const zstPath = compressedPath(snapshotPath);
27
+ const compressed = await compress(Buffer.from(content, 'utf-8'));
28
+ writeFileSync(zstPath, compressed);
29
+ return zstPath;
30
+ }
31
+ /**
32
+ * Read a snapshot, transparently handling both compressed and legacy formats.
33
+ *
34
+ * Resolution order:
35
+ * 1. `<snapshotPath>.zst` — decompress and return UTF-8 string
36
+ * 2. `<snapshotPath>` (legacy plain text) — read directly
37
+ * 3. Throws if neither exists
38
+ */
39
+ export async function readSnapshotContent(snapshotPath) {
40
+ const zstPath = compressedPath(snapshotPath);
41
+ if (existsSync(zstPath)) {
42
+ const compressed = readFileSync(zstPath);
43
+ const decompressed = await decompress(compressed);
44
+ return decompressed.toString('utf-8');
45
+ }
46
+ if (existsSync(snapshotPath)) {
47
+ return readFileSync(snapshotPath, 'utf-8');
48
+ }
49
+ throw new Error(`Snapshot not found: tried ${zstPath} and ${snapshotPath}`);
50
+ }
51
+ /**
52
+ * Check whether a snapshot exists on disk (either compressed or legacy).
53
+ */
54
+ export function snapshotExists(snapshotPath) {
55
+ return existsSync(compressedPath(snapshotPath)) || existsSync(snapshotPath);
56
+ }
57
+ /**
58
+ * Return the actual on-disk path for a snapshot (compressed if present,
59
+ * otherwise legacy), or `null` if neither exists.
60
+ */
61
+ export function resolveSnapshotPath(snapshotPath) {
62
+ const zstPath = compressedPath(snapshotPath);
63
+ if (existsSync(zstPath))
64
+ return zstPath;
65
+ if (existsSync(snapshotPath))
66
+ return snapshotPath;
67
+ return null;
68
+ }
69
+ //# sourceMappingURL=zstd-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zstd-io.js","sourceRoot":"","sources":["../../../src/tools/demerzel/zstd-io.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAExD,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB;IACjD,OAAO,YAAY,GAAG,UAAU,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,YAAoB,EAAE,OAAe;IACzE,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,YAAoB;IAC5D,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAE7C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;QAClD,OAAO,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,OAAO,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,QAAQ,YAAY,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB;IACjD,OAAO,UAAU,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AAC9E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC7C,IAAI,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,YAAY,CAAC;IAClD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * v2: SQLite + FTS5 memory system with 5-tier hierarchy and BM25 ranking.
8
8
  *
9
- * Tools (16 total):
9
+ * Tools (17 total):
10
10
  * Checkpoint/Session Tools (9):
11
11
  * - gaia_checkpoint: Save full structured state to disk
12
12
  * - gaia_status: Return lightweight index card (~150 tokens)
@@ -25,9 +25,10 @@
25
25
  * - gaia_delete: Delete memory + cascade links
26
26
  * - gaia_stats: Get memory statistics
27
27
  *
28
- * Linking Tools (2):
29
- * - gaia_link: Create typed link between memories
30
- * - gaia_graph: Get link graph for a memory
28
+ * Linking Tools (3):
29
+ * - gaia_link: Create typed link between memories (with optional valid_from backfill)
30
+ * - gaia_invalidate: Soft-delete a link by setting invalidated_at
31
+ * - gaia_graph: Get link graph for a memory (with optional as_of temporal filter)
31
32
  */
32
33
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
33
34
  export declare function registerGaiaTools(server: McpServer): void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/gaia/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA6GzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA42CzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/gaia/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8GzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAihDzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC"}
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * v2: SQLite + FTS5 memory system with 5-tier hierarchy and BM25 ranking.
8
8
  *
9
- * Tools (16 total):
9
+ * Tools (17 total):
10
10
  * Checkpoint/Session Tools (9):
11
11
  * - gaia_checkpoint: Save full structured state to disk
12
12
  * - gaia_status: Return lightweight index card (~150 tokens)
@@ -25,9 +25,10 @@
25
25
  * - gaia_delete: Delete memory + cascade links
26
26
  * - gaia_stats: Get memory statistics
27
27
  *
28
- * Linking Tools (2):
29
- * - gaia_link: Create typed link between memories
30
- * - gaia_graph: Get link graph for a memory
28
+ * Linking Tools (3):
29
+ * - gaia_link: Create typed link between memories (with optional valid_from backfill)
30
+ * - gaia_invalidate: Soft-delete a link by setting invalidated_at
31
+ * - gaia_graph: Get link graph for a memory (with optional as_of temporal filter)
31
32
  */
32
33
  import { z } from 'zod';
33
34
  import { nanoid } from 'nanoid';
@@ -37,6 +38,7 @@ import { homedir } from 'os';
37
38
  import { StorageService } from '../../services/storage.service.js';
38
39
  import { GitService } from '../../services/git.service.js';
39
40
  import { MemoriaStorage } from './storage.js';
41
+ import { createIngester } from './transcript-ingester.js';
40
42
  // =============================================================================
41
43
  // Memory Storage (v2.0)
42
44
  // =============================================================================
@@ -1155,7 +1157,9 @@ export function registerGaiaTools(server) {
1155
1157
  to_memory_id: z.string().describe('Target memory ID'),
1156
1158
  link_type: z.enum(['depends_on', 'extends', 'reverts', 'related', 'contradicts'])
1157
1159
  .describe('Link type: depends_on (requires), extends (builds on), reverts (undoes), related (associated), contradicts (conflicts)'),
1158
- }, async ({ from_memory_id, to_memory_id, link_type }) => {
1160
+ valid_from: z.string().optional()
1161
+ .describe('ISO 8601 timestamp for when this link became true. Defaults to now. Useful for backfilling historical links.'),
1162
+ }, async ({ from_memory_id, to_memory_id, link_type, valid_from }) => {
1159
1163
  try {
1160
1164
  const storage = getMemoryStorage();
1161
1165
  // Verify both memories exist
@@ -1183,10 +1187,12 @@ export function registerGaiaTools(server) {
1183
1187
  }],
1184
1188
  };
1185
1189
  }
1190
+ const validFromMs = valid_from ? new Date(valid_from).getTime() : undefined;
1186
1191
  const link = storage.createLink({
1187
1192
  from_memory_id,
1188
1193
  to_memory_id,
1189
1194
  link_type,
1195
+ validFrom: validFromMs,
1190
1196
  });
1191
1197
  return {
1192
1198
  content: [{
@@ -1194,10 +1200,13 @@ export function registerGaiaTools(server) {
1194
1200
  text: JSON.stringify({
1195
1201
  success: true,
1196
1202
  link: {
1203
+ link_id: link.link_id,
1197
1204
  from_memory_id: link.from_memory_id,
1198
1205
  to_memory_id: link.to_memory_id,
1199
1206
  link_type: link.link_type,
1200
1207
  created_at: link.created_at,
1208
+ valid_from: link.valid_from,
1209
+ invalidated_at: link.invalidated_at,
1201
1210
  },
1202
1211
  from_memory_content: fromMemory.content.substring(0, 100),
1203
1212
  to_memory_content: toMemory.content.substring(0, 100),
@@ -1215,10 +1224,65 @@ export function registerGaiaTools(server) {
1215
1224
  };
1216
1225
  }
1217
1226
  });
1227
+ // gaia_invalidate
1228
+ server.tool('gaia_invalidate', 'Invalidate a memory link by setting its invalidated_at timestamp. After invalidation, the link is excluded from gaia_graph queries unless a historical as_of timestamp is used. Idempotent: if the link is already invalidated, the existing state is returned without modification.', {
1229
+ link_id: z.string().describe('The link_id of the link to invalidate (returned by gaia_link)'),
1230
+ at: z.string().optional()
1231
+ .describe('ISO 8601 timestamp for when the link was invalidated. Defaults to now.'),
1232
+ }, async ({ link_id, at }) => {
1233
+ try {
1234
+ const storage = getMemoryStorage();
1235
+ const atMs = at ? new Date(at).getTime() : undefined;
1236
+ const result = storage.invalidateLink(link_id, atMs);
1237
+ if (!result.success && result.link.from_memory_id === '') {
1238
+ return {
1239
+ content: [{
1240
+ type: 'text',
1241
+ text: JSON.stringify({
1242
+ success: false,
1243
+ error: `Link not found: ${link_id}`,
1244
+ }, null, 2),
1245
+ }],
1246
+ };
1247
+ }
1248
+ return {
1249
+ content: [{
1250
+ type: 'text',
1251
+ text: JSON.stringify({
1252
+ success: result.success,
1253
+ ...(result.warning ? { warning: result.warning } : {}),
1254
+ link: {
1255
+ link_id: result.link.link_id,
1256
+ from_memory_id: result.link.from_memory_id,
1257
+ to_memory_id: result.link.to_memory_id,
1258
+ link_type: result.link.link_type,
1259
+ created_at: result.link.created_at,
1260
+ valid_from: result.link.valid_from,
1261
+ invalidated_at: result.link.invalidated_at,
1262
+ invalidated_at_iso: result.link.invalidated_at
1263
+ ? new Date(result.link.invalidated_at).toISOString()
1264
+ : null,
1265
+ },
1266
+ }, null, 2),
1267
+ }],
1268
+ };
1269
+ }
1270
+ catch (error) {
1271
+ return {
1272
+ content: [{
1273
+ type: 'text',
1274
+ text: `Error invalidating link: ${error instanceof Error ? error.message : String(error)}`,
1275
+ }],
1276
+ isError: true,
1277
+ };
1278
+ }
1279
+ });
1218
1280
  // gaia_graph
1219
- server.tool('gaia_graph', 'Get the link graph for a memory. Returns all linked memories grouped by link type.', {
1281
+ server.tool('gaia_graph', 'Get the link graph for a memory. Returns all linked memories grouped by link type. Supports temporal filtering via as_of to answer "what was true at time X?"', {
1220
1282
  memory_id: z.string().describe('Memory ID to get links for'),
1221
- }, async ({ memory_id }) => {
1283
+ as_of: z.string().optional()
1284
+ .describe('ISO 8601 timestamp — only return links that were valid at this point in time (valid_from <= as_of AND (invalidated_at IS NULL OR invalidated_at > as_of)). Defaults to now, which returns all currently-valid links.'),
1285
+ }, async ({ memory_id, as_of }) => {
1222
1286
  try {
1223
1287
  const storage = getMemoryStorage();
1224
1288
  // Verify memory exists
@@ -1234,7 +1298,8 @@ export function registerGaiaTools(server) {
1234
1298
  }],
1235
1299
  };
1236
1300
  }
1237
- const links = storage.getLinks(memory_id);
1301
+ const asOfMs = as_of ? new Date(as_of).getTime() : undefined;
1302
+ const links = storage.getLinks(memory_id, asOfMs);
1238
1303
  // Count total links
1239
1304
  const totalLinks = Object.values(links).reduce((sum, arr) => sum + arr.length, 0);
1240
1305
  return {
@@ -1245,6 +1310,7 @@ export function registerGaiaTools(server) {
1245
1310
  memory_id,
1246
1311
  memory_content: memory.content.substring(0, 100),
1247
1312
  total_links: totalLinks,
1313
+ as_of: as_of ?? new Date().toISOString(),
1248
1314
  links: {
1249
1315
  depends_on: links.depends_on.map(m => ({
1250
1316
  id: m.id,
@@ -1286,6 +1352,87 @@ export function registerGaiaTools(server) {
1286
1352
  };
1287
1353
  }
1288
1354
  });
1355
+ // ===========================================================================
1356
+ // Transcript Ingestion Tool
1357
+ // ===========================================================================
1358
+ // gaia_ingest_transcripts
1359
+ server.tool('gaia_ingest_transcripts', 'Walk ~/.claude/projects/**/*.jsonl, parse Claude Code conversation transcripts, and index human + assistant prose into Gaia\'s FTS5 memory store. Supports incremental re-runs (byte-offset tracking), deduplication, project filtering, and a dryRun preview mode.', {
1360
+ rootDir: z.string().optional()
1361
+ .describe('Root directory to walk for JSONL files. Defaults to ~/.claude/projects'),
1362
+ projectFilter: z.string().optional()
1363
+ .describe('Substring to match against project slugs (e.g. "foundation" to only ingest Foundation-related transcripts)'),
1364
+ since: z.string().optional()
1365
+ .describe('ISO 8601 timestamp — only ingest messages newer than this (e.g. "2026-01-01T00:00:00Z")'),
1366
+ dryRun: z.boolean().optional()
1367
+ .describe('Walk and report what WOULD be ingested without writing to Gaia. Default: false'),
1368
+ }, async ({ rootDir, projectFilter, since, dryRun = false }) => {
1369
+ try {
1370
+ const memStorage = getMemoryStorage();
1371
+ const db = memStorage.getInternalDb();
1372
+ const ingester = createIngester(db, memStorage);
1373
+ const stats = await ingester.ingest({
1374
+ rootDir,
1375
+ projectFilter,
1376
+ since,
1377
+ dryRun,
1378
+ });
1379
+ const lines = [];
1380
+ lines.push(`## gaia_ingest_transcripts${dryRun ? ' (DRY RUN)' : ''}`);
1381
+ lines.push('');
1382
+ lines.push(`Files found: ${stats.filesFound}`);
1383
+ lines.push(`Files skipped (no new content): ${stats.filesSkipped}`);
1384
+ lines.push(`Messages ingested: ${stats.messagesIngested}`);
1385
+ lines.push(`Messages skipped (dedupe): ${stats.messagesSkipped}`);
1386
+ lines.push(`Bytes processed: ${(stats.bytesProcessed / 1024).toFixed(1)} KB`);
1387
+ lines.push(`Parse errors: ${stats.parseErrors}`);
1388
+ lines.push('');
1389
+ if (stats.projectSlugs.length > 0) {
1390
+ lines.push(`Projects (${stats.projectSlugs.length}):`);
1391
+ for (const slug of stats.projectSlugs.slice(0, 20)) {
1392
+ lines.push(` - ${slug}`);
1393
+ }
1394
+ if (stats.projectSlugs.length > 20) {
1395
+ lines.push(` ... and ${stats.projectSlugs.length - 20} more`);
1396
+ }
1397
+ lines.push('');
1398
+ }
1399
+ if (stats.dateRange.earliest || stats.dateRange.latest) {
1400
+ lines.push(`Date range:`);
1401
+ lines.push(` Earliest: ${stats.dateRange.earliest ?? 'unknown'}`);
1402
+ lines.push(` Latest: ${stats.dateRange.latest ?? 'unknown'}`);
1403
+ lines.push('');
1404
+ }
1405
+ if (stats.parseErrorSamples.length > 0) {
1406
+ lines.push(`Sample parse errors:`);
1407
+ for (const sample of stats.parseErrorSamples) {
1408
+ lines.push(` - ${sample}`);
1409
+ }
1410
+ lines.push('');
1411
+ }
1412
+ if (dryRun) {
1413
+ lines.push('DRY RUN: No data was written to Gaia.');
1414
+ lines.push('Set dryRun: false to perform actual ingestion.');
1415
+ }
1416
+ else if (stats.messagesIngested > 0) {
1417
+ lines.push(`Memories are now searchable via gaia_search with tags: ["transcript"]`);
1418
+ }
1419
+ return {
1420
+ content: [{
1421
+ type: 'text',
1422
+ text: lines.join('\n'),
1423
+ }],
1424
+ };
1425
+ }
1426
+ catch (error) {
1427
+ return {
1428
+ content: [{
1429
+ type: 'text',
1430
+ text: `Error ingesting transcripts: ${error instanceof Error ? error.message : String(error)}`,
1431
+ }],
1432
+ isError: true,
1433
+ };
1434
+ }
1435
+ });
1289
1436
  }
1290
1437
  /**
1291
1438
  * Cleanup function to close database connection