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.
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/cli/commands/config.d.ts +6 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +56 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/extract.d.ts +8 -0
- package/dist/cli/commands/extract.d.ts.map +1 -0
- package/dist/cli/commands/extract.js +103 -0
- package/dist/cli/commands/extract.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +44 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/search.d.ts +6 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +45 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +8 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +132 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/status.d.ts +6 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +70 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +6 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +142 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +34 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/manager.d.ts +18 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +95 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/db/database.d.ts +55 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +414 -0
- package/dist/db/database.js.map +1 -0
- package/dist/extraction/extractor.d.ts +12 -0
- package/dist/extraction/extractor.d.ts.map +1 -0
- package/dist/extraction/extractor.js +265 -0
- package/dist/extraction/extractor.js.map +1 -0
- package/dist/extraction/filter.d.ts +19 -0
- package/dist/extraction/filter.d.ts.map +1 -0
- package/dist/extraction/filter.js +60 -0
- package/dist/extraction/filter.js.map +1 -0
- package/dist/extraction/scorer.d.ts +18 -0
- package/dist/extraction/scorer.d.ts.map +1 -0
- package/dist/extraction/scorer.js +107 -0
- package/dist/extraction/scorer.js.map +1 -0
- package/dist/hooks/post-tool-use.d.ts +14 -0
- package/dist/hooks/post-tool-use.d.ts.map +1 -0
- package/dist/hooks/post-tool-use.js +144 -0
- package/dist/hooks/post-tool-use.js.map +1 -0
- package/dist/hooks/session-end.d.ts +13 -0
- package/dist/hooks/session-end.d.ts.map +1 -0
- package/dist/hooks/session-end.js +85 -0
- package/dist/hooks/session-end.js.map +1 -0
- package/dist/hooks/session-start.d.ts +15 -0
- package/dist/hooks/session-start.d.ts.map +1 -0
- package/dist/hooks/session-start.js +77 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/session/parser.d.ts +30 -0
- package/dist/session/parser.d.ts.map +1 -0
- package/dist/session/parser.js +129 -0
- package/dist/session/parser.js.map +1 -0
- package/dist/sync/client.d.ts +72 -0
- package/dist/sync/client.d.ts.map +1 -0
- package/dist/sync/client.js +138 -0
- package/dist/sync/client.js.map +1 -0
- package/dist/sync/index.d.ts +8 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +6 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/synchronizer.d.ts +39 -0
- package/dist/sync/synchronizer.d.ts.map +1 -0
- package/dist/sync/synchronizer.js +169 -0
- package/dist/sync/synchronizer.js.map +1 -0
- package/dist/types/index.d.ts +140 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +48 -0
- package/dist/types/index.js.map +1 -0
- 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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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
|