@gettymade/roux 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.
@@ -0,0 +1,339 @@
1
+ import { Database } from 'better-sqlite3';
2
+
3
+ interface SourceRef {
4
+ type: 'file' | 'api' | 'manual';
5
+ path?: string;
6
+ lastModified?: Date;
7
+ }
8
+ /** The canonical data model. All modules speak Node. */
9
+ interface Node {
10
+ /** Store-specific format */
11
+ id: string;
12
+ title: string;
13
+ content: string;
14
+ tags: string[];
15
+ /** By id */
16
+ outgoingLinks: string[];
17
+ properties: Record<string, unknown>;
18
+ sourceRef?: SourceRef;
19
+ }
20
+ interface NodeWithContext extends Node {
21
+ /** Populated when depth > 0 */
22
+ neighbors?: Node[];
23
+ incomingCount?: number;
24
+ outgoingCount?: number;
25
+ }
26
+ declare function isNode(value: unknown): value is Node;
27
+ declare function isSourceRef(value: unknown): value is SourceRef;
28
+
29
+ type Direction = 'in' | 'out' | 'both';
30
+ interface NeighborOptions {
31
+ direction: Direction;
32
+ limit?: number;
33
+ }
34
+ /** Future first-class model. Currently implicit via Node.outgoingLinks. */
35
+ interface Edge {
36
+ source: string;
37
+ target: string;
38
+ /** e.g. parent, related */
39
+ type?: string;
40
+ weight?: number;
41
+ properties?: Record<string, unknown>;
42
+ }
43
+
44
+ type Metric = 'pagerank' | 'in_degree' | 'out_degree';
45
+ interface ListFilter {
46
+ /** Filter by tag (case-insensitive) */
47
+ tag?: string;
48
+ /** Filter by path prefix (startsWith) */
49
+ path?: string;
50
+ }
51
+ interface ListOptions {
52
+ /** Default 100, max 1000 */
53
+ limit?: number;
54
+ /** Default 0 */
55
+ offset?: number;
56
+ }
57
+ interface NodeSummary {
58
+ id: string;
59
+ title: string;
60
+ }
61
+ interface ListNodesResult {
62
+ nodes: NodeSummary[];
63
+ /** Total matching nodes (before limit/offset applied) */
64
+ total: number;
65
+ }
66
+ type ResolveStrategy = 'exact' | 'fuzzy' | 'semantic';
67
+ interface ResolveOptions {
68
+ /** Filter candidates by tag */
69
+ tag?: string;
70
+ /** Filter candidates by path prefix */
71
+ path?: string;
72
+ /** 0-1, default 0.7, ignored for 'exact' */
73
+ threshold?: number;
74
+ /** Default 'fuzzy' */
75
+ strategy?: ResolveStrategy;
76
+ }
77
+ interface ResolveResult {
78
+ /** Original input */
79
+ query: string;
80
+ /** Matched node ID or null */
81
+ match: string | null;
82
+ /** 0-1, 0 if no match */
83
+ score: number;
84
+ }
85
+ interface CentralityMetrics {
86
+ inDegree: number;
87
+ outDegree: number;
88
+ }
89
+ type TagMode = 'any' | 'all';
90
+ interface VectorSearchResult {
91
+ id: string;
92
+ distance: number;
93
+ }
94
+ /** Link with resolved title for MCP responses. */
95
+ interface LinkInfo {
96
+ id: string;
97
+ title: string;
98
+ }
99
+ /** Data persistence and graph operations. Required provider. */
100
+ interface StoreProvider {
101
+ createNode(node: Node): Promise<void>;
102
+ updateNode(id: string, updates: Partial<Node>): Promise<void>;
103
+ deleteNode(id: string): Promise<void>;
104
+ getNode(id: string): Promise<Node | null>;
105
+ getNodes(ids: string[]): Promise<Node[]>;
106
+ getNeighbors(id: string, options: NeighborOptions): Promise<Node[]>;
107
+ findPath(source: string, target: string): Promise<string[] | null>;
108
+ getHubs(metric: Metric, limit: number): Promise<Array<[string, number]>>;
109
+ storeEmbedding(id: string, vector: number[], model: string): Promise<void>;
110
+ searchByVector(vector: number[], limit: number): Promise<VectorSearchResult[]>;
111
+ searchByTags(tags: string[], mode: TagMode): Promise<Node[]>;
112
+ getRandomNode(tags?: string[]): Promise<Node | null>;
113
+ resolveTitles(ids: string[]): Promise<Map<string, string>>;
114
+ listNodes(filter: ListFilter, options?: ListOptions): Promise<ListNodesResult>;
115
+ resolveNodes(names: string[], options?: ResolveOptions): Promise<ResolveResult[]>;
116
+ nodesExist(ids: string[]): Promise<Map<string, boolean>>;
117
+ }
118
+ /** Stateless vector generation. Storage handled by StoreProvider. */
119
+ interface EmbeddingProvider {
120
+ embed(text: string): Promise<number[]>;
121
+ embedBatch(texts: string[]): Promise<number[][]>;
122
+ /** For storage allocation */
123
+ dimensions(): number;
124
+ modelId(): string;
125
+ }
126
+ /** Pluggable vector storage and similarity search. */
127
+ interface VectorProvider {
128
+ store(id: string, vector: number[], model: string): Promise<void>;
129
+ search(vector: number[], limit: number): Promise<VectorSearchResult[]>;
130
+ delete(id: string): Promise<void>;
131
+ getModel(id: string): Promise<string | null>;
132
+ hasEmbedding(id: string): boolean;
133
+ }
134
+ declare function isVectorProvider(value: unknown): value is VectorProvider;
135
+
136
+ interface SearchOptions {
137
+ /** Default: 10 */
138
+ limit?: number;
139
+ /** 0-1 */
140
+ threshold?: number;
141
+ tags?: string[];
142
+ }
143
+ /** Orchestration hub. Zero functionality without providers. */
144
+ interface GraphCore {
145
+ registerStore(provider: StoreProvider): void;
146
+ registerEmbedding(provider: EmbeddingProvider): void;
147
+ search(query: string, options?: SearchOptions): Promise<Node[]>;
148
+ getNode(id: string, depth?: number): Promise<NodeWithContext | null>;
149
+ createNode(node: Partial<Node>): Promise<Node>;
150
+ updateNode(id: string, updates: Partial<Node>): Promise<Node>;
151
+ deleteNode(id: string): Promise<boolean>;
152
+ getNeighbors(id: string, options: NeighborOptions): Promise<Node[]>;
153
+ findPath(source: string, target: string): Promise<string[] | null>;
154
+ getHubs(metric: Metric, limit: number): Promise<Array<[string, number]>>;
155
+ searchByTags(tags: string[], mode: TagMode, limit?: number): Promise<Node[]>;
156
+ getRandomNode(tags?: string[]): Promise<Node | null>;
157
+ listNodes(filter: ListFilter, options?: ListOptions): Promise<ListNodesResult>;
158
+ resolveNodes(names: string[], options?: ResolveOptions): Promise<ResolveResult[]>;
159
+ }
160
+
161
+ interface SourceConfig {
162
+ /** Relative to config file */
163
+ path: string;
164
+ include: string[];
165
+ /** .roux/ always excluded (hardcoded) */
166
+ exclude: string[];
167
+ }
168
+ interface CacheConfig {
169
+ /** SQLite directory */
170
+ path: string;
171
+ }
172
+ type ModelChangeBehavior = 'lazy' | 'eager';
173
+ interface SystemConfig {
174
+ /** Embedding regeneration strategy */
175
+ onModelChange: ModelChangeBehavior;
176
+ }
177
+ interface DocStoreConfig {
178
+ type: 'docstore';
179
+ }
180
+ interface LocalEmbeddingConfig {
181
+ type: 'local';
182
+ /** Default: Xenova/all-MiniLM-L6-v2 */
183
+ model?: string;
184
+ }
185
+ interface OllamaEmbeddingConfig {
186
+ type: 'ollama';
187
+ model: string;
188
+ endpoint?: string;
189
+ timeout?: number;
190
+ }
191
+ interface OpenAIEmbeddingConfig {
192
+ type: 'openai';
193
+ model: string;
194
+ timeout?: number;
195
+ }
196
+ type EmbeddingConfig = LocalEmbeddingConfig | OllamaEmbeddingConfig | OpenAIEmbeddingConfig;
197
+ interface OllamaLLMConfig {
198
+ type: 'ollama';
199
+ model: string;
200
+ endpoint?: string;
201
+ timeout?: number;
202
+ }
203
+ interface OpenAILLMConfig {
204
+ type: 'openai';
205
+ model: string;
206
+ timeout?: number;
207
+ }
208
+ type LLMConfig = OllamaLLMConfig | OpenAILLMConfig;
209
+ type StoreConfig = DocStoreConfig;
210
+ interface ProvidersConfig {
211
+ store: StoreConfig;
212
+ /** Defaults to local */
213
+ embedding?: EmbeddingConfig;
214
+ llm?: LLMConfig;
215
+ }
216
+ interface RouxConfig {
217
+ source?: SourceConfig;
218
+ cache?: CacheConfig;
219
+ system?: SystemConfig;
220
+ providers: ProvidersConfig;
221
+ }
222
+ declare const DEFAULT_CONFIG: Required<Pick<RouxConfig, 'source' | 'cache' | 'system'>> & {
223
+ providers: {
224
+ store: DocStoreConfig;
225
+ };
226
+ };
227
+
228
+ declare class GraphCoreImpl implements GraphCore {
229
+ private store;
230
+ private embedding;
231
+ registerStore(provider: StoreProvider): void;
232
+ registerEmbedding(provider: EmbeddingProvider): void;
233
+ private requireStore;
234
+ private requireEmbedding;
235
+ search(query: string, options?: SearchOptions): Promise<Node[]>;
236
+ getNode(id: string, depth?: number): Promise<NodeWithContext | null>;
237
+ createNode(partial: Partial<Node>): Promise<Node>;
238
+ updateNode(id: string, updates: Partial<Node>): Promise<Node>;
239
+ deleteNode(id: string): Promise<boolean>;
240
+ getNeighbors(id: string, options: NeighborOptions): Promise<Node[]>;
241
+ findPath(source: string, target: string): Promise<string[] | null>;
242
+ getHubs(metric: Metric, limit: number): Promise<Array<[string, number]>>;
243
+ searchByTags(tags: string[], mode: TagMode, limit?: number): Promise<Node[]>;
244
+ getRandomNode(tags?: string[]): Promise<Node | null>;
245
+ listNodes(filter: ListFilter, options?: ListOptions): Promise<ListNodesResult>;
246
+ resolveNodes(names: string[], options?: ResolveOptions): Promise<ResolveResult[]>;
247
+ private cosineSimilarity;
248
+ static fromConfig(config: RouxConfig): GraphCoreImpl;
249
+ }
250
+
251
+ declare class DocStore implements StoreProvider {
252
+ private cache;
253
+ private sourceRoot;
254
+ private graph;
255
+ private vectorProvider;
256
+ private ownsVectorProvider;
257
+ private watcher;
258
+ private debounceTimer;
259
+ private pendingChanges;
260
+ private onChangeCallback;
261
+ constructor(sourceRoot: string, cacheDir: string, vectorProvider?: VectorProvider);
262
+ sync(): Promise<void>;
263
+ createNode(node: Node): Promise<void>;
264
+ updateNode(id: string, updates: Partial<Node>): Promise<void>;
265
+ deleteNode(id: string): Promise<void>;
266
+ getNode(id: string): Promise<Node | null>;
267
+ getNodes(ids: string[]): Promise<Node[]>;
268
+ getAllNodeIds(): Promise<string[]>;
269
+ searchByTags(tags: string[], mode: TagMode): Promise<Node[]>;
270
+ getRandomNode(tags?: string[]): Promise<Node | null>;
271
+ resolveTitles(ids: string[]): Promise<Map<string, string>>;
272
+ listNodes(filter: ListFilter, options?: ListOptions): Promise<ListNodesResult>;
273
+ resolveNodes(names: string[], options?: ResolveOptions): Promise<ResolveResult[]>;
274
+ nodesExist(ids: string[]): Promise<Map<string, boolean>>;
275
+ getNeighbors(id: string, options: NeighborOptions): Promise<Node[]>;
276
+ findPath(source: string, target: string): Promise<string[] | null>;
277
+ getHubs(metric: Metric, limit: number): Promise<Array<[string, number]>>;
278
+ storeEmbedding(id: string, vector: number[], model: string): Promise<void>;
279
+ searchByVector(vector: number[], limit: number): Promise<VectorSearchResult[]>;
280
+ hasEmbedding(id: string): boolean;
281
+ close(): void;
282
+ startWatching(onChange?: (changedIds: string[]) => void): Promise<void>;
283
+ stopWatching(): void;
284
+ isWatching(): boolean;
285
+ private queueChange;
286
+ private processQueue;
287
+ private buildFilenameIndex;
288
+ private resolveOutgoingLinks;
289
+ private ensureGraph;
290
+ private rebuildGraph;
291
+ private static readonly EXCLUDED_DIRS;
292
+ private collectMarkdownFiles;
293
+ private getFileMtime;
294
+ private fileToNode;
295
+ /**
296
+ * Normalize a wiki-link target to an ID.
297
+ * - If it has a file extension, normalize as-is
298
+ * - If no extension, add .md
299
+ * - Lowercase, forward slashes
300
+ */
301
+ private normalizeWikiLink;
302
+ private hasFileExtension;
303
+ private validatePathWithinSource;
304
+ }
305
+
306
+ declare class TransformersEmbeddingProvider implements EmbeddingProvider {
307
+ private model;
308
+ private dims;
309
+ private pipe;
310
+ constructor(model?: string, dimensions?: number);
311
+ private getPipeline;
312
+ embed(text: string): Promise<number[]>;
313
+ embedBatch(texts: string[]): Promise<number[][]>;
314
+ dimensions(): number;
315
+ modelId(): string;
316
+ }
317
+
318
+ declare class SqliteVectorProvider implements VectorProvider {
319
+ private db;
320
+ private ownsDb;
321
+ constructor(pathOrDb: string | Database);
322
+ private init;
323
+ store(id: string, vector: number[], model: string): Promise<void>;
324
+ search(vector: number[], limit: number): Promise<VectorSearchResult[]>;
325
+ delete(id: string): Promise<void>;
326
+ getModel(id: string): Promise<string | null>;
327
+ hasEmbedding(id: string): boolean;
328
+ /** For testing: get table names */
329
+ getTableNames(): string[];
330
+ /** For testing: get vector blob size */
331
+ getVectorBlobSize(id: string): number | null;
332
+ /** Get total number of stored embeddings */
333
+ getEmbeddingCount(): number;
334
+ close(): void;
335
+ }
336
+
337
+ declare const VERSION = "0.1.0";
338
+
339
+ export { type CacheConfig, type CentralityMetrics, DEFAULT_CONFIG, type Direction, DocStore, type DocStoreConfig, type Edge, type EmbeddingConfig, type EmbeddingProvider, type GraphCore, GraphCoreImpl, type LLMConfig, type LinkInfo, type ListFilter, type ListOptions, type LocalEmbeddingConfig, type Metric, type ModelChangeBehavior, type NeighborOptions, type Node, type NodeSummary, type NodeWithContext, type OllamaEmbeddingConfig, type OllamaLLMConfig, type OpenAIEmbeddingConfig, type OpenAILLMConfig, type ProvidersConfig, type ResolveOptions, type ResolveResult, type ResolveStrategy, type RouxConfig, type SearchOptions, type SourceConfig, type SourceRef, SqliteVectorProvider, type StoreConfig, type StoreProvider, type SystemConfig, type TagMode, TransformersEmbeddingProvider, VERSION, type VectorProvider, type VectorSearchResult, isNode, isSourceRef, isVectorProvider };