@revealui/ai 0.2.8 → 0.2.9
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/README.md +2 -2
- package/dist/a2a/card.d.ts +1 -1
- package/dist/a2a/card.d.ts.map +1 -1
- package/dist/a2a/card.js +4 -4
- package/dist/a2a/handler.d.ts +4 -4
- package/dist/a2a/handler.js +5 -5
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/audit/emitter.d.ts +1 -1
- package/dist/audit/emitter.js +2 -2
- package/dist/audit/index.d.ts +2 -2
- package/dist/audit/index.js +2 -2
- package/dist/audit/store.d.ts +2 -2
- package/dist/audit/store.js +2 -2
- package/dist/client/errors.d.ts +13 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +28 -0
- package/dist/client/hooks/useAgentContext.d.ts.map +1 -1
- package/dist/client/hooks/useAgentContext.js +6 -5
- package/dist/client/hooks/useAgentStream.d.ts +2 -2
- package/dist/client/hooks/useAgentStream.js +3 -3
- package/dist/client/hooks/useEpisodicMemory.d.ts.map +1 -1
- package/dist/client/hooks/useEpisodicMemory.js +6 -5
- package/dist/client/hooks/useWorkingMemory.d.ts.map +1 -1
- package/dist/client/hooks/useWorkingMemory.js +7 -6
- package/dist/embeddings/index.d.ts +1 -1
- package/dist/embeddings/index.js +4 -4
- package/dist/inference/context-budget.d.ts +1 -1
- package/dist/inference/context-budget.js +4 -4
- package/dist/inference/index.d.ts +1 -1
- package/dist/inference/index.js +1 -1
- package/dist/inference/runRag.d.ts +3 -3
- package/dist/inference/runRag.d.ts.map +1 -1
- package/dist/inference/runRag.js +1 -1
- package/dist/inference/task-decomposer.d.ts +1 -1
- package/dist/inference/task-decomposer.d.ts.map +1 -1
- package/dist/inference/task-decomposer.js +3 -3
- package/dist/inference/tool-result-compressor.d.ts +1 -1
- package/dist/inference/tool-result-compressor.js +1 -1
- package/dist/ingestion/{cms-indexer.d.ts → admin-indexer.d.ts} +12 -12
- package/dist/ingestion/admin-indexer.d.ts.map +1 -0
- package/dist/ingestion/{cms-indexer.js → admin-indexer.js} +9 -9
- package/dist/ingestion/bm25.d.ts +1 -1
- package/dist/ingestion/bm25.js +1 -1
- package/dist/ingestion/file-parsers.d.ts +1 -1
- package/dist/ingestion/file-parsers.d.ts.map +1 -1
- package/dist/ingestion/file-parsers.js +36 -17
- package/dist/ingestion/hybrid-search.d.ts +1 -1
- package/dist/ingestion/hybrid-search.js +1 -1
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/index.d.ts.map +1 -1
- package/dist/ingestion/index.js +1 -1
- package/dist/ingestion/rag-vector-service.d.ts +1 -1
- package/dist/ingestion/rag-vector-service.js +1 -1
- package/dist/ingestion/reranker.d.ts +1 -1
- package/dist/ingestion/reranker.js +1 -1
- package/dist/ingestion/text-splitter.d.ts +1 -1
- package/dist/ingestion/text-splitter.js +2 -2
- package/dist/llm/client.d.ts +7 -10
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +10 -34
- package/dist/llm/key-validator.d.ts +1 -1
- package/dist/llm/key-validator.js +8 -8
- package/dist/llm/providers/base.d.ts +2 -2
- package/dist/llm/providers/groq.d.ts +2 -2
- package/dist/llm/providers/groq.d.ts.map +1 -1
- package/dist/llm/providers/groq.js +2 -2
- package/dist/llm/providers/inference-snaps.d.ts +5 -5
- package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
- package/dist/llm/providers/inference-snaps.js +4 -4
- package/dist/llm/providers/ollama.d.ts +2 -2
- package/dist/llm/providers/ollama.d.ts.map +1 -1
- package/dist/llm/providers/ollama.js +1 -1
- package/dist/llm/providers/openai-compat.d.ts +2 -2
- package/dist/llm/providers/openai-compat.js +5 -5
- package/dist/llm/providers/vultr.js +1 -1
- package/dist/llm/server.d.ts +0 -1
- package/dist/llm/server.d.ts.map +1 -1
- package/dist/llm/server.js +0 -1
- package/dist/llm/token-counter.d.ts.map +1 -1
- package/dist/llm/token-counter.js +11 -8
- package/dist/llm/workspace-provider-config.d.ts +1 -1
- package/dist/llm/workspace-provider-config.d.ts.map +1 -1
- package/dist/llm/workspace-provider-config.js +1 -1
- package/dist/memory/crdt/or-set.d.ts +12 -0
- package/dist/memory/crdt/or-set.d.ts.map +1 -1
- package/dist/memory/crdt/or-set.js +27 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -0
- package/dist/memory/persistence/crdt-persistence.d.ts +21 -1
- package/dist/memory/persistence/crdt-persistence.d.ts.map +1 -1
- package/dist/memory/persistence/crdt-persistence.js +67 -0
- package/dist/memory/preferences/user-preferences-manager.d.ts.map +1 -1
- package/dist/memory/preferences/user-preferences-manager.js +11 -1
- package/dist/memory/stores/episodic-memory.js +2 -2
- package/dist/memory/stores/working-memory.d.ts +7 -2
- package/dist/memory/stores/working-memory.d.ts.map +1 -1
- package/dist/memory/stores/working-memory.js +31 -17
- package/dist/memory/sync/index.d.ts +2 -0
- package/dist/memory/sync/index.d.ts.map +1 -0
- package/dist/memory/sync/index.js +1 -0
- package/dist/memory/sync/sync-manager.d.ts +104 -0
- package/dist/memory/sync/sync-manager.d.ts.map +1 -0
- package/dist/memory/sync/sync-manager.js +137 -0
- package/dist/memory/utils/validation.js +1 -1
- package/dist/memory/vector/vector-memory-service.d.ts +1 -1
- package/dist/memory/vector/vector-memory-service.js +1 -1
- package/dist/orchestration/agent.d.ts +2 -2
- package/dist/orchestration/defaults.d.ts +1 -1
- package/dist/orchestration/defaults.js +1 -1
- package/dist/orchestration/orchestrator.d.ts +3 -3
- package/dist/orchestration/orchestrator.js +3 -3
- package/dist/orchestration/runtime.d.ts +1 -1
- package/dist/orchestration/runtime.js +1 -1
- package/dist/orchestration/streaming-runtime.d.ts +2 -2
- package/dist/orchestration/streaming-runtime.js +2 -2
- package/dist/orchestration/ticket-agent.d.ts +11 -11
- package/dist/orchestration/ticket-agent.d.ts.map +1 -1
- package/dist/orchestration/ticket-agent.js +10 -10
- package/dist/skills/catalog/vercel-catalog.d.ts.map +1 -1
- package/dist/skills/catalog/vercel-catalog.js +7 -4
- package/dist/skills/loader/github-loader.d.ts.map +1 -1
- package/dist/skills/loader/github-loader.js +2 -0
- package/dist/skills/loader/local-loader.js +1 -1
- package/dist/skills/loader/vercel-loader.d.ts.map +1 -1
- package/dist/skills/loader/vercel-loader.js +2 -0
- package/dist/skills/parser/skill-md-parser.js +2 -2
- package/dist/skills/registry/skill-registry.js +1 -1
- package/dist/templates/prompt-spec.js +1 -1
- package/dist/templates/skill-spec.js +1 -1
- package/dist/tools/{cms → admin}/collection-tools.d.ts +2 -2
- package/dist/tools/admin/collection-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/collection-tools.js +8 -8
- package/dist/tools/{cms → admin}/factory.d.ts +11 -11
- package/dist/tools/admin/factory.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/factory.js +4 -4
- package/dist/tools/{cms → admin}/global-tools.d.ts +1 -1
- package/dist/tools/admin/global-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/global-tools.js +4 -4
- package/dist/tools/{cms → admin}/index.d.ts +4 -4
- package/dist/tools/admin/index.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/index.js +3 -3
- package/dist/tools/{cms → admin}/media-tools.d.ts +1 -1
- package/dist/tools/admin/media-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/media-tools.js +4 -4
- package/dist/tools/{cms → admin}/user-tools.d.ts +1 -1
- package/dist/tools/admin/user-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/user-tools.js +1 -1
- package/dist/tools/coding/file-edit.d.ts +1 -1
- package/dist/tools/coding/file-edit.js +2 -2
- package/dist/tools/coding/file-glob.d.ts +1 -1
- package/dist/tools/coding/file-glob.d.ts.map +1 -1
- package/dist/tools/coding/file-glob.js +2 -1
- package/dist/tools/coding/file-grep.d.ts +1 -1
- package/dist/tools/coding/file-grep.d.ts.map +1 -1
- package/dist/tools/coding/file-grep.js +2 -1
- package/dist/tools/coding/file-read.d.ts +1 -1
- package/dist/tools/coding/file-read.d.ts.map +1 -1
- package/dist/tools/coding/file-read.js +15 -9
- package/dist/tools/coding/file-write.d.ts +1 -1
- package/dist/tools/coding/file-write.js +1 -1
- package/dist/tools/coding/git-ops.d.ts +1 -1
- package/dist/tools/coding/git-ops.d.ts.map +1 -1
- package/dist/tools/coding/git-ops.js +5 -7
- package/dist/tools/coding/index.d.ts +1 -1
- package/dist/tools/coding/index.d.ts.map +1 -1
- package/dist/tools/coding/lint-fix.d.ts +1 -1
- package/dist/tools/coding/lint-fix.d.ts.map +1 -1
- package/dist/tools/coding/lint-fix.js +8 -4
- package/dist/tools/coding/project-context.d.ts +1 -1
- package/dist/tools/coding/project-context.d.ts.map +1 -1
- package/dist/tools/coding/project-context.js +25 -24
- package/dist/tools/coding/safety.d.ts +1 -1
- package/dist/tools/coding/safety.d.ts.map +1 -1
- package/dist/tools/coding/shell-exec.d.ts +1 -1
- package/dist/tools/coding/shell-exec.js +1 -1
- package/dist/tools/coding/test-runner.d.ts +1 -1
- package/dist/tools/coding/test-runner.d.ts.map +1 -1
- package/dist/tools/coding/test-runner.js +12 -7
- package/dist/tools/deduplicator.js +1 -1
- package/dist/tools/document-summarizer.js +2 -2
- package/dist/tools/memory/store-memory.d.ts +1 -1
- package/dist/tools/memory/store-memory.js +2 -2
- package/dist/tools/ticket-tools.d.ts +2 -2
- package/dist/tools/ticket-tools.js +3 -3
- package/dist/tools/web/duck-duck-go.d.ts +3 -3
- package/dist/tools/web/duck-duck-go.js +4 -4
- package/dist/tools/web/exa.d.ts +1 -1
- package/dist/tools/web/exa.js +1 -1
- package/dist/tools/web/scraper.js +1 -1
- package/dist/tools/web/tavily.d.ts +2 -2
- package/dist/tools/web/tavily.js +2 -2
- package/dist/tools/web/types.d.ts +2 -2
- package/dist/tools/web/types.js +2 -2
- package/package.json +20 -15
- package/dist/ingestion/cms-indexer.d.ts.map +0 -1
- package/dist/llm/providers/bitnet.d.ts +0 -28
- package/dist/llm/providers/bitnet.d.ts.map +0 -1
- package/dist/llm/providers/bitnet.js +0 -36
- package/dist/tools/cms/collection-tools.d.ts.map +0 -1
- package/dist/tools/cms/factory.d.ts.map +0 -1
- package/dist/tools/cms/global-tools.d.ts.map +0 -1
- package/dist/tools/cms/index.d.ts.map +0 -1
- package/dist/tools/cms/media-tools.d.ts.map +0 -1
- package/dist/tools/cms/user-tools.d.ts.map +0 -1
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
import { randomUUID } from 'node:crypto';
|
|
8
8
|
import { agentContexts, crdtOperations } from '@revealui/db/schema';
|
|
9
9
|
import { and, eq, gte } from 'drizzle-orm';
|
|
10
|
+
import { LWWRegister } from '../crdt/lww-register.js';
|
|
11
|
+
import { ORSet } from '../crdt/or-set.js';
|
|
12
|
+
import { PNCounter } from '../crdt/pn-counter.js';
|
|
10
13
|
import { findAgentContextById } from '../utils/sql-helpers.js';
|
|
11
14
|
// =============================================================================
|
|
12
15
|
// CRDT Persistence
|
|
@@ -198,4 +201,68 @@ export class CRDTPersistence {
|
|
|
198
201
|
}
|
|
199
202
|
return result;
|
|
200
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Rebuilds CRDT state by replaying operations from the log.
|
|
206
|
+
*
|
|
207
|
+
* @param crdtId - CRDT instance identifier
|
|
208
|
+
* @param crdtType - Type of CRDT to rebuild
|
|
209
|
+
* @param nodeId - Node ID for the rebuilt CRDT
|
|
210
|
+
* @param since - Optional timestamp to replay from (defaults to 0 = all)
|
|
211
|
+
* @returns Rebuilt CRDT instance, or null if no operations found
|
|
212
|
+
*/
|
|
213
|
+
async replayOperations(crdtId, crdtType, nodeId, since = 0) {
|
|
214
|
+
const operations = await this.getOperationsSince(crdtId, since);
|
|
215
|
+
if (operations.length === 0) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
if (crdtType === 'lww_register') {
|
|
219
|
+
const register = new LWWRegister(nodeId, null, 0);
|
|
220
|
+
for (const op of operations) {
|
|
221
|
+
if (op.operationType === 'set') {
|
|
222
|
+
register.set(op.payload.value, op.timestamp);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return register;
|
|
226
|
+
}
|
|
227
|
+
if (crdtType === 'or_set') {
|
|
228
|
+
const set = new ORSet(nodeId);
|
|
229
|
+
for (const op of operations) {
|
|
230
|
+
if (op.operationType === 'add') {
|
|
231
|
+
set.add(op.payload.value);
|
|
232
|
+
}
|
|
233
|
+
else if (op.operationType === 'remove' && typeof op.payload.tag === 'string') {
|
|
234
|
+
set.remove(op.payload.tag);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return set;
|
|
238
|
+
}
|
|
239
|
+
if (crdtType === 'pn_counter') {
|
|
240
|
+
const counter = new PNCounter(nodeId);
|
|
241
|
+
for (const op of operations) {
|
|
242
|
+
if (op.operationType === 'increment') {
|
|
243
|
+
counter.increment(typeof op.payload.delta === 'number' ? op.payload.delta : 1);
|
|
244
|
+
}
|
|
245
|
+
else if (op.operationType === 'decrement') {
|
|
246
|
+
counter.decrement(typeof op.payload.delta === 'number' ? op.payload.delta : 1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return counter;
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Deletes operations older than a timestamp (for cleanup after compaction).
|
|
255
|
+
*
|
|
256
|
+
* @param crdtId - CRDT instance identifier
|
|
257
|
+
* @param before - Unix timestamp (milliseconds) - delete operations older than this
|
|
258
|
+
* @returns Number of operations deleted
|
|
259
|
+
*/
|
|
260
|
+
async deleteOperationsBefore(crdtId, before) {
|
|
261
|
+
const { lt } = await import('drizzle-orm');
|
|
262
|
+
const result = await this.db
|
|
263
|
+
.delete(crdtOperations)
|
|
264
|
+
.where(and(eq(crdtOperations.crdtId, crdtId), lt(crdtOperations.timestamp, before)))
|
|
265
|
+
.returning();
|
|
266
|
+
return result.length;
|
|
267
|
+
}
|
|
201
268
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-preferences-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/preferences/user-preferences-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAe5E;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAkD;IAEhE;;;;;;OAMG;gBACS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;IAcxD;;;;OAIG;IACH,cAAc,IAAI,eAAe;IAIjC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAsB1D;;;;OAIG;IACH,cAAc,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI;IAUlD;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"user-preferences-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/preferences/user-preferences-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAe5E;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAkD;IAEhE;;;;;;OAMG;gBACS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;IAcxD;;;;OAIG;IACH,cAAc,IAAI,eAAe;IAIjC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAsB1D;;;;OAIG;IACH,cAAc,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI;IAUlD;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAkBnC;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAyChD;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB;IAM5D;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoF3B;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+E3B;;;;OAIG;IACH,MAAM,IAAI,eAAe,CAAC,eAAe,CAAC;IAI1C;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CACb,IAAI,EAAE,eAAe,CAAC,eAAe,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,QAAQ,GACX,sBAAsB;IAMzB;;;;OAIG;IACH,KAAK,IAAI,sBAAsB;IAI/B;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB"}
|
|
@@ -114,7 +114,10 @@ export class UserPreferencesManager {
|
|
|
114
114
|
const keys = key.split('.');
|
|
115
115
|
let value = prefs;
|
|
116
116
|
for (const k of keys) {
|
|
117
|
-
|
|
117
|
+
// Guard against prototype pollution reads
|
|
118
|
+
if (k === '__proto__' || k === 'constructor' || k === 'prototype')
|
|
119
|
+
return undefined;
|
|
120
|
+
if (value && typeof value === 'object' && Object.hasOwn(value, k)) {
|
|
118
121
|
value = value[k];
|
|
119
122
|
}
|
|
120
123
|
else {
|
|
@@ -138,6 +141,13 @@ export class UserPreferencesManager {
|
|
|
138
141
|
throw new ValidationError(`Invalid preference key: "${key}"`);
|
|
139
142
|
}
|
|
140
143
|
const parentKeys = keys.slice(0, -1);
|
|
144
|
+
// Guard against prototype pollution
|
|
145
|
+
const ForbiddenKeys = new Set(['__proto__', 'constructor', 'prototype']);
|
|
146
|
+
for (const k of keys) {
|
|
147
|
+
if (ForbiddenKeys.has(k)) {
|
|
148
|
+
throw new ValidationError(`Forbidden preference key segment: "${k}"`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
141
151
|
// Navigate to parent object in cloned structure
|
|
142
152
|
let parent = prefs;
|
|
143
153
|
for (const k of parentKeys) {
|
|
@@ -268,9 +268,9 @@ export class EpisodicMemory {
|
|
|
268
268
|
}
|
|
269
269
|
catch (error) {
|
|
270
270
|
// Embedding generation failed (e.g. embedding service unavailable).
|
|
271
|
-
// Return empty results
|
|
271
|
+
// Return empty results - do NOT fall back to getAll(), which would dump the
|
|
272
272
|
// entire memory store into agent context regardless of relevance.
|
|
273
|
-
void (error instanceof Error ? error.message : String(error)); // Semantic search failed
|
|
273
|
+
void (error instanceof Error ? error.message : String(error)); // Semantic search failed - return empty results
|
|
274
274
|
return [];
|
|
275
275
|
}
|
|
276
276
|
}
|
|
@@ -12,6 +12,7 @@ import type { AgentDefinition } from '@revealui/contracts/agents';
|
|
|
12
12
|
import { type LWWRegisterData } from '../crdt/lww-register.js';
|
|
13
13
|
import { type ORSetData } from '../crdt/or-set.js';
|
|
14
14
|
import type { CRDTPersistence } from '../persistence/crdt-persistence.js';
|
|
15
|
+
import type { SyncManager } from '../sync/sync-manager.js';
|
|
15
16
|
export interface SessionState {
|
|
16
17
|
status: 'active' | 'paused' | 'completed';
|
|
17
18
|
focus?: {
|
|
@@ -56,19 +57,23 @@ export declare class WorkingMemory {
|
|
|
56
57
|
private sessionId;
|
|
57
58
|
private nodeId;
|
|
58
59
|
private persistence?;
|
|
60
|
+
private syncManager?;
|
|
59
61
|
/**
|
|
60
62
|
* Creates a new WorkingMemory instance.
|
|
61
63
|
*
|
|
62
64
|
* @param sessionId - Unique session identifier
|
|
63
65
|
* @param nodeId - Unique node identifier (for CRDT operations)
|
|
64
66
|
* @param persistence - Optional persistence adapter
|
|
67
|
+
* @param syncManager - Optional sync manager for operation logging
|
|
65
68
|
*/
|
|
66
|
-
constructor(sessionId: string, nodeId: string, persistence?: CRDTPersistence);
|
|
69
|
+
constructor(sessionId: string, nodeId: string, persistence?: CRDTPersistence, syncManager?: SyncManager);
|
|
67
70
|
/**
|
|
68
71
|
* Sets the entire context object.
|
|
69
72
|
*
|
|
70
73
|
* @param context - Context data to set
|
|
71
74
|
*/
|
|
75
|
+
/** Logs a CRDT operation to the sync manager (fire-and-forget). */
|
|
76
|
+
private logOp;
|
|
72
77
|
/**
|
|
73
78
|
* Sets the entire context object.
|
|
74
79
|
*
|
|
@@ -199,7 +204,7 @@ export declare class WorkingMemory {
|
|
|
199
204
|
* @param persistence - Optional persistence adapter
|
|
200
205
|
* @returns New WorkingMemory instance
|
|
201
206
|
*/
|
|
202
|
-
static fromData(data: WorkingMemoryData, persistence?: CRDTPersistence): WorkingMemory;
|
|
207
|
+
static fromData(data: WorkingMemoryData, persistence?: CRDTPersistence, syncManager?: SyncManager): WorkingMemory;
|
|
203
208
|
/**
|
|
204
209
|
* Creates a copy of this WorkingMemory.
|
|
205
210
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"working-memory.d.ts","sourceRoot":"","sources":["../../../src/memory/stores/working-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"working-memory.d.ts","sourceRoot":"","sources":["../../../src/memory/stores/working-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,17 +36,20 @@ export class WorkingMemory {
|
|
|
36
36
|
sessionId;
|
|
37
37
|
nodeId;
|
|
38
38
|
persistence;
|
|
39
|
+
syncManager;
|
|
39
40
|
/**
|
|
40
41
|
* Creates a new WorkingMemory instance.
|
|
41
42
|
*
|
|
42
43
|
* @param sessionId - Unique session identifier
|
|
43
44
|
* @param nodeId - Unique node identifier (for CRDT operations)
|
|
44
45
|
* @param persistence - Optional persistence adapter
|
|
46
|
+
* @param syncManager - Optional sync manager for operation logging
|
|
45
47
|
*/
|
|
46
|
-
constructor(sessionId, nodeId, persistence) {
|
|
48
|
+
constructor(sessionId, nodeId, persistence, syncManager) {
|
|
47
49
|
this.sessionId = sessionId;
|
|
48
50
|
this.nodeId = nodeId;
|
|
49
51
|
this.persistence = persistence;
|
|
52
|
+
this.syncManager = syncManager;
|
|
50
53
|
// Initialize CRDTs
|
|
51
54
|
this.context = new LWWRegister(nodeId, {});
|
|
52
55
|
this.sessionState = new LWWRegister(nodeId, {
|
|
@@ -59,6 +62,13 @@ export class WorkingMemory {
|
|
|
59
62
|
*
|
|
60
63
|
* @param context - Context data to set
|
|
61
64
|
*/
|
|
65
|
+
/** Logs a CRDT operation to the sync manager (fire-and-forget). */
|
|
66
|
+
logOp(crdtType, operationType, payload) {
|
|
67
|
+
if (!this.syncManager)
|
|
68
|
+
return;
|
|
69
|
+
const crdtId = `working-memory:${this.sessionId}`;
|
|
70
|
+
void this.syncManager.logOperation(crdtId, crdtType, operationType, payload);
|
|
71
|
+
}
|
|
62
72
|
/**
|
|
63
73
|
* Sets the entire context object.
|
|
64
74
|
*
|
|
@@ -72,6 +82,7 @@ export class WorkingMemory {
|
|
|
72
82
|
*/
|
|
73
83
|
setContext(context) {
|
|
74
84
|
this.context.set(context);
|
|
85
|
+
this.logOp('lww_register', 'set', { value: context, key: 'context' });
|
|
75
86
|
}
|
|
76
87
|
/**
|
|
77
88
|
* Gets the current context.
|
|
@@ -89,10 +100,9 @@ export class WorkingMemory {
|
|
|
89
100
|
*/
|
|
90
101
|
updateContext(updates) {
|
|
91
102
|
const current = this.context.get();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
});
|
|
103
|
+
const merged = { ...current, ...updates };
|
|
104
|
+
this.context.set(merged);
|
|
105
|
+
this.logOp('lww_register', 'set', { value: merged, key: 'context' });
|
|
96
106
|
}
|
|
97
107
|
/**
|
|
98
108
|
* Gets a specific context value.
|
|
@@ -131,10 +141,9 @@ export class WorkingMemory {
|
|
|
131
141
|
*/
|
|
132
142
|
setContextValue(key, value) {
|
|
133
143
|
const current = this.context.get();
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
});
|
|
144
|
+
const updated = { ...current, [key]: value };
|
|
145
|
+
this.context.set(updated);
|
|
146
|
+
this.logOp('lww_register', 'set', { value: updated, key: 'context' });
|
|
138
147
|
}
|
|
139
148
|
/**
|
|
140
149
|
* Adds an agent to the active agents set.
|
|
@@ -143,7 +152,9 @@ export class WorkingMemory {
|
|
|
143
152
|
* @returns Unique tag for this agent addition
|
|
144
153
|
*/
|
|
145
154
|
addAgent(agent) {
|
|
146
|
-
|
|
155
|
+
const tag = this.activeAgents.add(agent);
|
|
156
|
+
this.logOp('or_set', 'add', { value: agent, tag });
|
|
157
|
+
return tag;
|
|
147
158
|
}
|
|
148
159
|
/**
|
|
149
160
|
* Removes an agent by tag.
|
|
@@ -152,7 +163,11 @@ export class WorkingMemory {
|
|
|
152
163
|
* @returns true if agent was removed
|
|
153
164
|
*/
|
|
154
165
|
removeAgent(tag) {
|
|
155
|
-
|
|
166
|
+
const removed = this.activeAgents.remove(tag);
|
|
167
|
+
if (removed) {
|
|
168
|
+
this.logOp('or_set', 'remove', { tag });
|
|
169
|
+
}
|
|
170
|
+
return removed;
|
|
156
171
|
}
|
|
157
172
|
/**
|
|
158
173
|
* Removes an agent by ID (removes all instances).
|
|
@@ -201,10 +216,9 @@ export class WorkingMemory {
|
|
|
201
216
|
*/
|
|
202
217
|
updateSessionState(state) {
|
|
203
218
|
const current = this.sessionState.get();
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
});
|
|
219
|
+
const merged = { ...current, ...state };
|
|
220
|
+
this.sessionState.set(merged);
|
|
221
|
+
this.logOp('lww_register', 'set', { value: merged, key: 'sessionState' });
|
|
208
222
|
}
|
|
209
223
|
/**
|
|
210
224
|
* Gets the current session state.
|
|
@@ -297,8 +311,8 @@ export class WorkingMemory {
|
|
|
297
311
|
* @param persistence - Optional persistence adapter
|
|
298
312
|
* @returns New WorkingMemory instance
|
|
299
313
|
*/
|
|
300
|
-
static fromData(data, persistence) {
|
|
301
|
-
const memory = new WorkingMemory(data.sessionId, data.nodeId, persistence);
|
|
314
|
+
static fromData(data, persistence, syncManager) {
|
|
315
|
+
const memory = new WorkingMemory(data.sessionId, data.nodeId, persistence, syncManager);
|
|
302
316
|
memory.context = LWWRegister.fromData(data.context);
|
|
303
317
|
memory.sessionState = LWWRegister.fromData(data.sessionState);
|
|
304
318
|
memory.activeAgents = ORSet.fromData(data.activeAgents);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/memory/sync/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SyncManager } from './sync-manager.js';
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRDT Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Coordinates state synchronization between distributed nodes.
|
|
5
|
+
* Supports both full-state merge and delta-based sync via the operation log.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - State-based sync: serialize → transfer → merge (simple, higher bandwidth)
|
|
9
|
+
* - Op-based sync: log ops → transfer deltas → replay (efficient, requires op log)
|
|
10
|
+
* - Anti-entropy: periodic full-state reconciliation to catch missed ops
|
|
11
|
+
*
|
|
12
|
+
* Transport-agnostic: the SyncManager produces/consumes serialized payloads.
|
|
13
|
+
* The actual transport (HTTP, WebSocket, message queue) is the caller's concern.
|
|
14
|
+
*/
|
|
15
|
+
import type { LWWRegisterData } from '../crdt/lww-register.js';
|
|
16
|
+
import type { ORSetData } from '../crdt/or-set.js';
|
|
17
|
+
import type { PNCounterData } from '../crdt/pn-counter.js';
|
|
18
|
+
import type { CRDTOperationPayload, CRDTPersistence, CRDTType } from '../persistence/crdt-persistence.js';
|
|
19
|
+
import type { WorkingMemory } from '../stores/working-memory.js';
|
|
20
|
+
export interface SyncState {
|
|
21
|
+
/** CRDT instance identifier */
|
|
22
|
+
crdtId: string;
|
|
23
|
+
/** Node that produced this state */
|
|
24
|
+
sourceNodeId: string;
|
|
25
|
+
/** Timestamp of this state snapshot */
|
|
26
|
+
timestamp: number;
|
|
27
|
+
/** Serialized CRDT states (composite) */
|
|
28
|
+
states: Record<string, LWWRegisterData<unknown> | ORSetData<unknown> | PNCounterData>;
|
|
29
|
+
}
|
|
30
|
+
export interface SyncDelta {
|
|
31
|
+
/** CRDT instance identifier */
|
|
32
|
+
crdtId: string;
|
|
33
|
+
/** Node that produced these operations */
|
|
34
|
+
sourceNodeId: string;
|
|
35
|
+
/** Operations since last sync point */
|
|
36
|
+
operations: CRDTOperationPayload[];
|
|
37
|
+
/** Timestamp of the last synced operation (for next delta request) */
|
|
38
|
+
lastSyncTimestamp: number;
|
|
39
|
+
}
|
|
40
|
+
export interface SyncResult {
|
|
41
|
+
/** Whether state changed as a result of sync */
|
|
42
|
+
changed: boolean;
|
|
43
|
+
/** Number of operations applied */
|
|
44
|
+
operationsApplied: number;
|
|
45
|
+
/** Number of conflicts resolved */
|
|
46
|
+
conflictsResolved: number;
|
|
47
|
+
/** Timestamp to use for next delta sync */
|
|
48
|
+
syncTimestamp: number;
|
|
49
|
+
}
|
|
50
|
+
export declare class SyncManager {
|
|
51
|
+
private nodeId;
|
|
52
|
+
private persistence;
|
|
53
|
+
/** Tracks the last sync timestamp per remote node */
|
|
54
|
+
private syncPoints;
|
|
55
|
+
constructor(nodeId: string, persistence: CRDTPersistence);
|
|
56
|
+
/**
|
|
57
|
+
* Produces a full-state snapshot for transfer to another node.
|
|
58
|
+
* The receiving node calls `mergeRemoteState()` with this payload.
|
|
59
|
+
*/
|
|
60
|
+
getLocalState(crdtId: string): Promise<SyncState>;
|
|
61
|
+
/**
|
|
62
|
+
* Merges a remote node's full state into local state.
|
|
63
|
+
* Uses CRDT merge semantics - order doesn't matter, result is deterministic.
|
|
64
|
+
*
|
|
65
|
+
* @returns WorkingMemory with merged state (caller decides whether to persist)
|
|
66
|
+
*/
|
|
67
|
+
mergeRemoteWorkingMemory(local: WorkingMemory, remote: WorkingMemory): {
|
|
68
|
+
merged: WorkingMemory;
|
|
69
|
+
changed: boolean;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Produces a delta payload (operations since a timestamp) for efficient sync.
|
|
73
|
+
* The receiving node calls `applyDelta()` with this payload.
|
|
74
|
+
*/
|
|
75
|
+
getDelta(crdtId: string, since: number): Promise<SyncDelta>;
|
|
76
|
+
/**
|
|
77
|
+
* Applies a delta from a remote node by replaying operations.
|
|
78
|
+
* Logs each remote operation locally for future delta requests from other nodes.
|
|
79
|
+
*/
|
|
80
|
+
applyDelta(delta: SyncDelta): Promise<SyncResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Logs a local operation to the persistence layer.
|
|
83
|
+
* Called by memory stores when they mutate CRDT state.
|
|
84
|
+
*/
|
|
85
|
+
logOperation(crdtId: string, crdtType: CRDTType, operationType: CRDTOperationPayload['operationType'], payload: Record<string, unknown>): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Gets the last sync timestamp for a remote node.
|
|
88
|
+
* Used to request only new operations on the next sync.
|
|
89
|
+
*/
|
|
90
|
+
getSyncPoint(remoteNodeId: string): number;
|
|
91
|
+
/**
|
|
92
|
+
* Sets the sync point for a remote node (e.g., after initial full-state sync).
|
|
93
|
+
*/
|
|
94
|
+
setSyncPoint(remoteNodeId: string, timestamp: number): void;
|
|
95
|
+
/**
|
|
96
|
+
* Gets all tracked sync points.
|
|
97
|
+
*/
|
|
98
|
+
getAllSyncPoints(): Map<string, number>;
|
|
99
|
+
/**
|
|
100
|
+
* Gets this manager's node ID.
|
|
101
|
+
*/
|
|
102
|
+
getNodeId(): string;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=sync-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/sync/sync-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,QAAQ,EACT,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAMjE,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,CAAC;CACvF;AAED,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;CACvB;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAkB;IACrC,qDAAqD;IACrD,OAAO,CAAC,UAAU,CAAkC;gBAExC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe;IAKxD;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAmBvD;;;;;OAKG;IACH,wBAAwB,CACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,aAAa,GACpB;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAgB9C;;;OAGG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAYjE;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IAyBvD;;;OAGG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,oBAAoB,CAAC,eAAe,CAAC,EACpD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAWhB;;;OAGG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAI1C;;OAEG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI3D;;OAEG;IACH,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIvC;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRDT Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Coordinates state synchronization between distributed nodes.
|
|
5
|
+
* Supports both full-state merge and delta-based sync via the operation log.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - State-based sync: serialize → transfer → merge (simple, higher bandwidth)
|
|
9
|
+
* - Op-based sync: log ops → transfer deltas → replay (efficient, requires op log)
|
|
10
|
+
* - Anti-entropy: periodic full-state reconciliation to catch missed ops
|
|
11
|
+
*
|
|
12
|
+
* Transport-agnostic: the SyncManager produces/consumes serialized payloads.
|
|
13
|
+
* The actual transport (HTTP, WebSocket, message queue) is the caller's concern.
|
|
14
|
+
*/
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// SyncManager
|
|
17
|
+
// =============================================================================
|
|
18
|
+
export class SyncManager {
|
|
19
|
+
nodeId;
|
|
20
|
+
persistence;
|
|
21
|
+
/** Tracks the last sync timestamp per remote node */
|
|
22
|
+
syncPoints = new Map();
|
|
23
|
+
constructor(nodeId, persistence) {
|
|
24
|
+
this.nodeId = nodeId;
|
|
25
|
+
this.persistence = persistence;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Produces a full-state snapshot for transfer to another node.
|
|
29
|
+
* The receiving node calls `mergeRemoteState()` with this payload.
|
|
30
|
+
*/
|
|
31
|
+
async getLocalState(crdtId) {
|
|
32
|
+
const states = await this.persistence.loadCompositeState(crdtId);
|
|
33
|
+
const stateRecord = {};
|
|
34
|
+
for (const [key, data] of states) {
|
|
35
|
+
stateRecord[key] = data;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
crdtId,
|
|
39
|
+
sourceNodeId: this.nodeId,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
states: stateRecord,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Merges a remote node's full state into local state.
|
|
46
|
+
* Uses CRDT merge semantics - order doesn't matter, result is deterministic.
|
|
47
|
+
*
|
|
48
|
+
* @returns WorkingMemory with merged state (caller decides whether to persist)
|
|
49
|
+
*/
|
|
50
|
+
mergeRemoteWorkingMemory(local, remote) {
|
|
51
|
+
const localData = local.toData();
|
|
52
|
+
const remoteData = remote.toData();
|
|
53
|
+
// Quick equality check - if timestamps match, nothing changed
|
|
54
|
+
if (localData.context.timestamp === remoteData.context.timestamp &&
|
|
55
|
+
localData.sessionState.timestamp === remoteData.sessionState.timestamp) {
|
|
56
|
+
return { merged: local, changed: false };
|
|
57
|
+
}
|
|
58
|
+
const merged = local.merge(remote);
|
|
59
|
+
return { merged, changed: true };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Produces a delta payload (operations since a timestamp) for efficient sync.
|
|
63
|
+
* The receiving node calls `applyDelta()` with this payload.
|
|
64
|
+
*/
|
|
65
|
+
async getDelta(crdtId, since) {
|
|
66
|
+
const operations = await this.persistence.getOperationsSince(crdtId, since);
|
|
67
|
+
return {
|
|
68
|
+
crdtId,
|
|
69
|
+
sourceNodeId: this.nodeId,
|
|
70
|
+
operations,
|
|
71
|
+
lastSyncTimestamp: operations.length > 0 ? (operations[operations.length - 1]?.timestamp ?? since) : since,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Applies a delta from a remote node by replaying operations.
|
|
76
|
+
* Logs each remote operation locally for future delta requests from other nodes.
|
|
77
|
+
*/
|
|
78
|
+
async applyDelta(delta) {
|
|
79
|
+
let applied = 0;
|
|
80
|
+
for (const op of delta.operations) {
|
|
81
|
+
// Skip operations from our own node (already applied locally)
|
|
82
|
+
if (op.nodeId === this.nodeId) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
// Log the remote operation locally
|
|
86
|
+
await this.persistence.appendOperation(op);
|
|
87
|
+
applied++;
|
|
88
|
+
}
|
|
89
|
+
// Update sync point for this remote node
|
|
90
|
+
this.syncPoints.set(delta.sourceNodeId, delta.lastSyncTimestamp);
|
|
91
|
+
return {
|
|
92
|
+
changed: applied > 0,
|
|
93
|
+
operationsApplied: applied,
|
|
94
|
+
conflictsResolved: 0, // CRDTs resolve conflicts automatically
|
|
95
|
+
syncTimestamp: delta.lastSyncTimestamp,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Logs a local operation to the persistence layer.
|
|
100
|
+
* Called by memory stores when they mutate CRDT state.
|
|
101
|
+
*/
|
|
102
|
+
async logOperation(crdtId, crdtType, operationType, payload) {
|
|
103
|
+
await this.persistence.appendOperation({
|
|
104
|
+
crdtId,
|
|
105
|
+
crdtType,
|
|
106
|
+
operationType,
|
|
107
|
+
payload,
|
|
108
|
+
nodeId: this.nodeId,
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Gets the last sync timestamp for a remote node.
|
|
114
|
+
* Used to request only new operations on the next sync.
|
|
115
|
+
*/
|
|
116
|
+
getSyncPoint(remoteNodeId) {
|
|
117
|
+
return this.syncPoints.get(remoteNodeId) ?? 0;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Sets the sync point for a remote node (e.g., after initial full-state sync).
|
|
121
|
+
*/
|
|
122
|
+
setSyncPoint(remoteNodeId, timestamp) {
|
|
123
|
+
this.syncPoints.set(remoteNodeId, timestamp);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets all tracked sync points.
|
|
127
|
+
*/
|
|
128
|
+
getAllSyncPoints() {
|
|
129
|
+
return new Map(this.syncPoints);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Gets this manager's node ID.
|
|
133
|
+
*/
|
|
134
|
+
getNodeId() {
|
|
135
|
+
return this.nodeId;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -118,7 +118,7 @@ export function estimateObjectSize(obj) {
|
|
|
118
118
|
const type = typeof obj;
|
|
119
119
|
if (type === 'string') {
|
|
120
120
|
// UTF-16 char units × 2 bytes each. This over-estimates multi-byte UTF-8 code
|
|
121
|
-
// points but is intentionally conservative
|
|
121
|
+
// points but is intentionally conservative - the limit stays tighter than the
|
|
122
122
|
// real in-process memory cost, which is what we want for a safety bound.
|
|
123
123
|
return obj.length * 2 + 8;
|
|
124
124
|
}
|
|
@@ -41,7 +41,7 @@ export declare class VectorMemoryService {
|
|
|
41
41
|
/**
|
|
42
42
|
* Search for similar memories using vector similarity.
|
|
43
43
|
*
|
|
44
|
-
* @param queryEmbedding - Query embedding vector (768 dimensions
|
|
44
|
+
* @param queryEmbedding - Query embedding vector (768 dimensions - Ollama nomic-embed-text)
|
|
45
45
|
* @param options - Search options (filtering, limits, etc.)
|
|
46
46
|
* @returns Array of memories with similarity scores, sorted by similarity (highest first)
|
|
47
47
|
*
|
|
@@ -42,7 +42,7 @@ export class VectorMemoryService {
|
|
|
42
42
|
/**
|
|
43
43
|
* Search for similar memories using vector similarity.
|
|
44
44
|
*
|
|
45
|
-
* @param queryEmbedding - Query embedding vector (768 dimensions
|
|
45
|
+
* @param queryEmbedding - Query embedding vector (768 dimensions - Ollama nomic-embed-text)
|
|
46
46
|
* @param options - Search options (filtering, limits, etc.)
|
|
47
47
|
* @returns Array of memories with similarity scores, sorted by similarity (highest first)
|
|
48
48
|
*
|
|
@@ -22,7 +22,7 @@ export interface AgentConfig {
|
|
|
22
22
|
webSearchProvider?: WebSearchProvider;
|
|
23
23
|
/**
|
|
24
24
|
* Capability tags used by AgentOrchestrator.findBestAgent() for routing.
|
|
25
|
-
* Example: ['
|
|
25
|
+
* Example: ['admin', 'search', 'ticket', 'summarize']
|
|
26
26
|
*/
|
|
27
27
|
capabilities?: string[];
|
|
28
28
|
}
|
|
@@ -70,7 +70,7 @@ export interface Agent {
|
|
|
70
70
|
*/
|
|
71
71
|
tools: Tool[];
|
|
72
72
|
/**
|
|
73
|
-
* Memory system (optional
|
|
73
|
+
* Memory system (optional - agents without memory skip episodic recall)
|
|
74
74
|
*/
|
|
75
75
|
memory?: EpisodicMemory;
|
|
76
76
|
/**
|
|
@@ -15,7 +15,7 @@ import type { Tool } from '../tools/base.js';
|
|
|
15
15
|
export declare const WORKSPACE_AGENT_DEFAULT_TOOLS: Tool[];
|
|
16
16
|
/**
|
|
17
17
|
* Returns the workspace agent default tool set, optionally merged with
|
|
18
|
-
* additional tools (e.g.
|
|
18
|
+
* additional tools (e.g. admin tools, MCP-discovered tools).
|
|
19
19
|
*/
|
|
20
20
|
export declare function getWorkspaceAgentTools(additionalTools?: Tool[]): Tool[];
|
|
21
21
|
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -15,7 +15,7 @@ import { webSearchTool } from '../tools/web/index.js';
|
|
|
15
15
|
export const WORKSPACE_AGENT_DEFAULT_TOOLS = [webSearchTool];
|
|
16
16
|
/**
|
|
17
17
|
* Returns the workspace agent default tool set, optionally merged with
|
|
18
|
-
* additional tools (e.g.
|
|
18
|
+
* additional tools (e.g. admin tools, MCP-discovered tools).
|
|
19
19
|
*/
|
|
20
20
|
export function getWorkspaceAgentTools(additionalTools = []) {
|
|
21
21
|
return [...WORKSPACE_AGENT_DEFAULT_TOOLS, ...additionalTools];
|
|
@@ -51,11 +51,11 @@ export declare class AgentOrchestrator {
|
|
|
51
51
|
* Find the best agent for a task.
|
|
52
52
|
*
|
|
53
53
|
* Routing priority:
|
|
54
|
-
* 1. Capability intersection
|
|
54
|
+
* 1. Capability intersection - agent whose AgentConfig.capabilities overlaps
|
|
55
55
|
* with task.requiredCapabilities (highest-overlap agent wins)
|
|
56
|
-
* 2. Tool-name substring match
|
|
56
|
+
* 2. Tool-name substring match - agent has a tool whose name includes the
|
|
57
57
|
* task type string (legacy fallback)
|
|
58
|
-
* 3. First registered agent
|
|
58
|
+
* 3. First registered agent - last-resort fallback
|
|
59
59
|
*/
|
|
60
60
|
private findBestAgent;
|
|
61
61
|
/**
|