@claudetree/core 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/dist/application/SessionManager.d.ts +18 -0
- package/dist/application/SessionManager.d.ts.map +1 -0
- package/dist/application/SessionManager.js +86 -0
- package/dist/application/SessionManager.js.map +1 -0
- package/dist/application/WorktreeSyncService.d.ts +17 -0
- package/dist/application/WorktreeSyncService.d.ts.map +1 -0
- package/dist/application/WorktreeSyncService.js +63 -0
- package/dist/application/WorktreeSyncService.js.map +1 -0
- package/dist/application/index.d.ts +3 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +3 -0
- package/dist/application/index.js.map +1 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +2 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/repositories/ICodeReviewRepository.d.ts +7 -0
- package/dist/domain/repositories/ICodeReviewRepository.d.ts.map +1 -0
- package/dist/domain/repositories/ICodeReviewRepository.js +2 -0
- package/dist/domain/repositories/ICodeReviewRepository.js.map +1 -0
- package/dist/domain/repositories/IEventRepository.d.ts +8 -0
- package/dist/domain/repositories/IEventRepository.d.ts.map +1 -0
- package/dist/domain/repositories/IEventRepository.js +2 -0
- package/dist/domain/repositories/IEventRepository.js.map +1 -0
- package/dist/domain/repositories/ISessionRepository.d.ts +31 -0
- package/dist/domain/repositories/ISessionRepository.d.ts.map +1 -0
- package/dist/domain/repositories/ISessionRepository.js +2 -0
- package/dist/domain/repositories/ISessionRepository.js.map +1 -0
- package/dist/domain/repositories/IToolApprovalRepository.d.ts +8 -0
- package/dist/domain/repositories/IToolApprovalRepository.d.ts.map +1 -0
- package/dist/domain/repositories/IToolApprovalRepository.js +2 -0
- package/dist/domain/repositories/IToolApprovalRepository.js.map +1 -0
- package/dist/domain/repositories/IWorktreeRepository.d.ts +8 -0
- package/dist/domain/repositories/IWorktreeRepository.d.ts.map +1 -0
- package/dist/domain/repositories/IWorktreeRepository.js +2 -0
- package/dist/domain/repositories/IWorktreeRepository.js.map +1 -0
- package/dist/domain/repositories/index.d.ts +6 -0
- package/dist/domain/repositories/index.d.ts.map +1 -0
- package/dist/domain/repositories/index.js +2 -0
- package/dist/domain/repositories/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.d.ts +17 -0
- package/dist/infra/claude/ClaudeSessionAdapter.d.ts.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.js +162 -0
- package/dist/infra/claude/ClaudeSessionAdapter.js.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.d.ts +2 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.d.ts.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.js +122 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.js.map +1 -0
- package/dist/infra/claude/index.d.ts +2 -0
- package/dist/infra/claude/index.d.ts.map +1 -0
- package/dist/infra/claude/index.js +2 -0
- package/dist/infra/claude/index.js.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.d.ts +14 -0
- package/dist/infra/git/GitWorktreeAdapter.d.ts.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.js +74 -0
- package/dist/infra/git/GitWorktreeAdapter.js.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.test.d.ts +2 -0
- package/dist/infra/git/GitWorktreeAdapter.test.d.ts.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.test.js +104 -0
- package/dist/infra/git/GitWorktreeAdapter.test.js.map +1 -0
- package/dist/infra/git/index.d.ts +2 -0
- package/dist/infra/git/index.d.ts.map +1 -0
- package/dist/infra/git/index.js +2 -0
- package/dist/infra/git/index.js.map +1 -0
- package/dist/infra/github/GitHubAdapter.d.ts +20 -0
- package/dist/infra/github/GitHubAdapter.d.ts.map +1 -0
- package/dist/infra/github/GitHubAdapter.js +61 -0
- package/dist/infra/github/GitHubAdapter.js.map +1 -0
- package/dist/infra/github/GitHubAdapter.test.d.ts +2 -0
- package/dist/infra/github/GitHubAdapter.test.d.ts.map +1 -0
- package/dist/infra/github/GitHubAdapter.test.js +116 -0
- package/dist/infra/github/GitHubAdapter.test.js.map +1 -0
- package/dist/infra/github/index.d.ts +3 -0
- package/dist/infra/github/index.d.ts.map +1 -0
- package/dist/infra/github/index.js +2 -0
- package/dist/infra/github/index.js.map +1 -0
- package/dist/infra/index.d.ts +6 -0
- package/dist/infra/index.d.ts.map +1 -0
- package/dist/infra/index.js +6 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/storage/FileCodeReviewRepository.d.ts +14 -0
- package/dist/infra/storage/FileCodeReviewRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileCodeReviewRepository.js +67 -0
- package/dist/infra/storage/FileCodeReviewRepository.js.map +1 -0
- package/dist/infra/storage/FileEventRepository.d.ts +16 -0
- package/dist/infra/storage/FileEventRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileEventRepository.js +58 -0
- package/dist/infra/storage/FileEventRepository.js.map +1 -0
- package/dist/infra/storage/FileSessionRepository.d.ts +17 -0
- package/dist/infra/storage/FileSessionRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileSessionRepository.js +68 -0
- package/dist/infra/storage/FileSessionRepository.js.map +1 -0
- package/dist/infra/storage/FileSessionRepository.test.d.ts +2 -0
- package/dist/infra/storage/FileSessionRepository.test.d.ts.map +1 -0
- package/dist/infra/storage/FileSessionRepository.test.js +84 -0
- package/dist/infra/storage/FileSessionRepository.test.js.map +1 -0
- package/dist/infra/storage/FileToolApprovalRepository.d.ts +17 -0
- package/dist/infra/storage/FileToolApprovalRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileToolApprovalRepository.js +90 -0
- package/dist/infra/storage/FileToolApprovalRepository.js.map +1 -0
- package/dist/infra/storage/index.d.ts +5 -0
- package/dist/infra/storage/index.d.ts.map +1 -0
- package/dist/infra/storage/index.js +5 -0
- package/dist/infra/storage/index.js.map +1 -0
- package/dist/infra/websocket/WebSocketServer.d.ts +15 -0
- package/dist/infra/websocket/WebSocketServer.d.ts.map +1 -0
- package/dist/infra/websocket/WebSocketServer.js +45 -0
- package/dist/infra/websocket/WebSocketServer.js.map +1 -0
- package/dist/infra/websocket/index.d.ts +3 -0
- package/dist/infra/websocket/index.d.ts.map +1 -0
- package/dist/infra/websocket/index.js +2 -0
- package/dist/infra/websocket/index.js.map +1 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lucas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CodeReview, EventType, FileChange, SessionEvent, ToolApproval } from '@claudetree/shared';
|
|
2
|
+
import type { IEventRepository } from '../domain/repositories/IEventRepository.js';
|
|
3
|
+
import type { IToolApprovalRepository } from '../domain/repositories/IToolApprovalRepository.js';
|
|
4
|
+
import type { ICodeReviewRepository } from '../domain/repositories/ICodeReviewRepository.js';
|
|
5
|
+
import type { WebSocketBroadcaster } from '../infra/websocket/WebSocketServer.js';
|
|
6
|
+
export declare class SessionManager {
|
|
7
|
+
private readonly eventRepo;
|
|
8
|
+
private readonly approvalRepo;
|
|
9
|
+
private readonly reviewRepo;
|
|
10
|
+
private readonly broadcaster;
|
|
11
|
+
constructor(eventRepo: IEventRepository, approvalRepo: IToolApprovalRepository, reviewRepo: ICodeReviewRepository, broadcaster: WebSocketBroadcaster);
|
|
12
|
+
recordEvent(sessionId: string, type: EventType, content: string, metadata?: Record<string, unknown>): Promise<SessionEvent>;
|
|
13
|
+
requestApproval(sessionId: string, toolName: string, parameters: Record<string, unknown>): Promise<ToolApproval>;
|
|
14
|
+
resolveApproval(id: string, approved: boolean, approvedBy: string): Promise<void>;
|
|
15
|
+
requestReview(sessionId: string, changes: FileChange[]): Promise<CodeReview>;
|
|
16
|
+
resolveReview(id: string, approved: boolean, comment?: string): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=SessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/application/SessionManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,YAAY,EACZ,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AACnF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AACjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iDAAiD,CAAC;AAC7F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAElF,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAHX,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,uBAAuB,EACrC,UAAU,EAAE,qBAAqB,EACjC,WAAW,EAAE,oBAAoB;IAG9C,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,YAAY,CAAC;IAqBlB,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,YAAY,CAAC;IAuBlB,eAAe,CACnB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAWV,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,UAAU,CAAC;IAsBhB,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,OAAO,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;CAUjB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
export class SessionManager {
|
|
3
|
+
eventRepo;
|
|
4
|
+
approvalRepo;
|
|
5
|
+
reviewRepo;
|
|
6
|
+
broadcaster;
|
|
7
|
+
constructor(eventRepo, approvalRepo, reviewRepo, broadcaster) {
|
|
8
|
+
this.eventRepo = eventRepo;
|
|
9
|
+
this.approvalRepo = approvalRepo;
|
|
10
|
+
this.reviewRepo = reviewRepo;
|
|
11
|
+
this.broadcaster = broadcaster;
|
|
12
|
+
}
|
|
13
|
+
async recordEvent(sessionId, type, content, metadata) {
|
|
14
|
+
const event = {
|
|
15
|
+
id: randomUUID(),
|
|
16
|
+
sessionId,
|
|
17
|
+
type,
|
|
18
|
+
content,
|
|
19
|
+
metadata,
|
|
20
|
+
timestamp: new Date(),
|
|
21
|
+
};
|
|
22
|
+
await this.eventRepo.append(event);
|
|
23
|
+
this.broadcaster.broadcast({
|
|
24
|
+
type: 'event:created',
|
|
25
|
+
payload: { sessionId, event },
|
|
26
|
+
timestamp: new Date(),
|
|
27
|
+
});
|
|
28
|
+
return event;
|
|
29
|
+
}
|
|
30
|
+
async requestApproval(sessionId, toolName, parameters) {
|
|
31
|
+
const approval = {
|
|
32
|
+
id: randomUUID(),
|
|
33
|
+
sessionId,
|
|
34
|
+
toolName,
|
|
35
|
+
parameters,
|
|
36
|
+
status: 'pending',
|
|
37
|
+
approvedBy: null,
|
|
38
|
+
requestedAt: new Date(),
|
|
39
|
+
resolvedAt: null,
|
|
40
|
+
};
|
|
41
|
+
await this.approvalRepo.save(approval);
|
|
42
|
+
this.broadcaster.broadcast({
|
|
43
|
+
type: 'approval:requested',
|
|
44
|
+
payload: { sessionId, approval },
|
|
45
|
+
timestamp: new Date(),
|
|
46
|
+
});
|
|
47
|
+
return approval;
|
|
48
|
+
}
|
|
49
|
+
async resolveApproval(id, approved, approvedBy) {
|
|
50
|
+
const status = approved ? 'approved' : 'rejected';
|
|
51
|
+
await this.approvalRepo.updateStatus(id, status, approvedBy);
|
|
52
|
+
this.broadcaster.broadcast({
|
|
53
|
+
type: 'approval:resolved',
|
|
54
|
+
payload: { id, status, approvedBy },
|
|
55
|
+
timestamp: new Date(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async requestReview(sessionId, changes) {
|
|
59
|
+
const review = {
|
|
60
|
+
id: randomUUID(),
|
|
61
|
+
sessionId,
|
|
62
|
+
status: 'pending',
|
|
63
|
+
comment: null,
|
|
64
|
+
changes,
|
|
65
|
+
requestedAt: new Date(),
|
|
66
|
+
resolvedAt: null,
|
|
67
|
+
};
|
|
68
|
+
await this.reviewRepo.save(review);
|
|
69
|
+
this.broadcaster.broadcast({
|
|
70
|
+
type: 'review:requested',
|
|
71
|
+
payload: { sessionId, review },
|
|
72
|
+
timestamp: new Date(),
|
|
73
|
+
});
|
|
74
|
+
return review;
|
|
75
|
+
}
|
|
76
|
+
async resolveReview(id, approved, comment) {
|
|
77
|
+
const status = approved ? 'approved' : 'rejected';
|
|
78
|
+
await this.reviewRepo.updateStatus(id, status, comment);
|
|
79
|
+
this.broadcaster.broadcast({
|
|
80
|
+
type: 'review:resolved',
|
|
81
|
+
payload: { id, status, comment },
|
|
82
|
+
timestamp: new Date(),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=SessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../src/application/SessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Session } from '@claudetree/shared';
|
|
2
|
+
import type { ISessionRepository } from '../domain/repositories/ISessionRepository.js';
|
|
3
|
+
import type { IWorktreeRepository } from '../domain/repositories/IWorktreeRepository.js';
|
|
4
|
+
export declare class WorktreeSyncService {
|
|
5
|
+
private readonly sessionRepo;
|
|
6
|
+
private readonly worktreeRepo;
|
|
7
|
+
constructor(sessionRepo: ISessionRepository, worktreeRepo: IWorktreeRepository);
|
|
8
|
+
/**
|
|
9
|
+
* Sync worktrees with sessions.
|
|
10
|
+
* Creates sessions for worktrees that don't have one.
|
|
11
|
+
* Returns newly created sessions.
|
|
12
|
+
*/
|
|
13
|
+
sync(): Promise<Session[]>;
|
|
14
|
+
private matchWorktree;
|
|
15
|
+
private createSessionFromWorktree;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=WorktreeSyncService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeSyncService.d.ts","sourceRoot":"","sources":["../../src/application/WorktreeSyncService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AAEzF,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,mBAAmB;IAGpD;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAyBhC,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,yBAAyB;CAqBlC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
export class WorktreeSyncService {
|
|
3
|
+
sessionRepo;
|
|
4
|
+
worktreeRepo;
|
|
5
|
+
constructor(sessionRepo, worktreeRepo) {
|
|
6
|
+
this.sessionRepo = sessionRepo;
|
|
7
|
+
this.worktreeRepo = worktreeRepo;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Sync worktrees with sessions.
|
|
11
|
+
* Creates sessions for worktrees that don't have one.
|
|
12
|
+
* Returns newly created sessions.
|
|
13
|
+
*/
|
|
14
|
+
async sync() {
|
|
15
|
+
const worktrees = await this.worktreeRepo.list();
|
|
16
|
+
const sessions = await this.sessionRepo.findAll();
|
|
17
|
+
const newSessions = [];
|
|
18
|
+
for (const worktree of worktrees) {
|
|
19
|
+
// Skip main worktree
|
|
20
|
+
if (worktree.isMainWorktree)
|
|
21
|
+
continue;
|
|
22
|
+
// Check if session exists for this worktree path
|
|
23
|
+
const hasSession = sessions.some((s) => s.worktreeId === worktree.path || this.matchWorktree(s, worktree));
|
|
24
|
+
if (!hasSession) {
|
|
25
|
+
const session = this.createSessionFromWorktree(worktree);
|
|
26
|
+
await this.sessionRepo.save(session);
|
|
27
|
+
newSessions.push(session);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return newSessions;
|
|
31
|
+
}
|
|
32
|
+
matchWorktree(session, worktree) {
|
|
33
|
+
// Match by branch name pattern (issue-XX or task-XX)
|
|
34
|
+
if (!worktree.branch)
|
|
35
|
+
return false;
|
|
36
|
+
const issueMatch = worktree.branch.match(/^issue-(\d+)/);
|
|
37
|
+
if (issueMatch && session.issueNumber === parseInt(issueMatch[1] ?? '0', 10)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
createSessionFromWorktree(worktree) {
|
|
43
|
+
// Extract issue number from branch name
|
|
44
|
+
let issueNumber = null;
|
|
45
|
+
if (worktree.branch) {
|
|
46
|
+
const match = worktree.branch.match(/^issue-(\d+)/);
|
|
47
|
+
if (match) {
|
|
48
|
+
issueNumber = parseInt(match[1] ?? '0', 10);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
id: randomUUID(),
|
|
53
|
+
worktreeId: worktree.path,
|
|
54
|
+
claudeSessionId: null,
|
|
55
|
+
status: 'pending',
|
|
56
|
+
issueNumber,
|
|
57
|
+
prompt: null,
|
|
58
|
+
createdAt: new Date(),
|
|
59
|
+
updatedAt: new Date(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=WorktreeSyncService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeSyncService.js","sourceRoot":"","sources":["../../src/application/WorktreeSyncService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKzC,MAAM,OAAO,mBAAmB;IAEX;IACA;IAFnB,YACmB,WAA+B,EAC/B,YAAiC;QADjC,gBAAW,GAAX,WAAW,CAAoB;QAC/B,iBAAY,GAAZ,YAAY,CAAqB;IACjD,CAAC;IAEJ;;;;OAIG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAElD,MAAM,WAAW,GAAc,EAAE,CAAC;QAElC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,qBAAqB;YACrB,IAAI,QAAQ,CAAC,cAAc;gBAAE,SAAS;YAEtC,iDAAiD;YACjD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CACzE,CAAC;YAEF,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,OAAO,GAAG,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC;gBACzD,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAEO,aAAa,CAAC,OAAgB,EAAE,QAA0B;QAChE,qDAAqD;QACrD,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAEnC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,UAAU,IAAI,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,yBAAyB,CAAC,QAA0B;QAC1D,wCAAwC;QACxC,IAAI,WAAW,GAAkB,IAAI,CAAC;QACtC,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACpD,IAAI,KAAK,EAAE,CAAC;gBACV,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,OAAO;YACL,EAAE,EAAE,UAAU,EAAE;YAChB,UAAU,EAAE,QAAQ,CAAC,IAAI;YACzB,eAAe,EAAE,IAAI;YACrB,MAAM,EAAE,SAAS;YACjB,WAAW;YACX,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CodeReview, ReviewStatus } from '@claudetree/shared';
|
|
2
|
+
export interface ICodeReviewRepository {
|
|
3
|
+
findBySessionId(sessionId: string): Promise<CodeReview | null>;
|
|
4
|
+
save(review: CodeReview): Promise<void>;
|
|
5
|
+
updateStatus(id: string, status: ReviewStatus, comment?: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ICodeReviewRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICodeReviewRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/ICodeReviewRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,YAAY,CACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICodeReviewRepository.js","sourceRoot":"","sources":["../../../src/domain/repositories/ICodeReviewRepository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SessionEvent } from '@claudetree/shared';
|
|
2
|
+
export interface IEventRepository {
|
|
3
|
+
findBySessionId(sessionId: string): Promise<SessionEvent[]>;
|
|
4
|
+
append(event: SessionEvent): Promise<void>;
|
|
5
|
+
getLatest(sessionId: string, limit: number): Promise<SessionEvent[]>;
|
|
6
|
+
clear(sessionId: string): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=IEventRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IEventRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/IEventRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACrE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IEventRepository.js","sourceRoot":"","sources":["../../../src/domain/repositories/IEventRepository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Session } from '@claudetree/shared';
|
|
2
|
+
export interface ISessionRepository {
|
|
3
|
+
findById(id: string): Promise<Session | null>;
|
|
4
|
+
findByWorktreeId(worktreeId: string): Promise<Session | null>;
|
|
5
|
+
findAll(): Promise<Session[]>;
|
|
6
|
+
save(session: Session): Promise<void>;
|
|
7
|
+
delete(id: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface IClaudeSessionAdapter {
|
|
10
|
+
start(config: ClaudeSessionConfig): Promise<ClaudeSessionResult>;
|
|
11
|
+
resume(sessionId: string, prompt: string): Promise<ClaudeSessionResult>;
|
|
12
|
+
stop(processId: string): Promise<void>;
|
|
13
|
+
getOutput(processId: string): AsyncIterable<ClaudeOutput>;
|
|
14
|
+
}
|
|
15
|
+
export interface ClaudeSessionConfig {
|
|
16
|
+
workingDir: string;
|
|
17
|
+
prompt: string;
|
|
18
|
+
allowedTools?: string[];
|
|
19
|
+
systemPrompt?: string;
|
|
20
|
+
resume?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ClaudeSessionResult {
|
|
23
|
+
processId: string;
|
|
24
|
+
claudeSessionId: string | null;
|
|
25
|
+
}
|
|
26
|
+
export interface ClaudeOutput {
|
|
27
|
+
type: 'text' | 'tool_use' | 'tool_result' | 'error' | 'done';
|
|
28
|
+
content: string;
|
|
29
|
+
timestamp: Date;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ISessionRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISessionRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/ISessionRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC9C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC9D,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACxE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISessionRepository.js","sourceRoot":"","sources":["../../../src/domain/repositories/ISessionRepository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ApprovalStatus, ToolApproval } from '@claudetree/shared';
|
|
2
|
+
export interface IToolApprovalRepository {
|
|
3
|
+
findBySessionId(sessionId: string): Promise<ToolApproval[]>;
|
|
4
|
+
findPending(sessionId: string): Promise<ToolApproval[]>;
|
|
5
|
+
save(approval: ToolApproval): Promise<void>;
|
|
6
|
+
updateStatus(id: string, status: ApprovalStatus, approvedBy?: string): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=IToolApprovalRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IToolApprovalRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/IToolApprovalRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC5D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,YAAY,CACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,cAAc,EACtB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IToolApprovalRepository.js","sourceRoot":"","sources":["../../../src/domain/repositories/IToolApprovalRepository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CreateWorktreeInput, Worktree, WorktreeListItem } from '@claudetree/shared';
|
|
2
|
+
export interface IWorktreeRepository {
|
|
3
|
+
list(): Promise<WorktreeListItem[]>;
|
|
4
|
+
create(input: CreateWorktreeInput): Promise<Worktree>;
|
|
5
|
+
remove(path: string, force?: boolean): Promise<void>;
|
|
6
|
+
prune(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=IWorktreeRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IWorktreeRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/IWorktreeRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE1F,MAAM,WAAW,mBAAmB;IAClC,IAAI,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IWorktreeRepository.js","sourceRoot":"","sources":["../../../src/domain/repositories/IWorktreeRepository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { IWorktreeRepository } from './IWorktreeRepository.js';
|
|
2
|
+
export type { ISessionRepository, IClaudeSessionAdapter, ClaudeSessionConfig, ClaudeSessionResult, ClaudeOutput, } from './ISessionRepository.js';
|
|
3
|
+
export type { IEventRepository } from './IEventRepository.js';
|
|
4
|
+
export type { IToolApprovalRepository } from './IToolApprovalRepository.js';
|
|
5
|
+
export type { ICodeReviewRepository } from './ICodeReviewRepository.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,GACb,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,YAAY,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/repositories/index.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { IClaudeSessionAdapter, ClaudeSessionConfig, ClaudeSessionResult, ClaudeOutput } from '../../domain/repositories/ISessionRepository.js';
|
|
3
|
+
export interface ClaudeOutputEvent {
|
|
4
|
+
processId: string;
|
|
5
|
+
output: ClaudeOutput;
|
|
6
|
+
}
|
|
7
|
+
export declare class ClaudeSessionAdapter extends EventEmitter implements IClaudeSessionAdapter {
|
|
8
|
+
private processes;
|
|
9
|
+
start(config: ClaudeSessionConfig): Promise<ClaudeSessionResult>;
|
|
10
|
+
resume(sessionId: string, prompt: string): Promise<ClaudeSessionResult>;
|
|
11
|
+
stop(processId: string): Promise<void>;
|
|
12
|
+
getOutput(processId: string): AsyncIterable<ClaudeOutput>;
|
|
13
|
+
isClaudeAvailable(): Promise<boolean>;
|
|
14
|
+
buildArgs(config: ClaudeSessionConfig): string[];
|
|
15
|
+
parseStreamOutput(line: string): ClaudeOutput;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=ClaudeSessionAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeSessionAdapter.d.ts","sourceRoot":"","sources":["../../../src/infra/claude/ClaudeSessionAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACb,MAAM,iDAAiD,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,oBACX,SAAQ,YACR,YAAW,qBAAqB;IAEhC,OAAO,CAAC,SAAS,CAAmC;IAE9C,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkChE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkBvE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC;IAgD1D,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAS3C,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,EAAE;IAuBhD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;CA+C9C"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { createInterface } from 'node:readline';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { execa } from 'execa';
|
|
6
|
+
export class ClaudeSessionAdapter extends EventEmitter {
|
|
7
|
+
processes = new Map();
|
|
8
|
+
async start(config) {
|
|
9
|
+
const args = this.buildArgs(config);
|
|
10
|
+
const processId = randomUUID();
|
|
11
|
+
console.log(`[ClaudeAdapter] Spawning: claude ${args.join(' ').slice(0, 100)}...`);
|
|
12
|
+
console.log(`[ClaudeAdapter] Working dir: ${config.workingDir}`);
|
|
13
|
+
const proc = spawn('claude', args, {
|
|
14
|
+
cwd: config.workingDir,
|
|
15
|
+
stdio: ['ignore', 'pipe', 'pipe'], // stdin을 ignore로 변경
|
|
16
|
+
});
|
|
17
|
+
proc.on('error', (err) => {
|
|
18
|
+
console.error(`[ClaudeAdapter] Process error: ${err.message}`);
|
|
19
|
+
});
|
|
20
|
+
proc.on('exit', (code, signal) => {
|
|
21
|
+
console.log(`[ClaudeAdapter] Process exited: code=${code}, signal=${signal}`);
|
|
22
|
+
});
|
|
23
|
+
if (proc.stderr) {
|
|
24
|
+
proc.stderr.on('data', (data) => {
|
|
25
|
+
console.error(`[ClaudeAdapter] stderr: ${data.toString()}`);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
this.processes.set(processId, proc);
|
|
29
|
+
return {
|
|
30
|
+
processId,
|
|
31
|
+
claudeSessionId: null,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async resume(sessionId, prompt) {
|
|
35
|
+
const processId = randomUUID();
|
|
36
|
+
const proc = spawn('claude', [
|
|
37
|
+
'-p', prompt,
|
|
38
|
+
'--resume', sessionId,
|
|
39
|
+
'--output-format', 'stream-json',
|
|
40
|
+
'--verbose',
|
|
41
|
+
]);
|
|
42
|
+
this.processes.set(processId, proc);
|
|
43
|
+
return {
|
|
44
|
+
processId,
|
|
45
|
+
claudeSessionId: sessionId,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async stop(processId) {
|
|
49
|
+
const proc = this.processes.get(processId);
|
|
50
|
+
if (proc) {
|
|
51
|
+
proc.kill();
|
|
52
|
+
this.processes.delete(processId);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async *getOutput(processId) {
|
|
56
|
+
const proc = this.processes.get(processId);
|
|
57
|
+
console.log(`[ClaudeAdapter] getOutput called for process: ${processId.slice(0, 8)}`);
|
|
58
|
+
if (!proc) {
|
|
59
|
+
console.error(`[ClaudeAdapter] No process found for ID: ${processId.slice(0, 8)}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!proc.stdout) {
|
|
63
|
+
console.error(`[ClaudeAdapter] No stdout for process: ${processId.slice(0, 8)}`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log(`[ClaudeAdapter] Setting up readline for stdout...`);
|
|
67
|
+
const rl = createInterface({
|
|
68
|
+
input: proc.stdout,
|
|
69
|
+
crlfDelay: Infinity,
|
|
70
|
+
});
|
|
71
|
+
console.log(`[ClaudeAdapter] Starting to read lines...`);
|
|
72
|
+
for await (const line of rl) {
|
|
73
|
+
console.log(`[ClaudeAdapter] Raw line received (${line.length} chars)`);
|
|
74
|
+
if (!line.trim())
|
|
75
|
+
continue;
|
|
76
|
+
const output = this.parseStreamOutput(line);
|
|
77
|
+
this.emit('output', {
|
|
78
|
+
processId,
|
|
79
|
+
output,
|
|
80
|
+
});
|
|
81
|
+
yield output;
|
|
82
|
+
}
|
|
83
|
+
console.log(`[ClaudeAdapter] Readline ended, waiting for process to close...`);
|
|
84
|
+
// Wait for process to exit
|
|
85
|
+
await new Promise((resolve) => {
|
|
86
|
+
proc.on('close', () => {
|
|
87
|
+
console.log(`[ClaudeAdapter] Process closed`);
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async isClaudeAvailable() {
|
|
93
|
+
try {
|
|
94
|
+
await execa('which', ['claude']);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
buildArgs(config) {
|
|
102
|
+
const args = [
|
|
103
|
+
'-p', config.prompt,
|
|
104
|
+
'--output-format', 'stream-json',
|
|
105
|
+
'--verbose',
|
|
106
|
+
'--permission-mode', 'acceptEdits', // 자동 승인
|
|
107
|
+
];
|
|
108
|
+
if (config.allowedTools?.length) {
|
|
109
|
+
args.push('--allowedTools', config.allowedTools.join(','));
|
|
110
|
+
}
|
|
111
|
+
if (config.systemPrompt) {
|
|
112
|
+
args.push('--append-system-prompt', config.systemPrompt);
|
|
113
|
+
}
|
|
114
|
+
if (config.resume) {
|
|
115
|
+
args.push('--resume', config.resume);
|
|
116
|
+
}
|
|
117
|
+
return args;
|
|
118
|
+
}
|
|
119
|
+
parseStreamOutput(line) {
|
|
120
|
+
const timestamp = new Date();
|
|
121
|
+
try {
|
|
122
|
+
const data = JSON.parse(line);
|
|
123
|
+
if (data.type === 'result') {
|
|
124
|
+
return {
|
|
125
|
+
type: 'done',
|
|
126
|
+
content: data.session_id || '',
|
|
127
|
+
timestamp,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (data.type === 'assistant' && data.message?.content) {
|
|
131
|
+
const content = data.message.content[0];
|
|
132
|
+
if (content?.type === 'tool_use') {
|
|
133
|
+
return {
|
|
134
|
+
type: 'tool_use',
|
|
135
|
+
content: `${content.name}: ${JSON.stringify(content.input)}`,
|
|
136
|
+
timestamp,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (content?.type === 'text') {
|
|
140
|
+
return {
|
|
141
|
+
type: 'text',
|
|
142
|
+
content: content.text,
|
|
143
|
+
timestamp,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
type: 'text',
|
|
149
|
+
content: JSON.stringify(data),
|
|
150
|
+
timestamp,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return {
|
|
155
|
+
type: 'text',
|
|
156
|
+
content: line,
|
|
157
|
+
timestamp,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=ClaudeSessionAdapter.js.map
|