@mmnto/totem 0.1.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 (69) hide show
  1. package/dist/chunkers/chunker.d.ts +12 -0
  2. package/dist/chunkers/chunker.d.ts.map +1 -0
  3. package/dist/chunkers/chunker.js +17 -0
  4. package/dist/chunkers/chunker.js.map +1 -0
  5. package/dist/chunkers/markdown-chunker.d.ts +17 -0
  6. package/dist/chunkers/markdown-chunker.d.ts.map +1 -0
  7. package/dist/chunkers/markdown-chunker.js +120 -0
  8. package/dist/chunkers/markdown-chunker.js.map +1 -0
  9. package/dist/chunkers/schema-file-chunker.d.ts +15 -0
  10. package/dist/chunkers/schema-file-chunker.d.ts.map +1 -0
  11. package/dist/chunkers/schema-file-chunker.js +55 -0
  12. package/dist/chunkers/schema-file-chunker.js.map +1 -0
  13. package/dist/chunkers/session-log-chunker.d.ts +14 -0
  14. package/dist/chunkers/session-log-chunker.d.ts.map +1 -0
  15. package/dist/chunkers/session-log-chunker.js +78 -0
  16. package/dist/chunkers/session-log-chunker.js.map +1 -0
  17. package/dist/chunkers/test-file-chunker.d.ts +17 -0
  18. package/dist/chunkers/test-file-chunker.d.ts.map +1 -0
  19. package/dist/chunkers/test-file-chunker.js +66 -0
  20. package/dist/chunkers/test-file-chunker.js.map +1 -0
  21. package/dist/chunkers/typescript-chunker.d.ts +17 -0
  22. package/dist/chunkers/typescript-chunker.d.ts.map +1 -0
  23. package/dist/chunkers/typescript-chunker.js +94 -0
  24. package/dist/chunkers/typescript-chunker.js.map +1 -0
  25. package/dist/config-schema.d.ts +229 -0
  26. package/dist/config-schema.d.ts.map +1 -0
  27. package/dist/config-schema.js +56 -0
  28. package/dist/config-schema.js.map +1 -0
  29. package/dist/embedders/embedder.d.ts +15 -0
  30. package/dist/embedders/embedder.d.ts.map +1 -0
  31. package/dist/embedders/embedder.js +11 -0
  32. package/dist/embedders/embedder.js.map +1 -0
  33. package/dist/embedders/ollama-embedder.d.ts +14 -0
  34. package/dist/embedders/ollama-embedder.d.ts.map +1 -0
  35. package/dist/embedders/ollama-embedder.js +67 -0
  36. package/dist/embedders/ollama-embedder.js.map +1 -0
  37. package/dist/embedders/openai-embedder.d.ts +9 -0
  38. package/dist/embedders/openai-embedder.d.ts.map +1 -0
  39. package/dist/embedders/openai-embedder.js +36 -0
  40. package/dist/embedders/openai-embedder.js.map +1 -0
  41. package/dist/index.d.ts +12 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +8 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/ingest/file-resolver.d.ts +14 -0
  46. package/dist/ingest/file-resolver.d.ts.map +1 -0
  47. package/dist/ingest/file-resolver.js +54 -0
  48. package/dist/ingest/file-resolver.js.map +1 -0
  49. package/dist/ingest/pipeline.d.ts +7 -0
  50. package/dist/ingest/pipeline.d.ts.map +1 -0
  51. package/dist/ingest/pipeline.js +79 -0
  52. package/dist/ingest/pipeline.js.map +1 -0
  53. package/dist/ingest/sync.d.ts +4 -0
  54. package/dist/ingest/sync.d.ts.map +1 -0
  55. package/dist/ingest/sync.js +3 -0
  56. package/dist/ingest/sync.js.map +1 -0
  57. package/dist/store/lance-schema.d.ts +42 -0
  58. package/dist/store/lance-schema.d.ts.map +1 -0
  59. package/dist/store/lance-schema.js +21 -0
  60. package/dist/store/lance-schema.js.map +1 -0
  61. package/dist/store/lance-store.d.ts +27 -0
  62. package/dist/store/lance-store.d.ts.map +1 -0
  63. package/dist/store/lance-store.js +106 -0
  64. package/dist/store/lance-store.js.map +1 -0
  65. package/dist/types.d.ts +75 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +2 -0
  68. package/dist/types.js.map +1 -0
  69. package/package.json +52 -0
