memorix 1.3.3 → 1.3.4
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/CHANGELOG.md +14 -0
- package/dist/cli/index.js +1162 -1098
- package/dist/index.d.ts +513 -0
- package/dist/index.js +14751 -14044
- package/dist/maintenance-runner.js +105 -52
- package/dist/media-video-runner.js +105 -52
- package/dist/memcode-runtime/CHANGELOG.md +14 -0
- package/dist/sdk.d.ts +5 -513
- package/dist/sdk.js +186 -75
- package/dist/vector-backfill-runner.js +105 -52
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +4 -3
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/media.ts +10 -2
- package/src/cli/commands/serve-http.ts +7 -38
- package/src/cli/commands/serve-shared.ts +18 -46
- package/src/cli/commands/serve.ts +3 -41
- package/src/cli/commands/setup.ts +24 -21
- package/src/cli/mcp-root-path.ts +36 -0
- package/src/index.ts +37 -55
- package/src/media/asset-store.ts +74 -6
- package/src/media/attachment.ts +12 -9
- package/src/media/media-store.ts +38 -4
- package/src/media/video-jobs.ts +39 -14
- package/src/memory/observations.ts +21 -2
- package/src/orchestrate/adapters/spawn-helper.ts +2 -0
- package/src/server/tool-profile.ts +7 -4
- package/src/server.ts +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,514 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { Entity, Relation, KnowledgeGraph } from './types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* These sources describe how Memorix learned a workspace binding. They are
|
|
7
|
+
* product facts, intentionally separate from any MCP transport session ID.
|
|
8
|
+
*/
|
|
9
|
+
type ProjectBindingSource = 'startup-cwd' | 'mcp-roots' | 'explicit-project-root';
|
|
10
|
+
interface ProjectBindingSnapshot {
|
|
11
|
+
projectRoot: string;
|
|
12
|
+
source: ProjectBindingSource;
|
|
13
|
+
explicit: boolean;
|
|
14
|
+
projectId?: string;
|
|
15
|
+
}
|
|
16
|
+
interface MemorixRequestContext extends ProjectBindingSnapshot {
|
|
17
|
+
actorId?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* One connection may keep this object today, while a future stateless adapter
|
|
21
|
+
* can construct it from fixed server configuration. No HTTP session identifier
|
|
22
|
+
* is accepted or stored here.
|
|
23
|
+
*/
|
|
24
|
+
declare class ProjectBindingController {
|
|
25
|
+
private current;
|
|
26
|
+
constructor(projectRoot: string);
|
|
27
|
+
snapshot(): ProjectBindingSnapshot;
|
|
28
|
+
requestContext(actorId?: string): MemorixRequestContext;
|
|
29
|
+
isExplicit(): boolean;
|
|
30
|
+
/** Roots are advisory and may never overwrite an explicit user binding. */
|
|
31
|
+
bindFromRoots(projectRoot: string): boolean;
|
|
32
|
+
bindExplicit(projectRoot: string): void;
|
|
33
|
+
bindStartup(projectRoot: string): void;
|
|
34
|
+
/** Set only after the caller has verified the path maps to a real project. */
|
|
35
|
+
recordResolvedProject(projectId: string, projectRoot?: string): void;
|
|
36
|
+
private replace;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* TeamEventBus — Process-local typed event emitter for team coordination.
|
|
41
|
+
*
|
|
42
|
+
* Phase 4b: Provides push-based acceleration within a single process.
|
|
43
|
+
* NOT a cross-process mechanism — the orchestrator uses SQLite polling.
|
|
44
|
+
*
|
|
45
|
+
* Architectural boundary (B1): This is process-local fanout only.
|
|
46
|
+
* No persistence, no cross-process delivery, no durability guarantees.
|
|
47
|
+
* If no listeners are registered, events are silently dropped.
|
|
48
|
+
*/
|
|
49
|
+
interface TeamEventMap {
|
|
50
|
+
'task:created': {
|
|
51
|
+
taskId: string;
|
|
52
|
+
projectId: string;
|
|
53
|
+
description: string;
|
|
54
|
+
};
|
|
55
|
+
'task:claimed': {
|
|
56
|
+
taskId: string;
|
|
57
|
+
projectId: string;
|
|
58
|
+
agentId: string;
|
|
59
|
+
};
|
|
60
|
+
'task:completed': {
|
|
61
|
+
taskId: string;
|
|
62
|
+
projectId: string;
|
|
63
|
+
agentId: string;
|
|
64
|
+
result?: string;
|
|
65
|
+
};
|
|
66
|
+
'task:failed': {
|
|
67
|
+
taskId: string;
|
|
68
|
+
projectId: string;
|
|
69
|
+
agentId: string;
|
|
70
|
+
result?: string;
|
|
71
|
+
};
|
|
72
|
+
'task:released': {
|
|
73
|
+
taskId: string;
|
|
74
|
+
projectId: string;
|
|
75
|
+
agentId: string;
|
|
76
|
+
};
|
|
77
|
+
'agent:joined': {
|
|
78
|
+
agentId: string;
|
|
79
|
+
projectId: string;
|
|
80
|
+
agentType: string;
|
|
81
|
+
};
|
|
82
|
+
'agent:left': {
|
|
83
|
+
agentId: string;
|
|
84
|
+
projectId: string;
|
|
85
|
+
};
|
|
86
|
+
'agent:stale': {
|
|
87
|
+
agentId: string;
|
|
88
|
+
projectId: string;
|
|
89
|
+
releasedTasks: number;
|
|
90
|
+
};
|
|
91
|
+
'handoff:created': {
|
|
92
|
+
observationId: number;
|
|
93
|
+
projectId: string;
|
|
94
|
+
fromAgent: string;
|
|
95
|
+
toAgent?: string;
|
|
96
|
+
taskId?: string;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
type TeamEventName = keyof TeamEventMap;
|
|
100
|
+
declare class TeamEventBus {
|
|
101
|
+
private emitter;
|
|
102
|
+
constructor();
|
|
103
|
+
/**
|
|
104
|
+
* Emit a typed event. Non-blocking, best-effort.
|
|
105
|
+
* If no listeners are registered, the event is silently dropped.
|
|
106
|
+
*/
|
|
107
|
+
emit<K extends TeamEventName>(event: K, data: TeamEventMap[K]): void;
|
|
108
|
+
/** Subscribe to a typed event. Returns unsubscribe function. */
|
|
109
|
+
on<K extends TeamEventName>(event: K, listener: (data: TeamEventMap[K]) => void): () => void;
|
|
110
|
+
/** Subscribe to a typed event, fire only once. */
|
|
111
|
+
once<K extends TeamEventName>(event: K, listener: (data: TeamEventMap[K]) => void): void;
|
|
112
|
+
/** Remove all listeners for a specific event, or all events if none specified. */
|
|
113
|
+
removeAllListeners(event?: TeamEventName): void;
|
|
114
|
+
/** Current listener count for a specific event. */
|
|
115
|
+
listenerCount(event: TeamEventName): number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* TeamStore - SQLite-backed persistence for orchestration coordination state.
|
|
120
|
+
*
|
|
121
|
+
* Phase 4a: Replaces the file-based team-state.json persistence with
|
|
122
|
+
* SQLite prepared statements on the shared DB handle (memorix.db).
|
|
123
|
+
*
|
|
124
|
+
* Provides:
|
|
125
|
+
* - Singleton init/get/reset pattern (same as SessionStore)
|
|
126
|
+
* - Shared DB handle via getDatabase()
|
|
127
|
+
* - One-time migration from team-state.json
|
|
128
|
+
* - Prepared statements for all team CRUD operations
|
|
129
|
+
*
|
|
130
|
+
* All team modules (registry, messages, tasks, locks) delegate to this store.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
interface TeamAgentRow {
|
|
134
|
+
agent_id: string;
|
|
135
|
+
project_id: string;
|
|
136
|
+
agent_type: string;
|
|
137
|
+
instance_id: string;
|
|
138
|
+
name: string;
|
|
139
|
+
role: string | null;
|
|
140
|
+
capabilities: string | null;
|
|
141
|
+
status: 'active' | 'inactive';
|
|
142
|
+
joined_at: number;
|
|
143
|
+
last_heartbeat: number;
|
|
144
|
+
left_at: number | null;
|
|
145
|
+
last_seen_obs_generation: number;
|
|
146
|
+
}
|
|
147
|
+
interface TeamMessageRow {
|
|
148
|
+
id: string;
|
|
149
|
+
project_id: string;
|
|
150
|
+
sender_agent_id: string;
|
|
151
|
+
recipient_agent_id: string | null;
|
|
152
|
+
type: string;
|
|
153
|
+
content: string;
|
|
154
|
+
payload: string | null;
|
|
155
|
+
task_id: string | null;
|
|
156
|
+
read_at: number | null;
|
|
157
|
+
created_at: number;
|
|
158
|
+
to_role: string | null;
|
|
159
|
+
handoff_status: string | null;
|
|
160
|
+
}
|
|
161
|
+
interface TeamTaskRow {
|
|
162
|
+
task_id: string;
|
|
163
|
+
project_id: string;
|
|
164
|
+
description: string;
|
|
165
|
+
status: 'pending' | 'in_progress' | 'completed' | 'failed';
|
|
166
|
+
assignee_agent_id: string | null;
|
|
167
|
+
result: string | null;
|
|
168
|
+
metadata: string | null;
|
|
169
|
+
created_by: string | null;
|
|
170
|
+
created_at: number;
|
|
171
|
+
updated_at: number;
|
|
172
|
+
required_role: string | null;
|
|
173
|
+
preferred_role: string | null;
|
|
174
|
+
}
|
|
175
|
+
interface TeamLockRow {
|
|
176
|
+
file: string;
|
|
177
|
+
project_id: string;
|
|
178
|
+
locked_by: string;
|
|
179
|
+
locked_at: number;
|
|
180
|
+
expires_at: number;
|
|
181
|
+
}
|
|
182
|
+
interface TeamRoleRow {
|
|
183
|
+
role_id: string;
|
|
184
|
+
project_id: string;
|
|
185
|
+
label: string;
|
|
186
|
+
description: string | null;
|
|
187
|
+
preferred_agent_types: string;
|
|
188
|
+
max_concurrent: number;
|
|
189
|
+
created_at: number;
|
|
190
|
+
}
|
|
191
|
+
declare class TeamStore {
|
|
192
|
+
private db;
|
|
193
|
+
private dataDir;
|
|
194
|
+
/** Optional event bus for same-process lifecycle notifications.
|
|
195
|
+
* Set via setEventBus(). Emit failures never block TeamStore writes. */
|
|
196
|
+
private eventBus;
|
|
197
|
+
setEventBus(bus: TeamEventBus): void;
|
|
198
|
+
getEventBus(): TeamEventBus | null;
|
|
199
|
+
private stmtAgentUpsert;
|
|
200
|
+
private stmtAgentFindByInstance;
|
|
201
|
+
private stmtAgentFindById;
|
|
202
|
+
private stmtAgentListByProject;
|
|
203
|
+
private stmtAgentUpdateHeartbeat;
|
|
204
|
+
private stmtAgentLeave;
|
|
205
|
+
private stmtAgentUpdateWatermark;
|
|
206
|
+
private stmtMsgInsert;
|
|
207
|
+
private stmtMsgInbox;
|
|
208
|
+
private stmtMsgMarkRead;
|
|
209
|
+
private stmtMsgMarkAllRead;
|
|
210
|
+
private stmtMsgUnreadCount;
|
|
211
|
+
private stmtMsgPruneRead;
|
|
212
|
+
private stmtMsgClearInbox;
|
|
213
|
+
private stmtMsgById;
|
|
214
|
+
private stmtTaskInsert;
|
|
215
|
+
private stmtTaskClaim;
|
|
216
|
+
private stmtTaskReClaim;
|
|
217
|
+
private stmtTaskComplete;
|
|
218
|
+
private stmtTaskFail;
|
|
219
|
+
private stmtTaskRelease;
|
|
220
|
+
private stmtTaskReleaseByAgent;
|
|
221
|
+
private stmtTaskById;
|
|
222
|
+
private stmtTaskListByProject;
|
|
223
|
+
private stmtTaskAvailable;
|
|
224
|
+
private stmtTaskDepInsert;
|
|
225
|
+
private stmtTaskDepsByTask;
|
|
226
|
+
private stmtTaskUnmetDeps;
|
|
227
|
+
private stmtLockUpsert;
|
|
228
|
+
private stmtLockGet;
|
|
229
|
+
private stmtLockDelete;
|
|
230
|
+
private stmtLockListByProject;
|
|
231
|
+
private stmtLockListByAgent;
|
|
232
|
+
private stmtLockDeleteByAgent;
|
|
233
|
+
private stmtLockDeleteExpired;
|
|
234
|
+
private stmtRoleInsert;
|
|
235
|
+
private stmtRoleDelete;
|
|
236
|
+
private stmtRoleListByProject;
|
|
237
|
+
private stmtRoleGetById;
|
|
238
|
+
private stmtRoleCountByProject;
|
|
239
|
+
init(dataDir: string): Promise<void>;
|
|
240
|
+
private prepareAgentStatements;
|
|
241
|
+
private prepareMessageStatements;
|
|
242
|
+
private prepareTaskStatements;
|
|
243
|
+
private prepareLockStatements;
|
|
244
|
+
/**
|
|
245
|
+
* Register or reactivate an agent.
|
|
246
|
+
* If an agent with the same (project_id, agent_type, instance_id) exists,
|
|
247
|
+
* reactivate it (preserving agent_id). Otherwise create a new one.
|
|
248
|
+
*/
|
|
249
|
+
registerAgent(input: {
|
|
250
|
+
projectId: string;
|
|
251
|
+
agentType: string;
|
|
252
|
+
instanceId?: string;
|
|
253
|
+
name?: string;
|
|
254
|
+
role?: string;
|
|
255
|
+
capabilities?: string[];
|
|
256
|
+
}): TeamAgentRow;
|
|
257
|
+
getAgent(agentId: string): TeamAgentRow | undefined;
|
|
258
|
+
getAgentByInstance(projectId: string, agentType: string, instanceId: string): TeamAgentRow | undefined;
|
|
259
|
+
listAgents(projectId: string, filter?: {
|
|
260
|
+
status?: 'active' | 'inactive';
|
|
261
|
+
}): TeamAgentRow[];
|
|
262
|
+
/** List agents across all projects (for global scope) */
|
|
263
|
+
listAllAgents(): TeamAgentRow[];
|
|
264
|
+
/** List locks across all projects (for global scope) */
|
|
265
|
+
listAllLocks(): TeamLockRow[];
|
|
266
|
+
/** List tasks across all projects (for global scope) */
|
|
267
|
+
listAllTasks(filter?: {
|
|
268
|
+
available?: boolean;
|
|
269
|
+
}): TeamTaskRow[];
|
|
270
|
+
heartbeat(agentId: string): boolean;
|
|
271
|
+
leaveAgent(agentId: string): boolean;
|
|
272
|
+
updateWatermark(agentId: string, generation: number): void;
|
|
273
|
+
/**
|
|
274
|
+
* Detect and mark stale agents. Returns list of stale agent IDs whose tasks/locks were released.
|
|
275
|
+
*/
|
|
276
|
+
detectAndMarkStale(projectId: string, staleTtlMs: number): string[];
|
|
277
|
+
getActiveCount(projectId: string): number;
|
|
278
|
+
sendMessage(input: {
|
|
279
|
+
projectId: string;
|
|
280
|
+
senderAgentId: string;
|
|
281
|
+
recipientAgentId?: string | null;
|
|
282
|
+
type: string;
|
|
283
|
+
content: string;
|
|
284
|
+
payload?: Record<string, unknown>;
|
|
285
|
+
taskId?: string;
|
|
286
|
+
toRole?: string | null;
|
|
287
|
+
handoffStatus?: string | null;
|
|
288
|
+
}): TeamMessageRow | {
|
|
289
|
+
error: string;
|
|
290
|
+
};
|
|
291
|
+
getInbox(projectId: string, agentId: string): TeamMessageRow[];
|
|
292
|
+
getUnreadCount(projectId: string, agentId: string): number;
|
|
293
|
+
markMessageRead(messageId: string): boolean;
|
|
294
|
+
markAllRead(projectId: string, agentId: string): number;
|
|
295
|
+
pruneReadMessages(projectId: string, olderThanMs: number): number;
|
|
296
|
+
clearInbox(projectId: string, agentId: string): number;
|
|
297
|
+
getMessageById(messageId: string): TeamMessageRow | undefined;
|
|
298
|
+
createTask(input: {
|
|
299
|
+
projectId: string;
|
|
300
|
+
description: string;
|
|
301
|
+
deps?: string[];
|
|
302
|
+
metadata?: Record<string, unknown>;
|
|
303
|
+
createdBy?: string;
|
|
304
|
+
requiredRole?: string | null;
|
|
305
|
+
preferredRole?: string | null;
|
|
306
|
+
}): TeamTaskRow;
|
|
307
|
+
getTask(taskId: string): TeamTaskRow | undefined;
|
|
308
|
+
getTaskDeps(taskId: string): string[];
|
|
309
|
+
/**
|
|
310
|
+
* Atomic task claim with dependency check.
|
|
311
|
+
* Uses BEGIN IMMEDIATE to serialize the dep check + claim atomically.
|
|
312
|
+
* Returns { success, task, reason? }.
|
|
313
|
+
*/
|
|
314
|
+
claimTask(taskId: string, agentId: string): {
|
|
315
|
+
success: boolean;
|
|
316
|
+
task?: TeamTaskRow;
|
|
317
|
+
reason?: string;
|
|
318
|
+
hint?: string;
|
|
319
|
+
};
|
|
320
|
+
completeTask(taskId: string, agentId: string, result?: string): {
|
|
321
|
+
success: boolean;
|
|
322
|
+
reason?: string;
|
|
323
|
+
};
|
|
324
|
+
failTask(taskId: string, agentId: string, result?: string): {
|
|
325
|
+
success: boolean;
|
|
326
|
+
reason?: string;
|
|
327
|
+
};
|
|
328
|
+
releaseTask(taskId: string, agentId: string): {
|
|
329
|
+
success: boolean;
|
|
330
|
+
reason?: string;
|
|
331
|
+
};
|
|
332
|
+
releaseTasksByAgent(agentId: string): number;
|
|
333
|
+
listTasks(projectId: string, filter?: {
|
|
334
|
+
status?: string;
|
|
335
|
+
assignee?: string;
|
|
336
|
+
available?: boolean;
|
|
337
|
+
}): TeamTaskRow[];
|
|
338
|
+
/**
|
|
339
|
+
* List available tasks for a specific agent, sorted by role affinity.
|
|
340
|
+
* Tasks whose preferred_role matches the agent's role come first,
|
|
341
|
+
* then tasks whose required_role matches, then role-agnostic tasks.
|
|
342
|
+
* Tasks whose required_role does NOT match the agent's role are excluded.
|
|
343
|
+
*/
|
|
344
|
+
listTasksForAgent(projectId: string, agentId: string): TeamTaskRow[];
|
|
345
|
+
private readonly DEFAULT_LOCK_TTL_MS;
|
|
346
|
+
acquireLock(projectId: string, file: string, agentId: string, ttlMs?: number): {
|
|
347
|
+
success: boolean;
|
|
348
|
+
lockedBy: string;
|
|
349
|
+
};
|
|
350
|
+
releaseLock(projectId: string, file: string, agentId: string): boolean;
|
|
351
|
+
getLockStatus(projectId: string, file: string): TeamLockRow | null;
|
|
352
|
+
listLocks(projectId: string, agentId?: string): TeamLockRow[];
|
|
353
|
+
releaseAllLocks(agentId: string): number;
|
|
354
|
+
cleanExpiredLocks(projectId: string): number;
|
|
355
|
+
private migrateFromJsonIfNeeded;
|
|
356
|
+
private prepareRoleStatements;
|
|
357
|
+
/**
|
|
358
|
+
* Seed default roles for a project if none exist yet.
|
|
359
|
+
* Uses projectId derived from the dataDir path.
|
|
360
|
+
*/
|
|
361
|
+
private seedDefaultRoles;
|
|
362
|
+
addRole(projectId: string, input: {
|
|
363
|
+
roleId: string;
|
|
364
|
+
label: string;
|
|
365
|
+
description?: string;
|
|
366
|
+
preferredAgentTypes?: string[];
|
|
367
|
+
maxConcurrent?: number;
|
|
368
|
+
}): TeamRoleRow;
|
|
369
|
+
removeRole(projectId: string, roleId: string): boolean;
|
|
370
|
+
listRoles(projectId: string): TeamRoleRow[];
|
|
371
|
+
getRole(roleId: string): TeamRoleRow | undefined;
|
|
372
|
+
/**
|
|
373
|
+
* Get role occupancy: for each role, how many active agents currently fill it.
|
|
374
|
+
*/
|
|
375
|
+
getRoleOccupancy(projectId: string): Array<{
|
|
376
|
+
role: TeamRoleRow;
|
|
377
|
+
activeAgents: TeamAgentRow[];
|
|
378
|
+
vacant: number;
|
|
379
|
+
}>;
|
|
380
|
+
/**
|
|
381
|
+
* Get handoff messages for a project, optionally filtered by role or status.
|
|
382
|
+
*/
|
|
383
|
+
listHandoffs(projectId: string, filter?: {
|
|
384
|
+
toRole?: string;
|
|
385
|
+
status?: string;
|
|
386
|
+
}): TeamMessageRow[];
|
|
387
|
+
/**
|
|
388
|
+
* Update handoff status for a message.
|
|
389
|
+
*/
|
|
390
|
+
updateHandoffStatus(messageId: string, status: string): boolean;
|
|
391
|
+
getDb(): any;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Knowledge Graph Manager
|
|
396
|
+
*
|
|
397
|
+
* Manages the Entity-Relation knowledge graph.
|
|
398
|
+
* Source: MCP Official Memory Server v0.6.3 (complete rewrite with same API).
|
|
399
|
+
*
|
|
400
|
+
* Key differences from official implementation:
|
|
401
|
+
* - Uses per-project JSONL files (official uses single file)
|
|
402
|
+
* - Async initialization with persistence layer
|
|
403
|
+
* - Project-scoped operations
|
|
404
|
+
*/
|
|
405
|
+
|
|
406
|
+
declare class KnowledgeGraphManager {
|
|
407
|
+
private entities;
|
|
408
|
+
private relations;
|
|
409
|
+
private projectDir;
|
|
410
|
+
private initialized;
|
|
411
|
+
/** Index: lowercase entity name → Entity for O(1) lookups */
|
|
412
|
+
private entityIndex;
|
|
413
|
+
constructor(projectDir: string);
|
|
414
|
+
/** Rebuild the entity name index */
|
|
415
|
+
private rebuildIndex;
|
|
416
|
+
/** Load graph from SQLite on first access */
|
|
417
|
+
init(): Promise<void>;
|
|
418
|
+
/** Find entity by name (case-insensitive, O(1)) */
|
|
419
|
+
findEntityByName(name: string): Entity | undefined;
|
|
420
|
+
/** Get all entity names as a Set (lowercase, for fast membership checks) */
|
|
421
|
+
getEntityNameSet(): Set<string>;
|
|
422
|
+
/** Persist current state to SQLite */
|
|
423
|
+
private save;
|
|
424
|
+
/** Create new entities (skip duplicates by name) */
|
|
425
|
+
createEntities(entities: Entity[]): Promise<Entity[]>;
|
|
426
|
+
/** Create new relations (skip duplicates) */
|
|
427
|
+
createRelations(relations: Relation[]): Promise<Relation[]>;
|
|
428
|
+
/** Add observations to existing entities */
|
|
429
|
+
addObservations(observations: {
|
|
430
|
+
entityName: string;
|
|
431
|
+
contents: string[];
|
|
432
|
+
}[]): Promise<{
|
|
433
|
+
entityName: string;
|
|
434
|
+
addedObservations: string[];
|
|
435
|
+
}[]>;
|
|
436
|
+
/** Delete entities and their associated relations */
|
|
437
|
+
deleteEntities(entityNames: string[]): Promise<void>;
|
|
438
|
+
/** Delete specific observations from entities */
|
|
439
|
+
deleteObservations(deletions: {
|
|
440
|
+
entityName: string;
|
|
441
|
+
observations: string[];
|
|
442
|
+
}[]): Promise<void>;
|
|
443
|
+
/** Delete specific relations */
|
|
444
|
+
deleteRelations(relations: Relation[]): Promise<void>;
|
|
445
|
+
/** Get all entity names (for Formation Pipeline entity resolution) */
|
|
446
|
+
getEntityNames(): string[];
|
|
447
|
+
/** Read the entire graph */
|
|
448
|
+
readGraph(): Promise<KnowledgeGraph>;
|
|
449
|
+
/** Search nodes by query string (upgraded from official's basic includes) */
|
|
450
|
+
searchNodes(query: string): Promise<KnowledgeGraph>;
|
|
451
|
+
/** Open specific nodes by name */
|
|
452
|
+
openNodes(names: string[]): Promise<KnowledgeGraph>;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Tool Profile System — Progressive Disclosure for MCP tools
|
|
457
|
+
*
|
|
458
|
+
* The full Memorix tool set contains 40+ tools, but most users only ever
|
|
459
|
+
* use a small subset (store / search / detail). Exposing all of them at
|
|
460
|
+
* tools/list time causes cognitive overload.
|
|
461
|
+
*
|
|
462
|
+
* We provide four profiles:
|
|
463
|
+
* - "micro" (stdio default): Agent-ready project context + bounded recovery/media controls — 9 tools.
|
|
464
|
+
* Suitable for normal MCP clients where every tool schema costs context tokens.
|
|
465
|
+
* - "lite": Core memory CRUD, sessions, reasoning, retention, backup — 18 tools.
|
|
466
|
+
* Suitable for solo users who want the full memory surface without team tools.
|
|
467
|
+
* - "team" (HTTP default): lite + orchestration coordination tools, dashboard, and Knowledge Workspace — 26 tools.
|
|
468
|
+
* Suitable when an operator explicitly wants task/message/lock surfaces.
|
|
469
|
+
* - "full": Everything, including niche / advanced tools (consolidate, dedup,
|
|
470
|
+
* formation metrics, skills, rules/workspace sync, KG-official, image ingest).
|
|
471
|
+
* Opt in via `MEMORIX_MODE=full` or `--mode full`.
|
|
472
|
+
*
|
|
473
|
+
* Users can override at any time via the `MEMORIX_MODE` env var, the `--mode`
|
|
474
|
+
* CLI flag, or programmatically via `createMemorixServer({ toolProfile: ... })`.
|
|
475
|
+
*/
|
|
476
|
+
type ToolProfile = 'micro' | 'lite' | 'team' | 'full';
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Create and configure the Memorix MCP Server.
|
|
480
|
+
*/
|
|
481
|
+
/** Optional shared TeamStore — passed by serve-http so all sessions share state */
|
|
482
|
+
interface SharedTeamInstances {
|
|
483
|
+
teamStore: TeamStore;
|
|
484
|
+
}
|
|
485
|
+
interface CreateMemorixServerOptions {
|
|
486
|
+
allowUntrackedFallback?: boolean;
|
|
487
|
+
deferProjectInitUntilBound?: boolean;
|
|
488
|
+
/**
|
|
489
|
+
* Register tools and return before loading the full project memory runtime.
|
|
490
|
+
* Intended for stdio clients and registries where MCP initialize/tools/list must
|
|
491
|
+
* complete quickly even when the local memory corpus is large.
|
|
492
|
+
*/
|
|
493
|
+
deferProjectRuntimeInit?: boolean;
|
|
494
|
+
dashboardMode?: 'standalone' | 'control-plane';
|
|
495
|
+
dashboardPort?: number;
|
|
496
|
+
toolProfile?: ToolProfile;
|
|
497
|
+
/**
|
|
498
|
+
* Product-scoped project binding. HTTP transports may keep it beside a
|
|
499
|
+
* legacy session adapter today; no project operation reads session headers.
|
|
500
|
+
*/
|
|
501
|
+
projectBinding?: ProjectBindingController;
|
|
502
|
+
}
|
|
503
|
+
declare function createMemorixServer(cwd?: string, existingServer?: McpServer, sharedTeam?: SharedTeamInstances, options?: CreateMemorixServerOptions): Promise<{
|
|
504
|
+
server: McpServer;
|
|
505
|
+
graphManager: KnowledgeGraphManager;
|
|
506
|
+
projectId: string;
|
|
507
|
+
deferredInit: () => Promise<void>;
|
|
508
|
+
switchProject: (newCwd: string) => Promise<boolean>;
|
|
509
|
+
isExplicitlyBound: () => boolean;
|
|
510
|
+
getRequestContext: () => MemorixRequestContext;
|
|
511
|
+
handleTransportClose: () => void;
|
|
512
|
+
}>;
|
|
513
|
+
|
|
514
|
+
export { type CreateMemorixServerOptions, createMemorixServer };
|