a2a-memory 0.1.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/cli/commands/config.d.ts +6 -0
  4. package/dist/cli/commands/config.d.ts.map +1 -0
  5. package/dist/cli/commands/config.js +56 -0
  6. package/dist/cli/commands/config.js.map +1 -0
  7. package/dist/cli/commands/extract.d.ts +8 -0
  8. package/dist/cli/commands/extract.d.ts.map +1 -0
  9. package/dist/cli/commands/extract.js +103 -0
  10. package/dist/cli/commands/extract.js.map +1 -0
  11. package/dist/cli/commands/list.d.ts +6 -0
  12. package/dist/cli/commands/list.d.ts.map +1 -0
  13. package/dist/cli/commands/list.js +44 -0
  14. package/dist/cli/commands/list.js.map +1 -0
  15. package/dist/cli/commands/search.d.ts +6 -0
  16. package/dist/cli/commands/search.d.ts.map +1 -0
  17. package/dist/cli/commands/search.js +45 -0
  18. package/dist/cli/commands/search.js.map +1 -0
  19. package/dist/cli/commands/setup.d.ts +8 -0
  20. package/dist/cli/commands/setup.d.ts.map +1 -0
  21. package/dist/cli/commands/setup.js +132 -0
  22. package/dist/cli/commands/setup.js.map +1 -0
  23. package/dist/cli/commands/status.d.ts +6 -0
  24. package/dist/cli/commands/status.d.ts.map +1 -0
  25. package/dist/cli/commands/status.js +70 -0
  26. package/dist/cli/commands/status.js.map +1 -0
  27. package/dist/cli/commands/sync.d.ts +6 -0
  28. package/dist/cli/commands/sync.d.ts.map +1 -0
  29. package/dist/cli/commands/sync.js +142 -0
  30. package/dist/cli/commands/sync.js.map +1 -0
  31. package/dist/cli/index.d.ts +14 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/cli/index.js +34 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/config/manager.d.ts +18 -0
  36. package/dist/config/manager.d.ts.map +1 -0
  37. package/dist/config/manager.js +95 -0
  38. package/dist/config/manager.js.map +1 -0
  39. package/dist/db/database.d.ts +55 -0
  40. package/dist/db/database.d.ts.map +1 -0
  41. package/dist/db/database.js +414 -0
  42. package/dist/db/database.js.map +1 -0
  43. package/dist/extraction/extractor.d.ts +12 -0
  44. package/dist/extraction/extractor.d.ts.map +1 -0
  45. package/dist/extraction/extractor.js +265 -0
  46. package/dist/extraction/extractor.js.map +1 -0
  47. package/dist/extraction/filter.d.ts +19 -0
  48. package/dist/extraction/filter.d.ts.map +1 -0
  49. package/dist/extraction/filter.js +60 -0
  50. package/dist/extraction/filter.js.map +1 -0
  51. package/dist/extraction/scorer.d.ts +18 -0
  52. package/dist/extraction/scorer.d.ts.map +1 -0
  53. package/dist/extraction/scorer.js +107 -0
  54. package/dist/extraction/scorer.js.map +1 -0
  55. package/dist/hooks/post-tool-use.d.ts +14 -0
  56. package/dist/hooks/post-tool-use.d.ts.map +1 -0
  57. package/dist/hooks/post-tool-use.js +144 -0
  58. package/dist/hooks/post-tool-use.js.map +1 -0
  59. package/dist/hooks/session-end.d.ts +13 -0
  60. package/dist/hooks/session-end.d.ts.map +1 -0
  61. package/dist/hooks/session-end.js +85 -0
  62. package/dist/hooks/session-end.js.map +1 -0
  63. package/dist/hooks/session-start.d.ts +15 -0
  64. package/dist/hooks/session-start.d.ts.map +1 -0
  65. package/dist/hooks/session-start.js +77 -0
  66. package/dist/hooks/session-start.js.map +1 -0
  67. package/dist/index.d.ts +17 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +18 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/session/parser.d.ts +30 -0
  72. package/dist/session/parser.d.ts.map +1 -0
  73. package/dist/session/parser.js +129 -0
  74. package/dist/session/parser.js.map +1 -0
  75. package/dist/sync/client.d.ts +72 -0
  76. package/dist/sync/client.d.ts.map +1 -0
  77. package/dist/sync/client.js +138 -0
  78. package/dist/sync/client.js.map +1 -0
  79. package/dist/sync/index.d.ts +8 -0
  80. package/dist/sync/index.d.ts.map +1 -0
  81. package/dist/sync/index.js +6 -0
  82. package/dist/sync/index.js.map +1 -0
  83. package/dist/sync/synchronizer.d.ts +39 -0
  84. package/dist/sync/synchronizer.d.ts.map +1 -0
  85. package/dist/sync/synchronizer.js +169 -0
  86. package/dist/sync/synchronizer.js.map +1 -0
  87. package/dist/types/index.d.ts +140 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/index.js +48 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/package.json +53 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-tool-use.js","sourceRoot":"","sources":["../../src/hooks/post-tool-use.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * SessionEnd Hook
