aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/claude/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/claude/index.ts')
-rw-r--r--src/main/claude/index.ts51
1 files changed, 23 insertions, 28 deletions
diff --git a/src/main/claude/index.ts b/src/main/claude/index.ts
index b8c9c07..4dd49f2 100644
--- a/src/main/claude/index.ts
+++ b/src/main/claude/index.ts
@@ -1,31 +1,24 @@
1import { query, type SDKMessage, type Query } from "@anthropic-ai/claude-agent-sdk"; 1import { query, type SDKMessage, type Query } from "@anthropic-ai/claude-agent-sdk";
2import type { Session } from "../db/sessions"; 2import type { Session } from "../db/sessions";
3import { getPhaseConfig, getNextPhase, getArtifactFilename, getSessionArtifactDir } from "./phases"; 3import { getPhaseConfig, getNextPhase, getArtifactFilename } from "./phases";
4import type { Phase, UserPermissionMode } from "./phases"; 4import type { Phase, UserPermissionMode } from "./phases";
5import { getProject } from "../db/projects"; 5import { getProject } from "../db/projects";
6import { updateSession } from "../db/sessions"; 6import { updateSession } from "../db/sessions";
7import fs from "node:fs"; 7import fs from "node:fs";
8import path from "node:path"; 8import path from "node:path";
9import os from "node:os";
10 9
11// Track active queries by session ID 10// Track active queries by session ID
12const activeQueries = new Map<string, Query>(); 11const activeQueries = new Map<string, Query>();
13 12
14// Global storage in home directory
15const GLOBAL_CLAUDE_FLOW_DIR = path.join(os.homedir(), ".claude-flow");
16
17function ensureDir(dirPath: string): void { 13function ensureDir(dirPath: string): void {
18 if (!fs.existsSync(dirPath)) { 14 if (!fs.existsSync(dirPath)) {
19 fs.mkdirSync(dirPath, { recursive: true }); 15 fs.mkdirSync(dirPath, { recursive: true });
20 } 16 }
21} 17}
22 18
23function getProjectDir(projectId: string): string { 19// Artifacts live inside the project directory so the SDK's Write tool can reach them
24 return path.join(GLOBAL_CLAUDE_FLOW_DIR, "projects", projectId); 20function getSessionDir(projectPath: string, sessionId: string): string {
25} 21 return path.join(projectPath, ".claude-flow", "sessions", sessionId);
26
27function getSessionDir(projectId: string, sessionId: string): string {
28 return path.join(getProjectDir(projectId), "sessions", sessionId);
29} 22}
30 23
31export interface SendMessageOptions { 24export interface SendMessageOptions {
@@ -42,12 +35,13 @@ export async function sendMessage({
42 const project = getProject(session.project_id); 35 const project = getProject(session.project_id);
43 if (!project) throw new Error("Project not found"); 36 if (!project) throw new Error("Project not found");
44 37
45 // Ensure session artifact directory exists in global storage 38 // Ensure session artifact directory exists inside the project
46 const sessionDir = getSessionDir(session.project_id, session.id); 39 const sessionDir = getSessionDir(project.path, session.id);
47 ensureDir(sessionDir); 40 ensureDir(sessionDir);
48 41
49 const phaseConfig = getPhaseConfig( 42 const phaseConfig = getPhaseConfig(
50 session.phase as Phase, 43 session.phase as Phase,
44 sessionDir,
51 session.permission_mode as UserPermissionMode 45 session.permission_mode as UserPermissionMode
52 ); 46 );
53 47
@@ -112,22 +106,26 @@ export function advancePhase(session: Session): Phase | null {
112} 106}
113 107
114/** 108/**
115 * Get the artifact path for a session and phase (in global storage) 109 * Get the artifact path for a session and phase (inside the project directory)
116 */ 110 */
117export function getArtifactPath(session: Session): string { 111export function getArtifactPath(session: Session): string {
112 const project = getProject(session.project_id);
113 if (!project) throw new Error("Project not found");
118 const filename = getArtifactFilename(session.phase as Phase); 114 const filename = getArtifactFilename(session.phase as Phase);
119 return path.join(getSessionDir(session.project_id, session.id), filename); 115 return path.join(getSessionDir(project.path, session.id), filename);
120} 116}
121 117
122/** 118/**
123 * Read an artifact file for a session (from global storage) 119 * Read an artifact file for a session
124 */ 120 */
125export function readSessionArtifact( 121export function readSessionArtifact(
126 projectId: string, 122 projectId: string,
127 sessionId: string, 123 sessionId: string,
128 filename: string 124 filename: string
129): string | null { 125): string | null {
130 const filePath = path.join(getSessionDir(projectId, sessionId), filename); 126 const project = getProject(projectId);
127 if (!project) return null;
128 const filePath = path.join(getSessionDir(project.path, sessionId), filename);
131 if (fs.existsSync(filePath)) { 129 if (fs.existsSync(filePath)) {
132 return fs.readFileSync(filePath, "utf-8"); 130 return fs.readFileSync(filePath, "utf-8");
133 } 131 }
@@ -135,7 +133,7 @@ export function readSessionArtifact(
135} 133}
136 134
137/** 135/**
138 * Write an artifact file for a session (to global storage) 136 * Write an artifact file for a session
139 */ 137 */
140export function writeSessionArtifact( 138export function writeSessionArtifact(
141 projectId: string, 139 projectId: string,
@@ -143,7 +141,9 @@ export function writeSessionArtifact(
143 filename: string, 141 filename: string,
144 content: string 142 content: string
145): void { 143): void {
146 const dir = getSessionDir(projectId, sessionId); 144 const project = getProject(projectId);
145 if (!project) throw new Error("Project not found");
146 const dir = getSessionDir(project.path, sessionId);
147 ensureDir(dir); 147 ensureDir(dir);
148 fs.writeFileSync(path.join(dir, filename), content, "utf-8"); 148 fs.writeFileSync(path.join(dir, filename), content, "utf-8");
149} 149}
@@ -168,22 +168,17 @@ export function writeClaudeMd(projectPath: string, content: string): void {
168} 168}
169 169
170/** 170/**
171 * Clear session artifacts from global storage 171 * Clear session artifacts
172 */ 172 */
173export function clearSessionArtifacts(projectId: string, sessionId: string): void { 173export function clearSessionArtifacts(projectId: string, sessionId: string): void {
174 const dir = getSessionDir(projectId, sessionId); 174 const project = getProject(projectId);
175 if (!project) return;
176 const dir = getSessionDir(project.path, sessionId);
175 if (fs.existsSync(dir)) { 177 if (fs.existsSync(dir)) {
176 fs.rmSync(dir, { recursive: true, force: true }); 178 fs.rmSync(dir, { recursive: true, force: true });
177 } 179 }
178} 180}
179 181
180/**
181 * Get the initial message for a phase
182 */
183export function getPhaseInitialMessage(phase: Phase): string {
184 return getPhaseConfig(phase).initialMessage;
185}
186
187// Re-export types 182// Re-export types
188export type { SDKMessage } from "@anthropic-ai/claude-agent-sdk"; 183export type { SDKMessage } from "@anthropic-ai/claude-agent-sdk";
189export type { Phase, UserPermissionMode } from "./phases"; 184export type { Phase, UserPermissionMode } from "./phases";