a2a-memory 0.1.1 → 0.5.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.
- package/dist/cli/commands/add.d.ts +8 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +45 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/cleanup.d.ts +8 -0
- package/dist/cli/commands/cleanup.d.ts.map +1 -0
- package/dist/cli/commands/cleanup.js +82 -0
- package/dist/cli/commands/cleanup.js.map +1 -0
- package/dist/cli/commands/edit.d.ts +8 -0
- package/dist/cli/commands/edit.d.ts.map +1 -0
- package/dist/cli/commands/edit.js +66 -0
- package/dist/cli/commands/edit.js.map +1 -0
- package/dist/cli/commands/embed.d.ts +8 -0
- package/dist/cli/commands/embed.d.ts.map +1 -0
- package/dist/cli/commands/embed.js +93 -0
- package/dist/cli/commands/embed.js.map +1 -0
- package/dist/cli/commands/rm.d.ts +8 -0
- package/dist/cli/commands/rm.d.ts.map +1 -0
- package/dist/cli/commands/rm.js +60 -0
- package/dist/cli/commands/rm.js.map +1 -0
- package/dist/cli/commands/team.d.ts +7 -0
- package/dist/cli/commands/team.d.ts.map +1 -0
- package/dist/cli/commands/team.js +144 -0
- package/dist/cli/commands/team.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +21 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/config/manager.d.ts +7 -0
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +96 -5
- package/dist/config/manager.js.map +1 -1
- package/dist/db/database.d.ts +24 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/database.js +190 -62
- package/dist/db/database.js.map +1 -1
- package/dist/embedding/index.d.ts +20 -0
- package/dist/embedding/index.d.ts.map +1 -0
- package/dist/embedding/index.js +28 -0
- package/dist/embedding/index.js.map +1 -0
- package/dist/embedding/local-provider.d.ts +40 -0
- package/dist/embedding/local-provider.d.ts.map +1 -0
- package/dist/embedding/local-provider.js +157 -0
- package/dist/embedding/local-provider.js.map +1 -0
- package/dist/embedding/openai-provider.d.ts +31 -0
- package/dist/embedding/openai-provider.d.ts.map +1 -0
- package/dist/embedding/openai-provider.js +92 -0
- package/dist/embedding/openai-provider.js.map +1 -0
- package/dist/extraction/extractor.d.ts +11 -1
- package/dist/extraction/extractor.d.ts.map +1 -1
- package/dist/extraction/extractor.js +63 -20
- package/dist/extraction/extractor.js.map +1 -1
- package/dist/extraction/scorer.d.ts +2 -0
- package/dist/extraction/scorer.d.ts.map +1 -1
- package/dist/extraction/scorer.js +23 -1
- package/dist/extraction/scorer.js.map +1 -1
- package/dist/extraction/similarity.d.ts +25 -0
- package/dist/extraction/similarity.d.ts.map +1 -0
- package/dist/extraction/similarity.js +85 -0
- package/dist/extraction/similarity.js.map +1 -0
- package/dist/hooks/post-tool-use.d.ts.map +1 -1
- package/dist/hooks/post-tool-use.js +28 -8
- package/dist/hooks/post-tool-use.js.map +1 -1
- package/dist/hooks/session-end.d.ts +1 -0
- package/dist/hooks/session-end.d.ts.map +1 -1
- package/dist/hooks/session-end.js +134 -11
- package/dist/hooks/session-end.js.map +1 -1
- package/dist/hooks/session-start.d.ts +2 -2
- package/dist/hooks/session-start.d.ts.map +1 -1
- package/dist/hooks/session-start.js +154 -22
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/shared.d.ts +18 -0
- package/dist/hooks/shared.d.ts.map +1 -0
- package/dist/hooks/shared.js +46 -0
- package/dist/hooks/shared.js.map +1 -0
- package/dist/index.d.ts +14 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/cleanup.d.ts +25 -0
- package/dist/lifecycle/cleanup.d.ts.map +1 -0
- package/dist/lifecycle/cleanup.js +52 -0
- package/dist/lifecycle/cleanup.js.map +1 -0
- package/dist/lifecycle/index.d.ts +12 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +10 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle/quality-scorer.d.ts +19 -0
- package/dist/lifecycle/quality-scorer.d.ts.map +1 -0
- package/dist/lifecycle/quality-scorer.js +40 -0
- package/dist/lifecycle/quality-scorer.js.map +1 -0
- package/dist/llm/client.d.ts +37 -0
- package/dist/llm/client.d.ts.map +1 -0
- package/dist/llm/client.js +154 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/llm/index.d.ts +6 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +5 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/search/index.d.ts +8 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +7 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/ranker.d.ts +30 -0
- package/dist/search/ranker.d.ts.map +1 -0
- package/dist/search/ranker.js +91 -0
- package/dist/search/ranker.js.map +1 -0
- package/dist/sync/client.d.ts +85 -0
- package/dist/sync/client.d.ts.map +1 -1
- package/dist/sync/client.js +112 -4
- package/dist/sync/client.js.map +1 -1
- package/dist/sync/index.d.ts +5 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +3 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/queue.d.ts +49 -0
- package/dist/sync/queue.d.ts.map +1 -0
- package/dist/sync/queue.js +112 -0
- package/dist/sync/queue.js.map +1 -0
- package/dist/sync/synchronizer.d.ts +19 -5
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +128 -70
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/sync/team-synchronizer.d.ts +43 -0
- package/dist/sync/team-synchronizer.d.ts.map +1 -0
- package/dist/sync/team-synchronizer.js +126 -0
- package/dist/sync/team-synchronizer.js.map +1 -0
- package/dist/sync/vector-clock.d.ts +23 -0
- package/dist/sync/vector-clock.d.ts.map +1 -0
- package/dist/sync/vector-clock.js +40 -0
- package/dist/sync/vector-clock.js.map +1 -0
- package/dist/types/index.d.ts +42 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +22 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
package/dist/sync/index.d.ts
CHANGED
|
@@ -5,4 +5,9 @@ export { A2AClient } from './client.js';
|
|
|
5
5
|
export type { A2AClientConfig, RemoteMemory } from './client.js';
|
|
6
6
|
export { MemorySynchronizer } from './synchronizer.js';
|
|
7
7
|
export type { SyncResult } from './synchronizer.js';
|
|
8
|
+
export { SyncQueue, mapCategory, mapTier } from './queue.js';
|
|
9
|
+
export type { QueueFlushResult, FlushOptions } from './queue.js';
|
|
10
|
+
export { LocalVectorClock } from './vector-clock.js';
|
|
11
|
+
export { TeamSynchronizer } from './team-synchronizer.js';
|
|
12
|
+
export type { TeamSyncResult, TeamSyncStatus } from './team-synchronizer.js';
|
|
8
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/sync/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/sync/index.js
CHANGED
|
@@ -3,4 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { A2AClient } from './client.js';
|
|
5
5
|
export { MemorySynchronizer } from './synchronizer.js';
|
|
6
|
+
export { SyncQueue, mapCategory, mapTier } from './queue.js';
|
|
7
|
+
export { LocalVectorClock } from './vector-clock.js';
|
|
8
|
+
export { TeamSynchronizer } from './team-synchronizer.js';
|
|
6
9
|
//# sourceMappingURL=index.js.map
|
package/dist/sync/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write-Behind Sync Queue
|
|
3
|
+
*
|
|
4
|
+
* 로컬 DB에 저장된 메모리를 원격 서버로 일괄 push합니다.
|
|
5
|
+
* 로컬 DB = 캐시, 원격 서버 = Single Source of Truth.
|
|
6
|
+
*/
|
|
7
|
+
import type { MemoryDatabase } from '../db/database.js';
|
|
8
|
+
import type { A2AClient } from './client.js';
|
|
9
|
+
import type { MemoryCategory, MemoryTier } from '../types/index.js';
|
|
10
|
+
export interface QueueFlushResult {
|
|
11
|
+
pushed: number;
|
|
12
|
+
failed: number;
|
|
13
|
+
errors: string[];
|
|
14
|
+
duration: number;
|
|
15
|
+
}
|
|
16
|
+
export interface FlushOptions {
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
maxRetries?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 로컬 category를 서버 호환 category로 변환
|
|
22
|
+
*/
|
|
23
|
+
export declare function mapCategory(category: string): MemoryCategory;
|
|
24
|
+
/**
|
|
25
|
+
* 로컬 tier를 서버 호환 tier로 변환
|
|
26
|
+
*/
|
|
27
|
+
export declare function mapTier(tier: string): MemoryTier;
|
|
28
|
+
export declare class SyncQueue {
|
|
29
|
+
private db;
|
|
30
|
+
private client;
|
|
31
|
+
constructor(db: MemoryDatabase, client: A2AClient);
|
|
32
|
+
/**
|
|
33
|
+
* 메모리를 sync 대기 상태로 설정 (~1ms)
|
|
34
|
+
*/
|
|
35
|
+
enqueue(memoryId: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* pending 메모리를 일괄 push
|
|
38
|
+
*/
|
|
39
|
+
flush(options?: FlushOptions): Promise<QueueFlushResult>;
|
|
40
|
+
/**
|
|
41
|
+
* 대기 중인 메모리 수
|
|
42
|
+
*/
|
|
43
|
+
getPendingCount(): number;
|
|
44
|
+
/**
|
|
45
|
+
* 재시도 포함 push (exponential backoff)
|
|
46
|
+
*/
|
|
47
|
+
private retryPush;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/sync/queue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAU,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE5E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAE5D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEhD;AAED,qBAAa,SAAS;IAElB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;gBADN,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,SAAS;IAG3B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0C9D;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;OAEG;YACW,SAAS;CAuBxB"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write-Behind Sync Queue
|
|
3
|
+
*
|
|
4
|
+
* 로컬 DB에 저장된 메모리를 원격 서버로 일괄 push합니다.
|
|
5
|
+
* 로컬 DB = 캐시, 원격 서버 = Single Source of Truth.
|
|
6
|
+
*/
|
|
7
|
+
// ============================================================
|
|
8
|
+
// Category/Tier 매핑 (로컬 레거시 → 서버 호환)
|
|
9
|
+
// ============================================================
|
|
10
|
+
const CATEGORY_MAP = {
|
|
11
|
+
preference: 'convention',
|
|
12
|
+
};
|
|
13
|
+
const TIER_MAP = {
|
|
14
|
+
procedural: 'semantic',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 로컬 category를 서버 호환 category로 변환
|
|
18
|
+
*/
|
|
19
|
+
export function mapCategory(category) {
|
|
20
|
+
return (CATEGORY_MAP[category] ?? category);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 로컬 tier를 서버 호환 tier로 변환
|
|
24
|
+
*/
|
|
25
|
+
export function mapTier(tier) {
|
|
26
|
+
return (TIER_MAP[tier] ?? tier);
|
|
27
|
+
}
|
|
28
|
+
export class SyncQueue {
|
|
29
|
+
db;
|
|
30
|
+
client;
|
|
31
|
+
constructor(db, client) {
|
|
32
|
+
this.db = db;
|
|
33
|
+
this.client = client;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 메모리를 sync 대기 상태로 설정 (~1ms)
|
|
37
|
+
*/
|
|
38
|
+
enqueue(memoryId) {
|
|
39
|
+
this.db.setSyncStatus(memoryId, null, 'pending');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* pending 메모리를 일괄 push
|
|
43
|
+
*/
|
|
44
|
+
async flush(options) {
|
|
45
|
+
const startTime = Date.now();
|
|
46
|
+
const timeoutMs = options?.timeoutMs ?? 5000;
|
|
47
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
48
|
+
const result = {
|
|
49
|
+
pushed: 0,
|
|
50
|
+
failed: 0,
|
|
51
|
+
errors: [],
|
|
52
|
+
duration: 0,
|
|
53
|
+
};
|
|
54
|
+
const pending = this.db.getPendingSyncMemories();
|
|
55
|
+
if (pending.length === 0) {
|
|
56
|
+
result.duration = Date.now() - startTime;
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
for (const memory of pending) {
|
|
60
|
+
// 타임아웃 체크
|
|
61
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
62
|
+
result.errors.push(`타임아웃: ${result.pushed}/${pending.length} 처리 완료`);
|
|
63
|
+
result.failed += pending.length - result.pushed - result.failed;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const remoteMemory = await this.retryPush(memory, maxRetries);
|
|
68
|
+
this.db.setSyncStatus(memory.id, remoteMemory.id, 'synced');
|
|
69
|
+
result.pushed++;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
result.failed++;
|
|
73
|
+
if (error instanceof Error) {
|
|
74
|
+
result.errors.push(`메모리 ${memory.id} push 실패: ${error.message}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
result.duration = Date.now() - startTime;
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 대기 중인 메모리 수
|
|
83
|
+
*/
|
|
84
|
+
getPendingCount() {
|
|
85
|
+
return this.db.getPendingSyncMemories().length;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 재시도 포함 push (exponential backoff)
|
|
89
|
+
*/
|
|
90
|
+
async retryPush(memory, maxRetries = 3) {
|
|
91
|
+
let lastError = null;
|
|
92
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
93
|
+
try {
|
|
94
|
+
return await this.client.createMemory({
|
|
95
|
+
content: memory.content,
|
|
96
|
+
category: mapCategory(memory.category),
|
|
97
|
+
tier: mapTier(memory.tier),
|
|
98
|
+
tags: memory.tags,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
103
|
+
if (attempt < maxRetries - 1) {
|
|
104
|
+
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
throw lastError;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/sync/queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Memory Synchronizer
|
|
3
|
-
* 로컬
|
|
3
|
+
* 로컬 메모리(캐시)와 원격 A2A 서버(Single Source of Truth) 간 동기화
|
|
4
4
|
*/
|
|
5
5
|
import type { MemoryDatabase } from '../db/database.js';
|
|
6
6
|
import type { A2AClient } from './client.js';
|
|
@@ -14,17 +14,31 @@ export interface SyncResult {
|
|
|
14
14
|
export declare class MemorySynchronizer {
|
|
15
15
|
private db;
|
|
16
16
|
private client;
|
|
17
|
-
|
|
17
|
+
private teamPath?;
|
|
18
|
+
private nodeId?;
|
|
19
|
+
private queue;
|
|
20
|
+
private failures;
|
|
21
|
+
private lastFailureAt;
|
|
22
|
+
private readonly maxFailures;
|
|
23
|
+
private readonly cooldownMs;
|
|
24
|
+
constructor(db: MemoryDatabase, client: A2AClient, teamPath?: string | undefined, nodeId?: string | undefined);
|
|
25
|
+
isCircuitOpen(): boolean;
|
|
26
|
+
recordSuccess(): void;
|
|
27
|
+
recordFailure(): void;
|
|
18
28
|
/**
|
|
19
|
-
* 양방향 동기화
|
|
29
|
+
* 양방향 동기화 (team 모드 시 TeamSynchronizer에 위임)
|
|
20
30
|
*/
|
|
21
31
|
sync(): Promise<SyncResult>;
|
|
22
32
|
/**
|
|
23
|
-
*
|
|
33
|
+
* 로컬 양방향 동기화 (기존 로직)
|
|
34
|
+
*/
|
|
35
|
+
private syncLocal;
|
|
36
|
+
/**
|
|
37
|
+
* 로컬→원격 (SyncQueue에 위임)
|
|
24
38
|
*/
|
|
25
39
|
push(): Promise<SyncResult>;
|
|
26
40
|
/**
|
|
27
|
-
*
|
|
41
|
+
* 원격→로컬 (페이지네이션 적용)
|
|
28
42
|
*/
|
|
29
43
|
pull(): Promise<SyncResult>;
|
|
30
44
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synchronizer.d.ts","sourceRoot":"","sources":["../../src/sync/synchronizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"synchronizer.d.ts","sourceRoot":"","sources":["../../src/sync/synchronizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,kBAAkB;IAQ3B,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,MAAM,CAAC;IAVjB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAG1B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,SAAS,EACjB,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,MAAM,CAAC,EAAE,MAAM,YAAA;IAKzB,aAAa,IAAI,OAAO;IAKxB,aAAa,IAAI,IAAI;IAIrB,aAAa,IAAI,IAAI;IAKrB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAejC;;OAEG;YACW,SAAS;IA+BvB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAyBjC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAiGjC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CAoBH"}
|
|
@@ -1,18 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Memory Synchronizer
|
|
3
|
-
* 로컬
|
|
3
|
+
* 로컬 메모리(캐시)와 원격 A2A 서버(Single Source of Truth) 간 동기화
|
|
4
4
|
*/
|
|
5
|
+
import { SyncQueue, mapCategory, mapTier } from './queue.js';
|
|
6
|
+
import { TeamSynchronizer } from './team-synchronizer.js';
|
|
7
|
+
const DEFAULT_PAGE_SIZE = 100;
|
|
5
8
|
export class MemorySynchronizer {
|
|
6
9
|
db;
|
|
7
10
|
client;
|
|
8
|
-
|
|
11
|
+
teamPath;
|
|
12
|
+
nodeId;
|
|
13
|
+
queue;
|
|
14
|
+
failures = 0;
|
|
15
|
+
lastFailureAt = 0;
|
|
16
|
+
maxFailures = 3;
|
|
17
|
+
cooldownMs = 30000;
|
|
18
|
+
constructor(db, client, teamPath, nodeId) {
|
|
9
19
|
this.db = db;
|
|
10
20
|
this.client = client;
|
|
21
|
+
this.teamPath = teamPath;
|
|
22
|
+
this.nodeId = nodeId;
|
|
23
|
+
this.queue = new SyncQueue(db, client);
|
|
24
|
+
}
|
|
25
|
+
isCircuitOpen() {
|
|
26
|
+
if (this.failures < this.maxFailures)
|
|
27
|
+
return false;
|
|
28
|
+
return (Date.now() - this.lastFailureAt) < this.cooldownMs;
|
|
29
|
+
}
|
|
30
|
+
recordSuccess() {
|
|
31
|
+
this.failures = 0;
|
|
32
|
+
}
|
|
33
|
+
recordFailure() {
|
|
34
|
+
this.failures++;
|
|
35
|
+
this.lastFailureAt = Date.now();
|
|
11
36
|
}
|
|
12
37
|
/**
|
|
13
|
-
* 양방향 동기화
|
|
38
|
+
* 양방향 동기화 (team 모드 시 TeamSynchronizer에 위임)
|
|
14
39
|
*/
|
|
15
40
|
async sync() {
|
|
41
|
+
if (this.teamPath && this.nodeId) {
|
|
42
|
+
const teamSync = new TeamSynchronizer(this.db, this.client, this.teamPath, this.nodeId);
|
|
43
|
+
const teamResult = await teamSync.syncDelta();
|
|
44
|
+
return {
|
|
45
|
+
pushed: teamResult.pushed,
|
|
46
|
+
pulled: teamResult.pulled,
|
|
47
|
+
conflicts: 0,
|
|
48
|
+
errors: teamResult.errors,
|
|
49
|
+
duration: teamResult.duration,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return this.syncLocal();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 로컬 양방향 동기화 (기존 로직)
|
|
56
|
+
*/
|
|
57
|
+
async syncLocal() {
|
|
16
58
|
const startTime = Date.now();
|
|
17
59
|
const result = {
|
|
18
60
|
pushed: 0,
|
|
@@ -41,50 +83,41 @@ export class MemorySynchronizer {
|
|
|
41
83
|
return result;
|
|
42
84
|
}
|
|
43
85
|
/**
|
|
44
|
-
*
|
|
86
|
+
* 로컬→원격 (SyncQueue에 위임)
|
|
45
87
|
*/
|
|
46
88
|
async push() {
|
|
89
|
+
if (this.isCircuitOpen()) {
|
|
90
|
+
return { pushed: 0, pulled: 0, conflicts: 0, errors: ['Circuit breaker open: too many consecutive failures'], duration: 0 };
|
|
91
|
+
}
|
|
47
92
|
const startTime = Date.now();
|
|
48
|
-
const result = {
|
|
49
|
-
pushed: 0,
|
|
50
|
-
pulled: 0,
|
|
51
|
-
conflicts: 0,
|
|
52
|
-
errors: [],
|
|
53
|
-
duration: 0,
|
|
54
|
-
};
|
|
55
93
|
try {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const remoteMemory = await this.client.createMemory({
|
|
60
|
-
content: memory.content,
|
|
61
|
-
category: memory.category,
|
|
62
|
-
tier: memory.tier,
|
|
63
|
-
tags: memory.tags,
|
|
64
|
-
});
|
|
65
|
-
// sync_status 업데이트
|
|
66
|
-
this.db.setSyncStatus(memory.id, remoteMemory.id, 'synced');
|
|
67
|
-
result.pushed++;
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
if (error instanceof Error) {
|
|
71
|
-
result.errors.push(`메모리 ${memory.id} 푸시 실패: ${error.message}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
94
|
+
const flushResult = await this.queue.flush();
|
|
95
|
+
if (flushResult.errors.length > 0) {
|
|
96
|
+
this.recordFailure();
|
|
74
97
|
}
|
|
98
|
+
else {
|
|
99
|
+
this.recordSuccess();
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
pushed: flushResult.pushed,
|
|
103
|
+
pulled: 0,
|
|
104
|
+
conflicts: 0,
|
|
105
|
+
errors: flushResult.errors,
|
|
106
|
+
duration: Date.now() - startTime,
|
|
107
|
+
};
|
|
75
108
|
}
|
|
76
109
|
catch (error) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
110
|
+
this.recordFailure();
|
|
111
|
+
throw error;
|
|
80
112
|
}
|
|
81
|
-
result.duration = Date.now() - startTime;
|
|
82
|
-
return result;
|
|
83
113
|
}
|
|
84
114
|
/**
|
|
85
|
-
*
|
|
115
|
+
* 원격→로컬 (페이지네이션 적용)
|
|
86
116
|
*/
|
|
87
117
|
async pull() {
|
|
118
|
+
if (this.isCircuitOpen()) {
|
|
119
|
+
return { pushed: 0, pulled: 0, conflicts: 0, errors: ['Circuit breaker open: too many consecutive failures'], duration: 0 };
|
|
120
|
+
}
|
|
88
121
|
const startTime = Date.now();
|
|
89
122
|
const result = {
|
|
90
123
|
pushed: 0,
|
|
@@ -94,48 +127,74 @@ export class MemorySynchronizer {
|
|
|
94
127
|
duration: 0,
|
|
95
128
|
};
|
|
96
129
|
try {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
this.db.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// 충돌 검사 (updated_at 비교)
|
|
116
|
-
const remoteUpdated = new Date(remote.updated_at);
|
|
117
|
-
const localUpdated = new Date(existing.updatedAt);
|
|
118
|
-
if (remoteUpdated > localUpdated) {
|
|
119
|
-
// 원격이 더 최신 → 로컬 업데이트
|
|
120
|
-
this.db.updateMemory(existing.id, {
|
|
130
|
+
let offset = 0;
|
|
131
|
+
let hasMore = true;
|
|
132
|
+
while (hasMore) {
|
|
133
|
+
const remoteMemories = await this.client.listMemories({
|
|
134
|
+
limit: DEFAULT_PAGE_SIZE,
|
|
135
|
+
offset,
|
|
136
|
+
includeEmbedding: true,
|
|
137
|
+
});
|
|
138
|
+
if (remoteMemories.length === 0) {
|
|
139
|
+
hasMore = false;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
for (const remote of remoteMemories) {
|
|
143
|
+
try {
|
|
144
|
+
const existing = this.db.findMemoryByRemoteId(remote.id);
|
|
145
|
+
if (!existing) {
|
|
146
|
+
// 새로운 메모리 — category/tier 매핑 적용
|
|
147
|
+
const created = this.db.createMemory({
|
|
121
148
|
content: remote.content,
|
|
122
|
-
category: remote.category,
|
|
123
|
-
tier: (remote.tier ??
|
|
124
|
-
tags: remote.tags ??
|
|
149
|
+
category: mapCategory(remote.category),
|
|
150
|
+
tier: mapTier(remote.tier ?? 'episodic'),
|
|
151
|
+
tags: remote.tags ?? [],
|
|
125
152
|
});
|
|
126
|
-
|
|
127
|
-
|
|
153
|
+
// 임베딩 저장
|
|
154
|
+
if (remote.embedding && remote.embedding.length > 0) {
|
|
155
|
+
this.db.saveEmbedding(created.id, remote.embedding);
|
|
156
|
+
}
|
|
157
|
+
this.db.setSyncStatus(created.id, remote.id, 'synced');
|
|
158
|
+
result.pulled++;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// 충돌 검사 (updated_at 비교)
|
|
162
|
+
const remoteUpdated = new Date(remote.updated_at);
|
|
163
|
+
const localUpdated = new Date(existing.updatedAt);
|
|
164
|
+
if (remoteUpdated > localUpdated) {
|
|
165
|
+
this.db.updateMemory(existing.id, {
|
|
166
|
+
content: remote.content,
|
|
167
|
+
category: mapCategory(remote.category),
|
|
168
|
+
tier: mapTier(remote.tier ?? existing.tier),
|
|
169
|
+
tags: remote.tags ?? existing.tags,
|
|
170
|
+
});
|
|
171
|
+
// 임베딩 업데이트
|
|
172
|
+
if (remote.embedding && remote.embedding.length > 0) {
|
|
173
|
+
this.db.saveEmbedding(existing.id, remote.embedding);
|
|
174
|
+
}
|
|
175
|
+
this.db.setSyncStatus(existing.id, remote.id, 'synced');
|
|
176
|
+
result.conflicts++;
|
|
177
|
+
}
|
|
128
178
|
}
|
|
129
179
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error instanceof Error) {
|
|
182
|
+
result.errors.push(`메모리 ${remote.id} 풀 실패: ${error.message}`);
|
|
183
|
+
}
|
|
134
184
|
}
|
|
135
185
|
}
|
|
186
|
+
// 다음 페이지
|
|
187
|
+
if (remoteMemories.length < DEFAULT_PAGE_SIZE) {
|
|
188
|
+
hasMore = false;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
offset += DEFAULT_PAGE_SIZE;
|
|
192
|
+
}
|
|
136
193
|
}
|
|
194
|
+
this.recordSuccess();
|
|
137
195
|
}
|
|
138
196
|
catch (error) {
|
|
197
|
+
this.recordFailure();
|
|
139
198
|
if (error instanceof Error) {
|
|
140
199
|
result.errors.push(error.message);
|
|
141
200
|
}
|
|
@@ -147,8 +206,7 @@ export class MemorySynchronizer {
|
|
|
147
206
|
* 동기화 상태 확인
|
|
148
207
|
*/
|
|
149
208
|
async getStatus() {
|
|
150
|
-
const pendingPush = this.
|
|
151
|
-
// 원격 메모리 개수 확인 (간단한 방법으로 limit=1 요청)
|
|
209
|
+
const pendingPush = this.queue.getPendingCount();
|
|
152
210
|
let pendingPull = 0;
|
|
153
211
|
try {
|
|
154
212
|
const remote = await this.client.listMemories({ limit: 1000 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synchronizer.js","sourceRoot":"","sources":["../../src/sync/synchronizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"synchronizer.js","sourceRoot":"","sources":["../../src/sync/synchronizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team Synchronizer
|
|
3
|
+
* 팀 메모리 풀과의 delta 동기화
|
|
4
|
+
*/
|
|
5
|
+
import type { MemoryDatabase } from '../db/database.js';
|
|
6
|
+
import type { A2AClient } from './client.js';
|
|
7
|
+
export interface TeamSyncResult {
|
|
8
|
+
pushed: number;
|
|
9
|
+
pulled: number;
|
|
10
|
+
errors: string[];
|
|
11
|
+
duration: number;
|
|
12
|
+
}
|
|
13
|
+
export interface TeamSyncStatus {
|
|
14
|
+
teamPath: string;
|
|
15
|
+
nodeId: string;
|
|
16
|
+
localMemoryCount: number;
|
|
17
|
+
pendingSync: number;
|
|
18
|
+
lastSyncedAt?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class TeamSynchronizer {
|
|
21
|
+
private db;
|
|
22
|
+
private client;
|
|
23
|
+
private teamPath;
|
|
24
|
+
private nodeId;
|
|
25
|
+
constructor(db: MemoryDatabase, client: A2AClient, teamPath: string, nodeId: string);
|
|
26
|
+
/**
|
|
27
|
+
* 전체 delta sync 사이클 (push + pull)
|
|
28
|
+
*/
|
|
29
|
+
syncDelta(): Promise<TeamSyncResult>;
|
|
30
|
+
/**
|
|
31
|
+
* 지정 메모리를 팀에 push
|
|
32
|
+
*/
|
|
33
|
+
pushToTeam(memoryIds: string[]): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* 팀 → 로컬 pull
|
|
36
|
+
*/
|
|
37
|
+
pullFromTeam(): Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* 팀 동기화 상태
|
|
40
|
+
*/
|
|
41
|
+
getTeamStatus(): Promise<TeamSyncStatus>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=team-synchronizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-synchronizer.d.ts","sourceRoot":"","sources":["../../src/sync/team-synchronizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;gBAHN,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM;IAGxB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IA0C1C;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAsCrC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;CAa/C"}
|