3
+ *
4
+ * Claude Code 세션 종료 시 실행됩니다.
5
+ * 세션 전체를 분석하여 요약 메모리를 생성합니다.
6
+ */
7
+ import type { SessionEndContext } from '../types/index.js';
8
+ export declare function handleSessionEnd(context: SessionEndContext): Promise<void>;
9
+ /**
10
+ * CLI 엔트리포인트
11
+ */
12
+ export declare function main(): Promise<void>;
13
+ //# sourceMappingURL=session-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.d.ts","sourceRoot":"","sources":["../../src/hooks/session-end.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkEhF;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB1C"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * SessionEnd Hook
3
+ *
4
+ * Claude Code 세션 종료 시 실행됩니다.
5
+ * 세션 전체를 분석하여 요약 메모리를 생성합니다.
6
+ */
7
+ import { MemoryDatabase } from '../db/database.js';
8
+ import { ConfigManager } from '../config/manager.js';
9
+ import { parseSessionFile, findSessionFiles } from '../session/parser.js';
10
+ import { extractMemories } from '../extraction/extractor.js';
11
+ export async function handleSessionEnd(context) {
12
+ const config = new ConfigManager().load();
13
+ if (!config.sessionSummary.enabled) {
14
+ return;
15
+ }
16
+ // 세션 파일 찾기
17
+ const sessionFiles = findSessionFiles(context.projectPath);
18
+ if (sessionFiles.length === 0) {
19
+ return;
20
+ }
21
+ // 가장 최근 세션 파일 사용
22
+ const latestSession = sessionFiles
23
+ .sort((a, b) => (b.sizeBytes - a.sizeBytes))[0];
24
+ const messages = parseSessionFile(latestSession.filePath);
25
+ // 최소 행동 수 미달 시 스킵
26
+ const toolUseCount = messages.filter((m) => Array.isArray(m.message.content) &&
27
+ m.message.content.some((b) => b.type === 'tool_use')).length;
28
+ if (toolUseCount < config.sessionSummary.minActions) {
29
+ return;
30
+ }
31
+ const db = new MemoryDatabase(config.db.path);
32
+ try {
33
+ db.initialize();
34
+ // 이미 처리된 세션인지 확인
35
+ const existingSession = db.getSession(latestSession.sessionId);
36
+ if (existingSession) {
37
+ return;
38
+ }
39
+ // 메모리 추출
40
+ const result = extractMemories(messages, context.projectPath);
41
+ // DB에 저장
42
+ for (const memory of result.memories) {
43
+ db.createMemory({
44
+ ...memory,
45
+ sessionId: latestSession.sessionId,
46
+ });
47
+ }
48
+ // 세션 기록
49
+ db.saveSession(latestSession.sessionId, context.projectPath, messages.length);
50
+ if (result.memories.length > 0) {
51
+ console.error(`[a2a] Session summary: ${result.memories.length} memories extracted from ${messages.length} messages`);
52
+ }
53
+ }
54
+ finally {
55
+ db.close();
56
+ }
57
+ }
58
+ /**
59
+ * CLI 엔트리포인트
60
+ */
61
+ export async function main() {
62
+ const chunks = [];
63
+ for await (const chunk of process.stdin) {
64
+ chunks.push(chunk);
65
+ }
66
+ const input = Buffer.concat(chunks).toString('utf-8').trim();
67
+ if (!input) {
68
+ process.exit(0);
69
+ }
70
+ try {
71
+ const context = JSON.parse(input);
72
+ await handleSessionEnd(context);
73
+ }
74
+ catch (err) {
75
+ console.error('[a2a] SessionEnd hook error:', err);
76
+ process.exit(0);
77
+ }
78
+ }
79
+ // 직접 실행 시에만 main() 호출
80
+ const isMainModule = process.argv[1]?.endsWith('session-end.js') ||
81
+ process.argv[1]?.endsWith('session-end.ts');
82
+ if (isMainModule) {
83
+ main();
84
+ }
85
+ //# sourceMappingURL=session-end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.js","sourceRoot":"","sources":["../../src/hooks/session-end.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * SessionStart Hook
3
+ *
4
+ * Claude Code 세션 시작 시 실행됩니다.
5
+ * 현재 프로젝트에 관련된 메모리를 검색하여 stdout으로 출력합니다.
6
+ * Claude Code는 stdout 출력을 컨텍스트에 주입합니다.
7
+ */
8
+ import type { SessionStartContext } from '../types/index.js';
9
+ export declare function handleSessionStart(context: SessionStartContext): Promise<string>;
10
+ /**
11
+ * CLI 엔트리포인트
12
+ * stdin으로 HookContext JSON을 받아 처리
13
+ */
14
+ export declare function main(): Promise<void>;
15
+ //# sourceMappingURL=session-start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.d.ts","sourceRoot":"","sources":["../../src/hooks/session-start.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyCtF;AAED;;;GAGG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAqB1C"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * SessionStart Hook
3
+ *
4
+ * Claude Code 세션 시작 시 실행됩니다.
5
+ * 현재 프로젝트에 관련된 메모리를 검색하여 stdout으로 출력합니다.
6
+ * Claude Code는 stdout 출력을 컨텍스트에 주입합니다.
7
+ */
8
+ import { MemoryDatabase } from '../db/database.js';
9
+ import { ConfigManager } from '../config/manager.js';
10
+ export async function handleSessionStart(context) {
11
+ const config = new ConfigManager().load();
12
+ if (!config.autoInject.enabled) {
13
+ return '';
14
+ }
15
+ const db = new MemoryDatabase(config.db.path);
16
+ try {
17
+ db.initialize();
18
+ const results = db.search({
19
+ query: context.projectPath,
20
+ limit: config.autoInject.maxMemories,
21
+ });
22
+ if (results.length === 0) {
23
+ return '';
24
+ }
25
+ const lines = [
26
+ '<!-- A2A Memory Context -->',
27
+ `<!-- ${results.length} relevant memories for ${context.projectPath} -->`,
28
+ ];
29
+ let totalTokens = 0;
30
+ for (const result of results) {
31
+ const estimatedTokens = Math.ceil(result.memory.content.length / 4);
32
+ if (totalTokens + estimatedTokens > config.autoInject.maxTokens)
33
+ break;
34
+ lines.push('');
35
+ lines.push(`### [${result.memory.category}] (score: ${result.score.toFixed(2)})`);
36
+ lines.push(result.memory.content);
37
+ totalTokens += estimatedTokens;
38
+ }
39
+ lines.push('<!-- /A2A Memory Context -->');
40
+ return lines.join('\n');
41
+ }
42
+ finally {
43
+ db.close();
44
+ }
45
+ }
46
+ /**
47
+ * CLI 엔트리포인트
48
+ * stdin으로 HookContext JSON을 받아 처리
49
+ */
50
+ export async function main() {
51
+ const chunks = [];
52
+ for await (const chunk of process.stdin) {
53
+ chunks.push(chunk);
54
+ }
55
+ const input = Buffer.concat(chunks).toString('utf-8').trim();
56
+ if (!input) {
57
+ process.exit(0);
58
+ }
59
+ try {
60
+ const context = JSON.parse(input);
61
+ const output = await handleSessionStart(context);
62
+ if (output) {
63
+ process.stdout.write(output);
64
+ }
65
+ }
66
+ catch (err) {
67
+ console.error('[a2a] SessionStart hook error:', err);
68
+ process.exit(0); // 에러 시에도 Claude Code 세션 차단하지 않음
69
+ }
70
+ }
71
+ // 직접 실행 시에만 main() 호출
72
+ const isMainModule = process.argv[1]?.endsWith('session-start.js') ||
73
+ process.argv[1]?.endsWith('session-start.ts');
74
+ if (isMainModule) {
75
+ main();
76
+ }
77
+ //# sourceMappingURL=session-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../src/hooks/session-start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A2A Memory Plugin - Public API
3
+ */
4
+ export type { Memory, MemoryCreateInput, MemorySearchOptions, MemorySearchResult, MemoryCategory, MemoryTier, SessionMessage, SessionContentBlock, SessionInfo, ExtractionResult, A2AConfig, HookContext, SessionStartContext, PostToolUseContext, SessionEndContext, SignificanceSignal, SignificanceResult, } from './types/index.js';
5
+ export { DEFAULT_CONFIG, SENSITIVE_PATTERNS } from './types/index.js';
6
+ export { MemoryDatabase } from './db/database.js';
7
+ export { ConfigManager } from './config/manager.js';
8
+ export { parseSessionFile, findSessionFiles, getSessionMessages } from './session/parser.js';
9
+ export { extractMemories } from './extraction/extractor.js';
10
+ export { scoreSignificance } from './extraction/scorer.js';
11
+ export { filterSensitiveInfo, isSensitivePath } from './extraction/filter.js';
12
+ export { handleSessionStart } from './hooks/session-start.js';
13
+ export { handlePostToolUse } from './hooks/post-tool-use.js';
14
+ export { handleSessionEnd } from './hooks/session-end.js';
15
+ export { A2AClient, MemorySynchronizer } from './sync/index.js';
16
+ export type { A2AClientConfig, RemoteMemory, SyncResult } from './sync/index.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,MAAM,EACN,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A2A Memory Plugin - Public API
3
+ */
4
+ export { DEFAULT_CONFIG, SENSITIVE_PATTERNS } from './types/index.js';
5
+ // Core modules
6
+ export { MemoryDatabase } from './db/database.js';
7
+ export { ConfigManager } from './config/manager.js';
8
+ export { parseSessionFile, findSessionFiles, getSessionMessages } from './session/parser.js';
9
+ export { extractMemories } from './extraction/extractor.js';
10
+ export { scoreSignificance } from './extraction/scorer.js';
11
+ export { filterSensitiveInfo, isSensitivePath } from './extraction/filter.js';
12
+ // Hooks
13
+ export { handleSessionStart } from './hooks/session-start.js';
14
+ export { handlePostToolUse } from './hooks/post-tool-use.js';
15
+ export { handleSessionEnd } from './hooks/session-end.js';
16
+ // Sync
17
+ export { A2AClient, MemorySynchronizer } from './sync/index.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuBH,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtE,eAAe;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9E,QAAQ;AACR,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO;AACP,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Session JSONL Parser
3
+ *
4
+ * Claude Code 세션 JSONL 파일을 파싱하여 SessionMessage 배열로 변환합니다.
5
+ * 세션 파일 위치: ~/.claude/projects/<project-slug>/<session-id>.jsonl
6
+ */
7
+ import type { SessionMessage, SessionInfo } from '../types/index.js';
8
+ /**
9
+ * JSONL 파일을 파싱하여 SessionMessage 배열 반환
10
+ */
11
+ export declare function parseSessionFile(filePath: string): SessionMessage[];
12
+ /**
13
+ * 프로젝트 경로를 Claude의 디렉토리 slug로 변환
14
+ * /Users/name/project → -Users-name-project
15
+ */
16
+ export declare function projectPathToSlug(projectPath: string): string;
17
+ /**
18
+ * Claude 디렉토리 slug를 프로젝트 경로로 변환
19
+ * -Users-name-project → /Users/name/project
20
+ */
21
+ export declare function slugToProjectPath(slug: string): string;
22
+ /**
23
+ * 세션 파일 목록 탐색
24
+ */
25
+ export declare function findSessionFiles(projectPath?: string): SessionInfo[];
26
+ /**
27
+ * 특정 세션의 메시지 반환
28
+ */
29
+ export declare function getSessionMessages(sessionId: string, projectPath: string): SessionMessage[];
30
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/session/parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrE;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAyBnE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKtD;AAUD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CA2DpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,cAAc,EAAE,CAIlB"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Session JSONL Parser
3
+ *
4
+ * Claude Code 세션 JSONL 파일을 파싱하여 SessionMessage 배열로 변환합니다.
5
+ * 세션 파일 위치: ~/.claude/projects/<project-slug>/<session-id>.jsonl
6
+ */
7
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
8
+ import { join, basename } from 'node:path';
9
+ import { homedir } from 'node:os';
10
+ const CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');
11
+ /**
12
+ * JSONL 파일을 파싱하여 SessionMessage 배열 반환
13
+ */
14
+ export function parseSessionFile(filePath) {
15
+ if (!existsSync(filePath)) {
16
+ console.error('[a2a] Session file not found:', filePath);
17
+ return [];
18
+ }
19
+ const content = readFileSync(filePath, 'utf-8');
20
+ const lines = content.split('\n');
21
+ const messages = [];
22
+ for (let i = 0; i < lines.length; i++) {
23
+ const line = lines[i].trim();
24
+ if (!line)
25
+ continue;
26
+ try {
27
+ const parsed = JSON.parse(line);
28
+ if (parsed.uuid && parsed.type && parsed.message) {
29
+ messages.push(parsed);
30
+ }
31
+ }
32
+ catch {
33
+ console.error(`[a2a] Invalid JSON at line ${i + 1} in ${filePath}`);
34
+ }
35
+ }
36
+ return messages;
37
+ }
38
+ /**
39
+ * 프로젝트 경로를 Claude의 디렉토리 slug로 변환
40
+ * /Users/name/project → -Users-name-project
41
+ */
42
+ export function projectPathToSlug(projectPath) {
43
+ return projectPath.replace(/\//g, '-');
44
+ }
45
+ /**
46
+ * Claude 디렉토리 slug를 프로젝트 경로로 변환
47
+ * -Users-name-project → /Users/name/project
48
+ */
49
+ export function slugToProjectPath(slug) {
50
+ if (slug.startsWith('-')) {
51
+ return slug.replace(/-/g, '/');
52
+ }
53
+ return slug;
54
+ }
55
+ /**
56
+ * JSONL 파일의 줄 수를 빠르게 계산
57
+ */
58
+ function countLines(filePath) {
59
+ const content = readFileSync(filePath, 'utf-8');
60
+ return content.split('\n').filter((line) => line.trim().length > 0).length;
61
+ }
62
+ /**
63
+ * 세션 파일 목록 탐색
64
+ */
65
+ export function findSessionFiles(projectPath) {
66
+ if (!existsSync(CLAUDE_PROJECTS_DIR)) {
67
+ return [];
68
+ }
69
+ const results = [];
70
+ try {
71
+ const projectDirs = projectPath
72
+ ? [projectPathToSlug(projectPath)]
73
+ : readdirSync(CLAUDE_PROJECTS_DIR);
74
+ for (const dir of projectDirs) {
75
+ const dirPath = join(CLAUDE_PROJECTS_DIR, dir);
76
+ if (!existsSync(dirPath))
77
+ continue;
78
+ let stat;
79
+ try {
80
+ stat = statSync(dirPath);
81
+ }
82
+ catch {
83
+ continue;
84
+ }
85
+ if (!stat.isDirectory())
86
+ continue;
87
+ let files;
88
+ try {
89
+ files = readdirSync(dirPath);
90
+ }
91
+ catch {
92
+ continue;
93
+ }
94
+ for (const file of files) {
95
+ if (!file.endsWith('.jsonl'))
96
+ continue;
97
+ const filePath = join(dirPath, file);
98
+ const sessionId = basename(file, '.jsonl');
99
+ try {
100
+ const fileStat = statSync(filePath);
101
+ const messageCount = countLines(filePath);
102
+ results.push({
103
+ sessionId,
104
+ projectPath: slugToProjectPath(dir),
105
+ filePath,
106
+ messageCount,
107
+ sizeBytes: fileStat.size,
108
+ });
109
+ }
110
+ catch {
111
+ console.error('[a2a] Failed to stat session file:', filePath);
112
+ }
113
+ }
114
+ }
115
+ }
116
+ catch (err) {
117
+ console.error('[a2a] Failed to scan session files:', err);
118
+ }
119
+ return results;
120
+ }
121
+ /**
122
+ * 특정 세션의 메시지 반환
123
+ */
124
+ export function getSessionMessages(sessionId, projectPath) {
125
+ const slug = projectPathToSlug(projectPath);
126
+ const filePath = join(CLAUDE_PROJECTS_DIR, slug, `${sessionId}.jsonl`);
127
+ return parseSessionFile(filePath);
128
+ }
129
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/session/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * A2A API Client
3
+ * Node.js 내장 fetch 사용 (외부 의존성 없음)
4
+ */
5
+ export interface A2AClientConfig {
6
+ baseUrl: string;
7
+ apiKey: string;
8
+ timeout?: number;
9
+ }
10
+ export interface RemoteMemory {
11
+ id: string;
12
+ content: string;
13
+ category: string;
14
+ tier?: string;
15
+ tags?: string[];
16
+ metadata?: Record<string, unknown>;
17
+ created_at: string;
18
+ updated_at: string;
19
+ }
20
+ export declare class A2AClient {
21
+ private config;
22
+ private timeout;
23
+ constructor(config: A2AClientConfig);
24
+ /**
25
+ * 메모리 생성
26
+ */
27
+ createMemory(input: {
28
+ content: string;
29
+ category: string;
30
+ tier?: string;
31
+ tags?: string[];
32
+ }): Promise<RemoteMemory>;
33
+ /**
34
+ * 메모리 검색
35
+ */
36
+ searchMemories(query: string, options?: {
37
+ limit?: number;
38
+ category?: string;
39
+ }): Promise<RemoteMemory[]>;
40
+ /**
41
+ * 메모리 목록
42
+ */
43
+ listMemories(options?: {
44
+ limit?: number;
45
+ offset?: number;
46
+ }): Promise<RemoteMemory[]>;
47
+ /**
48
+ * 메모리 업데이트
49
+ */
50
+ updateMemory(id: string, updates: Partial<{
51
+ content: string;
52
+ category: string;
53
+ tags: string[];
54
+ }>): Promise<RemoteMemory>;
55
+ /**
56
+ * 메모리 삭제
57
+ */
58
+ deleteMemory(id: string): Promise<void>;
59
+ /**
60
+ * 연결 테스트
61
+ */
62
+ testConnection(): Promise<boolean>;
63
+ /**
64
+ * HTTP 요청 실행
65
+ */
66
+ private request;
67
+ /**
68
+ * 에러 응답 처리
69
+ */
70
+ private handleErrorResponse;
71
+ }
72
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/sync/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,eAAe;IAKnC;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACjB,GAAG,OAAO,CAAC,YAAY,CAAC;IAWzB;;OAEG;IACG,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,OAAO,CAAC,YAAY,EAAE,CAAC;IAU1B;;OAEG;IACG,YAAY,CAAC,OAAO,CAAC,EAAE;QAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAW3B;;OAEG;IACG,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,GACtE,OAAO,CAAC,YAAY,CAAC;IAKxB;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IASxC;;OAEG;YACW,OAAO;IA0CrB;;OAEG;YACW,mBAAmB;CAyBlC"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * A2A API Client
3
+ * Node.js 내장 fetch 사용 (외부 의존성 없음)
4
+ */
5
+ export class A2AClient {
6
+ config;
7
+ timeout;
8
+ constructor(config) {
9
+ this.config = config;
10
+ this.timeout = config.timeout ?? 10000;
11
+ }
12
+ /**
13
+ * 메모리 생성
14
+ */
15
+ async createMemory(input) {
16
+ const response = await this.request('POST', '/api/v1/memories', {
17
+ content: input.content,
18
+ category: input.category,
19
+ tier: input.tier ?? 'tier2',
20
+ tags: input.tags ?? [],
21
+ });
22
+ return response;
23
+ }
24
+ /**
25
+ * 메모리 검색
26
+ */
27
+ async searchMemories(query, options) {
28
+ const response = await this.request('POST', '/api/v1/memories/search', {
29
+ query,
30
+ limit: options?.limit ?? 10,
31
+ category: options?.category,
32
+ });
33
+ return response.results ?? [];
34
+ }
35
+ /**
36
+ * 메모리 목록
37
+ */
38
+ async listMemories(options) {
39
+ const params = new URLSearchParams();
40
+ if (options?.limit)
41
+ params.set('limit', options.limit.toString());
42
+ if (options?.offset)
43
+ params.set('offset', options.offset.toString());
44
+ const path = `/api/v1/memories${params.toString() ? `?${params.toString()}` : ''}`;
45
+ const response = await this.request('GET', path);
46
+ return response.memories ?? [];
47
+ }
48
+ /**
49
+ * 메모리 업데이트
50
+ */
51
+ async updateMemory(id, updates) {
52
+ const response = await this.request('PATCH', `/api/v1/memories/${id}`, updates);
53
+ return response;
54
+ }
55
+ /**
56
+ * 메모리 삭제
57
+ */
58
+ async deleteMemory(id) {
59
+ await this.request('DELETE', `/api/v1/memories/${id}`);
60
+ }
61
+ /**
62
+ * 연결 테스트
63
+ */
64
+ async testConnection() {
65
+ try {
66
+ await this.request('GET', '/api/v1/memories?limit=1');
67
+ return true;
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * HTTP 요청 실행
75
+ */
76
+ async request(method, path, body) {
77
+ const url = `${this.config.baseUrl}${path}`;
78
+ const controller = new AbortController();
79
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
80
+ try {
81
+ const response = await fetch(url, {
82
+ method,
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ 'x-api-key': this.config.apiKey,
86
+ },
87
+ body: body ? JSON.stringify(body) : undefined,
88
+ signal: controller.signal,
89
+ });
90
+ clearTimeout(timeoutId);
91
+ if (!response.ok) {
92
+ await this.handleErrorResponse(response);
93
+ }
94
+ // DELETE는 빈 응답일 수 있음
95
+ if (method === 'DELETE' && response.status === 204) {
96
+ return;
97
+ }
98
+ return await response.json();
99
+ }
100
+ catch (error) {
101
+ clearTimeout(timeoutId);
102
+ if (error instanceof Error) {
103
+ if (error.name === 'AbortError') {
104
+ throw new Error(`요청 시간 초과: ${this.timeout}ms를 넘었습니다`);
105
+ }
106
+ throw new Error(`네트워크 오류: ${error.message}`);
107
+ }
108
+ throw error;
109
+ }
110
+ }
111
+ /**
112
+ * 에러 응답 처리
113
+ */
114
+ async handleErrorResponse(response) {
115
+ const status = response.status;
116
+ if (status === 401) {
117
+ throw new Error('인증 실패: API Key를 확인하세요');
118
+ }
119
+ if (status === 429) {
120
+ throw new Error('요청 제한: 잠시 후 다시 시도하세요');
121
+ }
122
+ let message = `HTTP ${status}`;
123
+ try {
124
+ const errorBody = await response.json();
125
+ if (errorBody.detail) {
126
+ message += `: ${errorBody.detail}`;
127
+ }
128
+ else if (errorBody.message) {
129
+ message += `: ${errorBody.message}`;
130
+ }
131
+ }
132
+ catch {
133
+ // JSON 파싱 실패 시 기본 메시지 사용
134
+ }
135
+ throw new Error(message);
136
+ }
137
+ }
138
+ //# sourceMappingURL=client.js.map