memorix 1.0.7 → 1.0.8

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.
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,677 @@
1
+ import { Entity, Relation, KnowledgeGraph, ProjectInfo, DetectionResult, ObservationType, ObservationStatus, ProgressInfo, Observation, IndexEntry } from './types.js';
2
+ export { AgentTarget, DEFAULT_CONFIG, DetectionFailure, DetectionFailureReason, DocumentType, KnowledgeLayer, MCPConfigAdapter, MCPServerEntry, MemorixConfig, MemorixDocument, MemoryRef, MiniSkill, OBSERVATION_ICONS, ObservationRef, RuleFormatAdapter, RuleSource, SearchOptions, Session, SkillConflict, SkillEntry, SnapshotObservation, SourceSnapshot, TOPIC_KEY_FAMILIES, TimelineContext, UnifiedRule, WorkflowEntry, WorkspaceSyncResult } from './types.js';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+
5
+ /**
6
+ * TeamEventBus — Process-local typed event emitter for team coordination.
7
+ *
8
+ * Phase 4b: Provides push-based acceleration within a single process.
9
+ * NOT a cross-process mechanism — the orchestrator uses SQLite polling.
10
+ *
11
+ * Architectural boundary (B1): This is process-local fanout only.
12
+ * No persistence, no cross-process delivery, no durability guarantees.
13
+ * If no listeners are registered, events are silently dropped.
14
+ */
15
+ interface TeamEventMap {
16
+ 'task:created': {
17
+ taskId: string;
18
+ projectId: string;
19
+ description: string;
20
+ };
21
+ 'task:claimed': {
22
+ taskId: string;
23
+ projectId: string;
24
+ agentId: string;
25
+ };
26
+ 'task:completed': {
27
+ taskId: string;
28
+ projectId: string;
29
+ agentId: string;
30
+ result?: string;
31
+ };
32
+ 'task:failed': {
33
+ taskId: string;
34
+ projectId: string;
35
+ agentId: string;
36
+ result?: string;
37
+ };
38
+ 'task:released': {
39
+ taskId: string;
40
+ projectId: string;
41
+ agentId: string;
42
+ };
43
+ 'agent:joined': {
44
+ agentId: string;
45
+ projectId: string;
46
+ agentType: string;
47
+ };
48
+ 'agent:left': {
49
+ agentId: string;
50
+ projectId: string;
51
+ };
52
+ 'agent:stale': {
53
+ agentId: string;
54
+ projectId: string;
55
+ releasedTasks: number;
56
+ };
57
+ 'handoff:created': {
58
+ observationId: number;
59
+ projectId: string;
60
+ fromAgent: string;
61
+ toAgent?: string;
62
+ taskId?: string;
63
+ };
64
+ }
65
+ type TeamEventName = keyof TeamEventMap;
66
+ declare class TeamEventBus {
67
+ private emitter;
68
+ constructor();
69
+ /**
70
+ * Emit a typed event. Non-blocking, best-effort.
71
+ * If no listeners are registered, the event is silently dropped.
72
+ */
73
+ emit<K extends TeamEventName>(event: K, data: TeamEventMap[K]): void;
74
+ /** Subscribe to a typed event. Returns unsubscribe function. */
75
+ on<K extends TeamEventName>(event: K, listener: (data: TeamEventMap[K]) => void): () => void;
76
+ /** Subscribe to a typed event, fire only once. */
77
+ once<K extends TeamEventName>(event: K, listener: (data: TeamEventMap[K]) => void): void;
78
+ /** Remove all listeners for a specific event, or all events if none specified. */
79
+ removeAllListeners(event?: TeamEventName): void;
80
+ /** Current listener count for a specific event. */
81
+ listenerCount(event: TeamEventName): number;
82
+ }
83
+
84
+ /**
85
+ * TeamStore - SQLite-backed persistence for autonomous Agent Team state.
86
+ *
87
+ * Phase 4a: Replaces the file-based team-state.json persistence with
88
+ * SQLite prepared statements on the shared DB handle (memorix.db).
89
+ *
90
+ * Provides:
91
+ * - Singleton init/get/reset pattern (same as SessionStore)
92
+ * - Shared DB handle via getDatabase()
93
+ * - One-time migration from team-state.json
94
+ * - Prepared statements for all team CRUD operations
95
+ *
96
+ * All team modules (registry, messages, tasks, locks) delegate to this store.
97
+ */
98
+
99
+ interface TeamAgentRow {
100
+ agent_id: string;
101
+ project_id: string;
102
+ agent_type: string;
103
+ instance_id: string;
104
+ name: string;
105
+ role: string | null;
106
+ capabilities: string | null;
107
+ status: 'active' | 'inactive';
108
+ joined_at: number;
109
+ last_heartbeat: number;
110
+ left_at: number | null;
111
+ last_seen_obs_generation: number;
112
+ }
113
+ interface TeamMessageRow {
114
+ id: string;
115
+ project_id: string;
116
+ sender_agent_id: string;
117
+ recipient_agent_id: string | null;
118
+ type: string;
119
+ content: string;
120
+ payload: string | null;
121
+ task_id: string | null;
122
+ read_at: number | null;
123
+ created_at: number;
124
+ to_role: string | null;
125
+ handoff_status: string | null;
126
+ }
127
+ interface TeamTaskRow {
128
+ task_id: string;
129
+ project_id: string;
130
+ description: string;
131
+ status: 'pending' | 'in_progress' | 'completed' | 'failed';
132
+ assignee_agent_id: string | null;
133
+ result: string | null;
134
+ metadata: string | null;
135
+ created_by: string | null;
136
+ created_at: number;
137
+ updated_at: number;
138
+ required_role: string | null;
139
+ preferred_role: string | null;
140
+ }
141
+ interface TeamLockRow {
142
+ file: string;
143
+ project_id: string;
144
+ locked_by: string;
145
+ locked_at: number;
146
+ expires_at: number;
147
+ }
148
+ interface TeamRoleRow {
149
+ role_id: string;
150
+ project_id: string;
151
+ label: string;
152
+ description: string | null;
153
+ preferred_agent_types: string;
154
+ max_concurrent: number;
155
+ created_at: number;
156
+ }
157
+ declare class TeamStore {
158
+ private db;
159
+ private dataDir;
160
+ /** Optional event bus for same-process lifecycle notifications.
161
+ * Set via setEventBus(). Emit failures never block TeamStore writes. */
162
+ private eventBus;
163
+ setEventBus(bus: TeamEventBus): void;
164
+ getEventBus(): TeamEventBus | null;
165
+ private stmtAgentUpsert;
166
+ private stmtAgentFindByInstance;
167
+ private stmtAgentFindById;
168
+ private stmtAgentListByProject;
169
+ private stmtAgentUpdateHeartbeat;
170
+ private stmtAgentLeave;
171
+ private stmtAgentUpdateWatermark;
172
+ private stmtMsgInsert;
173
+ private stmtMsgInbox;
174
+ private stmtMsgMarkRead;
175
+ private stmtMsgMarkAllRead;
176
+ private stmtMsgUnreadCount;
177
+ private stmtMsgPruneRead;
178
+ private stmtMsgClearInbox;
179
+ private stmtMsgById;
180
+ private stmtTaskInsert;
181
+ private stmtTaskClaim;
182
+ private stmtTaskReClaim;
183
+ private stmtTaskComplete;
184
+ private stmtTaskFail;
185
+ private stmtTaskRelease;
186
+ private stmtTaskReleaseByAgent;
187
+ private stmtTaskById;
188
+ private stmtTaskListByProject;
189
+ private stmtTaskAvailable;
190
+ private stmtTaskDepInsert;
191
+ private stmtTaskDepsByTask;
192
+ private stmtTaskUnmetDeps;
193
+ private stmtLockUpsert;
194
+ private stmtLockGet;
195
+ private stmtLockDelete;
196
+ private stmtLockListByProject;
197
+ private stmtLockListByAgent;
198
+ private stmtLockDeleteByAgent;
199
+ private stmtLockDeleteExpired;
200
+ private stmtRoleInsert;
201
+ private stmtRoleDelete;
202
+ private stmtRoleListByProject;
203
+ private stmtRoleGetById;
204
+ private stmtRoleCountByProject;
205
+ init(dataDir: string): Promise<void>;
206
+ private prepareAgentStatements;
207
+ private prepareMessageStatements;
208
+ private prepareTaskStatements;
209
+ private prepareLockStatements;
210
+ /**
211
+ * Register or reactivate an agent.
212
+ * If an agent with the same (project_id, agent_type, instance_id) exists,
213
+ * reactivate it (preserving agent_id). Otherwise create a new one.
214
+ */
215
+ registerAgent(input: {
216
+ projectId: string;
217
+ agentType: string;
218
+ instanceId?: string;
219
+ name?: string;
220
+ role?: string;
221
+ capabilities?: string[];
222
+ }): TeamAgentRow;
223
+ getAgent(agentId: string): TeamAgentRow | undefined;
224
+ getAgentByInstance(projectId: string, agentType: string, instanceId: string): TeamAgentRow | undefined;
225
+ listAgents(projectId: string, filter?: {
226
+ status?: 'active' | 'inactive';
227
+ }): TeamAgentRow[];
228
+ /** List agents across all projects (for global scope) */
229
+ listAllAgents(): TeamAgentRow[];
230
+ /** List locks across all projects (for global scope) */
231
+ listAllLocks(): TeamLockRow[];
232
+ /** List tasks across all projects (for global scope) */
233
+ listAllTasks(filter?: {
234
+ available?: boolean;
235
+ }): TeamTaskRow[];
236
+ heartbeat(agentId: string): boolean;
237
+ leaveAgent(agentId: string): boolean;
238
+ updateWatermark(agentId: string, generation: number): void;
239
+ /**
240
+ * Detect and mark stale agents. Returns list of stale agent IDs whose tasks/locks were released.
241
+ */
242
+ detectAndMarkStale(projectId: string, staleTtlMs: number): string[];
243
+ getActiveCount(projectId: string): number;
244
+ sendMessage(input: {
245
+ projectId: string;
246
+ senderAgentId: string;
247
+ recipientAgentId?: string | null;
248
+ type: string;
249
+ content: string;
250
+ payload?: Record<string, unknown>;
251
+ taskId?: string;
252
+ toRole?: string | null;
253
+ handoffStatus?: string | null;
254
+ }): TeamMessageRow | {
255
+ error: string;
256
+ };
257
+ getInbox(projectId: string, agentId: string): TeamMessageRow[];
258
+ getUnreadCount(projectId: string, agentId: string): number;
259
+ markMessageRead(messageId: string): boolean;
260
+ markAllRead(projectId: string, agentId: string): number;
261
+ pruneReadMessages(projectId: string, olderThanMs: number): number;
262
+ clearInbox(projectId: string, agentId: string): number;
263
+ getMessageById(messageId: string): TeamMessageRow | undefined;
264
+ createTask(input: {
265
+ projectId: string;
266
+ description: string;
267
+ deps?: string[];
268
+ metadata?: Record<string, unknown>;
269
+ createdBy?: string;
270
+ requiredRole?: string | null;
271
+ preferredRole?: string | null;
272
+ }): TeamTaskRow;
273
+ getTask(taskId: string): TeamTaskRow | undefined;
274
+ getTaskDeps(taskId: string): string[];
275
+ /**
276
+ * Atomic task claim with dependency check.
277
+ * Uses BEGIN IMMEDIATE to serialize the dep check + claim atomically.
278
+ * Returns { success, task, reason? }.
279
+ */
280
+ claimTask(taskId: string, agentId: string): {
281
+ success: boolean;
282
+ task?: TeamTaskRow;
283
+ reason?: string;
284
+ hint?: string;
285
+ };
286
+ completeTask(taskId: string, agentId: string, result?: string): {
287
+ success: boolean;
288
+ reason?: string;
289
+ };
290
+ failTask(taskId: string, agentId: string, result?: string): {
291
+ success: boolean;
292
+ reason?: string;
293
+ };
294
+ releaseTask(taskId: string, agentId: string): {
295
+ success: boolean;
296
+ reason?: string;
297
+ };
298
+ releaseTasksByAgent(agentId: string): number;
299
+ listTasks(projectId: string, filter?: {
300
+ status?: string;
301
+ assignee?: string;
302
+ available?: boolean;
303
+ }): TeamTaskRow[];
304
+ /**
305
+ * List available tasks for a specific agent, sorted by role affinity.
306
+ * Tasks whose preferred_role matches the agent's role come first,
307
+ * then tasks whose required_role matches, then role-agnostic tasks.
308
+ * Tasks whose required_role does NOT match the agent's role are excluded.
309
+ */
310
+ listTasksForAgent(projectId: string, agentId: string): TeamTaskRow[];
311
+ private readonly DEFAULT_LOCK_TTL_MS;
312
+ acquireLock(projectId: string, file: string, agentId: string, ttlMs?: number): {
313
+ success: boolean;
314
+ lockedBy: string;
315
+ };
316
+ releaseLock(projectId: string, file: string, agentId: string): boolean;
317
+ getLockStatus(projectId: string, file: string): TeamLockRow | null;
318
+ listLocks(projectId: string, agentId?: string): TeamLockRow[];
319
+ releaseAllLocks(agentId: string): number;
320
+ cleanExpiredLocks(projectId: string): number;
321
+ private migrateFromJsonIfNeeded;
322
+ private prepareRoleStatements;
323
+ /**
324
+ * Seed default roles for a project if none exist yet.
325
+ * Uses projectId derived from the dataDir path.
326
+ */
327
+ private seedDefaultRoles;
328
+ addRole(projectId: string, input: {
329
+ roleId: string;
330
+ label: string;
331
+ description?: string;
332
+ preferredAgentTypes?: string[];
333
+ maxConcurrent?: number;
334
+ }): TeamRoleRow;
335
+ removeRole(projectId: string, roleId: string): boolean;
336
+ listRoles(projectId: string): TeamRoleRow[];
337
+ getRole(roleId: string): TeamRoleRow | undefined;
338
+ /**
339
+ * Get role occupancy: for each role, how many active agents currently fill it.
340
+ */
341
+ getRoleOccupancy(projectId: string): Array<{
342
+ role: TeamRoleRow;
343
+ activeAgents: TeamAgentRow[];
344
+ vacant: number;
345
+ }>;
346
+ /**
347
+ * Get handoff messages for a project, optionally filtered by role or status.
348
+ */
349
+ listHandoffs(projectId: string, filter?: {
350
+ toRole?: string;
351
+ status?: string;
352
+ }): TeamMessageRow[];
353
+ /**
354
+ * Update handoff status for a message.
355
+ */
356
+ updateHandoffStatus(messageId: string, status: string): boolean;
357
+ getDb(): any;
358
+ }
359
+
360
+ /**
361
+ * Knowledge Graph Manager
362
+ *
363
+ * Manages the Entity-Relation knowledge graph.
364
+ * Source: MCP Official Memory Server v0.6.3 (complete rewrite with same API).
365
+ *
366
+ * Key differences from official implementation:
367
+ * - Uses per-project JSONL files (official uses single file)
368
+ * - Async initialization with persistence layer
369
+ * - Project-scoped operations
370
+ */
371
+
372
+ declare class KnowledgeGraphManager {
373
+ private entities;
374
+ private relations;
375
+ private projectDir;
376
+ private initialized;
377
+ /** Index: lowercase entity name → Entity for O(1) lookups */
378
+ private entityIndex;
379
+ constructor(projectDir: string);
380
+ /** Rebuild the entity name index */
381
+ private rebuildIndex;
382
+ /** Load graph from SQLite on first access */
383
+ init(): Promise<void>;
384
+ /** Find entity by name (case-insensitive, O(1)) */
385
+ findEntityByName(name: string): Entity | undefined;
386
+ /** Get all entity names as a Set (lowercase, for fast membership checks) */
387
+ getEntityNameSet(): Set<string>;
388
+ /** Persist current state to SQLite */
389
+ private save;
390
+ /** Create new entities (skip duplicates by name) */
391
+ createEntities(entities: Entity[]): Promise<Entity[]>;
392
+ /** Create new relations (skip duplicates) */
393
+ createRelations(relations: Relation[]): Promise<Relation[]>;
394
+ /** Add observations to existing entities */
395
+ addObservations(observations: {
396
+ entityName: string;
397
+ contents: string[];
398
+ }[]): Promise<{
399
+ entityName: string;
400
+ addedObservations: string[];
401
+ }[]>;
402
+ /** Delete entities and their associated relations */
403
+ deleteEntities(entityNames: string[]): Promise<void>;
404
+ /** Delete specific observations from entities */
405
+ deleteObservations(deletions: {
406
+ entityName: string;
407
+ observations: string[];
408
+ }[]): Promise<void>;
409
+ /** Delete specific relations */
410
+ deleteRelations(relations: Relation[]): Promise<void>;
411
+ /** Get all entity names (for Formation Pipeline entity resolution) */
412
+ getEntityNames(): string[];
413
+ /** Read the entire graph */
414
+ readGraph(): Promise<KnowledgeGraph>;
415
+ /** Search nodes by query string (upgraded from official's basic includes) */
416
+ searchNodes(query: string): Promise<KnowledgeGraph>;
417
+ /** Open specific nodes by name */
418
+ openNodes(names: string[]): Promise<KnowledgeGraph>;
419
+ }
420
+
421
+ /**
422
+ * Tool Profile System — Progressive Disclosure for MCP tools
423
+ *
424
+ * The full Memorix tool set contains 30+ tools, but most users only ever
425
+ * use a small subset (store / search / detail). Exposing all of them at
426
+ * tools/list time causes cognitive overload.
427
+ *
428
+ * We provide three profiles:
429
+ * - "lite" (stdio default): Core memory CRUD, sessions, reasoning, retention,
430
+ * backup — 13 tools. Suitable for solo users who just want cross-agent memory.
431
+ * - "team" (HTTP default): lite + autonomous agent team tools + dashboard — 20 tools.
432
+ * Suitable when an operator explicitly wants task/message/lock surfaces.
433
+ * - "full": Everything, including niche / advanced tools (consolidate, dedup,
434
+ * formation metrics, skills, rules/workspace sync, KG-official, image ingest).
435
+ * Opt in via `MEMORIX_MODE=full` or `--mode full`.
436
+ *
437
+ * Users can override at any time via the `MEMORIX_MODE` env var, the `--mode`
438
+ * CLI flag, or programmatically via `createMemorixServer({ toolProfile: ... })`.
439
+ */
440
+ type ToolProfile = 'lite' | 'team' | 'full';
441
+
442
+ /**
443
+ * Create and configure the Memorix MCP Server.
444
+ */
445
+ /** Optional shared TeamStore — passed by serve-http so all sessions share state */
446
+ interface SharedTeamInstances {
447
+ teamStore: TeamStore;
448
+ }
449
+ interface CreateMemorixServerOptions {
450
+ allowUntrackedFallback?: boolean;
451
+ deferProjectInitUntilBound?: boolean;
452
+ dashboardMode?: 'standalone' | 'control-plane';
453
+ dashboardPort?: number;
454
+ toolProfile?: ToolProfile;
455
+ }
456
+ declare function createMemorixServer(cwd?: string, existingServer?: McpServer, sharedTeam?: SharedTeamInstances, options?: CreateMemorixServerOptions): Promise<{
457
+ server: McpServer;
458
+ graphManager: KnowledgeGraphManager;
459
+ projectId: string;
460
+ deferredInit: () => Promise<void>;
461
+ switchProject: (newCwd: string) => Promise<boolean>;
462
+ isExplicitlyBound: () => boolean;
463
+ handleTransportClose: () => void;
464
+ }>;
465
+
466
+ /**
467
+ * Project Detector
468
+ *
469
+ * Strict .git-based project detection.
470
+ * No .git = not a project. No fallbacks, no accommodations.
471
+ *
472
+ * ID strategy:
473
+ * - .git + remote → normalizeGitRemote(remote) (globally unique, e.g. "user/repo")
474
+ * - .git + no remote → "local/<dirname>" (local git repo, no remote yet)
475
+ * - no .git → null (not a project)
476
+ */
477
+
478
+ /**
479
+ * Detect the current project identity from Git.
480
+ * Returns null if no .git directory is found — caller must handle this.
481
+ * @param cwd - Working directory to detect from (defaults to process.cwd())
482
+ */
483
+ declare function detectProject(cwd?: string): ProjectInfo | null;
484
+ /**
485
+ * Detect project with full diagnostic info.
486
+ * Returns both the project (if found) and a failure descriptor (if not).
487
+ * Callers can use failure.reason to produce actionable error messages.
488
+ */
489
+ declare function detectProjectWithDiagnostics(cwd?: string): DetectionResult;
490
+
491
+ /**
492
+ * Memorix SDK — Programmatic API for embedding Memorix into your own projects.
493
+ *
494
+ * Usage:
495
+ * import { createMemoryClient } from 'memorix/sdk';
496
+ *
497
+ * const client = await createMemoryClient({ projectRoot: '/path/to/repo' });
498
+ * await client.store({ entityName: 'auth', type: 'decision', title: '...', narrative: '...' });
499
+ * const results = await client.search('auth decisions');
500
+ * await client.close();
501
+ *
502
+ * For MCP server embedding:
503
+ * import { createMemorixServer } from 'memorix/sdk';
504
+ *
505
+ * const { server, projectId } = await createMemorixServer('/path/to/repo');
506
+ * // Connect to your own transport
507
+ */
508
+
509
+ /** Options for creating a MemoryClient */
510
+ interface MemoryClientOptions {
511
+ /** Absolute path to a Git project root. Required. */
512
+ projectRoot: string;
513
+ /**
514
+ * If true, suppress console.error diagnostic logs during initialization.
515
+ * Default: false.
516
+ */
517
+ silent?: boolean;
518
+ }
519
+ /** Input for storing an observation */
520
+ interface StoreInput {
521
+ entityName: string;
522
+ type: ObservationType;
523
+ title: string;
524
+ narrative: string;
525
+ facts?: string[];
526
+ filesModified?: string[];
527
+ concepts?: string[];
528
+ topicKey?: string;
529
+ sessionId?: string;
530
+ progress?: ProgressInfo;
531
+ source?: 'agent' | 'git' | 'manual';
532
+ commitHash?: string;
533
+ relatedCommits?: string[];
534
+ relatedEntities?: string[];
535
+ sourceDetail?: 'explicit' | 'hook' | 'git-ingest';
536
+ valueCategory?: 'core' | 'contextual' | 'ephemeral';
537
+ }
538
+ /** Result from storing an observation */
539
+ interface StoreResult {
540
+ observation: Observation;
541
+ upserted: boolean;
542
+ }
543
+ /** Options for searching */
544
+ interface ClientSearchOptions {
545
+ query: string;
546
+ /** Filter by observation type */
547
+ type?: ObservationType;
548
+ /** Filter by observation source */
549
+ source?: 'agent' | 'git' | 'manual';
550
+ /** Filter by status. Default: 'active' */
551
+ status?: ObservationStatus | 'all';
552
+ /** Maximum results. Default: 20 */
553
+ limit?: number;
554
+ }
555
+ /** Result from resolving observations */
556
+ interface ResolveResult {
557
+ resolved: number[];
558
+ notFound: number[];
559
+ }
560
+ /**
561
+ * A lightweight, self-contained memory client for reading and writing
562
+ * Memorix observations without MCP overhead.
563
+ *
564
+ * Each client initializes its own SQLite backend and Orama search index,
565
+ * scoped to a single project. Call `close()` when done to release resources.
566
+ */
567
+ declare class MemoryClient {
568
+ private _projectId;
569
+ private _projectRoot;
570
+ private _dataDir;
571
+ private _closed;
572
+ private _observations;
573
+ private _oramaStore;
574
+ private _obsStore;
575
+ private _freshness;
576
+ /** @internal — use createMemoryClient() instead */
577
+ constructor(projectId: string, projectRoot: string, dataDir: string);
578
+ /** The canonical project ID (derived from Git remote or local path) */
579
+ get projectId(): string;
580
+ /** The project root path */
581
+ get projectRoot(): string;
582
+ /** The Memorix data directory for this project */
583
+ get dataDir(): string;
584
+ /**
585
+ * @internal Initialize stores and search index.
586
+ * Called by createMemoryClient(). Do not call directly.
587
+ */
588
+ _init(silent: boolean): Promise<void>;
589
+ private _ensureOpen;
590
+ /**
591
+ * Store a new observation (or upsert if topicKey matches an existing one).
592
+ *
593
+ * @example
594
+ * ```ts
595
+ * const { observation } = await client.store({
596
+ * entityName: 'auth-module',
597
+ * type: 'decision',
598
+ * title: 'Use JWT for API auth',
599
+ * narrative: 'Chose JWT over session cookies for stateless API authentication.',
600
+ * facts: ['Token expiry: 1h', 'Refresh token: 7d'],
601
+ * });
602
+ * ```
603
+ */
604
+ store(input: StoreInput): Promise<StoreResult>;
605
+ /**
606
+ * Search observations using full-text and optional vector search.
607
+ *
608
+ * @example
609
+ * ```ts
610
+ * const results = await client.search({ query: 'authentication decisions' });
611
+ * for (const r of results) {
612
+ * console.log(`${r.title} (score: ${r.score})`);
613
+ * }
614
+ * ```
615
+ */
616
+ search(options: ClientSearchOptions): Promise<IndexEntry[]>;
617
+ /**
618
+ * Get a single observation by ID.
619
+ */
620
+ get(id: number): Promise<Observation | undefined>;
621
+ /**
622
+ * Get all observations for this project.
623
+ */
624
+ getAll(): Promise<Observation[]>;
625
+ /**
626
+ * Get the total observation count for this project.
627
+ */
628
+ count(): Promise<number>;
629
+ /**
630
+ * Mark observations as resolved or archived.
631
+ *
632
+ * Resolved observations are hidden from default search but recoverable.
633
+ * Archived observations are permanently hidden.
634
+ *
635
+ * @example
636
+ * ```ts
637
+ * await client.resolve([1, 2, 3]);
638
+ * await client.resolve([4], 'archived');
639
+ * ```
640
+ */
641
+ resolve(ids: number[], status?: ObservationStatus): Promise<ResolveResult>;
642
+ /**
643
+ * Release resources (close SQLite handle, reset index).
644
+ * The client cannot be used after calling close().
645
+ */
646
+ close(): Promise<void>;
647
+ }
648
+ /**
649
+ * Create a new MemoryClient for a project.
650
+ *
651
+ * This initializes SQLite, loads observations, and prepares the search index.
652
+ * Each client is independent — you can have multiple clients for different projects.
653
+ *
654
+ * @example
655
+ * ```ts
656
+ * import { createMemoryClient } from 'memorix/sdk';
657
+ *
658
+ * const client = await createMemoryClient({ projectRoot: '/home/user/my-project' });
659
+ *
660
+ * // Store a memory
661
+ * await client.store({
662
+ * entityName: 'api-gateway',
663
+ * type: 'gotcha',
664
+ * title: 'Rate limiter resets on deploy',
665
+ * narrative: 'In-memory rate limiter state is lost on every deploy...',
666
+ * });
667
+ *
668
+ * // Search memories
669
+ * const results = await client.search({ query: 'rate limiter' });
670
+ *
671
+ * // Clean up
672
+ * await client.close();
673
+ * ```
674
+ */
675
+ declare function createMemoryClient(options: MemoryClientOptions): Promise<MemoryClient>;
676
+
677
+ export { type ClientSearchOptions, type CreateMemorixServerOptions, DetectionResult, Entity, IndexEntry, KnowledgeGraph, MemoryClient, type MemoryClientOptions, Observation, ObservationStatus, ObservationType, ProgressInfo, ProjectInfo, Relation, type ResolveResult, type StoreInput, type StoreResult, createMemorixServer, createMemoryClient, detectProject, detectProjectWithDiagnostics };