a2a-memory 0.1.2 → 0.6.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.
Files changed (191) hide show
  1. package/README.md +262 -45
  2. package/dist/adapters/anthropic.d.ts +69 -0
  3. package/dist/adapters/anthropic.d.ts.map +1 -0
  4. package/dist/adapters/anthropic.js +116 -0
  5. package/dist/adapters/anthropic.js.map +1 -0
  6. package/dist/claude/sync.d.ts +57 -0
  7. package/dist/claude/sync.d.ts.map +1 -0
  8. package/dist/claude/sync.js +201 -0
  9. package/dist/claude/sync.js.map +1 -0
  10. package/dist/cli/commands/add.d.ts +8 -0
  11. package/dist/cli/commands/add.d.ts.map +1 -0
  12. package/dist/cli/commands/add.js +45 -0
  13. package/dist/cli/commands/add.js.map +1 -0
  14. package/dist/cli/commands/claude-sync.d.ts +11 -0
  15. package/dist/cli/commands/claude-sync.d.ts.map +1 -0
  16. package/dist/cli/commands/claude-sync.js +69 -0
  17. package/dist/cli/commands/claude-sync.js.map +1 -0
  18. package/dist/cli/commands/cleanup.d.ts +8 -0
  19. package/dist/cli/commands/cleanup.d.ts.map +1 -0
  20. package/dist/cli/commands/cleanup.js +82 -0
  21. package/dist/cli/commands/cleanup.js.map +1 -0
  22. package/dist/cli/commands/edit.d.ts +8 -0
  23. package/dist/cli/commands/edit.d.ts.map +1 -0
  24. package/dist/cli/commands/edit.js +66 -0
  25. package/dist/cli/commands/edit.js.map +1 -0
  26. package/dist/cli/commands/embed.d.ts +8 -0
  27. package/dist/cli/commands/embed.d.ts.map +1 -0
  28. package/dist/cli/commands/embed.js +93 -0
  29. package/dist/cli/commands/embed.js.map +1 -0
  30. package/dist/cli/commands/health.d.ts +8 -0
  31. package/dist/cli/commands/health.d.ts.map +1 -0
  32. package/dist/cli/commands/health.js +108 -0
  33. package/dist/cli/commands/health.js.map +1 -0
  34. package/dist/cli/commands/rm.d.ts +8 -0
  35. package/dist/cli/commands/rm.d.ts.map +1 -0
  36. package/dist/cli/commands/rm.js +60 -0
  37. package/dist/cli/commands/rm.js.map +1 -0
  38. package/dist/cli/commands/sync.d.ts.map +1 -1
  39. package/dist/cli/commands/sync.js +52 -0
  40. package/dist/cli/commands/sync.js.map +1 -1
  41. package/dist/cli/commands/team.d.ts +7 -0
  42. package/dist/cli/commands/team.d.ts.map +1 -0
  43. package/dist/cli/commands/team.js +144 -0
  44. package/dist/cli/commands/team.js.map +1 -0
  45. package/dist/cli/index.d.ts +5 -0
  46. package/dist/cli/index.d.ts.map +1 -1
  47. package/dist/cli/index.js +44 -1
  48. package/dist/cli/index.js.map +1 -1
  49. package/dist/config/manager.d.ts +16 -0
  50. package/dist/config/manager.d.ts.map +1 -1
  51. package/dist/config/manager.js +170 -5
  52. package/dist/config/manager.js.map +1 -1
  53. package/dist/db/database.d.ts +28 -3
  54. package/dist/db/database.d.ts.map +1 -1
  55. package/dist/db/database.js +291 -64
  56. package/dist/db/database.js.map +1 -1
  57. package/dist/embedding/index.d.ts +21 -0
  58. package/dist/embedding/index.d.ts.map +1 -0
  59. package/dist/embedding/index.js +29 -0
  60. package/dist/embedding/index.js.map +1 -0
  61. package/dist/embedding/local-provider.d.ts +40 -0
  62. package/dist/embedding/local-provider.d.ts.map +1 -0
  63. package/dist/embedding/local-provider.js +157 -0
  64. package/dist/embedding/local-provider.js.map +1 -0
  65. package/dist/embedding/openai-provider.d.ts +31 -0
  66. package/dist/embedding/openai-provider.d.ts.map +1 -0
  67. package/dist/embedding/openai-provider.js +92 -0
  68. package/dist/embedding/openai-provider.js.map +1 -0
  69. package/dist/embedding/quantization.d.ts +34 -0
  70. package/dist/embedding/quantization.d.ts.map +1 -0
  71. package/dist/embedding/quantization.js +89 -0
  72. package/dist/embedding/quantization.js.map +1 -0
  73. package/dist/extraction/extractor.d.ts +11 -1
  74. package/dist/extraction/extractor.d.ts.map +1 -1
  75. package/dist/extraction/extractor.js +63 -20
  76. package/dist/extraction/extractor.js.map +1 -1
  77. package/dist/extraction/filter.d.ts.map +1 -1
  78. package/dist/extraction/filter.js +25 -3
  79. package/dist/extraction/filter.js.map +1 -1
  80. package/dist/extraction/scorer.d.ts +2 -0
  81. package/dist/extraction/scorer.d.ts.map +1 -1
  82. package/dist/extraction/scorer.js +23 -1
  83. package/dist/extraction/scorer.js.map +1 -1
  84. package/dist/extraction/similarity.d.ts +25 -0
  85. package/dist/extraction/similarity.d.ts.map +1 -0
  86. package/dist/extraction/similarity.js +85 -0
  87. package/dist/extraction/similarity.js.map +1 -0
  88. package/dist/hooks/post-tool-use.d.ts.map +1 -1
  89. package/dist/hooks/post-tool-use.js +88 -53
  90. package/dist/hooks/post-tool-use.js.map +1 -1
  91. package/dist/hooks/session-end.d.ts +1 -0
  92. package/dist/hooks/session-end.d.ts.map +1 -1
  93. package/dist/hooks/session-end.js +173 -33
  94. package/dist/hooks/session-end.js.map +1 -1
  95. package/dist/hooks/session-start.d.ts +2 -2
  96. package/dist/hooks/session-start.d.ts.map +1 -1
  97. package/dist/hooks/session-start.js +172 -22
  98. package/dist/hooks/session-start.js.map +1 -1
  99. package/dist/hooks/shared.d.ts +18 -0
  100. package/dist/hooks/shared.d.ts.map +1 -0
  101. package/dist/hooks/shared.js +46 -0
  102. package/dist/hooks/shared.js.map +1 -0
  103. package/dist/i18n/index.d.ts +3 -0
  104. package/dist/i18n/index.d.ts.map +1 -0
  105. package/dist/i18n/index.js +2 -0
  106. package/dist/i18n/index.js.map +1 -0
  107. package/dist/i18n/messages.d.ts +82 -0
  108. package/dist/i18n/messages.d.ts.map +1 -0
  109. package/dist/i18n/messages.js +150 -0
  110. package/dist/i18n/messages.js.map +1 -0
  111. package/dist/index.d.ts +25 -5
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +20 -3
  114. package/dist/index.js.map +1 -1
  115. package/dist/lifecycle/cleanup.d.ts +25 -0
  116. package/dist/lifecycle/cleanup.d.ts.map +1 -0
  117. package/dist/lifecycle/cleanup.js +52 -0
  118. package/dist/lifecycle/cleanup.js.map +1 -0
  119. package/dist/lifecycle/index.d.ts +15 -0
  120. package/dist/lifecycle/index.d.ts.map +1 -0
  121. package/dist/lifecycle/index.js +12 -0
  122. package/dist/lifecycle/index.js.map +1 -0
  123. package/dist/lifecycle/quality-scorer.d.ts +19 -0
  124. package/dist/lifecycle/quality-scorer.d.ts.map +1 -0
  125. package/dist/lifecycle/quality-scorer.js +40 -0
  126. package/dist/lifecycle/quality-scorer.js.map +1 -0
  127. package/dist/lifecycle/tiering.d.ts +50 -0
  128. package/dist/lifecycle/tiering.d.ts.map +1 -0
  129. package/dist/lifecycle/tiering.js +235 -0
  130. package/dist/lifecycle/tiering.js.map +1 -0
  131. package/dist/llm/client.d.ts +37 -0
  132. package/dist/llm/client.d.ts.map +1 -0
  133. package/dist/llm/client.js +154 -0
  134. package/dist/llm/client.js.map +1 -0
  135. package/dist/llm/index.d.ts +6 -0
  136. package/dist/llm/index.d.ts.map +1 -0
  137. package/dist/llm/index.js +5 -0
  138. package/dist/llm/index.js.map +1 -0
  139. package/dist/search/index.d.ts +8 -0
  140. package/dist/search/index.d.ts.map +1 -0
  141. package/dist/search/index.js +7 -0
  142. package/dist/search/index.js.map +1 -0
  143. package/dist/search/ranker.d.ts +30 -0
  144. package/dist/search/ranker.d.ts.map +1 -0
  145. package/dist/search/ranker.js +91 -0
  146. package/dist/search/ranker.js.map +1 -0
  147. package/dist/sync/client.d.ts +103 -0
  148. package/dist/sync/client.d.ts.map +1 -1
  149. package/dist/sync/client.js +186 -6
  150. package/dist/sync/client.js.map +1 -1
  151. package/dist/sync/encryption.d.ts +72 -0
  152. package/dist/sync/encryption.d.ts.map +1 -0
  153. package/dist/sync/encryption.js +203 -0
  154. package/dist/sync/encryption.js.map +1 -0
  155. package/dist/sync/index.d.ts +9 -0
  156. package/dist/sync/index.d.ts.map +1 -1
  157. package/dist/sync/index.js +6 -0
  158. package/dist/sync/index.js.map +1 -1
  159. package/dist/sync/queue.d.ts +49 -0
  160. package/dist/sync/queue.d.ts.map +1 -0
  161. package/dist/sync/queue.js +112 -0
  162. package/dist/sync/queue.js.map +1 -0
  163. package/dist/sync/scheduler.d.ts +69 -0
  164. package/dist/sync/scheduler.d.ts.map +1 -0
  165. package/dist/sync/scheduler.js +140 -0
  166. package/dist/sync/scheduler.js.map +1 -0
  167. package/dist/sync/synchronizer.d.ts +19 -5
  168. package/dist/sync/synchronizer.d.ts.map +1 -1
  169. package/dist/sync/synchronizer.js +128 -70
  170. package/dist/sync/synchronizer.js.map +1 -1
  171. package/dist/sync/team-synchronizer.d.ts +43 -0
  172. package/dist/sync/team-synchronizer.d.ts.map +1 -0
  173. package/dist/sync/team-synchronizer.js +126 -0
  174. package/dist/sync/team-synchronizer.js.map +1 -0
  175. package/dist/sync/vector-clock.d.ts +23 -0
  176. package/dist/sync/vector-clock.d.ts.map +1 -0
  177. package/dist/sync/vector-clock.js +40 -0
  178. package/dist/sync/vector-clock.js.map +1 -0
  179. package/dist/types/index.d.ts +74 -2
  180. package/dist/types/index.d.ts.map +1 -1
  181. package/dist/types/index.js +56 -4
  182. package/dist/types/index.js.map +1 -1
  183. package/dist/utils/keychain.d.ts +50 -0
  184. package/dist/utils/keychain.d.ts.map +1 -0
  185. package/dist/utils/keychain.js +166 -0
  186. package/dist/utils/keychain.js.map +1 -0
  187. package/dist/utils/logger.d.ts +16 -0
  188. package/dist/utils/logger.d.ts.map +1 -0
  189. package/dist/utils/logger.js +118 -0
  190. package/dist/utils/logger.js.map +1 -0
  191. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Memory Synchronizer