@@ -0,0 +1,79 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { createChunker } from '../chunkers/chunker.js';
4
+ import { createEmbedder } from '../embedders/embedder.js';
5
+ import { LanceStore } from '../store/lance-store.js';
6
+ import { getChangedFiles, resolveFiles } from './file-resolver.js';
7
+ const EMBED_BATCH_SIZE = 100;
8
+ export async function runSync(config, options) {
9
+ const { projectRoot, incremental, onProgress } = options;
10
+ const log = onProgress ?? (() => { });
11
+ // 1. Create embedder
12
+ log('Initializing embedding provider...');
13
+ const embedder = createEmbedder(config.embedding);
14
+ // 2. Connect to store
15
+ const storePath = path.join(projectRoot, config.lanceDir);
16
+ const store = new LanceStore(storePath, embedder);
17
+ await store.connect();
18
+ // 3. Resolve files to process
19
+ const allFiles = resolveFiles(config.targets, projectRoot, config.ignorePatterns);
20
+ let filesToProcess;
21
+ if (incremental) {
22
+ const changedPaths = options.changedFiles ?? getChangedFiles(projectRoot, 'HEAD~1', log);
23
+ if (changedPaths === null) {
24
+ log('Git diff failed, falling back to full sync...');
25
+ await store.reset();
26
+ filesToProcess = allFiles;
27
+ log(`Full sync (fallback): ${filesToProcess.length} files to process`);
28
+ }
29
+ else {
30
+ const changedSet = new Set(changedPaths);
31
+ filesToProcess = allFiles.filter((f) => changedSet.has(f.relativePath));
32
+ log(`Incremental sync: ${filesToProcess.length} changed files (of ${allFiles.length} total)`);
33
+ }
34
+ }
35
+ else {
36
+ log('Full sync: resetting index...');
37
+ await store.reset();
38
+ filesToProcess = allFiles;
39
+ log(`Full sync: ${filesToProcess.length} files to process`);
40
+ }
41
+ // 4. Chunk all files
42
+ const allChunks = [];
43
+ for (const file of filesToProcess) {
44
+ log(`Chunking ${file.relativePath}...`);
45
+ let content;
46
+ try {
47
+ content = fs.readFileSync(file.absolutePath, 'utf-8');
48
+ }
49
+ catch (err) {
50
+ log(` Skipping (read error: ${err instanceof Error ? err.message : String(err)}): ${file.relativePath}`);
51
+ continue;
52
+ }
53
+ const chunker = createChunker(file.target.strategy);
54
+ const chunks = chunker.chunk(content, file.relativePath, file.target.type);
55
+ if (chunks.length === 0) {
56
+ log(` No chunks extracted from ${file.relativePath}`);
57
+ continue;
58
+ }
59
+ // For incremental: delete old chunks for this file before inserting new ones
60
+ if (incremental) {
61
+ await store.deleteByFile(file.relativePath);
62
+ }
63
+ allChunks.push(...chunks);
64
+ log(` ${chunks.length} chunks from ${file.relativePath}`);
65
+ }
66
+ // 5. Embed and store in batches
67
+ log(`Embedding ${allChunks.length} chunks...`);
68
+ for (let i = 0; i < allChunks.length; i += EMBED_BATCH_SIZE) {
69
+ const batch = allChunks.slice(i, i + EMBED_BATCH_SIZE);
70
+ await store.insert(batch);
71
+ log(` Embedded ${Math.min(i + EMBED_BATCH_SIZE, allChunks.length)}/${allChunks.length}`);
72
+ }
73
+ log(`Sync complete: ${allChunks.length} chunks from ${filesToProcess.length} files`);
74
+ return {
75
+ chunksProcessed: allChunks.length,
76
+ filesProcessed: filesToProcess.length,
77
+ };
78
+ }
79
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/ingest/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { ResolvedFile } from './file-resolver.js';
2
+ export { getChangedFiles, resolveFiles } from './file-resolver.js';
3
+ export { runSync } from './pipeline.js';
4
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/ingest/sync.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { getChangedFiles, resolveFiles } from './file-resolver.js';
2
+ export { runSync } from './pipeline.js';
3
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/ingest/sync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod schema for validating a stored chunk before insertion.
4
+ * The vector field is not validated by Zod (handled by LanceDB).
5
+ */
6
+ export declare const StoredChunkSchema: z.ZodObject<{
7
+ id: z.ZodString;
8
+ content: z.ZodString;
9
+ contextPrefix: z.ZodString;
10
+ filePath: z.ZodString;
11
+ type: z.ZodEnum<["code", "session_log", "spec"]>;
12
+ strategy: z.ZodEnum<["typescript-ast", "markdown-heading", "session-log", "schema-file", "test-file"]>;
13
+ label: z.ZodString;
14
+ startLine: z.ZodNumber;
15
+ endLine: z.ZodNumber;
16
+ metadata: z.ZodString;
17
+ }, "strip", z.ZodTypeAny, {
18
+ type: "code" | "session_log" | "spec";
19
+ strategy: "typescript-ast" | "markdown-heading" | "session-log" | "schema-file" | "test-file";
20
+ content: string;
21
+ contextPrefix: string;
22
+ filePath: string;
23
+ label: string;
24
+ startLine: number;
25
+ endLine: number;
26
+ id: string;
27
+ metadata: string;
28
+ }, {
29
+ type: "code" | "session_log" | "spec";
30
+ strategy: "typescript-ast" | "markdown-heading" | "session-log" | "schema-file" | "test-file";
31
+ content: string;
32
+ contextPrefix: string;
33
+ filePath: string;
34
+ label: string;
35
+ startLine: number;
36
+ endLine: number;
37
+ id: string;
38
+ metadata: string;
39
+ }>;
40
+ /** The LanceDB table name used for all totem data. */
41
+ export declare const TOTEM_TABLE_NAME = "totem_chunks";
42
+ //# sourceMappingURL=lance-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lance-schema.d.ts","sourceRoot":"","sources":["../../src/store/lance-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW5B,CAAC;AAEH,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,iBAAiB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ import { ChunkStrategySchema, ContentTypeSchema } from '../config-schema.js';
3
+ /**
4
+ * Zod schema for validating a stored chunk before insertion.
5
+ * The vector field is not validated by Zod (handled by LanceDB).
6
+ */
7
+ export const StoredChunkSchema = z.object({
8
+ id: z.string(),
9
+ content: z.string(),
10
+ contextPrefix: z.string(),
11
+ filePath: z.string(),
12
+ type: ContentTypeSchema,
13
+ strategy: ChunkStrategySchema,
14
+ label: z.string(),
15
+ startLine: z.number().int(),
16
+ endLine: z.number().int(),
17
+ metadata: z.string(), // JSON-stringified
18
+ });
19
+ /** The LanceDB table name used for all totem data. */
20
+ export const TOTEM_TABLE_NAME = 'totem_chunks';
21
+ //# sourceMappingURL=lance-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lance-schema.js","sourceRoot":"","sources":["../../src/store/lance-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,mBAAmB;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,mBAAmB;CAC1C,CAAC,CAAC;AAEH,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { Embedder } from '../embedders/embedder.js';
2
+ import type { Chunk, SearchOptions, SearchResult } from '../types.js';
3
+ export declare class LanceStore {
4
+ private db;
5
+ private table;
6
+ private dbPath;
7
+ private embedder;
8
+ constructor(dbPath: string, embedder: Embedder);
9
+ /** Connect to LanceDB. Must be called before any other operations. */
10
+ connect(): Promise<void>;
11
+ /** Insert chunks into the store. Embeds them first. */
12
+ insert(chunks: Chunk[]): Promise<void>;
13
+ /** Semantic vector search with optional type filtering. */
14
+ search(options: SearchOptions): Promise<SearchResult[]>;
15
+ /** Delete all chunks from a specific file (for incremental re-index). */
16
+ deleteByFile(filePath: string): Promise<void>;
17
+ /** Drop the entire table. Used for full re-index. */
18
+ reset(): Promise<void>;
19
+ /** Re-open the LanceDB connection, picking up rebuilt files after a full sync. */
20
+ reconnect(): Promise<void>;
21
+ /** Return stats about the current index. */
22
+ stats(): Promise<{
23
+ totalChunks: number;
24
+ byType: Record<string, number>;
25
+ }>;
26
+ }
27
+ //# sourceMappingURL=lance-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lance-store.d.ts","sourceRoot":"","sources":["../../src/store/lance-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAGnF,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAmC;IAC7C,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAW;gBAEf,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAK9C,sEAAsE;IAChE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B,uDAAuD;IACjD,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B5C,2DAA2D;IACrD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA0B7D,yEAAyE;IACnE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,qDAAqD;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B,kFAAkF;IAC5E,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAMhC,4CAA4C;IACtC,KAAK,IAAI,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;CAchF"}
@@ -0,0 +1,106 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import * as lancedb from '@lancedb/lancedb';
3
+ import { TOTEM_TABLE_NAME } from './lance-schema.js';
4
+ export class LanceStore {
5
+ db = null;
6
+ table = null;
7
+ dbPath;
8
+ embedder;
9
+ constructor(dbPath, embedder) {
10
+ this.dbPath = dbPath;
11
+ this.embedder = embedder;
12
+ }
13
+ /** Connect to LanceDB. Must be called before any other operations. */
14
+ async connect() {
15
+ this.db = await lancedb.connect(this.dbPath);
16
+ const tableNames = await this.db.tableNames();
17
+ if (tableNames.includes(TOTEM_TABLE_NAME)) {
18
+ this.table = await this.db.openTable(TOTEM_TABLE_NAME);
19
+ }
20
+ }
21
+ /** Insert chunks into the store. Embeds them first. */
22
+ async insert(chunks) {
23
+ if (chunks.length === 0)
24
+ return;
25
+ // Build the text to embed: contextPrefix + content
26
+ const textsToEmbed = chunks.map((c) => `${c.contextPrefix} ${c.content}`);
27
+ const vectors = await this.embedder.embed(textsToEmbed);
28
+ const rows = chunks.map((chunk, i) => ({
29
+ id: randomUUID(),
30
+ content: chunk.content,
31
+ contextPrefix: chunk.contextPrefix,
32
+ filePath: chunk.filePath,
33
+ type: chunk.type,
34
+ strategy: chunk.strategy,
35
+ label: chunk.label,
36
+ startLine: chunk.startLine,
37
+ endLine: chunk.endLine,
38
+ metadata: JSON.stringify(chunk.metadata),
39
+ vector: vectors[i],
40
+ }));
41
+ const data = rows;
42
+ if (!this.table) {
43
+ this.table = await this.db.createTable(TOTEM_TABLE_NAME, data);
44
+ }
45
+ else {
46
+ await this.table.add(data);
47
+ }
48
+ }
49
+ /** Semantic vector search with optional type filtering. */
50
+ async search(options) {
51
+ if (!this.table)
52
+ return [];
53
+ const maxResults = options.maxResults ?? 5;
54
+ const [queryVector] = await this.embedder.embed([options.query]);
55
+ let query = this.table.vectorSearch(queryVector).limit(maxResults);
56
+ if (options.typeFilter) {
57
+ query = query.where(`type = '${options.typeFilter.replace(/'/g, "''")}'`);
58
+ }
59
+ const results = await query.toArray();
60
+ return results.map((row) => ({
61
+ content: row['content'],
62
+ contextPrefix: row['contextPrefix'],
63
+ filePath: row['filePath'],
64
+ type: row['type'],
65
+ label: row['label'],
66
+ score: row['_distance'] != null ? 1 / (1 + row['_distance']) : 0,
67
+ metadata: JSON.parse(row['metadata'] || '{}'),
68
+ }));
69
+ }
70
+ /** Delete all chunks from a specific file (for incremental re-index). */
71
+ async deleteByFile(filePath) {
72
+ if (!this.table)
73
+ return;
74
+ await this.table.delete(`filePath = '${filePath.replace(/'/g, "''")}'`);
75
+ }
76
+ /** Drop the entire table. Used for full re-index. */
77
+ async reset() {
78
+ if (!this.db)
79
+ return;
80
+ const tableNames = await this.db.tableNames();
81
+ if (tableNames.includes(TOTEM_TABLE_NAME)) {
82
+ await this.db.dropTable(TOTEM_TABLE_NAME);
83
+ }
84
+ this.table = null;
85
+ }
86
+ /** Re-open the LanceDB connection, picking up rebuilt files after a full sync. */
87
+ async reconnect() {
88
+ this.db = null;
89
+ this.table = null;
90
+ await this.connect();
91
+ }
92
+ /** Return stats about the current index. */
93
+ async stats() {
94
+ if (!this.table)
95
+ return { totalChunks: 0, byType: {} };
96
+ const totalChunks = await this.table.countRows();
97
+ const typeRows = await this.table.query().select(['type']).toArray();
98
+ const byType = {};
99
+ for (const row of typeRows) {
100
+ const t = row['type'];
101
+ byType[t] = (byType[t] ?? 0) + 1;
102
+ }
103
+ return { totalChunks, byType };
104
+ }
105
+ }
106
+ //# sourceMappingURL=lance-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lance-store.js","sourceRoot":"","sources":["../../src/store/lance-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import type { ChunkStrategy, ContentType } from './config-schema.js';
2
+ /**
3
+ * A single chunk produced by any chunker.
4
+ * This is the unit that gets embedded and stored.
5
+ */
6
+ export interface Chunk {
7
+ /** The text content to embed */
8
+ content: string;
9
+ /** Contextual prefix prepended before embedding */
10
+ contextPrefix: string;
11
+ /** Source file path (relative to project root) */
12
+ filePath: string;
13
+ /** Content type for metadata filtering */
14
+ type: ContentType;
15
+ /** Chunking strategy that produced this chunk */
16
+ strategy: ChunkStrategy;
17
+ /** Human-readable identifier (function name, heading path, etc.) */
18
+ label: string;
19
+ /** Start line in original file (1-indexed) */
20
+ startLine: number;
21
+ /** End line in original file (1-indexed) */
22
+ endLine: number;
23
+ /** Optional structured metadata (frontmatter fields, etc.) */
24
+ metadata: Record<string, string>;
25
+ }
26
+ /**
27
+ * A stored record in LanceDB — chunk + its embedding vector.
28
+ */
29
+ export interface StoredChunk {
30
+ id: string;
31
+ content: string;
32
+ contextPrefix: string;
33
+ filePath: string;
34
+ type: string;
35
+ strategy: string;
36
+ label: string;
37
+ startLine: number;
38
+ endLine: number;
39
+ metadata: string;
40
+ vector: number[];
41
+ }
42
+ /**
43
+ * Result returned from a search query.
44
+ */
45
+ export interface SearchResult {
46
+ content: string;
47
+ contextPrefix: string;
48
+ filePath: string;
49
+ type: ContentType;
50
+ label: string;
51
+ score: number;
52
+ metadata: Record<string, string>;
53
+ }
54
+ /**
55
+ * Options for the sync operation.
56
+ */
57
+ export interface SyncOptions {
58
+ /** Project root directory (where totem.config.ts lives) */
59
+ projectRoot: string;
60
+ /** If true, only process files changed since last sync */
61
+ incremental: boolean;
62
+ /** If provided, only sync files matching these changed paths */
63
+ changedFiles?: string[];
64
+ /** Callback for progress reporting */
65
+ onProgress?: (message: string) => void;
66
+ }
67
+ /**
68
+ * Options for search queries.
69
+ */
70
+ export interface SearchOptions {
71
+ query: string;
72
+ typeFilter?: ContentType;
73
+ maxResults?: number;
74
+ }
75
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAErE;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAEhB,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IAEtB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IAEjB,0CAA0C;IAC1C,IAAI,EAAE,WAAW,CAAC;IAElB,iDAAiD;IACjD,QAAQ,EAAE,aAAa,CAAC;IAExB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAElB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAEhB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IAEpB,0DAA0D;IAC1D,WAAW,EAAE,OAAO,CAAC;IAErB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,sCAAsC;IACtC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@mmnto/totem",
3
+ "version": "0.1.0",
4
+ "description": "Persistent memory and context layer for AI agents",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "clean": "rm -rf dist",
18
+ "lint": "eslint src/",
19
+ "test": "echo \"No tests yet\" && exit 0"
20
+ },
21
+ "dependencies": {
22
+ "@lancedb/lancedb": "^0.13.0",
23
+ "glob": "^11.0.0",
24
+ "openai": "^4.77.0",
25
+ "remark-frontmatter": "^5.0.0",
26
+ "remark-parse": "^11.0.0",
27
+ "typescript": "^5.7.0",
28
+ "unified": "^11.0.0",
29
+ "yaml": "^2.4.0",
30
+ "zod": "^3.24.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/mdast": "^4.0.0"
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "license": "MIT",
39
+ "author": "mmnto-ai",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/mmnto-ai/totem.git",
43
+ "directory": "packages/core"
44
+ },
45
+ "homepage": "https://github.com/mmnto-ai/totem",
46
+ "bugs": {
47
+ "url": "https://github.com/mmnto-ai/totem/issues"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ }
52
+ }