3
- * 로컬 메모리와 원격 A2A 서버 간 동기화
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
- constructor(db: MemoryDatabase, client: A2AClient);
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;AAG7C,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;AAED,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;gBADN,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,SAAS;IAG3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IA+BjC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAyCjC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAgEjC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CAqBH"}
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
- * 로컬 메모리와 원격 A2A 서버 간 동기화
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
- constructor(db, client) {
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 pending = this.db.getPendingSyncMemories();
57
- for (const memory of pending) {
58
- try {
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
- if (error instanceof Error) {
78
- result.errors.push(error.message);
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
- // 원격 메모리 목록 가져오기 (최대 100개)
98
- const remoteMemories = await this.client.listMemories({ limit: 100 });
99
- for (const remote of remoteMemories) {
100
- try {
101
- // 이미 로컬에 있는지 확인 (remote_id 기준)
102
- const existing = this.db.findMemoryByRemoteId(remote.id);
103
- if (!existing) {
104
- // 새로운 메모리 생성
105
- const created = this.db.createMemory({
106
- content: remote.content,
107
- category: remote.category,
108
- tier: (remote.tier ?? 'tier2'),
109
- tags: remote.tags ?? [],
110
- });
111
- this.db.setSyncStatus(created.id, remote.id, 'synced');
112
- result.pulled++;
113
- }
114
- else {
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 ?? existing.tier),
124
- tags: remote.tags ?? existing.tags,
149
+ category: mapCategory(remote.category),
150
+ tier: mapTier(remote.tier ?? 'episodic'),
151
+ tags: remote.tags ?? [],
125
152
  });
126
- this.db.setSyncStatus(existing.id, remote.id, 'synced');
127
- result.conflicts++;
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
- catch (error) {
132
- if (error instanceof Error) {
133
- result.errors.push(`메모리 ${remote.id} 풀 실패: ${error.message}`);
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.db.getPendingSyncMemories().length;
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":"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"}
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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Team Synchronizer
3
+ * 팀 메모리 풀과의 delta 동기화
4
+ */
5
+ import { LocalVectorClock } from './vector-clock.js';
6
+ import { mapCategory, mapTier } from './queue.js';
7
+ const PAGE_SIZE = 100;
8
+ export class TeamSynchronizer {
9
+ db;
10
+ client;
11
+ teamPath;
12
+ nodeId;
13
+ constructor(db, client, teamPath, nodeId) {
14
+ this.db = db;
15
+ this.client = client;
16
+ this.teamPath = teamPath;
17
+ this.nodeId = nodeId;
18
+ }
19
+ /**
20
+ * 전체 delta sync 사이클 (push + pull)
21
+ */
22
+ async syncDelta() {
23
+ const startTime = Date.now();
24
+ const result = { pushed: 0, pulled: 0, errors: [], duration: 0 };
25
+ try {
26
+ // Push: 로컬 pending → 팀
27
+ const pending = this.db.getPendingSyncMemories();
28
+ for (const memory of pending) {
29
+ try {
30
+ const clock = new LocalVectorClock(this.nodeId, this.db.getVectorClock(memory.id) ?? undefined);
31
+ clock.increment();
32
+ await this.client.addTeamMemory(this.teamPath, {
33
+ content: memory.content,
34
+ category: memory.category,
35
+ tier: memory.tier,
36
+ tags: memory.tags,
37
+ });
38
+ this.db.saveVectorClock(memory.id, clock.toJSON());
39
+ this.db.setSyncStatus(memory.id, null, 'synced');
40
+ result.pushed++;
41
+ }
42
+ catch (error) {
43
+ result.errors.push(`Push failed for ${memory.id}: ${error instanceof Error ? error.message : String(error)}`);
44
+ }
45
+ }
46
+ // Pull: 팀 → 로컬
47
+ result.pulled = await this.pullFromTeam();
48
+ }
49
+ catch (error) {
50
+ result.errors.push(error instanceof Error ? error.message : String(error));
51
+ }
52
+ result.duration = Date.now() - startTime;
53
+ return result;
54
+ }
55
+ /**
56
+ * 지정 메모리를 팀에 push
57
+ */
58
+ async pushToTeam(memoryIds) {
59
+ for (const id of memoryIds) {
60
+ const memory = this.db.getMemory(id);
61
+ if (!memory)
62
+ continue;
63
+ const clock = new LocalVectorClock(this.nodeId, this.db.getVectorClock(id) ?? undefined);
64
+ clock.increment();
65
+ await this.client.addTeamMemory(this.teamPath, {
66
+ content: memory.content,
67
+ category: memory.category,
68
+ tier: memory.tier,
69
+ tags: memory.tags,
70
+ });
71
+ this.db.saveVectorClock(id, clock.toJSON());
72
+ this.db.setSyncStatus(id, null, 'synced');
73
+ }
74
+ }
75
+ /**
76
+ * 팀 → 로컬 pull
77
+ */
78
+ async pullFromTeam() {
79
+ let pulled = 0;
80
+ let offset = 0;
81
+ while (true) {
82
+ const remoteMemories = await this.client.listTeamMemories(this.teamPath, {
83
+ limit: PAGE_SIZE,
84
+ offset,
85
+ });
86
+ if (remoteMemories.length === 0)
87
+ break;
88
+ for (const remote of remoteMemories) {
89
+ const existing = this.db.findMemoryByRemoteId(remote.id);
90
+ if (!existing) {
91
+ const created = this.db.createMemory({
92
+ content: remote.content,
93
+ category: mapCategory(remote.category),
94
+ tier: mapTier(remote.tier ?? 'episodic'),
95
+ tags: remote.tags ?? [],
96
+ });
97
+ if (remote.embedding && remote.embedding.length > 0) {
98
+ this.db.saveEmbedding(created.id, remote.embedding);
99
+ }
100
+ this.db.setSyncStatus(created.id, remote.id, 'synced');
101
+ pulled++;
102
+ }
103
+ }
104
+ if (remoteMemories.length < PAGE_SIZE)
105
+ break;
106
+ offset += PAGE_SIZE;
107
+ }
108
+ return pulled;
109
+ }
110
+ /**
111
+ * 팀 동기화 상태
112
+ */
113
+ async getTeamStatus() {
114
+ const stats = this.db.getStats();
115
+ const pendingSync = this.db.getPendingSyncMemories().length;
116
+ const lastSyncedAt = this.db.getLastSyncedAt();
117
+ return {
118
+ teamPath: this.teamPath,
119
+ nodeId: this.nodeId,
120
+ localMemoryCount: stats.totalMemories,
121
+ pendingSync,
122
+ lastSyncedAt: lastSyncedAt ?? undefined,
123
+ };
124
+ }
125
+ }
126
+ //# sourceMappingURL=team-synchronizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-synchronizer.js","sourceRoot":"","sources":["../../src/sync/team-synchronizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Local Vector Clock
3
+ * CRDT 기반 동기화를 위한 로컬 벡터 클럭 관리
4
+ */
5
+ import type { VectorClockState } from '../types/index.js';
6
+ export declare class LocalVectorClock {
7
+ private nodeId;
8
+ private state;
9
+ constructor(nodeId: string, state?: VectorClockState);
10
+ /**
11
+ * 현재 노드의 카운터를 1 증가
12
+ */
13
+ increment(): VectorClockState;
14
+ /**
15
+ * 원격 벡터 클럭과 병합 (element-wise max)
16
+ */
17
+ merge(remote: VectorClockState): void;
18
+ getNodeId(): string;
19
+ get(nodeId: string): number;
20
+ toJSON(): VectorClockState;
21
+ static fromJSON(nodeId: string, data: VectorClockState): LocalVectorClock;
22
+ }
23
+ //# sourceMappingURL=vector-clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-clock.d.ts","sourceRoot":"","sources":["../../src/sync/vector-clock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAmB;gBAEpB,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,gBAAgB;IAKpD;;OAEG;IACH,SAAS,IAAI,gBAAgB;IAK7B;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAMrC,SAAS,IAAI,MAAM;IAInB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI3B,MAAM,IAAI,gBAAgB;IAI1B,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,gBAAgB;CAG1E"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Local Vector Clock
3
+ * CRDT 기반 동기화를 위한 로컬 벡터 클럭 관리
4
+ */
5
+ export class LocalVectorClock {
6
+ nodeId;
7
+ state;
8
+ constructor(nodeId, state) {
9
+ this.nodeId = nodeId;
10
+ this.state = state ? { ...state } : {};
11
+ }
12
+ /**
13
+ * 현재 노드의 카운터를 1 증가
14
+ */
15
+ increment() {
16
+ this.state[this.nodeId] = (this.state[this.nodeId] ?? 0) + 1;
17
+ return this.toJSON();
18
+ }
19
+ /**
20
+ * 원격 벡터 클럭과 병합 (element-wise max)
21
+ */
22
+ merge(remote) {
23
+ for (const [node, count] of Object.entries(remote)) {
24
+ this.state[node] = Math.max(this.state[node] ?? 0, count);
25
+ }
26
+ }
27
+ getNodeId() {
28
+ return this.nodeId;
29
+ }
30
+ get(nodeId) {
31
+ return this.state[nodeId] ?? 0;
32
+ }
33
+ toJSON() {
34
+ return { ...this.state };
35
+ }
36
+ static fromJSON(nodeId, data) {
37
+ return new LocalVectorClock(nodeId, data);
38
+ }
39
+ }
40
+ //# sourceMappingURL=vector-clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-clock.js","sourceRoot":"","sources":["../../src/sync/vector-clock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAS;IACf,KAAK,CAAmB;IAEhC,YAAY,MAAc,EAAE,KAAwB;QAClD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,SAAS;QACP,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAwB;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,MAAM;QACJ,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,MAAc,EAAE,IAAsB;QACpD,OAAO,IAAI,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;CACF"}