@kimuson/claude-code-viewer 0.4.6 → 0.4.8
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/README.md +4 -1
- package/dist/main.js +1385 -871
- package/dist/main.js.map +4 -4
- package/dist/static/assets/ProtectedRoute-DZMKEulP.js +56 -0
- package/dist/static/assets/eye-DJLA18Vn.js +6 -0
- package/dist/static/assets/index-BGKS2Bbu.js +199 -0
- package/dist/static/assets/index-CF6ATi6V.css +1 -0
- package/dist/static/assets/{index-CdW3wSEF.js → index-Ci8QWeAx.js} +2 -2
- package/dist/static/assets/index-vwZSVRGy.js +1 -0
- package/dist/static/assets/label-Mpn74N-5.js +1 -0
- package/dist/static/assets/login-OzgY3CHO.js +11 -0
- package/dist/static/assets/messages-B4nydqXe.js +1 -0
- package/dist/static/assets/messages-DQZZWrCH.js +1 -0
- package/dist/static/assets/messages-DRQIx4IO.js +1 -0
- package/dist/static/assets/{session-CqkSC6oA.js → session-CZ9W8T6v.js} +1 -1
- package/dist/static/assets/{session-Bqd0eFgp.js → session-CgidTvX7.js} +60 -70
- package/dist/static/index.html +2 -2
- package/package.json +18 -9
- package/dist/static/assets/index-C7tocoDE.js +0 -1
- package/dist/static/assets/index-Cl49R9Vk.js +0 -135
- package/dist/static/assets/index-DuTdxGMm.css +0 -1
- package/dist/static/assets/label-RSRHgdFZ.js +0 -105
- package/dist/static/assets/messages-BLhYHIq_.js +0 -1
- package/dist/static/assets/messages-BQx1DYxh.js +0 -1
- package/dist/static/assets/messages-DZXmj7Ql.js +0 -1
package/dist/main.js
CHANGED
|
@@ -6,33 +6,381 @@ import { resolve as resolve6 } from "node:path";
|
|
|
6
6
|
import { NodeContext as NodeContext2 } from "@effect/platform-node";
|
|
7
7
|
import { serve } from "@hono/node-server";
|
|
8
8
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
9
|
-
import { Effect as
|
|
9
|
+
import { Effect as Effect45 } from "effect";
|
|
10
|
+
|
|
11
|
+
// src/server/core/agent-session/index.ts
|
|
12
|
+
import { Layer as Layer3 } from "effect";
|
|
13
|
+
|
|
14
|
+
// src/server/core/agent-session/infrastructure/AgentSessionRepository.ts
|
|
15
|
+
import { FileSystem, Path } from "@effect/platform";
|
|
16
|
+
import { Context, Effect, Layer } from "effect";
|
|
17
|
+
|
|
18
|
+
// src/lib/conversation-schema/index.ts
|
|
19
|
+
import { z as z16 } from "zod";
|
|
20
|
+
|
|
21
|
+
// src/lib/conversation-schema/entry/AssistantEntrySchema.ts
|
|
22
|
+
import { z as z8 } from "zod";
|
|
23
|
+
|
|
24
|
+
// src/lib/conversation-schema/message/AssistantMessageSchema.ts
|
|
25
|
+
import { z as z6 } from "zod";
|
|
26
|
+
|
|
27
|
+
// src/lib/conversation-schema/content/TextContentSchema.ts
|
|
28
|
+
import { z } from "zod";
|
|
29
|
+
var TextContentSchema = z.object({
|
|
30
|
+
type: z.literal("text"),
|
|
31
|
+
text: z.string()
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// src/lib/conversation-schema/content/ThinkingContentSchema.ts
|
|
35
|
+
import { z as z2 } from "zod";
|
|
36
|
+
var ThinkingContentSchema = z2.object({
|
|
37
|
+
type: z2.literal("thinking"),
|
|
38
|
+
thinking: z2.string(),
|
|
39
|
+
signature: z2.string().optional()
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// src/lib/conversation-schema/content/ToolResultContentSchema.ts
|
|
43
|
+
import { z as z4 } from "zod";
|
|
44
|
+
|
|
45
|
+
// src/lib/conversation-schema/content/ImageContentSchema.ts
|
|
46
|
+
import { z as z3 } from "zod";
|
|
47
|
+
var ImageContentSchema = z3.object({
|
|
48
|
+
type: z3.literal("image"),
|
|
49
|
+
source: z3.object({
|
|
50
|
+
type: z3.literal("base64"),
|
|
51
|
+
data: z3.string(),
|
|
52
|
+
media_type: z3.enum(["image/png", "image/jpeg", "image/gif", "image/webp"])
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// src/lib/conversation-schema/content/ToolResultContentSchema.ts
|
|
57
|
+
var ToolResultContentSchema = z4.object({
|
|
58
|
+
type: z4.literal("tool_result"),
|
|
59
|
+
tool_use_id: z4.string(),
|
|
60
|
+
content: z4.union([
|
|
61
|
+
z4.string(),
|
|
62
|
+
z4.array(z4.union([TextContentSchema, ImageContentSchema]))
|
|
63
|
+
]),
|
|
64
|
+
is_error: z4.boolean().optional()
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// src/lib/conversation-schema/content/ToolUseContentSchema.ts
|
|
68
|
+
import { z as z5 } from "zod";
|
|
69
|
+
var ToolUseContentSchema = z5.object({
|
|
70
|
+
type: z5.literal("tool_use"),
|
|
71
|
+
id: z5.string(),
|
|
72
|
+
name: z5.string(),
|
|
73
|
+
input: z5.record(z5.string(), z5.unknown())
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// src/lib/conversation-schema/message/AssistantMessageSchema.ts
|
|
77
|
+
var AssistantMessageContentSchema = z6.union([
|
|
78
|
+
ThinkingContentSchema,
|
|
79
|
+
TextContentSchema,
|
|
80
|
+
ToolUseContentSchema,
|
|
81
|
+
ToolResultContentSchema
|
|
82
|
+
]);
|
|
83
|
+
var AssistantMessageSchema = z6.object({
|
|
84
|
+
id: z6.string(),
|
|
85
|
+
container: z6.null().optional(),
|
|
86
|
+
type: z6.literal("message"),
|
|
87
|
+
role: z6.literal("assistant"),
|
|
88
|
+
model: z6.string(),
|
|
89
|
+
content: z6.array(AssistantMessageContentSchema),
|
|
90
|
+
stop_reason: z6.string().nullable(),
|
|
91
|
+
stop_sequence: z6.string().nullable(),
|
|
92
|
+
usage: z6.object({
|
|
93
|
+
input_tokens: z6.number(),
|
|
94
|
+
cache_creation_input_tokens: z6.number().optional(),
|
|
95
|
+
cache_read_input_tokens: z6.number().optional(),
|
|
96
|
+
cache_creation: z6.object({
|
|
97
|
+
ephemeral_5m_input_tokens: z6.number(),
|
|
98
|
+
ephemeral_1h_input_tokens: z6.number()
|
|
99
|
+
}).optional(),
|
|
100
|
+
output_tokens: z6.number(),
|
|
101
|
+
service_tier: z6.string().nullable().optional(),
|
|
102
|
+
server_tool_use: z6.object({
|
|
103
|
+
web_search_requests: z6.number()
|
|
104
|
+
}).optional()
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// src/lib/conversation-schema/entry/BaseEntrySchema.ts
|
|
109
|
+
import { z as z7 } from "zod";
|
|
110
|
+
var BaseEntrySchema = z7.object({
|
|
111
|
+
// required
|
|
112
|
+
isSidechain: z7.boolean(),
|
|
113
|
+
userType: z7.enum(["external"]),
|
|
114
|
+
cwd: z7.string(),
|
|
115
|
+
sessionId: z7.string(),
|
|
116
|
+
version: z7.string(),
|
|
117
|
+
uuid: z7.uuid(),
|
|
118
|
+
timestamp: z7.string(),
|
|
119
|
+
// nullable
|
|
120
|
+
parentUuid: z7.uuid().nullable(),
|
|
121
|
+
// optional
|
|
122
|
+
isMeta: z7.boolean().optional(),
|
|
123
|
+
toolUseResult: z7.unknown().optional(),
|
|
124
|
+
// スキーマがツールごとに異なりすぎるし利用もしなそうなので unknown
|
|
125
|
+
gitBranch: z7.string().optional(),
|
|
126
|
+
isCompactSummary: z7.boolean().optional()
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// src/lib/conversation-schema/entry/AssistantEntrySchema.ts
|
|
130
|
+
var AssistantEntrySchema = BaseEntrySchema.extend({
|
|
131
|
+
// discriminator
|
|
132
|
+
type: z8.literal("assistant"),
|
|
133
|
+
// required
|
|
134
|
+
message: AssistantMessageSchema,
|
|
135
|
+
// optional
|
|
136
|
+
requestId: z8.string().optional(),
|
|
137
|
+
isApiErrorMessage: z8.boolean().optional()
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// src/lib/conversation-schema/entry/FileHIstorySnapshotEntrySchema.ts
|
|
141
|
+
import { z as z9 } from "zod";
|
|
142
|
+
var FileHistorySnapshotEntrySchema = z9.object({
|
|
143
|
+
// discriminator
|
|
144
|
+
type: z9.literal("file-history-snapshot"),
|
|
145
|
+
// required
|
|
146
|
+
messageId: z9.string(),
|
|
147
|
+
snapshot: z9.object({
|
|
148
|
+
messageId: z9.string(),
|
|
149
|
+
trackedFileBackups: z9.record(z9.string(), z9.unknown()),
|
|
150
|
+
timestamp: z9.string()
|
|
151
|
+
}),
|
|
152
|
+
isSnapshotUpdate: z9.boolean()
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// src/lib/conversation-schema/entry/QueueOperationEntrySchema.ts
|
|
156
|
+
import { z as z11 } from "zod";
|
|
157
|
+
|
|
158
|
+
// src/lib/conversation-schema/content/DocumentContentSchema.ts
|
|
159
|
+
import { z as z10 } from "zod";
|
|
160
|
+
var DocumentContentSchema = z10.object({
|
|
161
|
+
type: z10.literal("document"),
|
|
162
|
+
source: z10.union([
|
|
163
|
+
z10.object({
|
|
164
|
+
media_type: z10.literal("text/plain"),
|
|
165
|
+
type: z10.literal("text"),
|
|
166
|
+
data: z10.string()
|
|
167
|
+
}),
|
|
168
|
+
z10.object({
|
|
169
|
+
media_type: z10.enum(["application/pdf"]),
|
|
170
|
+
type: z10.literal("base64"),
|
|
171
|
+
data: z10.string()
|
|
172
|
+
})
|
|
173
|
+
])
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// src/lib/conversation-schema/entry/QueueOperationEntrySchema.ts
|
|
177
|
+
var QueueOperationContentSchema = z11.union([
|
|
178
|
+
z11.string(),
|
|
179
|
+
TextContentSchema,
|
|
180
|
+
ToolResultContentSchema,
|
|
181
|
+
ImageContentSchema,
|
|
182
|
+
DocumentContentSchema
|
|
183
|
+
]);
|
|
184
|
+
var QueueOperationEntrySchema = z11.union([
|
|
185
|
+
z11.object({
|
|
186
|
+
type: z11.literal("queue-operation"),
|
|
187
|
+
operation: z11.literal("enqueue"),
|
|
188
|
+
content: z11.union([
|
|
189
|
+
z11.string(),
|
|
190
|
+
z11.array(z11.union([z11.string(), QueueOperationContentSchema]))
|
|
191
|
+
]),
|
|
192
|
+
sessionId: z11.string(),
|
|
193
|
+
timestamp: z11.iso.datetime()
|
|
194
|
+
}),
|
|
195
|
+
z11.object({
|
|
196
|
+
type: z11.literal("queue-operation"),
|
|
197
|
+
operation: z11.literal("dequeue"),
|
|
198
|
+
sessionId: z11.string(),
|
|
199
|
+
timestamp: z11.iso.datetime()
|
|
200
|
+
})
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
// src/lib/conversation-schema/entry/SummaryEntrySchema.ts
|
|
204
|
+
import { z as z12 } from "zod";
|
|
205
|
+
var SummaryEntrySchema = z12.object({
|
|
206
|
+
type: z12.literal("summary"),
|
|
207
|
+
summary: z12.string(),
|
|
208
|
+
leafUuid: z12.string().uuid()
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// src/lib/conversation-schema/entry/SystemEntrySchema.ts
|
|
212
|
+
import { z as z13 } from "zod";
|
|
213
|
+
var SystemEntrySchema = BaseEntrySchema.extend({
|
|
214
|
+
// discriminator
|
|
215
|
+
type: z13.literal("system"),
|
|
216
|
+
// required
|
|
217
|
+
content: z13.string(),
|
|
218
|
+
toolUseID: z13.string(),
|
|
219
|
+
level: z13.enum(["info"])
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// src/lib/conversation-schema/entry/UserEntrySchema.ts
|
|
223
|
+
import { z as z15 } from "zod";
|
|
224
|
+
|
|
225
|
+
// src/lib/conversation-schema/message/UserMessageSchema.ts
|
|
226
|
+
import { z as z14 } from "zod";
|
|
227
|
+
var UserMessageContentSchema = z14.union([
|
|
228
|
+
z14.string(),
|
|
229
|
+
TextContentSchema,
|
|
230
|
+
ToolResultContentSchema,
|
|
231
|
+
ImageContentSchema,
|
|
232
|
+
DocumentContentSchema
|
|
233
|
+
]);
|
|
234
|
+
var UserMessageSchema = z14.object({
|
|
235
|
+
role: z14.literal("user"),
|
|
236
|
+
content: z14.union([
|
|
237
|
+
z14.string(),
|
|
238
|
+
z14.array(z14.union([z14.string(), UserMessageContentSchema]))
|
|
239
|
+
])
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// src/lib/conversation-schema/entry/UserEntrySchema.ts
|
|
243
|
+
var UserEntrySchema = BaseEntrySchema.extend({
|
|
244
|
+
// discriminator
|
|
245
|
+
type: z15.literal("user"),
|
|
246
|
+
// required
|
|
247
|
+
message: UserMessageSchema
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// src/lib/conversation-schema/index.ts
|
|
251
|
+
var ConversationSchema = z16.union([
|
|
252
|
+
UserEntrySchema,
|
|
253
|
+
AssistantEntrySchema,
|
|
254
|
+
SummaryEntrySchema,
|
|
255
|
+
SystemEntrySchema,
|
|
256
|
+
FileHistorySnapshotEntrySchema,
|
|
257
|
+
QueueOperationEntrySchema
|
|
258
|
+
]);
|
|
259
|
+
|
|
260
|
+
// src/server/core/claude-code/functions/parseJsonl.ts
|
|
261
|
+
var parseJsonl = (content) => {
|
|
262
|
+
const lines = content.trim().split("\n").filter((line) => line.trim() !== "");
|
|
263
|
+
return lines.map((line, index) => {
|
|
264
|
+
const parsed = ConversationSchema.safeParse(JSON.parse(line));
|
|
265
|
+
if (!parsed.success) {
|
|
266
|
+
const errorData = {
|
|
267
|
+
type: "x-error",
|
|
268
|
+
line,
|
|
269
|
+
lineNumber: index + 1
|
|
270
|
+
};
|
|
271
|
+
return errorData;
|
|
272
|
+
}
|
|
273
|
+
return parsed.data;
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// src/server/core/project/functions/id.ts
|
|
278
|
+
import { dirname } from "node:path";
|
|
279
|
+
var encodeProjectId = (fullPath) => {
|
|
280
|
+
return Buffer.from(fullPath).toString("base64url");
|
|
281
|
+
};
|
|
282
|
+
var decodeProjectId = (id) => {
|
|
283
|
+
return Buffer.from(id, "base64url").toString("utf-8");
|
|
284
|
+
};
|
|
285
|
+
var encodeProjectIdFromSessionFilePath = (sessionFilePath) => {
|
|
286
|
+
return encodeProjectId(dirname(sessionFilePath));
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/server/core/agent-session/infrastructure/AgentSessionRepository.ts
|
|
290
|
+
var LayerImpl = Effect.gen(function* () {
|
|
291
|
+
const fs = yield* FileSystem.FileSystem;
|
|
292
|
+
const path = yield* Path.Path;
|
|
293
|
+
const getAgentSessionByAgentId = (projectId, agentId) => Effect.gen(function* () {
|
|
294
|
+
const projectPath = decodeProjectId(projectId);
|
|
295
|
+
const agentFilePath = path.resolve(projectPath, `agent-${agentId}.jsonl`);
|
|
296
|
+
const exists = yield* fs.exists(agentFilePath);
|
|
297
|
+
if (!exists) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
const content = yield* fs.readFileString(agentFilePath);
|
|
301
|
+
const conversations = parseJsonl(content);
|
|
302
|
+
return conversations;
|
|
303
|
+
});
|
|
304
|
+
return {
|
|
305
|
+
getAgentSessionByAgentId
|
|
306
|
+
};
|
|
307
|
+
});
|
|
308
|
+
var AgentSessionRepository = class extends Context.Tag(
|
|
309
|
+
"AgentSessionRepository"
|
|
310
|
+
)() {
|
|
311
|
+
static {
|
|
312
|
+
this.Live = Layer.effect(this, LayerImpl);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// src/server/core/agent-session/presentation/AgentSessionController.ts
|
|
317
|
+
import { Context as Context2, Effect as Effect2, Layer as Layer2 } from "effect";
|
|
318
|
+
var LayerImpl2 = Effect2.gen(function* () {
|
|
319
|
+
const repository = yield* AgentSessionRepository;
|
|
320
|
+
const getAgentSession = (params) => Effect2.gen(function* () {
|
|
321
|
+
const { projectId, agentId } = params;
|
|
322
|
+
const conversations = yield* repository.getAgentSessionByAgentId(
|
|
323
|
+
projectId,
|
|
324
|
+
agentId
|
|
325
|
+
);
|
|
326
|
+
if (conversations === null) {
|
|
327
|
+
return {
|
|
328
|
+
status: 200,
|
|
329
|
+
response: {
|
|
330
|
+
agentSessionId: null,
|
|
331
|
+
conversations: []
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
status: 200,
|
|
337
|
+
response: {
|
|
338
|
+
agentSessionId: agentId,
|
|
339
|
+
conversations
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
getAgentSession
|
|
345
|
+
};
|
|
346
|
+
});
|
|
347
|
+
var AgentSessionController = class extends Context2.Tag(
|
|
348
|
+
"AgentSessionController"
|
|
349
|
+
)() {
|
|
350
|
+
static {
|
|
351
|
+
this.Live = Layer2.effect(this, LayerImpl2);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// src/server/core/agent-session/index.ts
|
|
356
|
+
var AgentSessionLayer = Layer3.mergeAll(AgentSessionRepository.Live);
|
|
10
357
|
|
|
11
358
|
// src/server/core/claude-code/presentation/ClaudeCodeController.ts
|
|
12
|
-
import { FileSystem as
|
|
13
|
-
import { Context as
|
|
359
|
+
import { FileSystem as FileSystem6, Path as Path8 } from "@effect/platform";
|
|
360
|
+
import { Context as Context9, Effect as Effect12, Layer as Layer11 } from "effect";
|
|
14
361
|
|
|
15
362
|
// src/server/core/platform/services/ApplicationContext.ts
|
|
16
363
|
import { homedir } from "node:os";
|
|
17
|
-
import { Path } from "@effect/platform";
|
|
18
|
-
import { Effect as
|
|
364
|
+
import { Path as Path2 } from "@effect/platform";
|
|
365
|
+
import { Effect as Effect4, Context as EffectContext, Layer as Layer5 } from "effect";
|
|
19
366
|
|
|
20
367
|
// src/server/core/platform/services/EnvService.ts
|
|
21
|
-
import { Context, Effect, Layer, Ref } from "effect";
|
|
368
|
+
import { Context as Context3, Effect as Effect3, Layer as Layer4, Ref } from "effect";
|
|
22
369
|
|
|
23
370
|
// src/server/core/platform/schema.ts
|
|
24
|
-
import { z } from "zod";
|
|
25
|
-
var envSchema =
|
|
26
|
-
NODE_ENV:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
371
|
+
import { z as z17 } from "zod";
|
|
372
|
+
var envSchema = z17.object({
|
|
373
|
+
NODE_ENV: z17.enum(["development", "production", "test"]).optional().default("development"),
|
|
374
|
+
GLOBAL_CLAUDE_DIR: z17.string().optional(),
|
|
375
|
+
NEXT_PHASE: z17.string().optional(),
|
|
376
|
+
PORT: z17.string().optional().default("3000").transform((val) => parseInt(val, 10)),
|
|
377
|
+
PATH: z17.string().optional(),
|
|
378
|
+
CLAUDE_CODE_VIEWER_CC_EXECUTABLE_PATH: z17.string().optional(),
|
|
379
|
+
CLAUDE_CODE_VIEWER_AUTH_PASSWORD: z17.string().optional()
|
|
32
380
|
});
|
|
33
381
|
|
|
34
382
|
// src/server/core/platform/services/EnvService.ts
|
|
35
|
-
var
|
|
383
|
+
var LayerImpl3 = Effect3.gen(function* () {
|
|
36
384
|
const envRef = yield* Ref.make(void 0);
|
|
37
385
|
const parseEnv = () => {
|
|
38
386
|
const parsed = envSchema.safeParse(process.env);
|
|
@@ -43,7 +391,7 @@ var LayerImpl = Effect.gen(function* () {
|
|
|
43
391
|
return parsed.data;
|
|
44
392
|
};
|
|
45
393
|
const getEnv = (key) => {
|
|
46
|
-
return
|
|
394
|
+
return Effect3.gen(function* () {
|
|
47
395
|
yield* Ref.update(envRef, (existingEnv) => {
|
|
48
396
|
if (existingEnv === void 0) {
|
|
49
397
|
return parseEnv();
|
|
@@ -63,18 +411,18 @@ var LayerImpl = Effect.gen(function* () {
|
|
|
63
411
|
getEnv
|
|
64
412
|
};
|
|
65
413
|
});
|
|
66
|
-
var EnvService = class extends
|
|
414
|
+
var EnvService = class extends Context3.Tag("EnvService")() {
|
|
67
415
|
static {
|
|
68
|
-
this.Live =
|
|
416
|
+
this.Live = Layer4.effect(this, LayerImpl3);
|
|
69
417
|
}
|
|
70
418
|
};
|
|
71
419
|
|
|
72
420
|
// src/server/core/platform/services/ApplicationContext.ts
|
|
73
|
-
var
|
|
74
|
-
const path = yield*
|
|
421
|
+
var LayerImpl4 = Effect4.gen(function* () {
|
|
422
|
+
const path = yield* Path2.Path;
|
|
75
423
|
const envService = yield* EnvService;
|
|
76
424
|
const globalClaudeDirectoryPath = yield* envService.getEnv("GLOBAL_CLAUDE_DIR").pipe(
|
|
77
|
-
|
|
425
|
+
Effect4.map(
|
|
78
426
|
(envVar) => envVar === void 0 ? path.resolve(homedir(), ".claude") : path.resolve(envVar)
|
|
79
427
|
)
|
|
80
428
|
);
|
|
@@ -89,38 +437,26 @@ var LayerImpl2 = Effect2.gen(function* () {
|
|
|
89
437
|
});
|
|
90
438
|
var ApplicationContext = class extends EffectContext.Tag("ApplicationContext")() {
|
|
91
439
|
static {
|
|
92
|
-
this.Live =
|
|
440
|
+
this.Live = Layer5.effect(this, LayerImpl4);
|
|
93
441
|
}
|
|
94
442
|
};
|
|
95
443
|
|
|
96
444
|
// src/server/core/project/infrastructure/ProjectRepository.ts
|
|
97
|
-
import { FileSystem as
|
|
98
|
-
import { Context as
|
|
99
|
-
|
|
100
|
-
// src/server/core/project/functions/id.ts
|
|
101
|
-
import { dirname } from "node:path";
|
|
102
|
-
var encodeProjectId = (fullPath) => {
|
|
103
|
-
return Buffer.from(fullPath).toString("base64url");
|
|
104
|
-
};
|
|
105
|
-
var decodeProjectId = (id) => {
|
|
106
|
-
return Buffer.from(id, "base64url").toString("utf-8");
|
|
107
|
-
};
|
|
108
|
-
var encodeProjectIdFromSessionFilePath = (sessionFilePath) => {
|
|
109
|
-
return encodeProjectId(dirname(sessionFilePath));
|
|
110
|
-
};
|
|
445
|
+
import { FileSystem as FileSystem4, Path as Path5 } from "@effect/platform";
|
|
446
|
+
import { Context as Context7, Effect as Effect8, Layer as Layer9, Option as Option2 } from "effect";
|
|
111
447
|
|
|
112
448
|
// src/server/core/project/services/ProjectMetaService.ts
|
|
113
|
-
import { FileSystem as
|
|
114
|
-
import { Context as
|
|
449
|
+
import { FileSystem as FileSystem3, Path as Path4 } from "@effect/platform";
|
|
450
|
+
import { Context as Context6, Effect as Effect7, Layer as Layer8, Option, Ref as Ref3 } from "effect";
|
|
115
451
|
import { z as z19 } from "zod";
|
|
116
452
|
|
|
117
453
|
// src/server/lib/storage/FileCacheStorage/index.ts
|
|
118
|
-
import { Context as
|
|
454
|
+
import { Context as Context5, Effect as Effect6, Layer as Layer7, Ref as Ref2, Runtime } from "effect";
|
|
119
455
|
|
|
120
456
|
// src/server/lib/storage/FileCacheStorage/PersistentService.ts
|
|
121
|
-
import { FileSystem, Path as
|
|
122
|
-
import { Context as
|
|
123
|
-
import { z as
|
|
457
|
+
import { FileSystem as FileSystem2, Path as Path3 } from "@effect/platform";
|
|
458
|
+
import { Context as Context4, Effect as Effect5, Layer as Layer6 } from "effect";
|
|
459
|
+
import { z as z18 } from "zod";
|
|
124
460
|
|
|
125
461
|
// src/server/lib/config/paths.ts
|
|
126
462
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -132,14 +468,14 @@ var claudeCodeViewerCacheDirPath = resolve(
|
|
|
132
468
|
);
|
|
133
469
|
|
|
134
470
|
// src/server/lib/storage/FileCacheStorage/PersistentService.ts
|
|
135
|
-
var saveSchema =
|
|
136
|
-
var
|
|
137
|
-
const path = yield*
|
|
471
|
+
var saveSchema = z18.array(z18.tuple([z18.string(), z18.unknown()]));
|
|
472
|
+
var LayerImpl5 = Effect5.gen(function* () {
|
|
473
|
+
const path = yield* Path3.Path;
|
|
138
474
|
const getCacheFilePath = (key) => path.resolve(claudeCodeViewerCacheDirPath, `${key}.json`);
|
|
139
475
|
const load = (key) => {
|
|
140
476
|
const cacheFilePath = getCacheFilePath(key);
|
|
141
|
-
return
|
|
142
|
-
const fs = yield*
|
|
477
|
+
return Effect5.gen(function* () {
|
|
478
|
+
const fs = yield* FileSystem2.FileSystem;
|
|
143
479
|
if (!(yield* fs.exists(claudeCodeViewerCacheDirPath))) {
|
|
144
480
|
yield* fs.makeDirectory(claudeCodeViewerCacheDirPath, {
|
|
145
481
|
recursive: true
|
|
@@ -169,8 +505,8 @@ var LayerImpl3 = Effect3.gen(function* () {
|
|
|
169
505
|
};
|
|
170
506
|
const save = (key, entries) => {
|
|
171
507
|
const cacheFilePath = getCacheFilePath(key);
|
|
172
|
-
return
|
|
173
|
-
const fs = yield*
|
|
508
|
+
return Effect5.gen(function* () {
|
|
509
|
+
const fs = yield* FileSystem2.FileSystem;
|
|
174
510
|
yield* fs.writeFileString(cacheFilePath, JSON.stringify(entries));
|
|
175
511
|
});
|
|
176
512
|
};
|
|
@@ -179,20 +515,20 @@ var LayerImpl3 = Effect3.gen(function* () {
|
|
|
179
515
|
save
|
|
180
516
|
};
|
|
181
517
|
});
|
|
182
|
-
var PersistentService = class extends
|
|
518
|
+
var PersistentService = class extends Context4.Tag("PersistentService")() {
|
|
183
519
|
static {
|
|
184
|
-
this.Live =
|
|
520
|
+
this.Live = Layer6.effect(this, LayerImpl5);
|
|
185
521
|
}
|
|
186
522
|
};
|
|
187
523
|
|
|
188
524
|
// src/server/lib/storage/FileCacheStorage/index.ts
|
|
189
|
-
var FileCacheStorage = () =>
|
|
190
|
-
var makeFileCacheStorageLayer = (storageKey, schema) =>
|
|
525
|
+
var FileCacheStorage = () => Context5.GenericTag("FileCacheStorage");
|
|
526
|
+
var makeFileCacheStorageLayer = (storageKey, schema) => Layer7.effect(
|
|
191
527
|
FileCacheStorage(),
|
|
192
|
-
|
|
528
|
+
Effect6.gen(function* () {
|
|
193
529
|
const persistentService = yield* PersistentService;
|
|
194
|
-
const runtime = yield*
|
|
195
|
-
const storageRef = yield*
|
|
530
|
+
const runtime = yield* Effect6.runtime();
|
|
531
|
+
const storageRef = yield* Effect6.gen(function* () {
|
|
196
532
|
const persistedData = yield* persistentService.load(storageKey);
|
|
197
533
|
const initialMap = /* @__PURE__ */ new Map();
|
|
198
534
|
for (const [key, value] of persistedData) {
|
|
@@ -206,311 +542,52 @@ var makeFileCacheStorageLayer = (storageKey, schema) => Layer4.effect(
|
|
|
206
542
|
const syncToFile = (entries) => {
|
|
207
543
|
Runtime.runFork(runtime)(persistentService.save(storageKey, entries));
|
|
208
544
|
};
|
|
209
|
-
return {
|
|
210
|
-
get: (key) =>
|
|
211
|
-
const storage = yield* Ref2.get(storageRef);
|
|
212
|
-
return storage.get(key);
|
|
213
|
-
}),
|
|
214
|
-
set: (key, value) =>
|
|
215
|
-
const before = yield* Ref2.get(storageRef);
|
|
216
|
-
const beforeString = JSON.stringify(Array.from(before.entries()));
|
|
217
|
-
yield* Ref2.update(storageRef, (map) => {
|
|
218
|
-
map.set(key, value);
|
|
219
|
-
return map;
|
|
220
|
-
});
|
|
221
|
-
const after = yield* Ref2.get(storageRef);
|
|
222
|
-
const afterString = JSON.stringify(Array.from(after.entries()));
|
|
223
|
-
if (beforeString !== afterString) {
|
|
224
|
-
syncToFile(Array.from(after.entries()));
|
|
225
|
-
}
|
|
226
|
-
}),
|
|
227
|
-
invalidate: (key) =>
|
|
228
|
-
const before = yield* Ref2.get(storageRef);
|
|
229
|
-
if (!before.has(key)) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
yield* Ref2.update(storageRef, (map) => {
|
|
233
|
-
map.delete(key);
|
|
234
|
-
return map;
|
|
235
|
-
});
|
|
236
|
-
const after = yield* Ref2.get(storageRef);
|
|
237
|
-
syncToFile(Array.from(after.entries()));
|
|
238
|
-
}),
|
|
239
|
-
getAll: () =>
|
|
240
|
-
const storage = yield* Ref2.get(storageRef);
|
|
241
|
-
return new Map(storage);
|
|
242
|
-
})
|
|
243
|
-
};
|
|
244
|
-
})
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
// src/lib/conversation-schema/index.ts
|
|
248
|
-
import { z as z18 } from "zod";
|
|
249
|
-
|
|
250
|
-
// src/lib/conversation-schema/entry/AssistantEntrySchema.ts
|
|
251
|
-
import { z as z10 } from "zod";
|
|
252
|
-
|
|
253
|
-
// src/lib/conversation-schema/message/AssistantMessageSchema.ts
|
|
254
|
-
import { z as z8 } from "zod";
|
|
255
|
-
|
|
256
|
-
// src/lib/conversation-schema/content/TextContentSchema.ts
|
|
257
|
-
import { z as z3 } from "zod";
|
|
258
|
-
var TextContentSchema = z3.object({
|
|
259
|
-
type: z3.literal("text"),
|
|
260
|
-
text: z3.string()
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// src/lib/conversation-schema/content/ThinkingContentSchema.ts
|
|
264
|
-
import { z as z4 } from "zod";
|
|
265
|
-
var ThinkingContentSchema = z4.object({
|
|
266
|
-
type: z4.literal("thinking"),
|
|
267
|
-
thinking: z4.string(),
|
|
268
|
-
signature: z4.string().optional()
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
// src/lib/conversation-schema/content/ToolResultContentSchema.ts
|
|
272
|
-
import { z as z6 } from "zod";
|
|
273
|
-
|
|
274
|
-
// src/lib/conversation-schema/content/ImageContentSchema.ts
|
|
275
|
-
import { z as z5 } from "zod";
|
|
276
|
-
var ImageContentSchema = z5.object({
|
|
277
|
-
type: z5.literal("image"),
|
|
278
|
-
source: z5.object({
|
|
279
|
-
type: z5.literal("base64"),
|
|
280
|
-
data: z5.string(),
|
|
281
|
-
media_type: z5.enum(["image/png", "image/jpeg", "image/gif", "image/webp"])
|
|
282
|
-
})
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
// src/lib/conversation-schema/content/ToolResultContentSchema.ts
|
|
286
|
-
var ToolResultContentSchema = z6.object({
|
|
287
|
-
type: z6.literal("tool_result"),
|
|
288
|
-
tool_use_id: z6.string(),
|
|
289
|
-
content: z6.union([
|
|
290
|
-
z6.string(),
|
|
291
|
-
z6.array(z6.union([TextContentSchema, ImageContentSchema]))
|
|
292
|
-
]),
|
|
293
|
-
is_error: z6.boolean().optional()
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
// src/lib/conversation-schema/content/ToolUseContentSchema.ts
|
|
297
|
-
import { z as z7 } from "zod";
|
|
298
|
-
var ToolUseContentSchema = z7.object({
|
|
299
|
-
type: z7.literal("tool_use"),
|
|
300
|
-
id: z7.string(),
|
|
301
|
-
name: z7.string(),
|
|
302
|
-
input: z7.record(z7.string(), z7.unknown())
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
// src/lib/conversation-schema/message/AssistantMessageSchema.ts
|
|
306
|
-
var AssistantMessageContentSchema = z8.union([
|
|
307
|
-
ThinkingContentSchema,
|
|
308
|
-
TextContentSchema,
|
|
309
|
-
ToolUseContentSchema,
|
|
310
|
-
ToolResultContentSchema
|
|
311
|
-
]);
|
|
312
|
-
var AssistantMessageSchema = z8.object({
|
|
313
|
-
id: z8.string(),
|
|
314
|
-
container: z8.null().optional(),
|
|
315
|
-
type: z8.literal("message"),
|
|
316
|
-
role: z8.literal("assistant"),
|
|
317
|
-
model: z8.string(),
|
|
318
|
-
content: z8.array(AssistantMessageContentSchema),
|
|
319
|
-
stop_reason: z8.string().nullable(),
|
|
320
|
-
stop_sequence: z8.string().nullable(),
|
|
321
|
-
usage: z8.object({
|
|
322
|
-
input_tokens: z8.number(),
|
|
323
|
-
cache_creation_input_tokens: z8.number().optional(),
|
|
324
|
-
cache_read_input_tokens: z8.number().optional(),
|
|
325
|
-
cache_creation: z8.object({
|
|
326
|
-
ephemeral_5m_input_tokens: z8.number(),
|
|
327
|
-
ephemeral_1h_input_tokens: z8.number()
|
|
328
|
-
}).optional(),
|
|
329
|
-
output_tokens: z8.number(),
|
|
330
|
-
service_tier: z8.string().nullable().optional(),
|
|
331
|
-
server_tool_use: z8.object({
|
|
332
|
-
web_search_requests: z8.number()
|
|
333
|
-
}).optional()
|
|
334
|
-
})
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
// src/lib/conversation-schema/entry/BaseEntrySchema.ts
|
|
338
|
-
import { z as z9 } from "zod";
|
|
339
|
-
var BaseEntrySchema = z9.object({
|
|
340
|
-
// required
|
|
341
|
-
isSidechain: z9.boolean(),
|
|
342
|
-
userType: z9.enum(["external"]),
|
|
343
|
-
cwd: z9.string(),
|
|
344
|
-
sessionId: z9.string(),
|
|
345
|
-
version: z9.string(),
|
|
346
|
-
uuid: z9.uuid(),
|
|
347
|
-
timestamp: z9.string(),
|
|
348
|
-
// nullable
|
|
349
|
-
parentUuid: z9.uuid().nullable(),
|
|
350
|
-
// optional
|
|
351
|
-
isMeta: z9.boolean().optional(),
|
|
352
|
-
toolUseResult: z9.unknown().optional(),
|
|
353
|
-
// スキーマがツールごとに異なりすぎるし利用もしなそうなので unknown
|
|
354
|
-
gitBranch: z9.string().optional(),
|
|
355
|
-
isCompactSummary: z9.boolean().optional()
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
// src/lib/conversation-schema/entry/AssistantEntrySchema.ts
|
|
359
|
-
var AssistantEntrySchema = BaseEntrySchema.extend({
|
|
360
|
-
// discriminator
|
|
361
|
-
type: z10.literal("assistant"),
|
|
362
|
-
// required
|
|
363
|
-
message: AssistantMessageSchema,
|
|
364
|
-
// optional
|
|
365
|
-
requestId: z10.string().optional(),
|
|
366
|
-
isApiErrorMessage: z10.boolean().optional()
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
// src/lib/conversation-schema/entry/FileHIstorySnapshotEntrySchema.ts
|
|
370
|
-
import { z as z11 } from "zod";
|
|
371
|
-
var FileHistorySnapshotEntrySchema = z11.object({
|
|
372
|
-
// discriminator
|
|
373
|
-
type: z11.literal("file-history-snapshot"),
|
|
374
|
-
// required
|
|
375
|
-
messageId: z11.string(),
|
|
376
|
-
snapshot: z11.object({
|
|
377
|
-
messageId: z11.string(),
|
|
378
|
-
trackedFileBackups: z11.record(z11.string(), z11.unknown()),
|
|
379
|
-
timestamp: z11.string()
|
|
380
|
-
}),
|
|
381
|
-
isSnapshotUpdate: z11.boolean()
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// src/lib/conversation-schema/entry/QueueOperationEntrySchema.ts
|
|
385
|
-
import { z as z13 } from "zod";
|
|
386
|
-
|
|
387
|
-
// src/lib/conversation-schema/content/DocumentContentSchema.ts
|
|
388
|
-
import { z as z12 } from "zod";
|
|
389
|
-
var DocumentContentSchema = z12.object({
|
|
390
|
-
type: z12.literal("document"),
|
|
391
|
-
source: z12.union([
|
|
392
|
-
z12.object({
|
|
393
|
-
media_type: z12.literal("text/plain"),
|
|
394
|
-
type: z12.literal("text"),
|
|
395
|
-
data: z12.string()
|
|
396
|
-
}),
|
|
397
|
-
z12.object({
|
|
398
|
-
media_type: z12.enum(["application/pdf"]),
|
|
399
|
-
type: z12.literal("base64"),
|
|
400
|
-
data: z12.string()
|
|
401
|
-
})
|
|
402
|
-
])
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
// src/lib/conversation-schema/entry/QueueOperationEntrySchema.ts
|
|
406
|
-
var QueueOperationContentSchema = z13.union([
|
|
407
|
-
z13.string(),
|
|
408
|
-
TextContentSchema,
|
|
409
|
-
ToolResultContentSchema,
|
|
410
|
-
ImageContentSchema,
|
|
411
|
-
DocumentContentSchema
|
|
412
|
-
]);
|
|
413
|
-
var QueueOperationEntrySchema = z13.union([
|
|
414
|
-
z13.object({
|
|
415
|
-
type: z13.literal("queue-operation"),
|
|
416
|
-
operation: z13.literal("enqueue"),
|
|
417
|
-
content: z13.union([
|
|
418
|
-
z13.string(),
|
|
419
|
-
z13.array(z13.union([z13.string(), QueueOperationContentSchema]))
|
|
420
|
-
]),
|
|
421
|
-
sessionId: z13.string(),
|
|
422
|
-
timestamp: z13.iso.datetime()
|
|
423
|
-
}),
|
|
424
|
-
z13.object({
|
|
425
|
-
type: z13.literal("queue-operation"),
|
|
426
|
-
operation: z13.literal("dequeue"),
|
|
427
|
-
sessionId: z13.string(),
|
|
428
|
-
timestamp: z13.iso.datetime()
|
|
429
|
-
})
|
|
430
|
-
]);
|
|
431
|
-
|
|
432
|
-
// src/lib/conversation-schema/entry/SummaryEntrySchema.ts
|
|
433
|
-
import { z as z14 } from "zod";
|
|
434
|
-
var SummaryEntrySchema = z14.object({
|
|
435
|
-
type: z14.literal("summary"),
|
|
436
|
-
summary: z14.string(),
|
|
437
|
-
leafUuid: z14.string().uuid()
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
// src/lib/conversation-schema/entry/SystemEntrySchema.ts
|
|
441
|
-
import { z as z15 } from "zod";
|
|
442
|
-
var SystemEntrySchema = BaseEntrySchema.extend({
|
|
443
|
-
// discriminator
|
|
444
|
-
type: z15.literal("system"),
|
|
445
|
-
// required
|
|
446
|
-
content: z15.string(),
|
|
447
|
-
toolUseID: z15.string(),
|
|
448
|
-
level: z15.enum(["info"])
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
// src/lib/conversation-schema/entry/UserEntrySchema.ts
|
|
452
|
-
import { z as z17 } from "zod";
|
|
453
|
-
|
|
454
|
-
// src/lib/conversation-schema/message/UserMessageSchema.ts
|
|
455
|
-
import { z as z16 } from "zod";
|
|
456
|
-
var UserMessageContentSchema = z16.union([
|
|
457
|
-
z16.string(),
|
|
458
|
-
TextContentSchema,
|
|
459
|
-
ToolResultContentSchema,
|
|
460
|
-
ImageContentSchema,
|
|
461
|
-
DocumentContentSchema
|
|
462
|
-
]);
|
|
463
|
-
var UserMessageSchema = z16.object({
|
|
464
|
-
role: z16.literal("user"),
|
|
465
|
-
content: z16.union([
|
|
466
|
-
z16.string(),
|
|
467
|
-
z16.array(z16.union([z16.string(), UserMessageContentSchema]))
|
|
468
|
-
])
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
// src/lib/conversation-schema/entry/UserEntrySchema.ts
|
|
472
|
-
var UserEntrySchema = BaseEntrySchema.extend({
|
|
473
|
-
// discriminator
|
|
474
|
-
type: z17.literal("user"),
|
|
475
|
-
// required
|
|
476
|
-
message: UserMessageSchema
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
// src/lib/conversation-schema/index.ts
|
|
480
|
-
var ConversationSchema = z18.union([
|
|
481
|
-
UserEntrySchema,
|
|
482
|
-
AssistantEntrySchema,
|
|
483
|
-
SummaryEntrySchema,
|
|
484
|
-
SystemEntrySchema,
|
|
485
|
-
FileHistorySnapshotEntrySchema,
|
|
486
|
-
QueueOperationEntrySchema
|
|
487
|
-
]);
|
|
488
|
-
|
|
489
|
-
// src/server/core/claude-code/functions/parseJsonl.ts
|
|
490
|
-
var parseJsonl = (content) => {
|
|
491
|
-
const lines = content.trim().split("\n").filter((line) => line.trim() !== "");
|
|
492
|
-
return lines.map((line, index) => {
|
|
493
|
-
const parsed = ConversationSchema.safeParse(JSON.parse(line));
|
|
494
|
-
if (!parsed.success) {
|
|
495
|
-
const errorData = {
|
|
496
|
-
type: "x-error",
|
|
497
|
-
line,
|
|
498
|
-
lineNumber: index + 1
|
|
499
|
-
};
|
|
500
|
-
return errorData;
|
|
501
|
-
}
|
|
502
|
-
return parsed.data;
|
|
503
|
-
});
|
|
504
|
-
};
|
|
545
|
+
return {
|
|
546
|
+
get: (key) => Effect6.gen(function* () {
|
|
547
|
+
const storage = yield* Ref2.get(storageRef);
|
|
548
|
+
return storage.get(key);
|
|
549
|
+
}),
|
|
550
|
+
set: (key, value) => Effect6.gen(function* () {
|
|
551
|
+
const before = yield* Ref2.get(storageRef);
|
|
552
|
+
const beforeString = JSON.stringify(Array.from(before.entries()));
|
|
553
|
+
yield* Ref2.update(storageRef, (map) => {
|
|
554
|
+
map.set(key, value);
|
|
555
|
+
return map;
|
|
556
|
+
});
|
|
557
|
+
const after = yield* Ref2.get(storageRef);
|
|
558
|
+
const afterString = JSON.stringify(Array.from(after.entries()));
|
|
559
|
+
if (beforeString !== afterString) {
|
|
560
|
+
syncToFile(Array.from(after.entries()));
|
|
561
|
+
}
|
|
562
|
+
}),
|
|
563
|
+
invalidate: (key) => Effect6.gen(function* () {
|
|
564
|
+
const before = yield* Ref2.get(storageRef);
|
|
565
|
+
if (!before.has(key)) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
yield* Ref2.update(storageRef, (map) => {
|
|
569
|
+
map.delete(key);
|
|
570
|
+
return map;
|
|
571
|
+
});
|
|
572
|
+
const after = yield* Ref2.get(storageRef);
|
|
573
|
+
syncToFile(Array.from(after.entries()));
|
|
574
|
+
}),
|
|
575
|
+
getAll: () => Effect6.gen(function* () {
|
|
576
|
+
const storage = yield* Ref2.get(storageRef);
|
|
577
|
+
return new Map(storage);
|
|
578
|
+
})
|
|
579
|
+
};
|
|
580
|
+
})
|
|
581
|
+
);
|
|
505
582
|
|
|
506
583
|
// src/server/core/project/services/ProjectMetaService.ts
|
|
507
584
|
var ProjectPathSchema = z19.string().nullable();
|
|
508
|
-
var
|
|
509
|
-
const fs = yield*
|
|
510
|
-
const path = yield*
|
|
585
|
+
var LayerImpl6 = Effect7.gen(function* () {
|
|
586
|
+
const fs = yield* FileSystem3.FileSystem;
|
|
587
|
+
const path = yield* Path4.Path;
|
|
511
588
|
const projectPathCache = yield* FileCacheStorage();
|
|
512
589
|
const projectMetaCacheRef = yield* Ref3.make(/* @__PURE__ */ new Map());
|
|
513
|
-
const extractProjectPathFromJsonl = (filePath) =>
|
|
590
|
+
const extractProjectPathFromJsonl = (filePath) => Effect7.gen(function* () {
|
|
514
591
|
const cached = yield* projectPathCache.get(filePath);
|
|
515
592
|
if (cached !== void 0) {
|
|
516
593
|
return cached;
|
|
@@ -531,7 +608,7 @@ var LayerImpl4 = Effect5.gen(function* () {
|
|
|
531
608
|
}
|
|
532
609
|
return cwd;
|
|
533
610
|
});
|
|
534
|
-
const getProjectMeta = (projectId) =>
|
|
611
|
+
const getProjectMeta = (projectId) => Effect7.gen(function* () {
|
|
535
612
|
const metaCache = yield* Ref3.get(projectMetaCacheRef);
|
|
536
613
|
const cached = metaCache.get(projectId);
|
|
537
614
|
if (cached !== void 0) {
|
|
@@ -539,9 +616,9 @@ var LayerImpl4 = Effect5.gen(function* () {
|
|
|
539
616
|
}
|
|
540
617
|
const claudeProjectPath = decodeProjectId(projectId);
|
|
541
618
|
const dirents = yield* fs.readDirectory(claudeProjectPath);
|
|
542
|
-
const fileEntries = yield*
|
|
619
|
+
const fileEntries = yield* Effect7.all(
|
|
543
620
|
dirents.filter((name) => name.endsWith(".jsonl")).map(
|
|
544
|
-
(name) =>
|
|
621
|
+
(name) => Effect7.gen(function* () {
|
|
545
622
|
const fullPath = path.resolve(claudeProjectPath, name);
|
|
546
623
|
const stat = yield* fs.stat(fullPath);
|
|
547
624
|
const mtime = Option.getOrElse(stat.mtime, () => /* @__PURE__ */ new Date(0));
|
|
@@ -575,7 +652,7 @@ var LayerImpl4 = Effect5.gen(function* () {
|
|
|
575
652
|
});
|
|
576
653
|
return projectMeta;
|
|
577
654
|
});
|
|
578
|
-
const invalidateProject = (projectId) =>
|
|
655
|
+
const invalidateProject = (projectId) => Effect7.gen(function* () {
|
|
579
656
|
yield* Ref3.update(projectMetaCacheRef, (cache) => {
|
|
580
657
|
cache.delete(projectId);
|
|
581
658
|
return cache;
|
|
@@ -586,28 +663,28 @@ var LayerImpl4 = Effect5.gen(function* () {
|
|
|
586
663
|
invalidateProject
|
|
587
664
|
};
|
|
588
665
|
});
|
|
589
|
-
var ProjectMetaService = class extends
|
|
666
|
+
var ProjectMetaService = class extends Context6.Tag("ProjectMetaService")() {
|
|
590
667
|
static {
|
|
591
|
-
this.Live =
|
|
592
|
-
|
|
668
|
+
this.Live = Layer8.effect(this, LayerImpl6).pipe(
|
|
669
|
+
Layer8.provide(
|
|
593
670
|
makeFileCacheStorageLayer("project-path-cache", ProjectPathSchema)
|
|
594
671
|
),
|
|
595
|
-
|
|
672
|
+
Layer8.provide(PersistentService.Live)
|
|
596
673
|
);
|
|
597
674
|
}
|
|
598
675
|
};
|
|
599
676
|
|
|
600
677
|
// src/server/core/project/infrastructure/ProjectRepository.ts
|
|
601
|
-
var
|
|
602
|
-
const fs = yield*
|
|
603
|
-
const path = yield*
|
|
678
|
+
var LayerImpl7 = Effect8.gen(function* () {
|
|
679
|
+
const fs = yield* FileSystem4.FileSystem;
|
|
680
|
+
const path = yield* Path5.Path;
|
|
604
681
|
const projectMetaService = yield* ProjectMetaService;
|
|
605
682
|
const context = yield* ApplicationContext;
|
|
606
|
-
const getProject = (projectId) =>
|
|
683
|
+
const getProject = (projectId) => Effect8.gen(function* () {
|
|
607
684
|
const fullPath = decodeProjectId(projectId);
|
|
608
685
|
const exists = yield* fs.exists(fullPath);
|
|
609
686
|
if (!exists) {
|
|
610
|
-
return yield*
|
|
687
|
+
return yield* Effect8.fail(new Error("Project not found"));
|
|
611
688
|
}
|
|
612
689
|
const stat = yield* fs.stat(fullPath);
|
|
613
690
|
const meta = yield* projectMetaService.getProjectMeta(projectId);
|
|
@@ -620,7 +697,7 @@ var LayerImpl5 = Effect6.gen(function* () {
|
|
|
620
697
|
}
|
|
621
698
|
};
|
|
622
699
|
});
|
|
623
|
-
const getProjects = () =>
|
|
700
|
+
const getProjects = () => Effect8.gen(function* () {
|
|
624
701
|
const dirExists = yield* fs.exists(
|
|
625
702
|
context.claudeCodePaths.claudeProjectsDirPath
|
|
626
703
|
);
|
|
@@ -634,14 +711,14 @@ var LayerImpl5 = Effect6.gen(function* () {
|
|
|
634
711
|
context.claudeCodePaths.claudeProjectsDirPath
|
|
635
712
|
);
|
|
636
713
|
const projectEffects = entries.map(
|
|
637
|
-
(entry) =>
|
|
714
|
+
(entry) => Effect8.gen(function* () {
|
|
638
715
|
const fullPath = path.resolve(
|
|
639
716
|
context.claudeCodePaths.claudeProjectsDirPath,
|
|
640
717
|
entry
|
|
641
718
|
);
|
|
642
|
-
const stat = yield*
|
|
643
|
-
() => fs.stat(fullPath).pipe(
|
|
644
|
-
).pipe(
|
|
719
|
+
const stat = yield* Effect8.tryPromise(
|
|
720
|
+
() => fs.stat(fullPath).pipe(Effect8.runPromise)
|
|
721
|
+
).pipe(Effect8.catchAll(() => Effect8.succeed(null)));
|
|
645
722
|
if (!stat || stat.type !== "Directory") {
|
|
646
723
|
return null;
|
|
647
724
|
}
|
|
@@ -655,7 +732,7 @@ var LayerImpl5 = Effect6.gen(function* () {
|
|
|
655
732
|
};
|
|
656
733
|
})
|
|
657
734
|
);
|
|
658
|
-
const projectsWithNulls = yield*
|
|
735
|
+
const projectsWithNulls = yield* Effect8.all(projectEffects, {
|
|
659
736
|
concurrency: "unbounded"
|
|
660
737
|
});
|
|
661
738
|
const projects = projectsWithNulls.filter(
|
|
@@ -671,12 +748,57 @@ var LayerImpl5 = Effect6.gen(function* () {
|
|
|
671
748
|
getProjects
|
|
672
749
|
};
|
|
673
750
|
});
|
|
674
|
-
var ProjectRepository = class extends
|
|
751
|
+
var ProjectRepository = class extends Context7.Tag("ProjectRepository")() {
|
|
675
752
|
static {
|
|
676
|
-
this.Live =
|
|
753
|
+
this.Live = Layer9.effect(this, LayerImpl7);
|
|
677
754
|
}
|
|
678
755
|
};
|
|
679
756
|
|
|
757
|
+
// src/server/core/claude-code/functions/scanCommandFiles.ts
|
|
758
|
+
import { FileSystem as FileSystem5, Path as Path6 } from "@effect/platform";
|
|
759
|
+
import { Effect as Effect9 } from "effect";
|
|
760
|
+
var pathToCommandName = (filePath, baseDir) => {
|
|
761
|
+
const normalizedBaseDir = baseDir.endsWith("/") ? baseDir.slice(0, -1) : baseDir;
|
|
762
|
+
const relativePath = filePath.startsWith(normalizedBaseDir) ? filePath.slice(normalizedBaseDir.length + 1) : filePath;
|
|
763
|
+
return relativePath.replace(/\.md$/, "").replace(/\//g, ":");
|
|
764
|
+
};
|
|
765
|
+
var scanCommandFilesRecursively = (dirPath) => Effect9.gen(function* () {
|
|
766
|
+
const fs = yield* FileSystem5.FileSystem;
|
|
767
|
+
const path = yield* Path6.Path;
|
|
768
|
+
const scanDirectory = (currentPath) => Effect9.gen(function* () {
|
|
769
|
+
const exists = yield* fs.exists(currentPath);
|
|
770
|
+
if (!exists) {
|
|
771
|
+
return [];
|
|
772
|
+
}
|
|
773
|
+
const items = yield* fs.readDirectory(currentPath);
|
|
774
|
+
const results = yield* Effect9.forEach(
|
|
775
|
+
items,
|
|
776
|
+
(item) => Effect9.gen(function* () {
|
|
777
|
+
if (item.startsWith(".")) {
|
|
778
|
+
return [];
|
|
779
|
+
}
|
|
780
|
+
const itemPath = path.join(currentPath, item);
|
|
781
|
+
const info = yield* fs.stat(itemPath);
|
|
782
|
+
if (info.type === "Directory") {
|
|
783
|
+
return yield* scanDirectory(itemPath);
|
|
784
|
+
}
|
|
785
|
+
if (info.type === "File" && item.endsWith(".md")) {
|
|
786
|
+
return [pathToCommandName(itemPath, dirPath)];
|
|
787
|
+
}
|
|
788
|
+
return [];
|
|
789
|
+
}),
|
|
790
|
+
{ concurrency: "unbounded" }
|
|
791
|
+
);
|
|
792
|
+
return results.flat();
|
|
793
|
+
});
|
|
794
|
+
return yield* scanDirectory(dirPath).pipe(
|
|
795
|
+
Effect9.match({
|
|
796
|
+
onSuccess: (items) => items,
|
|
797
|
+
onFailure: () => []
|
|
798
|
+
})
|
|
799
|
+
);
|
|
800
|
+
});
|
|
801
|
+
|
|
680
802
|
// src/server/core/claude-code/models/ClaudeCodeVersion.ts
|
|
681
803
|
import { z as z20 } from "zod";
|
|
682
804
|
var versionRegex = /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/;
|
|
@@ -704,7 +826,7 @@ var greaterThan = (a, b) => a.major > b.major || a.major === b.major && (a.minor
|
|
|
704
826
|
var greaterThanOrEqual = (a, b) => equals(a, b) || greaterThan(a, b);
|
|
705
827
|
|
|
706
828
|
// src/server/core/claude-code/services/ClaudeCodeService.ts
|
|
707
|
-
import { Context as
|
|
829
|
+
import { Context as Context8, Data as Data2, Effect as Effect11, Layer as Layer10 } from "effect";
|
|
708
830
|
|
|
709
831
|
// src/server/core/claude-code/functions/parseMcpListOutput.ts
|
|
710
832
|
var parseMcpListOutput = (output) => {
|
|
@@ -732,14 +854,14 @@ import { query as agentSdkQuery } from "@anthropic-ai/claude-agent-sdk";
|
|
|
732
854
|
import {
|
|
733
855
|
query as claudeCodeQuery
|
|
734
856
|
} from "@anthropic-ai/claude-code";
|
|
735
|
-
import { Command, Path as
|
|
736
|
-
import { Data, Effect as
|
|
857
|
+
import { Command, Path as Path7 } from "@effect/platform";
|
|
858
|
+
import { Data, Effect as Effect10 } from "effect";
|
|
737
859
|
var ClaudeCodePathNotFoundError = class extends Data.TaggedError(
|
|
738
860
|
"ClaudeCodePathNotFoundError"
|
|
739
861
|
) {
|
|
740
862
|
};
|
|
741
|
-
var resolveClaudeCodePath =
|
|
742
|
-
const path = yield*
|
|
863
|
+
var resolveClaudeCodePath = Effect10.gen(function* () {
|
|
864
|
+
const path = yield* Path7.Path;
|
|
743
865
|
const envService = yield* EnvService;
|
|
744
866
|
const specifiedExecutablePath = yield* envService.getEnv(
|
|
745
867
|
"CLAUDE_CODE_VIEWER_CC_EXECUTABLE_PATH"
|
|
@@ -756,15 +878,15 @@ var resolveClaudeCodePath = Effect7.gen(function* () {
|
|
|
756
878
|
Command.runInShell(true)
|
|
757
879
|
)
|
|
758
880
|
).pipe(
|
|
759
|
-
|
|
760
|
-
|
|
881
|
+
Effect10.map((output) => output.trim()),
|
|
882
|
+
Effect10.map((output) => output === "" ? null : output),
|
|
761
883
|
// 存在しない時、空文字になる模様
|
|
762
|
-
|
|
884
|
+
Effect10.catchAll(() => Effect10.succeed(null))
|
|
763
885
|
);
|
|
764
886
|
if (whichClaude !== null) {
|
|
765
887
|
return whichClaude;
|
|
766
888
|
}
|
|
767
|
-
const projectClaudeCode = yield*
|
|
889
|
+
const projectClaudeCode = yield* Effect10.try(() => {
|
|
768
890
|
const parts = __dirname.split("/");
|
|
769
891
|
const packagePath = parts.slice(0, parts.indexOf("claude-code-viewer") + 1).join("/");
|
|
770
892
|
return path.join(
|
|
@@ -775,8 +897,8 @@ var resolveClaudeCodePath = Effect7.gen(function* () {
|
|
|
775
897
|
"cli.js"
|
|
776
898
|
);
|
|
777
899
|
}).pipe(
|
|
778
|
-
|
|
779
|
-
return
|
|
900
|
+
Effect10.catchAll(() => {
|
|
901
|
+
return Effect10.fail(
|
|
780
902
|
new ClaudeCodePathNotFoundError({
|
|
781
903
|
message: "Claude Code CLI not found in any location"
|
|
782
904
|
})
|
|
@@ -785,7 +907,7 @@ var resolveClaudeCodePath = Effect7.gen(function* () {
|
|
|
785
907
|
);
|
|
786
908
|
return projectClaudeCode;
|
|
787
909
|
});
|
|
788
|
-
var Config =
|
|
910
|
+
var Config = Effect10.gen(function* () {
|
|
789
911
|
const claudeCodeExecutablePath = yield* resolveClaudeCodePath;
|
|
790
912
|
const claudeCodeVersion = fromCLIString(
|
|
791
913
|
yield* Command.string(Command.make(claudeCodeExecutablePath, "--version"))
|
|
@@ -795,7 +917,7 @@ var Config = Effect7.gen(function* () {
|
|
|
795
917
|
claudeCodeVersion
|
|
796
918
|
};
|
|
797
919
|
});
|
|
798
|
-
var getMcpListOutput = (projectCwd) =>
|
|
920
|
+
var getMcpListOutput = (projectCwd) => Effect10.gen(function* () {
|
|
799
921
|
const { claudeCodeExecutablePath } = yield* Config;
|
|
800
922
|
const output = yield* Command.string(
|
|
801
923
|
Command.make(
|
|
@@ -825,11 +947,17 @@ var getAvailableFeatures = (claudeCodeVersion) => ({
|
|
|
825
947
|
minor: 0,
|
|
826
948
|
patch: 125
|
|
827
949
|
// ClaudeCodeAgentSDK is available since v1.0.125
|
|
950
|
+
}) : false,
|
|
951
|
+
sidechainSeparation: claudeCodeVersion !== null ? greaterThanOrEqual(claudeCodeVersion, {
|
|
952
|
+
major: 2,
|
|
953
|
+
minor: 0,
|
|
954
|
+
patch: 28
|
|
955
|
+
// Sidechain conversations stored in agent-*.jsonl since v2.0.28
|
|
828
956
|
}) : false
|
|
829
957
|
});
|
|
830
958
|
var query = (prompt, options) => {
|
|
831
959
|
const { canUseTool, permissionMode, ...baseOptions } = options;
|
|
832
|
-
return
|
|
960
|
+
return Effect10.gen(function* () {
|
|
833
961
|
const { claudeCodeExecutablePath, claudeCodeVersion } = yield* Config;
|
|
834
962
|
const availableFeatures = getAvailableFeatures(claudeCodeVersion);
|
|
835
963
|
const options2 = {
|
|
@@ -879,23 +1007,23 @@ var ProjectPathNotFoundError = class extends Data2.TaggedError(
|
|
|
879
1007
|
"ProjectPathNotFoundError"
|
|
880
1008
|
) {
|
|
881
1009
|
};
|
|
882
|
-
var
|
|
1010
|
+
var LayerImpl8 = Effect11.gen(function* () {
|
|
883
1011
|
const projectRepository = yield* ProjectRepository;
|
|
884
|
-
const getClaudeCodeMeta = () =>
|
|
1012
|
+
const getClaudeCodeMeta = () => Effect11.gen(function* () {
|
|
885
1013
|
const config = yield* Config;
|
|
886
1014
|
return config;
|
|
887
1015
|
});
|
|
888
|
-
const getAvailableFeatures2 = () =>
|
|
1016
|
+
const getAvailableFeatures2 = () => Effect11.gen(function* () {
|
|
889
1017
|
const config = yield* Config;
|
|
890
1018
|
const features = getAvailableFeatures(
|
|
891
1019
|
config.claudeCodeVersion
|
|
892
1020
|
);
|
|
893
1021
|
return features;
|
|
894
1022
|
});
|
|
895
|
-
const getMcpList = (projectId) =>
|
|
1023
|
+
const getMcpList = (projectId) => Effect11.gen(function* () {
|
|
896
1024
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
897
1025
|
if (project.meta.projectPath === null) {
|
|
898
|
-
return yield*
|
|
1026
|
+
return yield* Effect11.fail(new ProjectPathNotFoundError({ projectId }));
|
|
899
1027
|
}
|
|
900
1028
|
const output = yield* getMcpListOutput(
|
|
901
1029
|
project.meta.projectPath
|
|
@@ -908,47 +1036,27 @@ var LayerImpl6 = Effect8.gen(function* () {
|
|
|
908
1036
|
getAvailableFeatures: getAvailableFeatures2
|
|
909
1037
|
};
|
|
910
1038
|
});
|
|
911
|
-
var ClaudeCodeService = class extends
|
|
1039
|
+
var ClaudeCodeService = class extends Context8.Tag("ClaudeCodeService")() {
|
|
912
1040
|
static {
|
|
913
|
-
this.Live =
|
|
1041
|
+
this.Live = Layer10.effect(this, LayerImpl8);
|
|
914
1042
|
}
|
|
915
1043
|
};
|
|
916
1044
|
|
|
917
1045
|
// src/server/core/claude-code/presentation/ClaudeCodeController.ts
|
|
918
|
-
var
|
|
1046
|
+
var LayerImpl9 = Effect12.gen(function* () {
|
|
919
1047
|
const projectRepository = yield* ProjectRepository;
|
|
920
1048
|
const claudeCodeService = yield* ClaudeCodeService;
|
|
921
1049
|
const context = yield* ApplicationContext;
|
|
922
|
-
|
|
923
|
-
const path = yield*
|
|
924
|
-
const getClaudeCommands = (options) =>
|
|
1050
|
+
yield* FileSystem6.FileSystem;
|
|
1051
|
+
const path = yield* Path8.Path;
|
|
1052
|
+
const getClaudeCommands = (options) => Effect12.gen(function* () {
|
|
925
1053
|
const { projectId } = options;
|
|
926
1054
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
927
|
-
const globalCommands = yield*
|
|
928
|
-
|
|
929
|
-
(items) => items.filter((item) => item.endsWith(".md")).map((item) => item.replace(/\.md$/, ""))
|
|
930
|
-
)
|
|
931
|
-
).pipe(
|
|
932
|
-
Effect9.match({
|
|
933
|
-
onSuccess: (items) => items,
|
|
934
|
-
onFailure: () => {
|
|
935
|
-
return [];
|
|
936
|
-
}
|
|
937
|
-
})
|
|
1055
|
+
const globalCommands = yield* scanCommandFilesRecursively(
|
|
1056
|
+
context.claudeCodePaths.claudeCommandsDirPath
|
|
938
1057
|
);
|
|
939
|
-
const projectCommands = project.meta.projectPath === null ? [] : yield*
|
|
1058
|
+
const projectCommands = project.meta.projectPath === null ? [] : yield* scanCommandFilesRecursively(
|
|
940
1059
|
path.resolve(project.meta.projectPath, ".claude", "commands")
|
|
941
|
-
).pipe(
|
|
942
|
-
Effect9.map(
|
|
943
|
-
(items) => items.filter((item) => item.endsWith(".md")).map((item) => item.replace(/\.md$/, ""))
|
|
944
|
-
)
|
|
945
|
-
).pipe(
|
|
946
|
-
Effect9.match({
|
|
947
|
-
onSuccess: (items) => items,
|
|
948
|
-
onFailure: () => {
|
|
949
|
-
return [];
|
|
950
|
-
}
|
|
951
|
-
})
|
|
952
1060
|
);
|
|
953
1061
|
return {
|
|
954
1062
|
response: {
|
|
@@ -959,7 +1067,7 @@ var LayerImpl7 = Effect9.gen(function* () {
|
|
|
959
1067
|
status: 200
|
|
960
1068
|
};
|
|
961
1069
|
});
|
|
962
|
-
const getMcpListRoute = (options) =>
|
|
1070
|
+
const getMcpListRoute = (options) => Effect12.gen(function* () {
|
|
963
1071
|
const { projectId } = options;
|
|
964
1072
|
const servers = yield* claudeCodeService.getMcpList(projectId);
|
|
965
1073
|
return {
|
|
@@ -967,7 +1075,7 @@ var LayerImpl7 = Effect9.gen(function* () {
|
|
|
967
1075
|
status: 200
|
|
968
1076
|
};
|
|
969
1077
|
});
|
|
970
|
-
const getClaudeCodeMeta = () =>
|
|
1078
|
+
const getClaudeCodeMeta = () => Effect12.gen(function* () {
|
|
971
1079
|
const config = yield* claudeCodeService.getClaudeCodeMeta();
|
|
972
1080
|
return {
|
|
973
1081
|
response: {
|
|
@@ -977,7 +1085,7 @@ var LayerImpl7 = Effect9.gen(function* () {
|
|
|
977
1085
|
status: 200
|
|
978
1086
|
};
|
|
979
1087
|
});
|
|
980
|
-
const getAvailableFeatures2 = () =>
|
|
1088
|
+
const getAvailableFeatures2 = () => Effect12.gen(function* () {
|
|
981
1089
|
const features = yield* claudeCodeService.getAvailableFeatures();
|
|
982
1090
|
const featuresList = Object.entries(features).flatMap(([key, value]) => {
|
|
983
1091
|
return [
|
|
@@ -999,22 +1107,22 @@ var LayerImpl7 = Effect9.gen(function* () {
|
|
|
999
1107
|
getAvailableFeatures: getAvailableFeatures2
|
|
1000
1108
|
};
|
|
1001
1109
|
});
|
|
1002
|
-
var ClaudeCodeController = class extends
|
|
1110
|
+
var ClaudeCodeController = class extends Context9.Tag("ClaudeCodeController")() {
|
|
1003
1111
|
static {
|
|
1004
|
-
this.Live =
|
|
1112
|
+
this.Live = Layer11.effect(this, LayerImpl9);
|
|
1005
1113
|
}
|
|
1006
1114
|
};
|
|
1007
1115
|
|
|
1008
1116
|
// src/server/core/claude-code/presentation/ClaudeCodePermissionController.ts
|
|
1009
|
-
import { Context as
|
|
1117
|
+
import { Context as Context12, Effect as Effect15, Layer as Layer14 } from "effect";
|
|
1010
1118
|
|
|
1011
1119
|
// src/server/core/claude-code/services/ClaudeCodePermissionService.ts
|
|
1012
|
-
import { Context as
|
|
1120
|
+
import { Context as Context11, Effect as Effect14, Layer as Layer13, Ref as Ref4 } from "effect";
|
|
1013
1121
|
import { ulid } from "ulid";
|
|
1014
1122
|
|
|
1015
1123
|
// src/server/core/events/services/EventBus.ts
|
|
1016
|
-
import { Context as
|
|
1017
|
-
var layerImpl =
|
|
1124
|
+
import { Context as Context10, Effect as Effect13, Layer as Layer12 } from "effect";
|
|
1125
|
+
var layerImpl = Effect13.gen(function* () {
|
|
1018
1126
|
const listenersMap = /* @__PURE__ */ new Map();
|
|
1019
1127
|
const getListeners = (event) => {
|
|
1020
1128
|
if (!listenersMap.has(event)) {
|
|
@@ -1022,7 +1130,7 @@ var layerImpl = Effect10.gen(function* () {
|
|
|
1022
1130
|
}
|
|
1023
1131
|
return listenersMap.get(event);
|
|
1024
1132
|
};
|
|
1025
|
-
const emit = (event, data) =>
|
|
1133
|
+
const emit = (event, data) => Effect13.gen(function* () {
|
|
1026
1134
|
const listeners = getListeners(event);
|
|
1027
1135
|
void Promise.allSettled(
|
|
1028
1136
|
Array.from(listeners).map(async (listener) => {
|
|
@@ -1030,11 +1138,11 @@ var layerImpl = Effect10.gen(function* () {
|
|
|
1030
1138
|
})
|
|
1031
1139
|
);
|
|
1032
1140
|
});
|
|
1033
|
-
const on = (event, listener) =>
|
|
1141
|
+
const on = (event, listener) => Effect13.sync(() => {
|
|
1034
1142
|
const listeners = getListeners(event);
|
|
1035
1143
|
listeners.add(listener);
|
|
1036
1144
|
});
|
|
1037
|
-
const off = (event, listener) =>
|
|
1145
|
+
const off = (event, listener) => Effect13.sync(() => {
|
|
1038
1146
|
const listeners = getListeners(event);
|
|
1039
1147
|
listeners.delete(listener);
|
|
1040
1148
|
});
|
|
@@ -1044,18 +1152,18 @@ var layerImpl = Effect10.gen(function* () {
|
|
|
1044
1152
|
off
|
|
1045
1153
|
};
|
|
1046
1154
|
});
|
|
1047
|
-
var EventBus = class extends
|
|
1155
|
+
var EventBus = class extends Context10.Tag("EventBus")() {
|
|
1048
1156
|
static {
|
|
1049
|
-
this.Live =
|
|
1157
|
+
this.Live = Layer12.effect(this, layerImpl);
|
|
1050
1158
|
}
|
|
1051
1159
|
};
|
|
1052
1160
|
|
|
1053
1161
|
// src/server/core/claude-code/services/ClaudeCodePermissionService.ts
|
|
1054
|
-
var
|
|
1162
|
+
var LayerImpl10 = Effect14.gen(function* () {
|
|
1055
1163
|
const pendingPermissionRequestsRef = yield* Ref4.make(/* @__PURE__ */ new Map());
|
|
1056
1164
|
const permissionResponsesRef = yield* Ref4.make(/* @__PURE__ */ new Map());
|
|
1057
1165
|
const eventBus = yield* EventBus;
|
|
1058
|
-
const waitPermissionResponse = (request, options) =>
|
|
1166
|
+
const waitPermissionResponse = (request, options) => Effect14.gen(function* () {
|
|
1059
1167
|
yield* Ref4.update(pendingPermissionRequestsRef, (requests) => {
|
|
1060
1168
|
requests.set(request.id, request);
|
|
1061
1169
|
return requests;
|
|
@@ -1071,14 +1179,14 @@ var LayerImpl8 = Effect11.gen(function* () {
|
|
|
1071
1179
|
if (response !== null) {
|
|
1072
1180
|
break;
|
|
1073
1181
|
}
|
|
1074
|
-
yield*
|
|
1182
|
+
yield* Effect14.sleep(1e3);
|
|
1075
1183
|
passedMs += 1e3;
|
|
1076
1184
|
}
|
|
1077
1185
|
return response;
|
|
1078
1186
|
});
|
|
1079
1187
|
const createCanUseToolRelatedOptions = (options) => {
|
|
1080
1188
|
const { taskId, userConfig, sessionId } = options;
|
|
1081
|
-
return
|
|
1189
|
+
return Effect14.gen(function* () {
|
|
1082
1190
|
const claudeCodeConfig = yield* Config;
|
|
1083
1191
|
if (!getAvailableFeatures(claudeCodeConfig.claudeCodeVersion).canUseTool) {
|
|
1084
1192
|
return {
|
|
@@ -1107,7 +1215,7 @@ var LayerImpl8 = Effect11.gen(function* () {
|
|
|
1107
1215
|
toolInput,
|
|
1108
1216
|
timestamp: Date.now()
|
|
1109
1217
|
};
|
|
1110
|
-
const response = await
|
|
1218
|
+
const response = await Effect14.runPromise(
|
|
1111
1219
|
waitPermissionResponse(permissionRequest, { timeoutMs: 6e4 })
|
|
1112
1220
|
);
|
|
1113
1221
|
if (response === null) {
|
|
@@ -1134,7 +1242,7 @@ var LayerImpl8 = Effect11.gen(function* () {
|
|
|
1134
1242
|
};
|
|
1135
1243
|
});
|
|
1136
1244
|
};
|
|
1137
|
-
const respondToPermissionRequest = (response) =>
|
|
1245
|
+
const respondToPermissionRequest = (response) => Effect14.gen(function* () {
|
|
1138
1246
|
yield* Ref4.update(permissionResponsesRef, (responses) => {
|
|
1139
1247
|
responses.set(response.permissionRequestId, response);
|
|
1140
1248
|
return responses;
|
|
@@ -1149,20 +1257,20 @@ var LayerImpl8 = Effect11.gen(function* () {
|
|
|
1149
1257
|
respondToPermissionRequest
|
|
1150
1258
|
};
|
|
1151
1259
|
});
|
|
1152
|
-
var ClaudeCodePermissionService = class extends
|
|
1260
|
+
var ClaudeCodePermissionService = class extends Context11.Tag(
|
|
1153
1261
|
"ClaudeCodePermissionService"
|
|
1154
1262
|
)() {
|
|
1155
1263
|
static {
|
|
1156
|
-
this.Live =
|
|
1264
|
+
this.Live = Layer13.effect(this, LayerImpl10);
|
|
1157
1265
|
}
|
|
1158
1266
|
};
|
|
1159
1267
|
|
|
1160
1268
|
// src/server/core/claude-code/presentation/ClaudeCodePermissionController.ts
|
|
1161
|
-
var
|
|
1269
|
+
var LayerImpl11 = Effect15.gen(function* () {
|
|
1162
1270
|
const claudeCodePermissionService = yield* ClaudeCodePermissionService;
|
|
1163
|
-
const permissionResponse = (options) =>
|
|
1271
|
+
const permissionResponse = (options) => Effect15.sync(() => {
|
|
1164
1272
|
const { permissionResponse: permissionResponse2 } = options;
|
|
1165
|
-
|
|
1273
|
+
Effect15.runFork(
|
|
1166
1274
|
claudeCodePermissionService.respondToPermissionRequest(
|
|
1167
1275
|
permissionResponse2
|
|
1168
1276
|
)
|
|
@@ -1178,19 +1286,19 @@ var LayerImpl9 = Effect12.gen(function* () {
|
|
|
1178
1286
|
permissionResponse
|
|
1179
1287
|
};
|
|
1180
1288
|
});
|
|
1181
|
-
var ClaudeCodePermissionController = class extends
|
|
1289
|
+
var ClaudeCodePermissionController = class extends Context12.Tag(
|
|
1182
1290
|
"ClaudeCodePermissionController"
|
|
1183
1291
|
)() {
|
|
1184
1292
|
static {
|
|
1185
|
-
this.Live =
|
|
1293
|
+
this.Live = Layer14.effect(this, LayerImpl11);
|
|
1186
1294
|
}
|
|
1187
1295
|
};
|
|
1188
1296
|
|
|
1189
1297
|
// src/server/core/claude-code/presentation/ClaudeCodeSessionProcessController.ts
|
|
1190
|
-
import { Context as
|
|
1298
|
+
import { Context as Context19, Effect as Effect23, Layer as Layer21 } from "effect";
|
|
1191
1299
|
|
|
1192
1300
|
// src/server/core/platform/services/UserConfigService.ts
|
|
1193
|
-
import { Context as
|
|
1301
|
+
import { Context as Context13, Effect as Effect16, Layer as Layer15, Ref as Ref5 } from "effect";
|
|
1194
1302
|
|
|
1195
1303
|
// src/lib/i18n/localeDetection.ts
|
|
1196
1304
|
var DEFAULT_LOCALE = "en";
|
|
@@ -1242,7 +1350,7 @@ var detectLocaleFromAcceptLanguage = (header) => {
|
|
|
1242
1350
|
};
|
|
1243
1351
|
|
|
1244
1352
|
// src/server/core/platform/services/UserConfigService.ts
|
|
1245
|
-
var
|
|
1353
|
+
var LayerImpl12 = Effect16.gen(function* () {
|
|
1246
1354
|
const configRef = yield* Ref5.make({
|
|
1247
1355
|
hideNoUserMessageSession: true,
|
|
1248
1356
|
unifySameTitleSession: false,
|
|
@@ -1251,10 +1359,10 @@ var LayerImpl10 = Effect13.gen(function* () {
|
|
|
1251
1359
|
locale: DEFAULT_LOCALE,
|
|
1252
1360
|
theme: "system"
|
|
1253
1361
|
});
|
|
1254
|
-
const setUserConfig = (newConfig) =>
|
|
1362
|
+
const setUserConfig = (newConfig) => Effect16.gen(function* () {
|
|
1255
1363
|
yield* Ref5.update(configRef, () => newConfig);
|
|
1256
1364
|
});
|
|
1257
|
-
const getUserConfig = () =>
|
|
1365
|
+
const getUserConfig = () => Effect16.gen(function* () {
|
|
1258
1366
|
const config = yield* Ref5.get(configRef);
|
|
1259
1367
|
return config;
|
|
1260
1368
|
});
|
|
@@ -1263,14 +1371,14 @@ var LayerImpl10 = Effect13.gen(function* () {
|
|
|
1263
1371
|
setUserConfig
|
|
1264
1372
|
};
|
|
1265
1373
|
});
|
|
1266
|
-
var UserConfigService = class extends
|
|
1374
|
+
var UserConfigService = class extends Context13.Tag("UserConfigService")() {
|
|
1267
1375
|
static {
|
|
1268
|
-
this.Live =
|
|
1376
|
+
this.Live = Layer15.effect(this, LayerImpl12);
|
|
1269
1377
|
}
|
|
1270
1378
|
};
|
|
1271
1379
|
|
|
1272
1380
|
// src/server/core/claude-code/services/ClaudeCodeLifeCycleService.ts
|
|
1273
|
-
import { Context as
|
|
1381
|
+
import { Context as Context18, Effect as Effect22, Layer as Layer20, Runtime as Runtime2 } from "effect";
|
|
1274
1382
|
import { ulid as ulid2 } from "ulid";
|
|
1275
1383
|
|
|
1276
1384
|
// src/lib/controllablePromise.ts
|
|
@@ -1300,8 +1408,8 @@ var controllablePromise = () => {
|
|
|
1300
1408
|
};
|
|
1301
1409
|
|
|
1302
1410
|
// src/server/core/session/infrastructure/SessionRepository.ts
|
|
1303
|
-
import { FileSystem as
|
|
1304
|
-
import { Context as
|
|
1411
|
+
import { FileSystem as FileSystem8, Path as Path9 } from "@effect/platform";
|
|
1412
|
+
import { Context as Context16, Effect as Effect19, Layer as Layer18, Option as Option3 } from "effect";
|
|
1305
1413
|
|
|
1306
1414
|
// src/server/core/claude-code/functions/parseUserMessage.ts
|
|
1307
1415
|
import { z as z21 } from "zod";
|
|
@@ -1377,29 +1485,32 @@ var decodeSessionId = (projectId, sessionId) => {
|
|
|
1377
1485
|
return resolve2(projectPath, `${sessionId}.jsonl`);
|
|
1378
1486
|
};
|
|
1379
1487
|
|
|
1488
|
+
// src/server/core/session/functions/isRegularSessionFile.ts
|
|
1489
|
+
var isRegularSessionFile = (filename) => filename.endsWith(".jsonl") && !filename.startsWith("agent-");
|
|
1490
|
+
|
|
1380
1491
|
// src/server/core/session/infrastructure/VirtualConversationDatabase.ts
|
|
1381
|
-
import { Context as
|
|
1382
|
-
var VirtualConversationDatabase = class extends
|
|
1492
|
+
import { Context as Context14, Effect as Effect17, Layer as Layer16, Ref as Ref6 } from "effect";
|
|
1493
|
+
var VirtualConversationDatabase = class extends Context14.Tag(
|
|
1383
1494
|
"VirtualConversationDatabase"
|
|
1384
1495
|
)() {
|
|
1385
1496
|
static {
|
|
1386
|
-
this.Live =
|
|
1497
|
+
this.Live = Layer16.effect(
|
|
1387
1498
|
this,
|
|
1388
|
-
|
|
1499
|
+
Effect17.gen(function* () {
|
|
1389
1500
|
const storageRef = yield* Ref6.make([]);
|
|
1390
|
-
const getProjectVirtualConversations = (projectId) =>
|
|
1501
|
+
const getProjectVirtualConversations = (projectId) => Effect17.gen(function* () {
|
|
1391
1502
|
const conversations = yield* Ref6.get(storageRef);
|
|
1392
1503
|
return conversations.filter(
|
|
1393
1504
|
(conversation) => conversation.projectId === projectId
|
|
1394
1505
|
);
|
|
1395
1506
|
});
|
|
1396
|
-
const getSessionVirtualConversation = (sessionId) =>
|
|
1507
|
+
const getSessionVirtualConversation = (sessionId) => Effect17.gen(function* () {
|
|
1397
1508
|
const conversations = yield* Ref6.get(storageRef);
|
|
1398
1509
|
return conversations.find(
|
|
1399
1510
|
(conversation) => conversation.sessionId === sessionId
|
|
1400
1511
|
) ?? null;
|
|
1401
1512
|
});
|
|
1402
|
-
const createVirtualConversation2 = (projectId, sessionId, createConversations) =>
|
|
1513
|
+
const createVirtualConversation2 = (projectId, sessionId, createConversations) => Effect17.gen(function* () {
|
|
1403
1514
|
yield* Ref6.update(storageRef, (conversations) => {
|
|
1404
1515
|
const existingRecord = conversations.find(
|
|
1405
1516
|
(record) => record.projectId === projectId && record.sessionId === sessionId
|
|
@@ -1418,7 +1529,7 @@ var VirtualConversationDatabase = class extends Context12.Tag(
|
|
|
1418
1529
|
return conversations;
|
|
1419
1530
|
});
|
|
1420
1531
|
});
|
|
1421
|
-
const deleteVirtualConversations = (sessionId) =>
|
|
1532
|
+
const deleteVirtualConversations = (sessionId) => Effect17.gen(function* () {
|
|
1422
1533
|
yield* Ref6.update(storageRef, (conversations) => {
|
|
1423
1534
|
return conversations.filter((c) => c.sessionId !== sessionId);
|
|
1424
1535
|
});
|
|
@@ -1435,8 +1546,8 @@ var VirtualConversationDatabase = class extends Context12.Tag(
|
|
|
1435
1546
|
};
|
|
1436
1547
|
|
|
1437
1548
|
// src/server/core/session/services/SessionMetaService.ts
|
|
1438
|
-
import { FileSystem as
|
|
1439
|
-
import { Context as
|
|
1549
|
+
import { FileSystem as FileSystem7 } from "@effect/platform";
|
|
1550
|
+
import { Context as Context15, Effect as Effect18, Layer as Layer17, Ref as Ref7 } from "effect";
|
|
1440
1551
|
|
|
1441
1552
|
// src/server/core/session/constants/pricing.ts
|
|
1442
1553
|
var MODEL_PRICING = {
|
|
@@ -1582,17 +1693,17 @@ var extractFirstUserMessage = (conversation) => {
|
|
|
1582
1693
|
|
|
1583
1694
|
// src/server/core/session/services/SessionMetaService.ts
|
|
1584
1695
|
var parsedUserMessageOrNullSchema = parsedUserMessageSchema.nullable();
|
|
1585
|
-
var SessionMetaService = class extends
|
|
1696
|
+
var SessionMetaService = class extends Context15.Tag("SessionMetaService")() {
|
|
1586
1697
|
static {
|
|
1587
|
-
this.Live =
|
|
1698
|
+
this.Live = Layer17.effect(
|
|
1588
1699
|
this,
|
|
1589
|
-
|
|
1590
|
-
const fs = yield*
|
|
1700
|
+
Effect18.gen(function* () {
|
|
1701
|
+
const fs = yield* FileSystem7.FileSystem;
|
|
1591
1702
|
const firstUserMessageCache = yield* FileCacheStorage();
|
|
1592
1703
|
const sessionMetaCacheRef = yield* Ref7.make(
|
|
1593
1704
|
/* @__PURE__ */ new Map()
|
|
1594
1705
|
);
|
|
1595
|
-
const getFirstUserMessage = (jsonlFilePath, lines) =>
|
|
1706
|
+
const getFirstUserMessage = (jsonlFilePath, lines) => Effect18.gen(function* () {
|
|
1596
1707
|
const cached = yield* firstUserMessageCache.get(jsonlFilePath);
|
|
1597
1708
|
if (cached !== void 0) {
|
|
1598
1709
|
return cached;
|
|
@@ -1677,7 +1788,7 @@ var SessionMetaService = class extends Context13.Tag("SessionMetaService")() {
|
|
|
1677
1788
|
modelName: lastModelName
|
|
1678
1789
|
};
|
|
1679
1790
|
};
|
|
1680
|
-
const getSessionMeta = (projectId, sessionId) =>
|
|
1791
|
+
const getSessionMeta = (projectId, sessionId) => Effect18.gen(function* () {
|
|
1681
1792
|
const metaCache = yield* Ref7.get(sessionMetaCacheRef);
|
|
1682
1793
|
const cached = metaCache.get(sessionId);
|
|
1683
1794
|
if (cached !== void 0) {
|
|
@@ -1706,7 +1817,7 @@ var SessionMetaService = class extends Context13.Tag("SessionMetaService")() {
|
|
|
1706
1817
|
});
|
|
1707
1818
|
return sessionMeta;
|
|
1708
1819
|
});
|
|
1709
|
-
const invalidateSession = (_projectId, sessionId) =>
|
|
1820
|
+
const invalidateSession = (_projectId, sessionId) => Effect18.gen(function* () {
|
|
1710
1821
|
yield* Ref7.update(sessionMetaCacheRef, (cache) => {
|
|
1711
1822
|
cache.delete(sessionId);
|
|
1712
1823
|
return cache;
|
|
@@ -1718,30 +1829,30 @@ var SessionMetaService = class extends Context13.Tag("SessionMetaService")() {
|
|
|
1718
1829
|
};
|
|
1719
1830
|
})
|
|
1720
1831
|
).pipe(
|
|
1721
|
-
|
|
1832
|
+
Layer17.provide(
|
|
1722
1833
|
makeFileCacheStorageLayer(
|
|
1723
1834
|
"first-user-message-cache",
|
|
1724
1835
|
parsedUserMessageOrNullSchema
|
|
1725
1836
|
)
|
|
1726
1837
|
),
|
|
1727
|
-
|
|
1838
|
+
Layer17.provide(PersistentService.Live)
|
|
1728
1839
|
);
|
|
1729
1840
|
}
|
|
1730
1841
|
};
|
|
1731
1842
|
|
|
1732
1843
|
// src/server/core/session/infrastructure/SessionRepository.ts
|
|
1733
|
-
var
|
|
1734
|
-
const fs = yield*
|
|
1735
|
-
const path = yield*
|
|
1844
|
+
var LayerImpl13 = Effect19.gen(function* () {
|
|
1845
|
+
const fs = yield* FileSystem8.FileSystem;
|
|
1846
|
+
const path = yield* Path9.Path;
|
|
1736
1847
|
const sessionMetaService = yield* SessionMetaService;
|
|
1737
1848
|
const virtualConversationDatabase = yield* VirtualConversationDatabase;
|
|
1738
|
-
const getSession = (projectId, sessionId) =>
|
|
1849
|
+
const getSession = (projectId, sessionId) => Effect19.gen(function* () {
|
|
1739
1850
|
const sessionPath = decodeSessionId(projectId, sessionId);
|
|
1740
1851
|
const virtualConversation = yield* virtualConversationDatabase.getSessionVirtualConversation(
|
|
1741
1852
|
sessionId
|
|
1742
1853
|
);
|
|
1743
1854
|
const exists = yield* fs.exists(sessionPath);
|
|
1744
|
-
const sessionDetail = yield* exists ?
|
|
1855
|
+
const sessionDetail = yield* exists ? Effect19.gen(function* () {
|
|
1745
1856
|
const content = yield* fs.readFileString(sessionPath);
|
|
1746
1857
|
const allLines = content.split("\n").filter((line) => line.trim());
|
|
1747
1858
|
const conversations = parseJsonl(allLines.join("\n"));
|
|
@@ -1779,7 +1890,7 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1779
1890
|
return sessionDetail2;
|
|
1780
1891
|
}) : (() => {
|
|
1781
1892
|
if (virtualConversation === null) {
|
|
1782
|
-
return
|
|
1893
|
+
return Effect19.succeed(null);
|
|
1783
1894
|
}
|
|
1784
1895
|
const lastConversation = virtualConversation.conversations.filter(
|
|
1785
1896
|
(conversation) => conversation.type === "user" || conversation.type === "assistant" || conversation.type === "system"
|
|
@@ -1809,13 +1920,13 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1809
1920
|
conversations: virtualConversation.conversations,
|
|
1810
1921
|
lastModifiedAt: lastConversation !== void 0 ? new Date(lastConversation.timestamp) : /* @__PURE__ */ new Date()
|
|
1811
1922
|
};
|
|
1812
|
-
return
|
|
1923
|
+
return Effect19.succeed(virtualSession);
|
|
1813
1924
|
})();
|
|
1814
1925
|
return {
|
|
1815
1926
|
session: sessionDetail
|
|
1816
1927
|
};
|
|
1817
1928
|
});
|
|
1818
|
-
const getSessions = (projectId, options) =>
|
|
1929
|
+
const getSessions = (projectId, options) => Effect19.gen(function* () {
|
|
1819
1930
|
const { maxCount = 20, cursor } = options ?? {};
|
|
1820
1931
|
const claudeProjectPath = decodeProjectId(projectId);
|
|
1821
1932
|
const dirExists = yield* fs.exists(claudeProjectPath);
|
|
@@ -1823,8 +1934,8 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1823
1934
|
console.warn(`Project directory not found at ${claudeProjectPath}`);
|
|
1824
1935
|
return { sessions: [] };
|
|
1825
1936
|
}
|
|
1826
|
-
const dirents = yield*
|
|
1827
|
-
try: () => fs.readDirectory(claudeProjectPath).pipe(
|
|
1937
|
+
const dirents = yield* Effect19.tryPromise({
|
|
1938
|
+
try: () => fs.readDirectory(claudeProjectPath).pipe(Effect19.runPromise),
|
|
1828
1939
|
catch: (error) => {
|
|
1829
1940
|
console.warn(
|
|
1830
1941
|
`Failed to read sessions for project ${projectId}:`,
|
|
@@ -1832,14 +1943,14 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1832
1943
|
);
|
|
1833
1944
|
return new Error("Failed to read directory");
|
|
1834
1945
|
}
|
|
1835
|
-
}).pipe(
|
|
1836
|
-
const sessionEffects = dirents.filter(
|
|
1837
|
-
(entry) =>
|
|
1946
|
+
}).pipe(Effect19.catchAll(() => Effect19.succeed([])));
|
|
1947
|
+
const sessionEffects = dirents.filter(isRegularSessionFile).map(
|
|
1948
|
+
(entry) => Effect19.gen(function* () {
|
|
1838
1949
|
const fullPath = path.resolve(claudeProjectPath, entry);
|
|
1839
1950
|
const sessionId = encodeSessionId(fullPath);
|
|
1840
|
-
const stat = yield*
|
|
1841
|
-
() => fs.stat(fullPath).pipe(
|
|
1842
|
-
).pipe(
|
|
1951
|
+
const stat = yield* Effect19.tryPromise(
|
|
1952
|
+
() => fs.stat(fullPath).pipe(Effect19.runPromise)
|
|
1953
|
+
).pipe(Effect19.catchAll(() => Effect19.succeed(null)));
|
|
1843
1954
|
if (!stat) {
|
|
1844
1955
|
return null;
|
|
1845
1956
|
}
|
|
@@ -1850,7 +1961,7 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1850
1961
|
};
|
|
1851
1962
|
})
|
|
1852
1963
|
);
|
|
1853
|
-
const sessionsWithNulls = yield*
|
|
1964
|
+
const sessionsWithNulls = yield* Effect19.all(sessionEffects, {
|
|
1854
1965
|
concurrency: "unbounded"
|
|
1855
1966
|
});
|
|
1856
1967
|
const sessions = sessionsWithNulls.filter((s) => s !== null).sort(
|
|
@@ -1865,9 +1976,9 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1865
1976
|
index + 1,
|
|
1866
1977
|
Math.min(index + 1 + maxCount, sessions.length)
|
|
1867
1978
|
);
|
|
1868
|
-
const sessionsWithMeta2 = yield*
|
|
1979
|
+
const sessionsWithMeta2 = yield* Effect19.all(
|
|
1869
1980
|
sessionsToReturn2.map(
|
|
1870
|
-
(item) =>
|
|
1981
|
+
(item) => Effect19.gen(function* () {
|
|
1871
1982
|
const meta = yield* sessionMetaService.getSessionMeta(
|
|
1872
1983
|
projectId,
|
|
1873
1984
|
item.id
|
|
@@ -1930,9 +2041,9 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1930
2041
|
0,
|
|
1931
2042
|
Math.min(maxCount, sessions.length)
|
|
1932
2043
|
);
|
|
1933
|
-
const sessionsWithMeta = yield*
|
|
2044
|
+
const sessionsWithMeta = yield* Effect19.all(
|
|
1934
2045
|
sessionsToReturn.map(
|
|
1935
|
-
(item) =>
|
|
2046
|
+
(item) => Effect19.gen(function* () {
|
|
1936
2047
|
const meta = yield* sessionMetaService.getSessionMeta(
|
|
1937
2048
|
projectId,
|
|
1938
2049
|
item.id
|
|
@@ -1954,9 +2065,9 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1954
2065
|
getSessions
|
|
1955
2066
|
};
|
|
1956
2067
|
});
|
|
1957
|
-
var SessionRepository = class extends
|
|
2068
|
+
var SessionRepository = class extends Context16.Tag("SessionRepository")() {
|
|
1958
2069
|
static {
|
|
1959
|
-
this.Live =
|
|
2070
|
+
this.Live = Layer18.effect(this, LayerImpl13);
|
|
1960
2071
|
}
|
|
1961
2072
|
};
|
|
1962
2073
|
|
|
@@ -2056,7 +2167,7 @@ var fallbackSdkMessage = (message) => {
|
|
|
2056
2167
|
};
|
|
2057
2168
|
|
|
2058
2169
|
// src/server/core/claude-code/models/CCSessionProcess.ts
|
|
2059
|
-
import { Effect as
|
|
2170
|
+
import { Effect as Effect20 } from "effect";
|
|
2060
2171
|
var isPublic = (process2) => {
|
|
2061
2172
|
return process2.type === "initialized" || process2.type === "file_created" || process2.type === "paused";
|
|
2062
2173
|
};
|
|
@@ -2067,7 +2178,7 @@ var getAliveTasks = (process2) => {
|
|
|
2067
2178
|
};
|
|
2068
2179
|
var createVirtualConversation = (process2, ctx) => {
|
|
2069
2180
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2070
|
-
return
|
|
2181
|
+
return Effect20.gen(function* () {
|
|
2071
2182
|
const config = yield* Config;
|
|
2072
2183
|
const virtualConversation = {
|
|
2073
2184
|
type: "user",
|
|
@@ -2089,7 +2200,7 @@ var createVirtualConversation = (process2, ctx) => {
|
|
|
2089
2200
|
};
|
|
2090
2201
|
|
|
2091
2202
|
// src/server/core/claude-code/services/ClaudeCodeSessionProcessService.ts
|
|
2092
|
-
import { Context as
|
|
2203
|
+
import { Context as Context17, Data as Data3, Effect as Effect21, Layer as Layer19, Ref as Ref8 } from "effect";
|
|
2093
2204
|
var SessionProcessNotFoundError = class extends Data3.TaggedError(
|
|
2094
2205
|
"SessionProcessNotFoundError"
|
|
2095
2206
|
) {
|
|
@@ -2108,12 +2219,12 @@ var IllegalStateChangeError = class extends Data3.TaggedError(
|
|
|
2108
2219
|
};
|
|
2109
2220
|
var TaskNotFoundError = class extends Data3.TaggedError("TaskNotFoundError") {
|
|
2110
2221
|
};
|
|
2111
|
-
var
|
|
2222
|
+
var LayerImpl14 = Effect21.gen(function* () {
|
|
2112
2223
|
const processesRef = yield* Ref8.make([]);
|
|
2113
2224
|
const eventBus = yield* EventBus;
|
|
2114
2225
|
const startSessionProcess = (options) => {
|
|
2115
2226
|
const { sessionDef, taskDef } = options;
|
|
2116
|
-
return
|
|
2227
|
+
return Effect21.gen(function* () {
|
|
2117
2228
|
const task = {
|
|
2118
2229
|
def: taskDef,
|
|
2119
2230
|
status: "pending"
|
|
@@ -2136,10 +2247,10 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2136
2247
|
};
|
|
2137
2248
|
const continueSessionProcess = (options) => {
|
|
2138
2249
|
const { sessionProcessId } = options;
|
|
2139
|
-
return
|
|
2250
|
+
return Effect21.gen(function* () {
|
|
2140
2251
|
const process2 = yield* getSessionProcess(sessionProcessId);
|
|
2141
2252
|
if (process2.type !== "paused") {
|
|
2142
|
-
return yield*
|
|
2253
|
+
return yield* Effect21.fail(
|
|
2143
2254
|
new SessionProcessNotPausedError({
|
|
2144
2255
|
sessionProcessId
|
|
2145
2256
|
})
|
|
@@ -2147,7 +2258,7 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2147
2258
|
}
|
|
2148
2259
|
const [firstAliveTask] = getAliveTasks(process2);
|
|
2149
2260
|
if (firstAliveTask !== void 0) {
|
|
2150
|
-
return yield*
|
|
2261
|
+
return yield* Effect21.fail(
|
|
2151
2262
|
new SessionProcessAlreadyAliveError({
|
|
2152
2263
|
sessionProcessId,
|
|
2153
2264
|
aliveTaskId: firstAliveTask.def.taskId,
|
|
@@ -2177,13 +2288,13 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2177
2288
|
});
|
|
2178
2289
|
};
|
|
2179
2290
|
const getSessionProcess = (sessionProcessId) => {
|
|
2180
|
-
return
|
|
2291
|
+
return Effect21.gen(function* () {
|
|
2181
2292
|
const processes = yield* Ref8.get(processesRef);
|
|
2182
2293
|
const result = processes.find(
|
|
2183
2294
|
(p) => p.def.sessionProcessId === sessionProcessId
|
|
2184
2295
|
);
|
|
2185
2296
|
if (result === void 0) {
|
|
2186
|
-
return yield*
|
|
2297
|
+
return yield* Effect21.fail(
|
|
2187
2298
|
new SessionProcessNotFoundError({ sessionProcessId })
|
|
2188
2299
|
);
|
|
2189
2300
|
}
|
|
@@ -2191,13 +2302,13 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2191
2302
|
});
|
|
2192
2303
|
};
|
|
2193
2304
|
const getSessionProcesses = () => {
|
|
2194
|
-
return
|
|
2305
|
+
return Effect21.gen(function* () {
|
|
2195
2306
|
const processes = yield* Ref8.get(processesRef);
|
|
2196
2307
|
return processes;
|
|
2197
2308
|
});
|
|
2198
2309
|
};
|
|
2199
2310
|
const getTask = (taskId) => {
|
|
2200
|
-
return
|
|
2311
|
+
return Effect21.gen(function* () {
|
|
2201
2312
|
const processes = yield* Ref8.get(processesRef);
|
|
2202
2313
|
const result = processes.flatMap((p) => {
|
|
2203
2314
|
const found = p.tasks.find((t) => t.def.taskId === taskId);
|
|
@@ -2212,14 +2323,14 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2212
2323
|
];
|
|
2213
2324
|
}).at(0);
|
|
2214
2325
|
if (result === void 0) {
|
|
2215
|
-
return yield*
|
|
2326
|
+
return yield* Effect21.fail(new TaskNotFoundError({ taskId }));
|
|
2216
2327
|
}
|
|
2217
2328
|
return result;
|
|
2218
2329
|
});
|
|
2219
2330
|
};
|
|
2220
2331
|
const dangerouslyChangeProcessState = (options) => {
|
|
2221
2332
|
const { sessionProcessId, nextState } = options;
|
|
2222
|
-
return
|
|
2333
|
+
return Effect21.gen(function* () {
|
|
2223
2334
|
const processes = yield* Ref8.get(processesRef);
|
|
2224
2335
|
const targetProcess = processes.find(
|
|
2225
2336
|
(p) => p.def.sessionProcessId === sessionProcessId
|
|
@@ -2248,7 +2359,7 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2248
2359
|
};
|
|
2249
2360
|
const changeTaskState = (options) => {
|
|
2250
2361
|
const { sessionProcessId, taskId, nextTask } = options;
|
|
2251
|
-
return
|
|
2362
|
+
return Effect21.gen(function* () {
|
|
2252
2363
|
const { task } = yield* getTask(taskId);
|
|
2253
2364
|
yield* Ref8.update(processesRef, (processes) => {
|
|
2254
2365
|
return processes.map(
|
|
@@ -2269,10 +2380,10 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2269
2380
|
};
|
|
2270
2381
|
const toNotInitializedState = (options) => {
|
|
2271
2382
|
const { sessionProcessId, rawUserMessage } = options;
|
|
2272
|
-
return
|
|
2383
|
+
return Effect21.gen(function* () {
|
|
2273
2384
|
const currentProcess = yield* getSessionProcess(sessionProcessId);
|
|
2274
2385
|
if (currentProcess.type !== "pending") {
|
|
2275
|
-
return yield*
|
|
2386
|
+
return yield* Effect21.fail(
|
|
2276
2387
|
new IllegalStateChangeError({
|
|
2277
2388
|
from: currentProcess.type,
|
|
2278
2389
|
to: "not_initialized"
|
|
@@ -2305,10 +2416,10 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2305
2416
|
};
|
|
2306
2417
|
const toInitializedState = (options) => {
|
|
2307
2418
|
const { sessionProcessId, initContext } = options;
|
|
2308
|
-
return
|
|
2419
|
+
return Effect21.gen(function* () {
|
|
2309
2420
|
const currentProcess = yield* getSessionProcess(sessionProcessId);
|
|
2310
2421
|
if (currentProcess.type !== "not_initialized") {
|
|
2311
|
-
return yield*
|
|
2422
|
+
return yield* Effect21.fail(
|
|
2312
2423
|
new IllegalStateChangeError({
|
|
2313
2424
|
from: currentProcess.type,
|
|
2314
2425
|
to: "initialized"
|
|
@@ -2334,10 +2445,10 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2334
2445
|
};
|
|
2335
2446
|
const toFileCreatedState = (options) => {
|
|
2336
2447
|
const { sessionProcessId } = options;
|
|
2337
|
-
return
|
|
2448
|
+
return Effect21.gen(function* () {
|
|
2338
2449
|
const currentProcess = yield* getSessionProcess(sessionProcessId);
|
|
2339
2450
|
if (currentProcess.type !== "initialized") {
|
|
2340
|
-
return yield*
|
|
2451
|
+
return yield* Effect21.fail(
|
|
2341
2452
|
new IllegalStateChangeError({
|
|
2342
2453
|
from: currentProcess.type,
|
|
2343
2454
|
to: "file_created"
|
|
@@ -2363,10 +2474,10 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2363
2474
|
};
|
|
2364
2475
|
const toPausedState = (options) => {
|
|
2365
2476
|
const { sessionProcessId, resultMessage } = options;
|
|
2366
|
-
return
|
|
2477
|
+
return Effect21.gen(function* () {
|
|
2367
2478
|
const currentProcess = yield* getSessionProcess(sessionProcessId);
|
|
2368
2479
|
if (currentProcess.type !== "file_created") {
|
|
2369
|
-
return yield*
|
|
2480
|
+
return yield* Effect21.fail(
|
|
2370
2481
|
new IllegalStateChangeError({
|
|
2371
2482
|
from: currentProcess.type,
|
|
2372
2483
|
to: "paused"
|
|
@@ -2400,7 +2511,7 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2400
2511
|
};
|
|
2401
2512
|
const toCompletedState = (options) => {
|
|
2402
2513
|
const { sessionProcessId, error } = options;
|
|
2403
|
-
return
|
|
2514
|
+
return Effect21.gen(function* () {
|
|
2404
2515
|
const currentProcess = yield* getSessionProcess(sessionProcessId);
|
|
2405
2516
|
const currentTask = currentProcess.type === "not_initialized" || currentProcess.type === "initialized" || currentProcess.type === "file_created" ? currentProcess.currentTask : void 0;
|
|
2406
2517
|
const newTask = currentTask !== void 0 ? error !== void 0 ? {
|
|
@@ -2453,25 +2564,25 @@ var LayerImpl12 = Effect18.gen(function* () {
|
|
|
2453
2564
|
changeTaskState
|
|
2454
2565
|
};
|
|
2455
2566
|
});
|
|
2456
|
-
var ClaudeCodeSessionProcessService = class extends
|
|
2567
|
+
var ClaudeCodeSessionProcessService = class extends Context17.Tag(
|
|
2457
2568
|
"ClaudeCodeSessionProcessService"
|
|
2458
2569
|
)() {
|
|
2459
2570
|
static {
|
|
2460
|
-
this.Live =
|
|
2571
|
+
this.Live = Layer19.effect(this, LayerImpl14);
|
|
2461
2572
|
}
|
|
2462
2573
|
};
|
|
2463
2574
|
|
|
2464
2575
|
// src/server/core/claude-code/services/ClaudeCodeLifeCycleService.ts
|
|
2465
|
-
var
|
|
2576
|
+
var LayerImpl15 = Effect22.gen(function* () {
|
|
2466
2577
|
const eventBusService = yield* EventBus;
|
|
2467
2578
|
const sessionRepository = yield* SessionRepository;
|
|
2468
2579
|
const sessionProcessService = yield* ClaudeCodeSessionProcessService;
|
|
2469
2580
|
const virtualConversationDatabase = yield* VirtualConversationDatabase;
|
|
2470
2581
|
const permissionService = yield* ClaudeCodePermissionService;
|
|
2471
|
-
const runtime = yield*
|
|
2582
|
+
const runtime = yield* Effect22.runtime();
|
|
2472
2583
|
const continueTask = (options) => {
|
|
2473
2584
|
const { sessionProcessId, baseSessionId, input } = options;
|
|
2474
|
-
return
|
|
2585
|
+
return Effect22.gen(function* () {
|
|
2475
2586
|
const { sessionProcess, task } = yield* sessionProcessService.continueSessionProcess({
|
|
2476
2587
|
sessionProcessId,
|
|
2477
2588
|
taskDef: {
|
|
@@ -2499,7 +2610,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2499
2610
|
};
|
|
2500
2611
|
const startTask = (options) => {
|
|
2501
2612
|
const { baseSession, input, userConfig } = options;
|
|
2502
|
-
return
|
|
2613
|
+
return Effect22.gen(function* () {
|
|
2503
2614
|
const {
|
|
2504
2615
|
generateMessages,
|
|
2505
2616
|
setNextMessage,
|
|
@@ -2527,7 +2638,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2527
2638
|
const sessionFileCreatedPromise = controllablePromise();
|
|
2528
2639
|
setMessageGeneratorHooks({
|
|
2529
2640
|
onNewUserMessageResolved: async (input2) => {
|
|
2530
|
-
|
|
2641
|
+
Effect22.runFork(
|
|
2531
2642
|
sessionProcessService.toNotInitializedState({
|
|
2532
2643
|
sessionProcessId: sessionProcess.def.sessionProcessId,
|
|
2533
2644
|
rawUserMessage: input2.text
|
|
@@ -2535,7 +2646,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2535
2646
|
);
|
|
2536
2647
|
}
|
|
2537
2648
|
});
|
|
2538
|
-
const handleMessage = (message) =>
|
|
2649
|
+
const handleMessage = (message) => Effect22.gen(function* () {
|
|
2539
2650
|
const processState = yield* sessionProcessService.getSessionProcess(
|
|
2540
2651
|
sessionProcess.def.sessionProcessId
|
|
2541
2652
|
);
|
|
@@ -2543,7 +2654,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2543
2654
|
return "break";
|
|
2544
2655
|
}
|
|
2545
2656
|
if (processState.type === "paused") {
|
|
2546
|
-
yield*
|
|
2657
|
+
yield* Effect22.die(
|
|
2547
2658
|
new Error("Illegal state: paused is not expected")
|
|
2548
2659
|
);
|
|
2549
2660
|
}
|
|
@@ -2615,7 +2726,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2615
2726
|
});
|
|
2616
2727
|
const handleSessionProcessDaemon = async () => {
|
|
2617
2728
|
const messageIter = await Runtime2.runPromise(runtime)(
|
|
2618
|
-
|
|
2729
|
+
Effect22.gen(function* () {
|
|
2619
2730
|
const permissionOptions = yield* permissionService.createCanUseToolRelatedOptions({
|
|
2620
2731
|
taskId: task.def.taskId,
|
|
2621
2732
|
userConfig,
|
|
@@ -2636,7 +2747,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2636
2747
|
const result = await Runtime2.runPromise(runtime)(
|
|
2637
2748
|
handleMessage(fallbackMessage)
|
|
2638
2749
|
).catch((error) => {
|
|
2639
|
-
|
|
2750
|
+
Effect22.runFork(
|
|
2640
2751
|
sessionProcessService.changeTaskState({
|
|
2641
2752
|
sessionProcessId: sessionProcess.def.sessionProcessId,
|
|
2642
2753
|
taskId: task.def.taskId,
|
|
@@ -2667,7 +2778,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2667
2778
|
if (sessionFileCreatedPromise.status === "pending") {
|
|
2668
2779
|
sessionFileCreatedPromise.reject(error);
|
|
2669
2780
|
}
|
|
2670
|
-
await
|
|
2781
|
+
await Effect22.runPromise(
|
|
2671
2782
|
sessionProcessService.changeTaskState({
|
|
2672
2783
|
sessionProcessId: sessionProcess.def.sessionProcessId,
|
|
2673
2784
|
taskId: task.def.taskId,
|
|
@@ -2690,8 +2801,8 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2690
2801
|
}
|
|
2691
2802
|
throw error;
|
|
2692
2803
|
}).finally(() => {
|
|
2693
|
-
|
|
2694
|
-
|
|
2804
|
+
Effect22.runFork(
|
|
2805
|
+
Effect22.gen(function* () {
|
|
2695
2806
|
const currentProcess = yield* sessionProcessService.getSessionProcess(
|
|
2696
2807
|
sessionProcess.def.sessionProcessId
|
|
2697
2808
|
);
|
|
@@ -2707,16 +2818,16 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2707
2818
|
daemonPromise,
|
|
2708
2819
|
awaitSessionInitialized: async () => await sessionInitializedPromise.promise,
|
|
2709
2820
|
awaitSessionFileCreated: async () => await sessionFileCreatedPromise.promise,
|
|
2710
|
-
yieldSessionInitialized: () =>
|
|
2711
|
-
yieldSessionFileCreated: () =>
|
|
2821
|
+
yieldSessionInitialized: () => Effect22.promise(() => sessionInitializedPromise.promise),
|
|
2822
|
+
yieldSessionFileCreated: () => Effect22.promise(() => sessionFileCreatedPromise.promise)
|
|
2712
2823
|
};
|
|
2713
2824
|
});
|
|
2714
2825
|
};
|
|
2715
|
-
const getPublicSessionProcesses = () =>
|
|
2826
|
+
const getPublicSessionProcesses = () => Effect22.gen(function* () {
|
|
2716
2827
|
const processes = yield* sessionProcessService.getSessionProcesses();
|
|
2717
2828
|
return processes.filter((process2) => isPublic(process2));
|
|
2718
2829
|
});
|
|
2719
|
-
const abortTask = (sessionProcessId) =>
|
|
2830
|
+
const abortTask = (sessionProcessId) => Effect22.gen(function* () {
|
|
2720
2831
|
const currentProcess = yield* sessionProcessService.getSessionProcess(sessionProcessId);
|
|
2721
2832
|
currentProcess.def.abortController.abort();
|
|
2722
2833
|
yield* sessionProcessService.toCompletedState({
|
|
@@ -2724,7 +2835,7 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2724
2835
|
error: new Error("Task aborted")
|
|
2725
2836
|
});
|
|
2726
2837
|
});
|
|
2727
|
-
const abortAllTasks = () =>
|
|
2838
|
+
const abortAllTasks = () => Effect22.gen(function* () {
|
|
2728
2839
|
const processes = yield* sessionProcessService.getSessionProcesses();
|
|
2729
2840
|
for (const process2 of processes) {
|
|
2730
2841
|
yield* sessionProcessService.toCompletedState({
|
|
@@ -2741,20 +2852,20 @@ var LayerImpl13 = Effect19.gen(function* () {
|
|
|
2741
2852
|
getPublicSessionProcesses
|
|
2742
2853
|
};
|
|
2743
2854
|
});
|
|
2744
|
-
var ClaudeCodeLifeCycleService = class extends
|
|
2855
|
+
var ClaudeCodeLifeCycleService = class extends Context18.Tag(
|
|
2745
2856
|
"ClaudeCodeLifeCycleService"
|
|
2746
2857
|
)() {
|
|
2747
2858
|
static {
|
|
2748
|
-
this.Live =
|
|
2859
|
+
this.Live = Layer20.effect(this, LayerImpl15);
|
|
2749
2860
|
}
|
|
2750
2861
|
};
|
|
2751
2862
|
|
|
2752
2863
|
// src/server/core/claude-code/presentation/ClaudeCodeSessionProcessController.ts
|
|
2753
|
-
var
|
|
2864
|
+
var LayerImpl16 = Effect23.gen(function* () {
|
|
2754
2865
|
const projectRepository = yield* ProjectRepository;
|
|
2755
2866
|
const claudeCodeLifeCycleService = yield* ClaudeCodeLifeCycleService;
|
|
2756
2867
|
const userConfigService = yield* UserConfigService;
|
|
2757
|
-
const getSessionProcesses = () =>
|
|
2868
|
+
const getSessionProcesses = () => Effect23.gen(function* () {
|
|
2758
2869
|
const publicSessionProcesses = yield* claudeCodeLifeCycleService.getPublicSessionProcesses();
|
|
2759
2870
|
return {
|
|
2760
2871
|
response: {
|
|
@@ -2770,7 +2881,7 @@ var LayerImpl14 = Effect20.gen(function* () {
|
|
|
2770
2881
|
status: 200
|
|
2771
2882
|
};
|
|
2772
2883
|
});
|
|
2773
|
-
const createSessionProcess = (options) =>
|
|
2884
|
+
const createSessionProcess = (options) => Effect23.gen(function* () {
|
|
2774
2885
|
const { projectId, input, baseSessionId } = options;
|
|
2775
2886
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
2776
2887
|
const userConfig = yield* userConfigService.getUserConfig();
|
|
@@ -2801,7 +2912,7 @@ var LayerImpl14 = Effect20.gen(function* () {
|
|
|
2801
2912
|
}
|
|
2802
2913
|
};
|
|
2803
2914
|
});
|
|
2804
|
-
const continueSessionProcess = (options) =>
|
|
2915
|
+
const continueSessionProcess = (options) => Effect23.gen(function* () {
|
|
2805
2916
|
const { projectId, input, baseSessionId, sessionProcessId } = options;
|
|
2806
2917
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
2807
2918
|
if (project.meta.projectPath === null) {
|
|
@@ -2832,16 +2943,16 @@ var LayerImpl14 = Effect20.gen(function* () {
|
|
|
2832
2943
|
continueSessionProcess
|
|
2833
2944
|
};
|
|
2834
2945
|
});
|
|
2835
|
-
var ClaudeCodeSessionProcessController = class extends
|
|
2946
|
+
var ClaudeCodeSessionProcessController = class extends Context19.Tag(
|
|
2836
2947
|
"ClaudeCodeSessionProcessController"
|
|
2837
2948
|
)() {
|
|
2838
2949
|
static {
|
|
2839
|
-
this.Live =
|
|
2950
|
+
this.Live = Layer21.effect(this, LayerImpl16);
|
|
2840
2951
|
}
|
|
2841
2952
|
};
|
|
2842
2953
|
|
|
2843
2954
|
// src/server/core/events/presentation/SSEController.ts
|
|
2844
|
-
import { Context as
|
|
2955
|
+
import { Context as Context21, Effect as Effect25, Layer as Layer23 } from "effect";
|
|
2845
2956
|
|
|
2846
2957
|
// src/server/core/events/functions/adaptInternalEventToSSE.ts
|
|
2847
2958
|
var adaptInternalEventToSSE = (rawStream, options) => {
|
|
@@ -2868,12 +2979,12 @@ var adaptInternalEventToSSE = (rawStream, options) => {
|
|
|
2868
2979
|
};
|
|
2869
2980
|
|
|
2870
2981
|
// src/server/core/events/functions/typeSafeSSE.ts
|
|
2871
|
-
import { Context as
|
|
2982
|
+
import { Context as Context20, Effect as Effect24, Layer as Layer22 } from "effect";
|
|
2872
2983
|
import { ulid as ulid3 } from "ulid";
|
|
2873
|
-
var TypeSafeSSE = class extends
|
|
2984
|
+
var TypeSafeSSE = class extends Context20.Tag("TypeSafeSSE")() {
|
|
2874
2985
|
static {
|
|
2875
|
-
this.make = (stream) =>
|
|
2876
|
-
writeSSE: (event, data) =>
|
|
2986
|
+
this.make = (stream) => Layer22.succeed(this, {
|
|
2987
|
+
writeSSE: (event, data) => Effect24.tryPromise({
|
|
2877
2988
|
try: async () => {
|
|
2878
2989
|
const id = ulid3();
|
|
2879
2990
|
await stream.writeSSE({
|
|
@@ -2898,44 +3009,52 @@ var TypeSafeSSE = class extends Context18.Tag("TypeSafeSSE")() {
|
|
|
2898
3009
|
};
|
|
2899
3010
|
|
|
2900
3011
|
// src/server/core/events/presentation/SSEController.ts
|
|
2901
|
-
var
|
|
3012
|
+
var LayerImpl17 = Effect25.gen(function* () {
|
|
2902
3013
|
const eventBus = yield* EventBus;
|
|
2903
|
-
const handleSSE = (rawStream) =>
|
|
3014
|
+
const handleSSE = (rawStream) => Effect25.gen(function* () {
|
|
2904
3015
|
const typeSafeSSE = yield* TypeSafeSSE;
|
|
2905
3016
|
yield* typeSafeSSE.writeSSE("connect", {
|
|
2906
3017
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2907
3018
|
});
|
|
2908
3019
|
const onHeartbeat = () => {
|
|
2909
|
-
|
|
3020
|
+
Effect25.runFork(
|
|
2910
3021
|
typeSafeSSE.writeSSE("heartbeat", {
|
|
2911
3022
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2912
3023
|
})
|
|
2913
3024
|
);
|
|
2914
3025
|
};
|
|
2915
3026
|
const onSessionListChanged = (event) => {
|
|
2916
|
-
|
|
3027
|
+
Effect25.runFork(
|
|
2917
3028
|
typeSafeSSE.writeSSE("sessionListChanged", {
|
|
2918
3029
|
projectId: event.projectId
|
|
2919
3030
|
})
|
|
2920
3031
|
);
|
|
2921
3032
|
};
|
|
2922
3033
|
const onSessionChanged = (event) => {
|
|
2923
|
-
|
|
3034
|
+
Effect25.runFork(
|
|
2924
3035
|
typeSafeSSE.writeSSE("sessionChanged", {
|
|
2925
3036
|
projectId: event.projectId,
|
|
2926
3037
|
sessionId: event.sessionId
|
|
2927
3038
|
})
|
|
2928
3039
|
);
|
|
2929
3040
|
};
|
|
3041
|
+
const onAgentSessionChanged = (event) => {
|
|
3042
|
+
Effect25.runFork(
|
|
3043
|
+
typeSafeSSE.writeSSE("agentSessionChanged", {
|
|
3044
|
+
projectId: event.projectId,
|
|
3045
|
+
agentSessionId: event.agentSessionId
|
|
3046
|
+
})
|
|
3047
|
+
);
|
|
3048
|
+
};
|
|
2930
3049
|
const onSessionProcessChanged = (event) => {
|
|
2931
|
-
|
|
3050
|
+
Effect25.runFork(
|
|
2932
3051
|
typeSafeSSE.writeSSE("sessionProcessChanged", {
|
|
2933
3052
|
processes: event.processes
|
|
2934
3053
|
})
|
|
2935
3054
|
);
|
|
2936
3055
|
};
|
|
2937
3056
|
const onPermissionRequested = (event) => {
|
|
2938
|
-
|
|
3057
|
+
Effect25.runFork(
|
|
2939
3058
|
typeSafeSSE.writeSSE("permissionRequested", {
|
|
2940
3059
|
permissionRequest: event.permissionRequest
|
|
2941
3060
|
})
|
|
@@ -2943,16 +3062,18 @@ var LayerImpl15 = Effect22.gen(function* () {
|
|
|
2943
3062
|
};
|
|
2944
3063
|
yield* eventBus.on("sessionListChanged", onSessionListChanged);
|
|
2945
3064
|
yield* eventBus.on("sessionChanged", onSessionChanged);
|
|
3065
|
+
yield* eventBus.on("agentSessionChanged", onAgentSessionChanged);
|
|
2946
3066
|
yield* eventBus.on("sessionProcessChanged", onSessionProcessChanged);
|
|
2947
3067
|
yield* eventBus.on("heartbeat", onHeartbeat);
|
|
2948
3068
|
yield* eventBus.on("permissionRequested", onPermissionRequested);
|
|
2949
3069
|
const { connectionPromise } = adaptInternalEventToSSE(rawStream, {
|
|
2950
3070
|
timeout: 5 * 60 * 1e3,
|
|
2951
3071
|
cleanUp: async () => {
|
|
2952
|
-
await
|
|
2953
|
-
|
|
3072
|
+
await Effect25.runPromise(
|
|
3073
|
+
Effect25.gen(function* () {
|
|
2954
3074
|
yield* eventBus.off("sessionListChanged", onSessionListChanged);
|
|
2955
3075
|
yield* eventBus.off("sessionChanged", onSessionChanged);
|
|
3076
|
+
yield* eventBus.off("agentSessionChanged", onAgentSessionChanged);
|
|
2956
3077
|
yield* eventBus.off(
|
|
2957
3078
|
"sessionProcessChanged",
|
|
2958
3079
|
onSessionProcessChanged
|
|
@@ -2963,34 +3084,64 @@ var LayerImpl15 = Effect22.gen(function* () {
|
|
|
2963
3084
|
);
|
|
2964
3085
|
}
|
|
2965
3086
|
});
|
|
2966
|
-
yield*
|
|
3087
|
+
yield* Effect25.promise(() => connectionPromise);
|
|
2967
3088
|
});
|
|
2968
3089
|
return {
|
|
2969
3090
|
handleSSE
|
|
2970
3091
|
};
|
|
2971
3092
|
});
|
|
2972
|
-
var SSEController = class extends
|
|
3093
|
+
var SSEController = class extends Context21.Tag("SSEController")() {
|
|
2973
3094
|
static {
|
|
2974
|
-
this.Live =
|
|
3095
|
+
this.Live = Layer23.effect(this, LayerImpl17);
|
|
2975
3096
|
}
|
|
2976
3097
|
};
|
|
2977
3098
|
|
|
2978
3099
|
// src/server/core/events/services/fileWatcher.ts
|
|
2979
3100
|
import { watch } from "node:fs";
|
|
2980
|
-
import { Path as
|
|
2981
|
-
import { Context as
|
|
3101
|
+
import { Path as Path10 } from "@effect/platform";
|
|
3102
|
+
import { Context as Context22, Effect as Effect26, Layer as Layer24, Ref as Ref9 } from "effect";
|
|
3103
|
+
|
|
3104
|
+
// src/server/core/events/functions/parseSessionFilePath.ts
|
|
2982
3105
|
import z22 from "zod";
|
|
2983
|
-
var
|
|
2984
|
-
var
|
|
3106
|
+
var sessionFileRegExp = /(?<projectId>.*?)\/(?<sessionId>.*?)\.jsonl$/;
|
|
3107
|
+
var agentFileRegExp = /(?<projectId>.*?)\/agent-(?<agentSessionId>.*?)\.jsonl$/;
|
|
3108
|
+
var sessionFileGroupSchema = z22.object({
|
|
2985
3109
|
projectId: z22.string(),
|
|
2986
3110
|
sessionId: z22.string()
|
|
2987
3111
|
});
|
|
2988
|
-
var
|
|
3112
|
+
var agentFileGroupSchema = z22.object({
|
|
3113
|
+
projectId: z22.string(),
|
|
3114
|
+
agentSessionId: z22.string()
|
|
3115
|
+
});
|
|
3116
|
+
var parseSessionFilePath = (filePath) => {
|
|
3117
|
+
const agentMatch = filePath.match(agentFileRegExp);
|
|
3118
|
+
const agentGroups = agentFileGroupSchema.safeParse(agentMatch?.groups);
|
|
3119
|
+
if (agentGroups.success) {
|
|
3120
|
+
return {
|
|
3121
|
+
type: "agent",
|
|
3122
|
+
projectId: agentGroups.data.projectId,
|
|
3123
|
+
agentSessionId: agentGroups.data.agentSessionId
|
|
3124
|
+
};
|
|
3125
|
+
}
|
|
3126
|
+
const sessionMatch = filePath.match(sessionFileRegExp);
|
|
3127
|
+
const sessionGroups = sessionFileGroupSchema.safeParse(sessionMatch?.groups);
|
|
3128
|
+
if (sessionGroups.success) {
|
|
3129
|
+
return {
|
|
3130
|
+
type: "session",
|
|
3131
|
+
projectId: sessionGroups.data.projectId,
|
|
3132
|
+
sessionId: sessionGroups.data.sessionId
|
|
3133
|
+
};
|
|
3134
|
+
}
|
|
3135
|
+
return null;
|
|
3136
|
+
};
|
|
3137
|
+
|
|
3138
|
+
// src/server/core/events/services/fileWatcher.ts
|
|
3139
|
+
var FileWatcherService = class extends Context22.Tag("FileWatcherService")() {
|
|
2989
3140
|
static {
|
|
2990
|
-
this.Live =
|
|
3141
|
+
this.Live = Layer24.effect(
|
|
2991
3142
|
this,
|
|
2992
|
-
|
|
2993
|
-
const path = yield*
|
|
3143
|
+
Effect26.gen(function* () {
|
|
3144
|
+
const path = yield* Path10.Path;
|
|
2994
3145
|
const eventBus = yield* EventBus;
|
|
2995
3146
|
const context = yield* ApplicationContext;
|
|
2996
3147
|
const isWatchingRef = yield* Ref9.make(false);
|
|
@@ -2999,11 +3150,11 @@ var FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
|
|
|
2999
3150
|
/* @__PURE__ */ new Map()
|
|
3000
3151
|
);
|
|
3001
3152
|
const debounceTimersRef = yield* Ref9.make(/* @__PURE__ */ new Map());
|
|
3002
|
-
const startWatching = () =>
|
|
3153
|
+
const startWatching = () => Effect26.gen(function* () {
|
|
3003
3154
|
const isWatching = yield* Ref9.get(isWatchingRef);
|
|
3004
3155
|
if (isWatching) return;
|
|
3005
3156
|
yield* Ref9.set(isWatchingRef, true);
|
|
3006
|
-
yield*
|
|
3157
|
+
yield* Effect26.tryPromise({
|
|
3007
3158
|
try: async () => {
|
|
3008
3159
|
console.log(
|
|
3009
3160
|
"Starting file watcher on:",
|
|
@@ -3014,38 +3165,44 @@ var FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
|
|
|
3014
3165
|
{ persistent: false, recursive: true },
|
|
3015
3166
|
(_eventType, filename) => {
|
|
3016
3167
|
if (!filename) return;
|
|
3017
|
-
const
|
|
3018
|
-
|
|
3019
|
-
);
|
|
3020
|
-
if (!groups.success) return;
|
|
3021
|
-
const { sessionId } = groups.data;
|
|
3168
|
+
const fileMatch = parseSessionFilePath(filename);
|
|
3169
|
+
if (fileMatch === null) return;
|
|
3022
3170
|
const fullPath = path.join(
|
|
3023
3171
|
context.claudeCodePaths.claudeProjectsDirPath,
|
|
3024
3172
|
filename
|
|
3025
3173
|
);
|
|
3026
3174
|
const encodedProjectId = encodeProjectIdFromSessionFilePath(fullPath);
|
|
3027
|
-
const debounceKey = `${encodedProjectId}/${sessionId}`;
|
|
3028
|
-
|
|
3029
|
-
|
|
3175
|
+
const debounceKey = fileMatch.type === "agent" ? `${encodedProjectId}/agent-${fileMatch.agentSessionId}` : `${encodedProjectId}/${fileMatch.sessionId}`;
|
|
3176
|
+
Effect26.runPromise(
|
|
3177
|
+
Effect26.gen(function* () {
|
|
3030
3178
|
const timers = yield* Ref9.get(debounceTimersRef);
|
|
3031
3179
|
const existingTimer = timers.get(debounceKey);
|
|
3032
3180
|
if (existingTimer) {
|
|
3033
3181
|
clearTimeout(existingTimer);
|
|
3034
3182
|
}
|
|
3035
3183
|
const newTimer = setTimeout(() => {
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3184
|
+
if (fileMatch.type === "agent") {
|
|
3185
|
+
Effect26.runFork(
|
|
3186
|
+
eventBus.emit("agentSessionChanged", {
|
|
3187
|
+
projectId: encodedProjectId,
|
|
3188
|
+
agentSessionId: fileMatch.agentSessionId
|
|
3189
|
+
})
|
|
3190
|
+
);
|
|
3191
|
+
} else {
|
|
3192
|
+
Effect26.runFork(
|
|
3193
|
+
eventBus.emit("sessionChanged", {
|
|
3194
|
+
projectId: encodedProjectId,
|
|
3195
|
+
sessionId: fileMatch.sessionId
|
|
3196
|
+
})
|
|
3197
|
+
);
|
|
3198
|
+
Effect26.runFork(
|
|
3199
|
+
eventBus.emit("sessionListChanged", {
|
|
3200
|
+
projectId: encodedProjectId
|
|
3201
|
+
})
|
|
3202
|
+
);
|
|
3203
|
+
}
|
|
3204
|
+
Effect26.runPromise(
|
|
3205
|
+
Effect26.gen(function* () {
|
|
3049
3206
|
const currentTimers = yield* Ref9.get(debounceTimersRef);
|
|
3050
3207
|
currentTimers.delete(debounceKey);
|
|
3051
3208
|
yield* Ref9.set(debounceTimersRef, currentTimers);
|
|
@@ -3058,7 +3215,7 @@ var FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
|
|
|
3058
3215
|
);
|
|
3059
3216
|
}
|
|
3060
3217
|
);
|
|
3061
|
-
await
|
|
3218
|
+
await Effect26.runPromise(Ref9.set(watcherRef, watcher));
|
|
3062
3219
|
console.log("File watcher initialization completed");
|
|
3063
3220
|
},
|
|
3064
3221
|
catch: (error) => {
|
|
@@ -3069,10 +3226,10 @@ var FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
|
|
|
3069
3226
|
}
|
|
3070
3227
|
}).pipe(
|
|
3071
3228
|
// エラーが発生しても続行する
|
|
3072
|
-
|
|
3229
|
+
Effect26.catchAll(() => Effect26.void)
|
|
3073
3230
|
);
|
|
3074
3231
|
});
|
|
3075
|
-
const stop = () =>
|
|
3232
|
+
const stop = () => Effect26.gen(function* () {
|
|
3076
3233
|
const timers = yield* Ref9.get(debounceTimersRef);
|
|
3077
3234
|
for (const [, timer] of timers) {
|
|
3078
3235
|
clearTimeout(timer);
|
|
@@ -3080,12 +3237,12 @@ var FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
|
|
|
3080
3237
|
yield* Ref9.set(debounceTimersRef, /* @__PURE__ */ new Map());
|
|
3081
3238
|
const watcher = yield* Ref9.get(watcherRef);
|
|
3082
3239
|
if (watcher) {
|
|
3083
|
-
yield*
|
|
3240
|
+
yield* Effect26.sync(() => watcher.close());
|
|
3084
3241
|
yield* Ref9.set(watcherRef, null);
|
|
3085
3242
|
}
|
|
3086
3243
|
const projectWatchers = yield* Ref9.get(projectWatchersRef);
|
|
3087
3244
|
for (const [, projectWatcher] of projectWatchers) {
|
|
3088
|
-
yield*
|
|
3245
|
+
yield* Effect26.sync(() => projectWatcher.close());
|
|
3089
3246
|
}
|
|
3090
3247
|
yield* Ref9.set(projectWatchersRef, /* @__PURE__ */ new Map());
|
|
3091
3248
|
yield* Ref9.set(isWatchingRef, false);
|
|
@@ -3100,10 +3257,10 @@ var FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
|
|
|
3100
3257
|
};
|
|
3101
3258
|
|
|
3102
3259
|
// src/server/core/feature-flag/presentation/FeatureFlagController.ts
|
|
3103
|
-
import { Context as
|
|
3104
|
-
var
|
|
3260
|
+
import { Context as Context23, Effect as Effect27, Layer as Layer25 } from "effect";
|
|
3261
|
+
var LayerImpl18 = Effect27.gen(function* () {
|
|
3105
3262
|
const claudeCodeService = yield* ClaudeCodeService;
|
|
3106
|
-
const getFlags = () =>
|
|
3263
|
+
const getFlags = () => Effect27.gen(function* () {
|
|
3107
3264
|
const claudeCodeFeatures = yield* claudeCodeService.getAvailableFeatures();
|
|
3108
3265
|
return {
|
|
3109
3266
|
response: {
|
|
@@ -3115,6 +3272,10 @@ var LayerImpl16 = Effect24.gen(function* () {
|
|
|
3115
3272
|
{
|
|
3116
3273
|
name: "agent-sdk",
|
|
3117
3274
|
enabled: claudeCodeFeatures.agentSdk
|
|
3275
|
+
},
|
|
3276
|
+
{
|
|
3277
|
+
name: "sidechain-separation",
|
|
3278
|
+
enabled: claudeCodeFeatures.sidechainSeparation
|
|
3118
3279
|
}
|
|
3119
3280
|
]
|
|
3120
3281
|
},
|
|
@@ -3125,15 +3286,15 @@ var LayerImpl16 = Effect24.gen(function* () {
|
|
|
3125
3286
|
getFlags
|
|
3126
3287
|
};
|
|
3127
3288
|
});
|
|
3128
|
-
var FeatureFlagController = class extends
|
|
3289
|
+
var FeatureFlagController = class extends Context23.Tag("FeatureFlagController")() {
|
|
3129
3290
|
static {
|
|
3130
|
-
this.Live =
|
|
3291
|
+
this.Live = Layer25.effect(this, LayerImpl18);
|
|
3131
3292
|
}
|
|
3132
3293
|
};
|
|
3133
3294
|
|
|
3134
3295
|
// src/server/core/file-system/presentation/FileSystemController.ts
|
|
3135
3296
|
import { homedir as homedir3 } from "node:os";
|
|
3136
|
-
import { Context as
|
|
3297
|
+
import { Context as Context24, Effect as Effect28, Layer as Layer26 } from "effect";
|
|
3137
3298
|
|
|
3138
3299
|
// src/server/core/file-system/functions/getDirectoryListing.ts
|
|
3139
3300
|
import { existsSync } from "node:fs";
|
|
@@ -3266,9 +3427,9 @@ var getFileCompletion = async (projectPath, basePath = "/") => {
|
|
|
3266
3427
|
};
|
|
3267
3428
|
|
|
3268
3429
|
// src/server/core/file-system/presentation/FileSystemController.ts
|
|
3269
|
-
var
|
|
3430
|
+
var LayerImpl19 = Effect28.gen(function* () {
|
|
3270
3431
|
const projectRepository = yield* ProjectRepository;
|
|
3271
|
-
const getFileCompletionRoute = (options) =>
|
|
3432
|
+
const getFileCompletionRoute = (options) => Effect28.gen(function* () {
|
|
3272
3433
|
const { projectId, basePath } = options;
|
|
3273
3434
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
3274
3435
|
if (project.meta.projectPath === null) {
|
|
@@ -3279,7 +3440,7 @@ var LayerImpl17 = Effect25.gen(function* () {
|
|
|
3279
3440
|
}
|
|
3280
3441
|
const projectPath = project.meta.projectPath;
|
|
3281
3442
|
try {
|
|
3282
|
-
const result = yield*
|
|
3443
|
+
const result = yield* Effect28.promise(
|
|
3283
3444
|
() => getFileCompletion(projectPath, basePath)
|
|
3284
3445
|
);
|
|
3285
3446
|
return {
|
|
@@ -3294,7 +3455,7 @@ var LayerImpl17 = Effect25.gen(function* () {
|
|
|
3294
3455
|
};
|
|
3295
3456
|
}
|
|
3296
3457
|
});
|
|
3297
|
-
const getDirectoryListingRoute = (options) =>
|
|
3458
|
+
const getDirectoryListingRoute = (options) => Effect28.promise(async () => {
|
|
3298
3459
|
const { currentPath, showHidden = false } = options;
|
|
3299
3460
|
const rootPath = "/";
|
|
3300
3461
|
const defaultPath = homedir3();
|
|
@@ -3323,14 +3484,14 @@ var LayerImpl17 = Effect25.gen(function* () {
|
|
|
3323
3484
|
getDirectoryListingRoute
|
|
3324
3485
|
};
|
|
3325
3486
|
});
|
|
3326
|
-
var FileSystemController = class extends
|
|
3487
|
+
var FileSystemController = class extends Context24.Tag("FileSystemController")() {
|
|
3327
3488
|
static {
|
|
3328
|
-
this.Live =
|
|
3489
|
+
this.Live = Layer26.effect(this, LayerImpl19);
|
|
3329
3490
|
}
|
|
3330
3491
|
};
|
|
3331
3492
|
|
|
3332
3493
|
// src/server/core/git/presentation/GitController.ts
|
|
3333
|
-
import { Context as
|
|
3494
|
+
import { Context as Context26, Effect as Effect30, Either as Either2, Layer as Layer28 } from "effect";
|
|
3334
3495
|
|
|
3335
3496
|
// src/server/core/git/functions/getDiff.ts
|
|
3336
3497
|
import { readFile } from "node:fs/promises";
|
|
@@ -3669,8 +3830,8 @@ var getDiff = async (cwd, fromRefText, toRefText) => {
|
|
|
3669
3830
|
};
|
|
3670
3831
|
|
|
3671
3832
|
// src/server/core/git/services/GitService.ts
|
|
3672
|
-
import { Command as Command2, FileSystem as
|
|
3673
|
-
import { Context as
|
|
3833
|
+
import { Command as Command2, FileSystem as FileSystem9, Path as Path11 } from "@effect/platform";
|
|
3834
|
+
import { Context as Context25, Data as Data4, Duration, Effect as Effect29, Either, Layer as Layer27 } from "effect";
|
|
3674
3835
|
|
|
3675
3836
|
// src/server/core/git/functions/parseGitBranchesOutput.ts
|
|
3676
3837
|
var parseGitBranchesOutput = (output) => {
|
|
@@ -3747,14 +3908,14 @@ var GitCommandError = class extends Data4.TaggedError("GitCommandError") {
|
|
|
3747
3908
|
};
|
|
3748
3909
|
var DetachedHeadError = class extends Data4.TaggedError("DetachedHeadError") {
|
|
3749
3910
|
};
|
|
3750
|
-
var
|
|
3751
|
-
const fs = yield*
|
|
3752
|
-
const path = yield*
|
|
3911
|
+
var LayerImpl20 = Effect29.gen(function* () {
|
|
3912
|
+
const fs = yield* FileSystem9.FileSystem;
|
|
3913
|
+
const path = yield* Path11.Path;
|
|
3753
3914
|
const envService = yield* EnvService;
|
|
3754
|
-
const execGitCommand = (args, cwd) =>
|
|
3915
|
+
const execGitCommand = (args, cwd) => Effect29.gen(function* () {
|
|
3755
3916
|
const absoluteCwd = path.resolve(cwd);
|
|
3756
3917
|
if (!(yield* fs.exists(absoluteCwd))) {
|
|
3757
|
-
return yield*
|
|
3918
|
+
return yield* Effect29.fail(
|
|
3758
3919
|
new NotARepositoryError({ cwd: absoluteCwd })
|
|
3759
3920
|
);
|
|
3760
3921
|
}
|
|
@@ -3764,9 +3925,9 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3764
3925
|
PATH: yield* envService.getEnv("PATH")
|
|
3765
3926
|
})
|
|
3766
3927
|
);
|
|
3767
|
-
const result = yield*
|
|
3928
|
+
const result = yield* Effect29.either(Command2.string(command));
|
|
3768
3929
|
if (Either.isLeft(result)) {
|
|
3769
|
-
return yield*
|
|
3930
|
+
return yield* Effect29.fail(
|
|
3770
3931
|
new GitCommandError({
|
|
3771
3932
|
cwd: absoluteCwd,
|
|
3772
3933
|
command: `git ${args.join(" ")}`
|
|
@@ -3775,22 +3936,22 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3775
3936
|
}
|
|
3776
3937
|
return result.right;
|
|
3777
3938
|
});
|
|
3778
|
-
const getBranches = (cwd) =>
|
|
3939
|
+
const getBranches = (cwd) => Effect29.gen(function* () {
|
|
3779
3940
|
const result = yield* execGitCommand(["branch", "-vv", "--all"], cwd);
|
|
3780
3941
|
return parseGitBranchesOutput(result);
|
|
3781
3942
|
});
|
|
3782
|
-
const getCurrentBranch = (cwd) =>
|
|
3943
|
+
const getCurrentBranch = (cwd) => Effect29.gen(function* () {
|
|
3783
3944
|
const currentBranch = yield* execGitCommand(
|
|
3784
3945
|
["branch", "--show-current"],
|
|
3785
3946
|
cwd
|
|
3786
|
-
).pipe(
|
|
3947
|
+
).pipe(Effect29.map((result) => result.trim()));
|
|
3787
3948
|
if (currentBranch === "") {
|
|
3788
|
-
return yield*
|
|
3949
|
+
return yield* Effect29.fail(new DetachedHeadError({ cwd }));
|
|
3789
3950
|
}
|
|
3790
3951
|
return currentBranch;
|
|
3791
3952
|
});
|
|
3792
|
-
const branchExists = (cwd, branchName) =>
|
|
3793
|
-
const result = yield*
|
|
3953
|
+
const branchExists = (cwd, branchName) => Effect29.gen(function* () {
|
|
3954
|
+
const result = yield* Effect29.either(
|
|
3794
3955
|
execGitCommand(["branch", "--exists", branchName], cwd)
|
|
3795
3956
|
);
|
|
3796
3957
|
if (Either.isLeft(result)) {
|
|
@@ -3798,7 +3959,7 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3798
3959
|
}
|
|
3799
3960
|
return true;
|
|
3800
3961
|
});
|
|
3801
|
-
const getCommits = (cwd) =>
|
|
3962
|
+
const getCommits = (cwd) => Effect29.gen(function* () {
|
|
3802
3963
|
const result = yield* execGitCommand(
|
|
3803
3964
|
[
|
|
3804
3965
|
"log",
|
|
@@ -3812,9 +3973,9 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3812
3973
|
);
|
|
3813
3974
|
return parseGitCommitsOutput(result);
|
|
3814
3975
|
});
|
|
3815
|
-
const stageFiles = (cwd, files) =>
|
|
3976
|
+
const stageFiles = (cwd, files) => Effect29.gen(function* () {
|
|
3816
3977
|
if (files.length === 0) {
|
|
3817
|
-
return yield*
|
|
3978
|
+
return yield* Effect29.fail(
|
|
3818
3979
|
new GitCommandError({
|
|
3819
3980
|
cwd,
|
|
3820
3981
|
command: "git add (no files)"
|
|
@@ -3824,10 +3985,10 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3824
3985
|
const result = yield* execGitCommand(["add", ...files], cwd);
|
|
3825
3986
|
return result;
|
|
3826
3987
|
});
|
|
3827
|
-
const commit = (cwd, message) =>
|
|
3988
|
+
const commit = (cwd, message) => Effect29.gen(function* () {
|
|
3828
3989
|
const trimmedMessage = message.trim();
|
|
3829
3990
|
if (trimmedMessage.length === 0) {
|
|
3830
|
-
return yield*
|
|
3991
|
+
return yield* Effect29.fail(
|
|
3831
3992
|
new GitCommandError({
|
|
3832
3993
|
cwd,
|
|
3833
3994
|
command: "git commit (empty message)"
|
|
@@ -3864,7 +4025,7 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3864
4025
|
);
|
|
3865
4026
|
return sha.trim();
|
|
3866
4027
|
});
|
|
3867
|
-
const push = (cwd) =>
|
|
4028
|
+
const push = (cwd) => Effect29.gen(function* () {
|
|
3868
4029
|
const branch = yield* getCurrentBranch(cwd);
|
|
3869
4030
|
const absoluteCwd = path.resolve(cwd);
|
|
3870
4031
|
const command = Command2.make("git", "push", "origin", "HEAD").pipe(
|
|
@@ -3873,12 +4034,12 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3873
4034
|
PATH: yield* envService.getEnv("PATH")
|
|
3874
4035
|
})
|
|
3875
4036
|
);
|
|
3876
|
-
const exitCodeResult = yield*
|
|
3877
|
-
Command2.exitCode(command).pipe(
|
|
4037
|
+
const exitCodeResult = yield* Effect29.either(
|
|
4038
|
+
Command2.exitCode(command).pipe(Effect29.timeout(Duration.seconds(60)))
|
|
3878
4039
|
);
|
|
3879
4040
|
if (Either.isLeft(exitCodeResult)) {
|
|
3880
4041
|
console.log("[GitService.push] Command failed or timeout");
|
|
3881
|
-
return yield*
|
|
4042
|
+
return yield* Effect29.fail(
|
|
3882
4043
|
new GitCommandError({
|
|
3883
4044
|
cwd: absoluteCwd,
|
|
3884
4045
|
command: "git push origin HEAD (timeout after 60s)"
|
|
@@ -3896,10 +4057,10 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3896
4057
|
}),
|
|
3897
4058
|
Command2.stderr("inherit")
|
|
3898
4059
|
)
|
|
3899
|
-
).pipe(
|
|
4060
|
+
).pipe(Effect29.orElse(() => Effect29.succeed([])));
|
|
3900
4061
|
const stderr = Array.from(stderrLines).join("\n");
|
|
3901
4062
|
console.log("[GitService.push] Failed with stderr:", stderr);
|
|
3902
|
-
return yield*
|
|
4063
|
+
return yield* Effect29.fail(
|
|
3903
4064
|
new GitCommandError({
|
|
3904
4065
|
cwd: absoluteCwd,
|
|
3905
4066
|
command: `git push origin HEAD - ${stderr}`
|
|
@@ -3909,20 +4070,20 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3909
4070
|
console.log("[GitService.push] Push succeeded");
|
|
3910
4071
|
return { branch, output: "success" };
|
|
3911
4072
|
});
|
|
3912
|
-
const getBranchHash = (cwd, branchName) =>
|
|
4073
|
+
const getBranchHash = (cwd, branchName) => Effect29.gen(function* () {
|
|
3913
4074
|
const result = yield* execGitCommand(["rev-parse", branchName], cwd).pipe(
|
|
3914
|
-
|
|
4075
|
+
Effect29.map((output) => output.trim().split("\n")[0] ?? null)
|
|
3915
4076
|
);
|
|
3916
4077
|
return result;
|
|
3917
4078
|
});
|
|
3918
|
-
const getBranchNamesByCommitHash = (cwd, hash) =>
|
|
4079
|
+
const getBranchNamesByCommitHash = (cwd, hash) => Effect29.gen(function* () {
|
|
3919
4080
|
const result = yield* execGitCommand(
|
|
3920
4081
|
["branch", "--contains", hash, "--format=%(refname:short)"],
|
|
3921
4082
|
cwd
|
|
3922
4083
|
);
|
|
3923
4084
|
return result.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
3924
4085
|
});
|
|
3925
|
-
const compareCommitHash = (cwd, targetHash, compareHash) =>
|
|
4086
|
+
const compareCommitHash = (cwd, targetHash, compareHash) => Effect29.gen(function* () {
|
|
3926
4087
|
const aheadResult = yield* execGitCommand(
|
|
3927
4088
|
["rev-list", `${targetHash}..${compareHash}`],
|
|
3928
4089
|
cwd
|
|
@@ -3944,7 +4105,7 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3944
4105
|
}
|
|
3945
4106
|
return "un-related";
|
|
3946
4107
|
});
|
|
3947
|
-
const getCommitsWithParent = (cwd, options) =>
|
|
4108
|
+
const getCommitsWithParent = (cwd, options) => Effect29.gen(function* () {
|
|
3948
4109
|
const { offset, limit } = options;
|
|
3949
4110
|
const result = yield* execGitCommand(
|
|
3950
4111
|
[
|
|
@@ -3971,7 +4132,7 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
3971
4132
|
}
|
|
3972
4133
|
return commits;
|
|
3973
4134
|
});
|
|
3974
|
-
const findBaseBranch = (cwd, targetBranch) =>
|
|
4135
|
+
const findBaseBranch = (cwd, targetBranch) => Effect29.gen(function* () {
|
|
3975
4136
|
let offset = 0;
|
|
3976
4137
|
const limit = 20;
|
|
3977
4138
|
while (offset < 100) {
|
|
@@ -4005,7 +4166,7 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
4005
4166
|
}
|
|
4006
4167
|
return null;
|
|
4007
4168
|
});
|
|
4008
|
-
const getCommitsBetweenBranches = (cwd, baseBranch, targetBranch) =>
|
|
4169
|
+
const getCommitsBetweenBranches = (cwd, baseBranch, targetBranch) => Effect29.gen(function* () {
|
|
4009
4170
|
const result = yield* execGitCommand(
|
|
4010
4171
|
[
|
|
4011
4172
|
"log",
|
|
@@ -4033,17 +4194,17 @@ var LayerImpl18 = Effect26.gen(function* () {
|
|
|
4033
4194
|
getCommitsBetweenBranches
|
|
4034
4195
|
};
|
|
4035
4196
|
});
|
|
4036
|
-
var GitService = class extends
|
|
4197
|
+
var GitService = class extends Context25.Tag("GitService")() {
|
|
4037
4198
|
static {
|
|
4038
|
-
this.Live =
|
|
4199
|
+
this.Live = Layer27.effect(this, LayerImpl20);
|
|
4039
4200
|
}
|
|
4040
4201
|
};
|
|
4041
4202
|
|
|
4042
4203
|
// src/server/core/git/presentation/GitController.ts
|
|
4043
|
-
var
|
|
4204
|
+
var LayerImpl21 = Effect30.gen(function* () {
|
|
4044
4205
|
const gitService = yield* GitService;
|
|
4045
4206
|
const projectRepository = yield* ProjectRepository;
|
|
4046
|
-
const getGitDiff = (options) =>
|
|
4207
|
+
const getGitDiff = (options) => Effect30.gen(function* () {
|
|
4047
4208
|
const { projectId, fromRef, toRef } = options;
|
|
4048
4209
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
4049
4210
|
try {
|
|
@@ -4054,7 +4215,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4054
4215
|
};
|
|
4055
4216
|
}
|
|
4056
4217
|
const projectPath = project.meta.projectPath;
|
|
4057
|
-
const result = yield*
|
|
4218
|
+
const result = yield* Effect30.promise(
|
|
4058
4219
|
() => getDiff(projectPath, fromRef, toRef)
|
|
4059
4220
|
);
|
|
4060
4221
|
return {
|
|
@@ -4075,7 +4236,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4075
4236
|
};
|
|
4076
4237
|
}
|
|
4077
4238
|
});
|
|
4078
|
-
const commitFiles = (options) =>
|
|
4239
|
+
const commitFiles = (options) => Effect30.gen(function* () {
|
|
4079
4240
|
const { projectId, files, message } = options;
|
|
4080
4241
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
4081
4242
|
if (project.meta.projectPath === null) {
|
|
@@ -4088,7 +4249,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4088
4249
|
const projectPath = project.meta.projectPath;
|
|
4089
4250
|
console.log("[GitController.commitFiles] Project path:", projectPath);
|
|
4090
4251
|
console.log("[GitController.commitFiles] Staging files...");
|
|
4091
|
-
const stageResult = yield*
|
|
4252
|
+
const stageResult = yield* Effect30.either(
|
|
4092
4253
|
gitService.stageFiles(projectPath, files)
|
|
4093
4254
|
);
|
|
4094
4255
|
if (Either2.isLeft(stageResult)) {
|
|
@@ -4108,7 +4269,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4108
4269
|
}
|
|
4109
4270
|
console.log("[GitController.commitFiles] Stage succeeded");
|
|
4110
4271
|
console.log("[GitController.commitFiles] Committing...");
|
|
4111
|
-
const commitResult = yield*
|
|
4272
|
+
const commitResult = yield* Effect30.either(
|
|
4112
4273
|
gitService.commit(projectPath, message)
|
|
4113
4274
|
);
|
|
4114
4275
|
if (Either2.isLeft(commitResult)) {
|
|
@@ -4143,7 +4304,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4143
4304
|
status: 200
|
|
4144
4305
|
};
|
|
4145
4306
|
});
|
|
4146
|
-
const pushCommits = (options) =>
|
|
4307
|
+
const pushCommits = (options) => Effect30.gen(function* () {
|
|
4147
4308
|
const { projectId } = options;
|
|
4148
4309
|
console.log("[GitController.pushCommits] Request:", { projectId });
|
|
4149
4310
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
@@ -4157,7 +4318,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4157
4318
|
const projectPath = project.meta.projectPath;
|
|
4158
4319
|
console.log("[GitController.pushCommits] Project path:", projectPath);
|
|
4159
4320
|
console.log("[GitController.pushCommits] Pushing...");
|
|
4160
|
-
const pushResult = yield*
|
|
4321
|
+
const pushResult = yield* Effect30.either(gitService.push(projectPath));
|
|
4161
4322
|
if (Either2.isLeft(pushResult)) {
|
|
4162
4323
|
console.log(
|
|
4163
4324
|
"[GitController.pushCommits] Push failed:",
|
|
@@ -4186,7 +4347,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4186
4347
|
status: 200
|
|
4187
4348
|
};
|
|
4188
4349
|
});
|
|
4189
|
-
const commitAndPush = (options) =>
|
|
4350
|
+
const commitAndPush = (options) => Effect30.gen(function* () {
|
|
4190
4351
|
const { projectId, files, message } = options;
|
|
4191
4352
|
console.log("[GitController.commitAndPush] Request:", {
|
|
4192
4353
|
projectId,
|
|
@@ -4237,7 +4398,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4237
4398
|
status: 200
|
|
4238
4399
|
};
|
|
4239
4400
|
});
|
|
4240
|
-
const getCurrentRevisions = (options) =>
|
|
4401
|
+
const getCurrentRevisions = (options) => Effect30.gen(function* () {
|
|
4241
4402
|
const { projectId } = options;
|
|
4242
4403
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
4243
4404
|
if (project.meta.projectPath === null) {
|
|
@@ -4247,7 +4408,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4247
4408
|
};
|
|
4248
4409
|
}
|
|
4249
4410
|
const projectPath = project.meta.projectPath;
|
|
4250
|
-
const currentBranchResult = yield*
|
|
4411
|
+
const currentBranchResult = yield* Effect30.either(
|
|
4251
4412
|
gitService.getCurrentBranch(projectPath)
|
|
4252
4413
|
);
|
|
4253
4414
|
if (Either2.isLeft(currentBranchResult)) {
|
|
@@ -4259,10 +4420,10 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4259
4420
|
};
|
|
4260
4421
|
}
|
|
4261
4422
|
const currentBranch = currentBranchResult.right;
|
|
4262
|
-
const baseBranchResult = yield*
|
|
4423
|
+
const baseBranchResult = yield* Effect30.either(
|
|
4263
4424
|
gitService.findBaseBranch(projectPath, currentBranch)
|
|
4264
4425
|
);
|
|
4265
|
-
const allBranchesResult = yield*
|
|
4426
|
+
const allBranchesResult = yield* Effect30.either(
|
|
4266
4427
|
gitService.getBranches(projectPath)
|
|
4267
4428
|
);
|
|
4268
4429
|
if (Either2.isLeft(allBranchesResult)) {
|
|
@@ -4287,7 +4448,7 @@ var LayerImpl19 = Effect27.gen(function* () {
|
|
|
4287
4448
|
let commits = [];
|
|
4288
4449
|
if (Either2.isRight(baseBranchResult) && baseBranchResult.right !== null) {
|
|
4289
4450
|
const baseBranchHash = baseBranchResult.right.hash;
|
|
4290
|
-
const commitsResult = yield*
|
|
4451
|
+
const commitsResult = yield* Effect30.either(
|
|
4291
4452
|
gitService.getCommitsBetweenBranches(
|
|
4292
4453
|
projectPath,
|
|
4293
4454
|
baseBranchHash,
|
|
@@ -4350,21 +4511,21 @@ function getPushErrorMessage(code) {
|
|
|
4350
4511
|
};
|
|
4351
4512
|
return messages[code];
|
|
4352
4513
|
}
|
|
4353
|
-
var GitController = class extends
|
|
4514
|
+
var GitController = class extends Context26.Tag("GitController")() {
|
|
4354
4515
|
static {
|
|
4355
|
-
this.Live =
|
|
4516
|
+
this.Live = Layer28.effect(this, LayerImpl21);
|
|
4356
4517
|
}
|
|
4357
4518
|
};
|
|
4358
4519
|
|
|
4359
4520
|
// src/server/core/project/presentation/ProjectController.ts
|
|
4360
|
-
import { FileSystem as
|
|
4361
|
-
import { Context as
|
|
4521
|
+
import { FileSystem as FileSystem10, Path as Path13 } from "@effect/platform";
|
|
4522
|
+
import { Context as Context27, Effect as Effect32, Layer as Layer29 } from "effect";
|
|
4362
4523
|
|
|
4363
4524
|
// src/server/core/claude-code/functions/computeClaudeProjectFilePath.ts
|
|
4364
|
-
import { Path as
|
|
4365
|
-
import { Effect as
|
|
4366
|
-
var computeClaudeProjectFilePath = (options) =>
|
|
4367
|
-
const path = yield*
|
|
4525
|
+
import { Path as Path12 } from "@effect/platform";
|
|
4526
|
+
import { Effect as Effect31 } from "effect";
|
|
4527
|
+
var computeClaudeProjectFilePath = (options) => Effect31.gen(function* () {
|
|
4528
|
+
const path = yield* Path12.Path;
|
|
4368
4529
|
const { projectPath, claudeProjectsDirPath } = options;
|
|
4369
4530
|
return path.join(
|
|
4370
4531
|
claudeProjectsDirPath,
|
|
@@ -4373,22 +4534,22 @@ var computeClaudeProjectFilePath = (options) => Effect28.gen(function* () {
|
|
|
4373
4534
|
});
|
|
4374
4535
|
|
|
4375
4536
|
// src/server/core/project/presentation/ProjectController.ts
|
|
4376
|
-
var
|
|
4537
|
+
var LayerImpl22 = Effect32.gen(function* () {
|
|
4377
4538
|
const projectRepository = yield* ProjectRepository;
|
|
4378
4539
|
const claudeCodeLifeCycleService = yield* ClaudeCodeLifeCycleService;
|
|
4379
4540
|
const userConfigService = yield* UserConfigService;
|
|
4380
4541
|
const sessionRepository = yield* SessionRepository;
|
|
4381
4542
|
const context = yield* ApplicationContext;
|
|
4382
|
-
const fileSystem = yield*
|
|
4383
|
-
const path = yield*
|
|
4384
|
-
const getProjects = () =>
|
|
4543
|
+
const fileSystem = yield* FileSystem10.FileSystem;
|
|
4544
|
+
const path = yield* Path13.Path;
|
|
4545
|
+
const getProjects = () => Effect32.gen(function* () {
|
|
4385
4546
|
const { projects } = yield* projectRepository.getProjects();
|
|
4386
4547
|
return {
|
|
4387
4548
|
status: 200,
|
|
4388
4549
|
response: { projects }
|
|
4389
4550
|
};
|
|
4390
4551
|
});
|
|
4391
|
-
const getProject = (options) =>
|
|
4552
|
+
const getProject = (options) => Effect32.gen(function* () {
|
|
4392
4553
|
const { projectId, cursor } = options;
|
|
4393
4554
|
const userConfig = yield* userConfigService.getUserConfig();
|
|
4394
4555
|
const { project } = yield* projectRepository.getProject(projectId);
|
|
@@ -4442,7 +4603,7 @@ var LayerImpl20 = Effect29.gen(function* () {
|
|
|
4442
4603
|
}
|
|
4443
4604
|
};
|
|
4444
4605
|
});
|
|
4445
|
-
const getProjectLatestSession = (options) =>
|
|
4606
|
+
const getProjectLatestSession = (options) => Effect32.gen(function* () {
|
|
4446
4607
|
const { projectId } = options;
|
|
4447
4608
|
const { sessions } = yield* sessionRepository.getSessions(projectId, {
|
|
4448
4609
|
maxCount: 1
|
|
@@ -4454,7 +4615,7 @@ var LayerImpl20 = Effect29.gen(function* () {
|
|
|
4454
4615
|
}
|
|
4455
4616
|
};
|
|
4456
4617
|
});
|
|
4457
|
-
const createProject = (options) =>
|
|
4618
|
+
const createProject = (options) => Effect32.gen(function* () {
|
|
4458
4619
|
const { projectPath } = options;
|
|
4459
4620
|
const claudeProjectFilePath = yield* computeClaudeProjectFilePath({
|
|
4460
4621
|
projectPath,
|
|
@@ -4491,16 +4652,16 @@ var LayerImpl20 = Effect29.gen(function* () {
|
|
|
4491
4652
|
createProject
|
|
4492
4653
|
};
|
|
4493
4654
|
});
|
|
4494
|
-
var ProjectController = class extends
|
|
4655
|
+
var ProjectController = class extends Context27.Tag("ProjectController")() {
|
|
4495
4656
|
static {
|
|
4496
|
-
this.Live =
|
|
4657
|
+
this.Live = Layer29.effect(this, LayerImpl22);
|
|
4497
4658
|
}
|
|
4498
4659
|
};
|
|
4499
4660
|
|
|
4500
4661
|
// src/server/core/scheduler/config.ts
|
|
4501
4662
|
import { homedir as homedir4 } from "node:os";
|
|
4502
|
-
import { FileSystem as
|
|
4503
|
-
import { Context as
|
|
4663
|
+
import { FileSystem as FileSystem11, Path as Path14 } from "@effect/platform";
|
|
4664
|
+
import { Context as Context28, Data as Data5, Effect as Effect33, Layer as Layer30 } from "effect";
|
|
4504
4665
|
|
|
4505
4666
|
// src/server/core/scheduler/schema.ts
|
|
4506
4667
|
import { z as z23 } from "zod";
|
|
@@ -4561,29 +4722,29 @@ var ConfigParseError = class extends Data5.TaggedError("ConfigParseError") {
|
|
|
4561
4722
|
};
|
|
4562
4723
|
var CONFIG_DIR = "scheduler";
|
|
4563
4724
|
var CONFIG_FILE = "schedules.json";
|
|
4564
|
-
var SchedulerConfigBaseDir = class extends
|
|
4725
|
+
var SchedulerConfigBaseDir = class extends Context28.Tag(
|
|
4565
4726
|
"SchedulerConfigBaseDir"
|
|
4566
4727
|
)() {
|
|
4567
4728
|
static {
|
|
4568
|
-
this.Live =
|
|
4729
|
+
this.Live = Layer30.succeed(this, `${homedir4()}/.claude-code-viewer`);
|
|
4569
4730
|
}
|
|
4570
4731
|
};
|
|
4571
|
-
var getConfigPath =
|
|
4572
|
-
const path = yield*
|
|
4732
|
+
var getConfigPath = Effect33.gen(function* () {
|
|
4733
|
+
const path = yield* Path14.Path;
|
|
4573
4734
|
const baseDir = yield* SchedulerConfigBaseDir;
|
|
4574
4735
|
return path.join(baseDir, CONFIG_DIR, CONFIG_FILE);
|
|
4575
4736
|
});
|
|
4576
|
-
var readConfig =
|
|
4577
|
-
const fs = yield*
|
|
4737
|
+
var readConfig = Effect33.gen(function* () {
|
|
4738
|
+
const fs = yield* FileSystem11.FileSystem;
|
|
4578
4739
|
const configPath = yield* getConfigPath;
|
|
4579
4740
|
const exists = yield* fs.exists(configPath);
|
|
4580
4741
|
if (!exists) {
|
|
4581
|
-
return yield*
|
|
4742
|
+
return yield* Effect33.fail(
|
|
4582
4743
|
new ConfigFileNotFoundError({ path: configPath })
|
|
4583
4744
|
);
|
|
4584
4745
|
}
|
|
4585
4746
|
const content = yield* fs.readFileString(configPath);
|
|
4586
|
-
const jsonResult = yield*
|
|
4747
|
+
const jsonResult = yield* Effect33.try({
|
|
4587
4748
|
try: () => JSON.parse(content),
|
|
4588
4749
|
catch: (error) => new ConfigParseError({
|
|
4589
4750
|
path: configPath,
|
|
@@ -4592,7 +4753,7 @@ var readConfig = Effect30.gen(function* () {
|
|
|
4592
4753
|
});
|
|
4593
4754
|
const parsed = schedulerConfigSchema.safeParse(jsonResult);
|
|
4594
4755
|
if (!parsed.success) {
|
|
4595
|
-
return yield*
|
|
4756
|
+
return yield* Effect33.fail(
|
|
4596
4757
|
new ConfigParseError({
|
|
4597
4758
|
path: configPath,
|
|
4598
4759
|
cause: parsed.error
|
|
@@ -4601,24 +4762,24 @@ var readConfig = Effect30.gen(function* () {
|
|
|
4601
4762
|
}
|
|
4602
4763
|
return parsed.data;
|
|
4603
4764
|
});
|
|
4604
|
-
var writeConfig = (config) =>
|
|
4605
|
-
const fs = yield*
|
|
4606
|
-
const path = yield*
|
|
4765
|
+
var writeConfig = (config) => Effect33.gen(function* () {
|
|
4766
|
+
const fs = yield* FileSystem11.FileSystem;
|
|
4767
|
+
const path = yield* Path14.Path;
|
|
4607
4768
|
const configPath = yield* getConfigPath;
|
|
4608
4769
|
const configDir = path.dirname(configPath);
|
|
4609
4770
|
yield* fs.makeDirectory(configDir, { recursive: true });
|
|
4610
4771
|
const content = JSON.stringify(config, null, 2);
|
|
4611
4772
|
yield* fs.writeFileString(configPath, content);
|
|
4612
4773
|
});
|
|
4613
|
-
var initializeConfig =
|
|
4774
|
+
var initializeConfig = Effect33.gen(function* () {
|
|
4614
4775
|
const result = yield* readConfig.pipe(
|
|
4615
|
-
|
|
4616
|
-
ConfigFileNotFoundError: () =>
|
|
4776
|
+
Effect33.catchTags({
|
|
4777
|
+
ConfigFileNotFoundError: () => Effect33.gen(function* () {
|
|
4617
4778
|
const initialConfig = { jobs: [] };
|
|
4618
4779
|
yield* writeConfig(initialConfig);
|
|
4619
4780
|
return initialConfig;
|
|
4620
4781
|
}),
|
|
4621
|
-
ConfigParseError: () =>
|
|
4782
|
+
ConfigParseError: () => Effect33.gen(function* () {
|
|
4622
4783
|
const initialConfig = { jobs: [] };
|
|
4623
4784
|
yield* writeConfig(initialConfig);
|
|
4624
4785
|
return initialConfig;
|
|
@@ -4630,21 +4791,21 @@ var initializeConfig = Effect30.gen(function* () {
|
|
|
4630
4791
|
|
|
4631
4792
|
// src/server/core/scheduler/domain/Scheduler.ts
|
|
4632
4793
|
import {
|
|
4633
|
-
Context as
|
|
4794
|
+
Context as Context29,
|
|
4634
4795
|
Cron,
|
|
4635
4796
|
Data as Data6,
|
|
4636
4797
|
Duration as Duration2,
|
|
4637
|
-
Effect as
|
|
4798
|
+
Effect as Effect35,
|
|
4638
4799
|
Fiber,
|
|
4639
|
-
Layer as
|
|
4800
|
+
Layer as Layer31,
|
|
4640
4801
|
Ref as Ref10,
|
|
4641
4802
|
Schedule
|
|
4642
4803
|
} from "effect";
|
|
4643
4804
|
import { ulid as ulid4 } from "ulid";
|
|
4644
4805
|
|
|
4645
4806
|
// src/server/core/scheduler/domain/Job.ts
|
|
4646
|
-
import { Effect as
|
|
4647
|
-
var executeJob = (job) =>
|
|
4807
|
+
import { Effect as Effect34 } from "effect";
|
|
4808
|
+
var executeJob = (job) => Effect34.gen(function* () {
|
|
4648
4809
|
const lifeCycleService = yield* ClaudeCodeLifeCycleService;
|
|
4649
4810
|
const projectRepository = yield* ProjectRepository;
|
|
4650
4811
|
const userConfigService = yield* UserConfigService;
|
|
@@ -4652,7 +4813,7 @@ var executeJob = (job) => Effect31.gen(function* () {
|
|
|
4652
4813
|
const { project } = yield* projectRepository.getProject(message.projectId);
|
|
4653
4814
|
const userConfig = yield* userConfigService.getUserConfig();
|
|
4654
4815
|
if (project.meta.projectPath === null) {
|
|
4655
|
-
return yield*
|
|
4816
|
+
return yield* Effect34.fail(
|
|
4656
4817
|
new Error(`Project path not found for projectId: ${message.projectId}`)
|
|
4657
4818
|
);
|
|
4658
4819
|
}
|
|
@@ -4686,15 +4847,15 @@ var InvalidCronExpressionError = class extends Data6.TaggedError(
|
|
|
4686
4847
|
"InvalidCronExpressionError"
|
|
4687
4848
|
) {
|
|
4688
4849
|
};
|
|
4689
|
-
var
|
|
4850
|
+
var LayerImpl23 = Effect35.gen(function* () {
|
|
4690
4851
|
const fibersRef = yield* Ref10.make(/* @__PURE__ */ new Map());
|
|
4691
4852
|
const runningJobsRef = yield* Ref10.make(/* @__PURE__ */ new Set());
|
|
4692
|
-
const startJob = (job) =>
|
|
4853
|
+
const startJob = (job) => Effect35.gen(function* () {
|
|
4693
4854
|
const now = /* @__PURE__ */ new Date();
|
|
4694
4855
|
if (job.schedule.type === "cron") {
|
|
4695
4856
|
const cronResult = Cron.parse(job.schedule.expression);
|
|
4696
4857
|
if (cronResult._tag === "Left") {
|
|
4697
|
-
return yield*
|
|
4858
|
+
return yield* Effect35.fail(
|
|
4698
4859
|
new InvalidCronExpressionError({
|
|
4699
4860
|
expression: job.schedule.expression,
|
|
4700
4861
|
cause: cronResult.left
|
|
@@ -4702,12 +4863,12 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4702
4863
|
);
|
|
4703
4864
|
}
|
|
4704
4865
|
const cronSchedule = Schedule.cron(cronResult.right);
|
|
4705
|
-
const fiber = yield*
|
|
4866
|
+
const fiber = yield* Effect35.gen(function* () {
|
|
4706
4867
|
const nextTime = Cron.next(cronResult.right, /* @__PURE__ */ new Date());
|
|
4707
4868
|
const nextDelay = Math.max(0, nextTime.getTime() - Date.now());
|
|
4708
|
-
yield*
|
|
4709
|
-
yield*
|
|
4710
|
-
}).pipe(
|
|
4869
|
+
yield* Effect35.sleep(Duration2.millis(nextDelay));
|
|
4870
|
+
yield* Effect35.repeat(runJobWithConcurrencyControl(job), cronSchedule);
|
|
4871
|
+
}).pipe(Effect35.forkDaemon);
|
|
4711
4872
|
yield* Ref10.update(
|
|
4712
4873
|
fibersRef,
|
|
4713
4874
|
(fibers) => new Map(fibers).set(job.id, fiber)
|
|
@@ -4718,17 +4879,17 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4718
4879
|
}
|
|
4719
4880
|
const delay = calculateReservedDelay(job, now);
|
|
4720
4881
|
const delayDuration = Duration2.millis(delay);
|
|
4721
|
-
const fiber = yield*
|
|
4882
|
+
const fiber = yield* Effect35.delay(
|
|
4722
4883
|
runJobWithConcurrencyControl(job),
|
|
4723
4884
|
delayDuration
|
|
4724
|
-
).pipe(
|
|
4885
|
+
).pipe(Effect35.forkDaemon);
|
|
4725
4886
|
yield* Ref10.update(
|
|
4726
4887
|
fibersRef,
|
|
4727
4888
|
(fibers) => new Map(fibers).set(job.id, fiber)
|
|
4728
4889
|
);
|
|
4729
4890
|
}
|
|
4730
4891
|
});
|
|
4731
|
-
const runJobWithConcurrencyControl = (job) =>
|
|
4892
|
+
const runJobWithConcurrencyControl = (job) => Effect35.gen(function* () {
|
|
4732
4893
|
if (job.schedule.type === "cron" && job.schedule.concurrencyPolicy === "skip") {
|
|
4733
4894
|
const runningJobs = yield* Ref10.get(runningJobsRef);
|
|
4734
4895
|
if (runningJobs.has(job.id)) {
|
|
@@ -4738,9 +4899,9 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4738
4899
|
yield* Ref10.update(runningJobsRef, (jobs) => new Set(jobs).add(job.id));
|
|
4739
4900
|
if (job.schedule.type === "reserved") {
|
|
4740
4901
|
const result2 = yield* executeJob(job).pipe(
|
|
4741
|
-
|
|
4742
|
-
onSuccess: () =>
|
|
4743
|
-
onFailure: () =>
|
|
4902
|
+
Effect35.matchEffect({
|
|
4903
|
+
onSuccess: () => Effect35.void,
|
|
4904
|
+
onFailure: () => Effect35.void
|
|
4744
4905
|
})
|
|
4745
4906
|
);
|
|
4746
4907
|
yield* Ref10.update(runningJobsRef, (jobs) => {
|
|
@@ -4749,18 +4910,18 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4749
4910
|
return newJobs;
|
|
4750
4911
|
});
|
|
4751
4912
|
yield* deleteJobFromConfig(job.id).pipe(
|
|
4752
|
-
|
|
4913
|
+
Effect35.catchAll((error) => {
|
|
4753
4914
|
console.error(
|
|
4754
4915
|
`[Scheduler] Failed to delete reserved job ${job.id}:`,
|
|
4755
4916
|
error
|
|
4756
4917
|
);
|
|
4757
|
-
return
|
|
4918
|
+
return Effect35.void;
|
|
4758
4919
|
})
|
|
4759
4920
|
);
|
|
4760
4921
|
return result2;
|
|
4761
4922
|
}
|
|
4762
4923
|
const result = yield* executeJob(job).pipe(
|
|
4763
|
-
|
|
4924
|
+
Effect35.matchEffect({
|
|
4764
4925
|
onSuccess: () => updateJobStatus(job.id, "success", (/* @__PURE__ */ new Date()).toISOString()),
|
|
4765
4926
|
onFailure: () => updateJobStatus(job.id, "failed", (/* @__PURE__ */ new Date()).toISOString())
|
|
4766
4927
|
})
|
|
@@ -4772,7 +4933,7 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4772
4933
|
});
|
|
4773
4934
|
return result;
|
|
4774
4935
|
});
|
|
4775
|
-
const updateJobStatus = (jobId, status, runAt) =>
|
|
4936
|
+
const updateJobStatus = (jobId, status, runAt) => Effect35.gen(function* () {
|
|
4776
4937
|
const config = yield* readConfig;
|
|
4777
4938
|
const job = config.jobs.find((j) => j.id === jobId);
|
|
4778
4939
|
if (job === void 0) {
|
|
@@ -4788,7 +4949,7 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4788
4949
|
};
|
|
4789
4950
|
yield* writeConfig(updatedConfig);
|
|
4790
4951
|
});
|
|
4791
|
-
const stopJob = (jobId) =>
|
|
4952
|
+
const stopJob = (jobId) => Effect35.gen(function* () {
|
|
4792
4953
|
const fibers = yield* Ref10.get(fibersRef);
|
|
4793
4954
|
const fiber = fibers.get(jobId);
|
|
4794
4955
|
if (fiber !== void 0) {
|
|
@@ -4800,7 +4961,7 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4800
4961
|
});
|
|
4801
4962
|
}
|
|
4802
4963
|
});
|
|
4803
|
-
const startScheduler =
|
|
4964
|
+
const startScheduler = Effect35.gen(function* () {
|
|
4804
4965
|
yield* initializeConfig;
|
|
4805
4966
|
const config = yield* readConfig;
|
|
4806
4967
|
for (const job of config.jobs) {
|
|
@@ -4809,27 +4970,27 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4809
4970
|
}
|
|
4810
4971
|
}
|
|
4811
4972
|
});
|
|
4812
|
-
const stopScheduler =
|
|
4973
|
+
const stopScheduler = Effect35.gen(function* () {
|
|
4813
4974
|
const fibers = yield* Ref10.get(fibersRef);
|
|
4814
4975
|
for (const fiber of fibers.values()) {
|
|
4815
4976
|
yield* Fiber.interrupt(fiber);
|
|
4816
4977
|
}
|
|
4817
4978
|
yield* Ref10.set(fibersRef, /* @__PURE__ */ new Map());
|
|
4818
4979
|
});
|
|
4819
|
-
const getJobs = () =>
|
|
4980
|
+
const getJobs = () => Effect35.gen(function* () {
|
|
4820
4981
|
const config = yield* readConfig.pipe(
|
|
4821
|
-
|
|
4822
|
-
ConfigFileNotFoundError: () => initializeConfig.pipe(
|
|
4823
|
-
ConfigParseError: () => initializeConfig.pipe(
|
|
4982
|
+
Effect35.catchTags({
|
|
4983
|
+
ConfigFileNotFoundError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] }))),
|
|
4984
|
+
ConfigParseError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] })))
|
|
4824
4985
|
})
|
|
4825
4986
|
);
|
|
4826
4987
|
return config.jobs;
|
|
4827
4988
|
});
|
|
4828
|
-
const addJob = (newJob) =>
|
|
4989
|
+
const addJob = (newJob) => Effect35.gen(function* () {
|
|
4829
4990
|
const config = yield* readConfig.pipe(
|
|
4830
|
-
|
|
4831
|
-
ConfigFileNotFoundError: () => initializeConfig.pipe(
|
|
4832
|
-
ConfigParseError: () => initializeConfig.pipe(
|
|
4991
|
+
Effect35.catchTags({
|
|
4992
|
+
ConfigFileNotFoundError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] }))),
|
|
4993
|
+
ConfigParseError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] })))
|
|
4833
4994
|
})
|
|
4834
4995
|
);
|
|
4835
4996
|
const job = {
|
|
@@ -4848,16 +5009,16 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4848
5009
|
}
|
|
4849
5010
|
return job;
|
|
4850
5011
|
});
|
|
4851
|
-
const updateJob = (jobId, updates) =>
|
|
5012
|
+
const updateJob = (jobId, updates) => Effect35.gen(function* () {
|
|
4852
5013
|
const config = yield* readConfig.pipe(
|
|
4853
|
-
|
|
4854
|
-
ConfigFileNotFoundError: () => initializeConfig.pipe(
|
|
4855
|
-
ConfigParseError: () => initializeConfig.pipe(
|
|
5014
|
+
Effect35.catchTags({
|
|
5015
|
+
ConfigFileNotFoundError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] }))),
|
|
5016
|
+
ConfigParseError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] })))
|
|
4856
5017
|
})
|
|
4857
5018
|
);
|
|
4858
5019
|
const job = config.jobs.find((j) => j.id === jobId);
|
|
4859
5020
|
if (job === void 0) {
|
|
4860
|
-
return yield*
|
|
5021
|
+
return yield* Effect35.fail(new SchedulerJobNotFoundError({ jobId }));
|
|
4861
5022
|
}
|
|
4862
5023
|
yield* stopJob(jobId);
|
|
4863
5024
|
const updatedJob = {
|
|
@@ -4873,32 +5034,32 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4873
5034
|
}
|
|
4874
5035
|
return updatedJob;
|
|
4875
5036
|
});
|
|
4876
|
-
const deleteJobFromConfig = (jobId) =>
|
|
5037
|
+
const deleteJobFromConfig = (jobId) => Effect35.gen(function* () {
|
|
4877
5038
|
const config = yield* readConfig.pipe(
|
|
4878
|
-
|
|
4879
|
-
ConfigFileNotFoundError: () => initializeConfig.pipe(
|
|
4880
|
-
ConfigParseError: () => initializeConfig.pipe(
|
|
5039
|
+
Effect35.catchTags({
|
|
5040
|
+
ConfigFileNotFoundError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] }))),
|
|
5041
|
+
ConfigParseError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] })))
|
|
4881
5042
|
})
|
|
4882
5043
|
);
|
|
4883
5044
|
const job = config.jobs.find((j) => j.id === jobId);
|
|
4884
5045
|
if (job === void 0) {
|
|
4885
|
-
return yield*
|
|
5046
|
+
return yield* Effect35.fail(new SchedulerJobNotFoundError({ jobId }));
|
|
4886
5047
|
}
|
|
4887
5048
|
const updatedConfig = {
|
|
4888
5049
|
jobs: config.jobs.filter((j) => j.id !== jobId)
|
|
4889
5050
|
};
|
|
4890
5051
|
yield* writeConfig(updatedConfig);
|
|
4891
5052
|
});
|
|
4892
|
-
const deleteJob = (jobId) =>
|
|
5053
|
+
const deleteJob = (jobId) => Effect35.gen(function* () {
|
|
4893
5054
|
const config = yield* readConfig.pipe(
|
|
4894
|
-
|
|
4895
|
-
ConfigFileNotFoundError: () => initializeConfig.pipe(
|
|
4896
|
-
ConfigParseError: () => initializeConfig.pipe(
|
|
5055
|
+
Effect35.catchTags({
|
|
5056
|
+
ConfigFileNotFoundError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] }))),
|
|
5057
|
+
ConfigParseError: () => initializeConfig.pipe(Effect35.map(() => ({ jobs: [] })))
|
|
4897
5058
|
})
|
|
4898
5059
|
);
|
|
4899
5060
|
const job = config.jobs.find((j) => j.id === jobId);
|
|
4900
5061
|
if (job === void 0) {
|
|
4901
|
-
return yield*
|
|
5062
|
+
return yield* Effect35.fail(new SchedulerJobNotFoundError({ jobId }));
|
|
4902
5063
|
}
|
|
4903
5064
|
yield* stopJob(jobId);
|
|
4904
5065
|
yield* deleteJobFromConfig(jobId);
|
|
@@ -4912,24 +5073,24 @@ var LayerImpl21 = Effect32.gen(function* () {
|
|
|
4912
5073
|
deleteJob
|
|
4913
5074
|
};
|
|
4914
5075
|
});
|
|
4915
|
-
var SchedulerService = class extends
|
|
5076
|
+
var SchedulerService = class extends Context29.Tag("SchedulerService")() {
|
|
4916
5077
|
static {
|
|
4917
|
-
this.Live =
|
|
5078
|
+
this.Live = Layer31.effect(this, LayerImpl23);
|
|
4918
5079
|
}
|
|
4919
5080
|
};
|
|
4920
5081
|
|
|
4921
5082
|
// src/server/core/scheduler/presentation/SchedulerController.ts
|
|
4922
|
-
import { Context as
|
|
4923
|
-
var
|
|
5083
|
+
import { Context as Context30, Effect as Effect36, Layer as Layer32 } from "effect";
|
|
5084
|
+
var LayerImpl24 = Effect36.gen(function* () {
|
|
4924
5085
|
const schedulerService = yield* SchedulerService;
|
|
4925
|
-
const getJobs = () =>
|
|
5086
|
+
const getJobs = () => Effect36.gen(function* () {
|
|
4926
5087
|
const jobs = yield* schedulerService.getJobs();
|
|
4927
5088
|
return {
|
|
4928
5089
|
response: jobs,
|
|
4929
5090
|
status: 200
|
|
4930
5091
|
};
|
|
4931
5092
|
});
|
|
4932
|
-
const addJob = (options) =>
|
|
5093
|
+
const addJob = (options) => Effect36.gen(function* () {
|
|
4933
5094
|
const { job } = options;
|
|
4934
5095
|
const result = yield* schedulerService.addJob(job);
|
|
4935
5096
|
return {
|
|
@@ -4937,12 +5098,12 @@ var LayerImpl22 = Effect33.gen(function* () {
|
|
|
4937
5098
|
status: 201
|
|
4938
5099
|
};
|
|
4939
5100
|
});
|
|
4940
|
-
const updateJob = (options) =>
|
|
5101
|
+
const updateJob = (options) => Effect36.gen(function* () {
|
|
4941
5102
|
const { id, job } = options;
|
|
4942
5103
|
const result = yield* schedulerService.updateJob(id, job).pipe(
|
|
4943
|
-
|
|
5104
|
+
Effect36.catchTag(
|
|
4944
5105
|
"SchedulerJobNotFoundError",
|
|
4945
|
-
() =>
|
|
5106
|
+
() => Effect36.succeed(null)
|
|
4946
5107
|
)
|
|
4947
5108
|
);
|
|
4948
5109
|
if (result === null) {
|
|
@@ -4956,14 +5117,14 @@ var LayerImpl22 = Effect33.gen(function* () {
|
|
|
4956
5117
|
status: 200
|
|
4957
5118
|
};
|
|
4958
5119
|
});
|
|
4959
|
-
const deleteJob = (options) =>
|
|
5120
|
+
const deleteJob = (options) => Effect36.gen(function* () {
|
|
4960
5121
|
const { id } = options;
|
|
4961
5122
|
const result = yield* schedulerService.deleteJob(id).pipe(
|
|
4962
|
-
|
|
5123
|
+
Effect36.catchTag(
|
|
4963
5124
|
"SchedulerJobNotFoundError",
|
|
4964
|
-
() =>
|
|
5125
|
+
() => Effect36.succeed(false)
|
|
4965
5126
|
),
|
|
4966
|
-
|
|
5127
|
+
Effect36.map(() => true)
|
|
4967
5128
|
);
|
|
4968
5129
|
if (!result) {
|
|
4969
5130
|
return {
|
|
@@ -4983,17 +5144,239 @@ var LayerImpl22 = Effect33.gen(function* () {
|
|
|
4983
5144
|
deleteJob
|
|
4984
5145
|
};
|
|
4985
5146
|
});
|
|
4986
|
-
var SchedulerController = class extends
|
|
5147
|
+
var SchedulerController = class extends Context30.Tag("SchedulerController")() {
|
|
4987
5148
|
static {
|
|
4988
|
-
this.Live =
|
|
5149
|
+
this.Live = Layer32.effect(this, LayerImpl24);
|
|
5150
|
+
}
|
|
5151
|
+
};
|
|
5152
|
+
|
|
5153
|
+
// src/server/core/search/presentation/SearchController.ts
|
|
5154
|
+
import { Context as Context32, Effect as Effect38, Layer as Layer34 } from "effect";
|
|
5155
|
+
|
|
5156
|
+
// src/server/core/search/services/SearchService.ts
|
|
5157
|
+
import { FileSystem as FileSystem12, Path as Path15 } from "@effect/platform";
|
|
5158
|
+
import { Context as Context31, Effect as Effect37, Layer as Layer33, Ref as Ref11 } from "effect";
|
|
5159
|
+
import MiniSearch from "minisearch";
|
|
5160
|
+
|
|
5161
|
+
// src/server/core/search/functions/extractSearchableText.ts
|
|
5162
|
+
var extractSearchableText = (conversation) => {
|
|
5163
|
+
if (conversation.type === "x-error") {
|
|
5164
|
+
return null;
|
|
5165
|
+
}
|
|
5166
|
+
if (conversation.type === "user") {
|
|
5167
|
+
return extractUserText(conversation);
|
|
5168
|
+
}
|
|
5169
|
+
if (conversation.type === "assistant") {
|
|
5170
|
+
return extractAssistantText(conversation);
|
|
5171
|
+
}
|
|
5172
|
+
return null;
|
|
5173
|
+
};
|
|
5174
|
+
var extractUserText = (entry) => {
|
|
5175
|
+
const content = entry.message.content;
|
|
5176
|
+
if (typeof content === "string") {
|
|
5177
|
+
return content;
|
|
5178
|
+
}
|
|
5179
|
+
return content.map((item) => {
|
|
5180
|
+
if (typeof item === "string") return item;
|
|
5181
|
+
if ("text" in item && typeof item.text === "string") return item.text;
|
|
5182
|
+
return "";
|
|
5183
|
+
}).filter(Boolean).join(" ");
|
|
5184
|
+
};
|
|
5185
|
+
var extractAssistantText = (entry) => {
|
|
5186
|
+
return entry.message.content.filter((item) => {
|
|
5187
|
+
return item.type === "text" && "text" in item;
|
|
5188
|
+
}).map((item) => item.text).join(" ");
|
|
5189
|
+
};
|
|
5190
|
+
|
|
5191
|
+
// src/server/core/search/services/SearchService.ts
|
|
5192
|
+
var INDEX_TTL_MS = 6e4;
|
|
5193
|
+
var MAX_TEXT_LENGTH = 2e3;
|
|
5194
|
+
var MAX_ASSISTANT_TEXT_LENGTH = 500;
|
|
5195
|
+
var createMiniSearchIndex = () => new MiniSearch({
|
|
5196
|
+
fields: ["text"],
|
|
5197
|
+
storeFields: ["id"],
|
|
5198
|
+
searchOptions: {
|
|
5199
|
+
fuzzy: 0.2,
|
|
5200
|
+
prefix: true,
|
|
5201
|
+
boost: { text: 1 }
|
|
5202
|
+
}
|
|
5203
|
+
});
|
|
5204
|
+
var LayerImpl25 = Effect37.gen(function* () {
|
|
5205
|
+
const fs = yield* FileSystem12.FileSystem;
|
|
5206
|
+
const path = yield* Path15.Path;
|
|
5207
|
+
const context = yield* ApplicationContext;
|
|
5208
|
+
const indexCacheRef = yield* Ref11.make(null);
|
|
5209
|
+
const buildIndex = () => Effect37.gen(function* () {
|
|
5210
|
+
const { claudeProjectsDirPath } = context.claudeCodePaths;
|
|
5211
|
+
const dirExists = yield* fs.exists(claudeProjectsDirPath);
|
|
5212
|
+
if (!dirExists) {
|
|
5213
|
+
return { index: createMiniSearchIndex(), documents: /* @__PURE__ */ new Map() };
|
|
5214
|
+
}
|
|
5215
|
+
const projectEntries = yield* fs.readDirectory(claudeProjectsDirPath);
|
|
5216
|
+
const miniSearch = createMiniSearchIndex();
|
|
5217
|
+
const documentEffects = projectEntries.map(
|
|
5218
|
+
(projectEntry) => Effect37.gen(function* () {
|
|
5219
|
+
const projectPath = path.resolve(claudeProjectsDirPath, projectEntry);
|
|
5220
|
+
const stat = yield* fs.stat(projectPath).pipe(Effect37.catchAll(() => Effect37.succeed(null)));
|
|
5221
|
+
if (stat?.type !== "Directory") {
|
|
5222
|
+
return [];
|
|
5223
|
+
}
|
|
5224
|
+
const projectId = encodeProjectId(projectPath);
|
|
5225
|
+
const projectName = path.basename(projectPath);
|
|
5226
|
+
const sessionEntries = yield* fs.readDirectory(projectPath).pipe(Effect37.catchAll(() => Effect37.succeed([])));
|
|
5227
|
+
const sessionFiles = sessionEntries.filter(isRegularSessionFile);
|
|
5228
|
+
const sessionDocuments = yield* Effect37.all(
|
|
5229
|
+
sessionFiles.map(
|
|
5230
|
+
(sessionFile) => Effect37.gen(function* () {
|
|
5231
|
+
const sessionPath = path.resolve(projectPath, sessionFile);
|
|
5232
|
+
const sessionId = encodeSessionId(sessionPath);
|
|
5233
|
+
const content = yield* fs.readFileString(sessionPath).pipe(Effect37.catchAll(() => Effect37.succeed("")));
|
|
5234
|
+
if (!content) return [];
|
|
5235
|
+
const conversations = parseJsonl(content);
|
|
5236
|
+
const documents = [];
|
|
5237
|
+
for (let i = 0; i < conversations.length; i++) {
|
|
5238
|
+
const conversation = conversations[i];
|
|
5239
|
+
if (conversation === void 0) continue;
|
|
5240
|
+
if (conversation.type !== "user" && conversation.type !== "assistant") {
|
|
5241
|
+
continue;
|
|
5242
|
+
}
|
|
5243
|
+
let text = extractSearchableText(conversation);
|
|
5244
|
+
if (!text || text.length < 3) continue;
|
|
5245
|
+
const maxLen = conversation.type === "user" ? MAX_TEXT_LENGTH : MAX_ASSISTANT_TEXT_LENGTH;
|
|
5246
|
+
if (text.length > maxLen) {
|
|
5247
|
+
text = text.slice(0, maxLen);
|
|
5248
|
+
}
|
|
5249
|
+
documents.push({
|
|
5250
|
+
id: `${sessionId}:${i}`,
|
|
5251
|
+
projectId,
|
|
5252
|
+
projectName,
|
|
5253
|
+
sessionId,
|
|
5254
|
+
conversationIndex: i,
|
|
5255
|
+
type: conversation.type,
|
|
5256
|
+
text,
|
|
5257
|
+
timestamp: "timestamp" in conversation ? conversation.timestamp : ""
|
|
5258
|
+
});
|
|
5259
|
+
}
|
|
5260
|
+
return documents;
|
|
5261
|
+
})
|
|
5262
|
+
),
|
|
5263
|
+
{ concurrency: 20 }
|
|
5264
|
+
);
|
|
5265
|
+
return sessionDocuments.flat();
|
|
5266
|
+
})
|
|
5267
|
+
);
|
|
5268
|
+
const allDocuments = yield* Effect37.all(documentEffects, {
|
|
5269
|
+
concurrency: 10
|
|
5270
|
+
});
|
|
5271
|
+
const flatDocuments = allDocuments.flat();
|
|
5272
|
+
miniSearch.addAll(flatDocuments);
|
|
5273
|
+
const documentsMap = /* @__PURE__ */ new Map();
|
|
5274
|
+
for (const doc of flatDocuments) {
|
|
5275
|
+
documentsMap.set(doc.id, doc);
|
|
5276
|
+
}
|
|
5277
|
+
return { index: miniSearch, documents: documentsMap };
|
|
5278
|
+
});
|
|
5279
|
+
const getIndex = () => Effect37.gen(function* () {
|
|
5280
|
+
const cached = yield* Ref11.get(indexCacheRef);
|
|
5281
|
+
const now = Date.now();
|
|
5282
|
+
if (cached && now - cached.builtAt < INDEX_TTL_MS) {
|
|
5283
|
+
return { index: cached.index, documents: cached.documents };
|
|
5284
|
+
}
|
|
5285
|
+
const { index, documents } = yield* buildIndex();
|
|
5286
|
+
yield* Ref11.set(indexCacheRef, { index, documents, builtAt: now });
|
|
5287
|
+
return { index, documents };
|
|
5288
|
+
});
|
|
5289
|
+
const search = (query2, limit = 20, projectId) => Effect37.gen(function* () {
|
|
5290
|
+
const { claudeProjectsDirPath } = context.claudeCodePaths;
|
|
5291
|
+
const dirExists = yield* fs.exists(claudeProjectsDirPath);
|
|
5292
|
+
if (!dirExists) {
|
|
5293
|
+
return { results: [] };
|
|
5294
|
+
}
|
|
5295
|
+
const { index: miniSearch, documents } = yield* getIndex();
|
|
5296
|
+
const searchResults = miniSearch.search(query2).slice(0, limit * 2);
|
|
5297
|
+
const results = [];
|
|
5298
|
+
for (const result of searchResults) {
|
|
5299
|
+
if (results.length >= limit) break;
|
|
5300
|
+
const doc = documents.get(String(result.id));
|
|
5301
|
+
if (!doc) continue;
|
|
5302
|
+
if (projectId && doc.projectId !== projectId) continue;
|
|
5303
|
+
const score = doc.type === "user" ? result.score * 1.2 : result.score;
|
|
5304
|
+
const snippetLength = 150;
|
|
5305
|
+
const text = doc.text;
|
|
5306
|
+
const queryLower = query2.toLowerCase();
|
|
5307
|
+
const textLower = text.toLowerCase();
|
|
5308
|
+
const matchIndex = textLower.indexOf(queryLower);
|
|
5309
|
+
let snippet;
|
|
5310
|
+
if (matchIndex !== -1) {
|
|
5311
|
+
const start = Math.max(0, matchIndex - 50);
|
|
5312
|
+
const end = Math.min(text.length, start + snippetLength);
|
|
5313
|
+
snippet = (start > 0 ? "..." : "") + text.slice(start, end) + (end < text.length ? "..." : "");
|
|
5314
|
+
} else {
|
|
5315
|
+
snippet = text.slice(0, snippetLength) + (text.length > snippetLength ? "..." : "");
|
|
5316
|
+
}
|
|
5317
|
+
results.push({
|
|
5318
|
+
projectId: doc.projectId,
|
|
5319
|
+
projectName: doc.projectName,
|
|
5320
|
+
sessionId: doc.sessionId,
|
|
5321
|
+
conversationIndex: doc.conversationIndex,
|
|
5322
|
+
type: doc.type,
|
|
5323
|
+
snippet,
|
|
5324
|
+
timestamp: doc.timestamp,
|
|
5325
|
+
score
|
|
5326
|
+
});
|
|
5327
|
+
}
|
|
5328
|
+
return { results };
|
|
5329
|
+
});
|
|
5330
|
+
const invalidateIndex = () => Ref11.set(indexCacheRef, null);
|
|
5331
|
+
return {
|
|
5332
|
+
search,
|
|
5333
|
+
invalidateIndex
|
|
5334
|
+
};
|
|
5335
|
+
});
|
|
5336
|
+
var SearchService = class extends Context31.Tag("SearchService")() {
|
|
5337
|
+
static {
|
|
5338
|
+
this.Live = Layer33.effect(this, LayerImpl25);
|
|
5339
|
+
}
|
|
5340
|
+
};
|
|
5341
|
+
|
|
5342
|
+
// src/server/core/search/presentation/SearchController.ts
|
|
5343
|
+
var LayerImpl26 = Effect38.gen(function* () {
|
|
5344
|
+
const searchService = yield* SearchService;
|
|
5345
|
+
const search = (options) => Effect38.gen(function* () {
|
|
5346
|
+
const { query: query2, limit, projectId } = options;
|
|
5347
|
+
if (query2.trim().length < 2) {
|
|
5348
|
+
return {
|
|
5349
|
+
status: 400,
|
|
5350
|
+
response: {
|
|
5351
|
+
error: "Query must contain at least 2 non-whitespace characters"
|
|
5352
|
+
}
|
|
5353
|
+
};
|
|
5354
|
+
}
|
|
5355
|
+
const { results } = yield* searchService.search(
|
|
5356
|
+
query2.trim(),
|
|
5357
|
+
limit,
|
|
5358
|
+
projectId
|
|
5359
|
+
);
|
|
5360
|
+
return {
|
|
5361
|
+
status: 200,
|
|
5362
|
+
response: { results }
|
|
5363
|
+
};
|
|
5364
|
+
});
|
|
5365
|
+
return {
|
|
5366
|
+
search
|
|
5367
|
+
};
|
|
5368
|
+
});
|
|
5369
|
+
var SearchController = class extends Context32.Tag("SearchController")() {
|
|
5370
|
+
static {
|
|
5371
|
+
this.Live = Layer34.effect(this, LayerImpl26);
|
|
4989
5372
|
}
|
|
4990
5373
|
};
|
|
4991
5374
|
|
|
4992
5375
|
// src/server/core/session/presentation/SessionController.ts
|
|
4993
|
-
import { Context as
|
|
5376
|
+
import { Context as Context33, Effect as Effect40, Layer as Layer35 } from "effect";
|
|
4994
5377
|
|
|
4995
5378
|
// src/server/core/session/services/ExportService.ts
|
|
4996
|
-
import { Effect as
|
|
5379
|
+
import { Effect as Effect39 } from "effect";
|
|
4997
5380
|
var escapeHtml = (text) => {
|
|
4998
5381
|
const map = {
|
|
4999
5382
|
"&": "&",
|
|
@@ -5252,7 +5635,7 @@ var renderGroupedAssistantEntries = (entries) => {
|
|
|
5252
5635
|
</div>
|
|
5253
5636
|
`;
|
|
5254
5637
|
};
|
|
5255
|
-
var generateSessionHtml = (session, projectId) =>
|
|
5638
|
+
var generateSessionHtml = (session, projectId) => Effect39.gen(function* () {
|
|
5256
5639
|
const grouped = groupConsecutiveAssistantMessages(session.conversations);
|
|
5257
5640
|
const conversationsHtml = grouped.map((group) => {
|
|
5258
5641
|
if (group.type === "grouped") {
|
|
@@ -5772,9 +6155,9 @@ var generateSessionHtml = (session, projectId) => Effect34.gen(function* () {
|
|
|
5772
6155
|
});
|
|
5773
6156
|
|
|
5774
6157
|
// src/server/core/session/presentation/SessionController.ts
|
|
5775
|
-
var
|
|
6158
|
+
var LayerImpl27 = Effect40.gen(function* () {
|
|
5776
6159
|
const sessionRepository = yield* SessionRepository;
|
|
5777
|
-
const getSession = (options) =>
|
|
6160
|
+
const getSession = (options) => Effect40.gen(function* () {
|
|
5778
6161
|
const { projectId, sessionId } = options;
|
|
5779
6162
|
const { session } = yield* sessionRepository.getSession(
|
|
5780
6163
|
projectId,
|
|
@@ -5785,7 +6168,7 @@ var LayerImpl23 = Effect35.gen(function* () {
|
|
|
5785
6168
|
response: { session }
|
|
5786
6169
|
};
|
|
5787
6170
|
});
|
|
5788
|
-
const exportSessionHtml = (options) =>
|
|
6171
|
+
const exportSessionHtml = (options) => Effect40.gen(function* () {
|
|
5789
6172
|
const { projectId, sessionId } = options;
|
|
5790
6173
|
const { session } = yield* sessionRepository.getSession(
|
|
5791
6174
|
projectId,
|
|
@@ -5808,9 +6191,9 @@ var LayerImpl23 = Effect35.gen(function* () {
|
|
|
5808
6191
|
exportSessionHtml
|
|
5809
6192
|
};
|
|
5810
6193
|
});
|
|
5811
|
-
var SessionController = class extends
|
|
6194
|
+
var SessionController = class extends Context33.Tag("SessionController")() {
|
|
5812
6195
|
static {
|
|
5813
|
-
this.Live =
|
|
6196
|
+
this.Live = Layer35.effect(this, LayerImpl27);
|
|
5814
6197
|
}
|
|
5815
6198
|
};
|
|
5816
6199
|
|
|
@@ -5819,12 +6202,12 @@ import { Hono } from "hono";
|
|
|
5819
6202
|
var honoApp = new Hono();
|
|
5820
6203
|
|
|
5821
6204
|
// src/server/hono/initialize.ts
|
|
5822
|
-
import { Context as
|
|
5823
|
-
var InitializeService = class extends
|
|
6205
|
+
import { Context as Context34, Effect as Effect41, Layer as Layer36, Ref as Ref12, Schedule as Schedule2 } from "effect";
|
|
6206
|
+
var InitializeService = class extends Context34.Tag("InitializeService")() {
|
|
5824
6207
|
static {
|
|
5825
|
-
this.Live =
|
|
6208
|
+
this.Live = Layer36.effect(
|
|
5826
6209
|
this,
|
|
5827
|
-
|
|
6210
|
+
Effect41.gen(function* () {
|
|
5828
6211
|
const eventBus = yield* EventBus;
|
|
5829
6212
|
const fileWatcher = yield* FileWatcherService;
|
|
5830
6213
|
const projectRepository = yield* ProjectRepository;
|
|
@@ -5832,22 +6215,22 @@ var InitializeService = class extends Context30.Tag("InitializeService")() {
|
|
|
5832
6215
|
const projectMetaService = yield* ProjectMetaService;
|
|
5833
6216
|
const sessionMetaService = yield* SessionMetaService;
|
|
5834
6217
|
const virtualConversationDatabase = yield* VirtualConversationDatabase;
|
|
5835
|
-
const listenersRef = yield*
|
|
6218
|
+
const listenersRef = yield* Ref12.make({});
|
|
5836
6219
|
const startInitialization = () => {
|
|
5837
|
-
return
|
|
6220
|
+
return Effect41.gen(function* () {
|
|
5838
6221
|
yield* fileWatcher.startWatching();
|
|
5839
|
-
const daemon =
|
|
6222
|
+
const daemon = Effect41.repeat(
|
|
5840
6223
|
eventBus.emit("heartbeat", {}),
|
|
5841
6224
|
Schedule2.fixed("10 seconds")
|
|
5842
6225
|
);
|
|
5843
6226
|
console.log("start heartbeat");
|
|
5844
|
-
yield*
|
|
6227
|
+
yield* Effect41.forkDaemon(daemon);
|
|
5845
6228
|
console.log("after starting heartbeat fork");
|
|
5846
6229
|
const onSessionChanged = (event) => {
|
|
5847
|
-
|
|
6230
|
+
Effect41.runFork(
|
|
5848
6231
|
projectMetaService.invalidateProject(event.projectId)
|
|
5849
6232
|
);
|
|
5850
|
-
|
|
6233
|
+
Effect41.runFork(
|
|
5851
6234
|
sessionMetaService.invalidateSession(
|
|
5852
6235
|
event.projectId,
|
|
5853
6236
|
event.sessionId
|
|
@@ -5856,7 +6239,7 @@ var InitializeService = class extends Context30.Tag("InitializeService")() {
|
|
|
5856
6239
|
};
|
|
5857
6240
|
const onSessionProcessChanged = (event) => {
|
|
5858
6241
|
if ((event.changed.type === "completed" || event.changed.type === "paused") && event.changed.sessionId !== void 0) {
|
|
5859
|
-
|
|
6242
|
+
Effect41.runFork(
|
|
5860
6243
|
virtualConversationDatabase.deleteVirtualConversations(
|
|
5861
6244
|
event.changed.sessionId
|
|
5862
6245
|
)
|
|
@@ -5864,18 +6247,18 @@ var InitializeService = class extends Context30.Tag("InitializeService")() {
|
|
|
5864
6247
|
return;
|
|
5865
6248
|
}
|
|
5866
6249
|
};
|
|
5867
|
-
yield*
|
|
6250
|
+
yield* Ref12.set(listenersRef, {
|
|
5868
6251
|
sessionChanged: onSessionChanged,
|
|
5869
6252
|
sessionProcessChanged: onSessionProcessChanged
|
|
5870
6253
|
});
|
|
5871
6254
|
yield* eventBus.on("sessionChanged", onSessionChanged);
|
|
5872
6255
|
yield* eventBus.on("sessionProcessChanged", onSessionProcessChanged);
|
|
5873
|
-
yield*
|
|
6256
|
+
yield* Effect41.gen(function* () {
|
|
5874
6257
|
console.log("Initializing projects cache");
|
|
5875
6258
|
const { projects } = yield* projectRepository.getProjects();
|
|
5876
6259
|
console.log(`${projects.length} projects cache initialized`);
|
|
5877
6260
|
console.log("Initializing sessions cache");
|
|
5878
|
-
const results = yield*
|
|
6261
|
+
const results = yield* Effect41.all(
|
|
5879
6262
|
projects.map(
|
|
5880
6263
|
(project) => sessionRepository.getSessions(project.id)
|
|
5881
6264
|
),
|
|
@@ -5887,13 +6270,13 @@ var InitializeService = class extends Context30.Tag("InitializeService")() {
|
|
|
5887
6270
|
);
|
|
5888
6271
|
console.log(`${totalSessions} sessions cache initialized`);
|
|
5889
6272
|
}).pipe(
|
|
5890
|
-
|
|
5891
|
-
|
|
6273
|
+
Effect41.catchAll(() => Effect41.void),
|
|
6274
|
+
Effect41.withSpan("initialize-cache")
|
|
5892
6275
|
);
|
|
5893
|
-
}).pipe(
|
|
6276
|
+
}).pipe(Effect41.withSpan("start-initialization"));
|
|
5894
6277
|
};
|
|
5895
|
-
const stopCleanup = () =>
|
|
5896
|
-
const listeners = yield*
|
|
6278
|
+
const stopCleanup = () => Effect41.gen(function* () {
|
|
6279
|
+
const listeners = yield* Ref12.get(listenersRef);
|
|
5897
6280
|
if (listeners.sessionChanged) {
|
|
5898
6281
|
yield* eventBus.off("sessionChanged", listeners.sessionChanged);
|
|
5899
6282
|
}
|
|
@@ -5903,7 +6286,7 @@ var InitializeService = class extends Context30.Tag("InitializeService")() {
|
|
|
5903
6286
|
listeners.sessionProcessChanged
|
|
5904
6287
|
);
|
|
5905
6288
|
}
|
|
5906
|
-
yield*
|
|
6289
|
+
yield* Ref12.set(listenersRef, {});
|
|
5907
6290
|
yield* fileWatcher.stop();
|
|
5908
6291
|
});
|
|
5909
6292
|
return {
|
|
@@ -5915,10 +6298,62 @@ var InitializeService = class extends Context30.Tag("InitializeService")() {
|
|
|
5915
6298
|
}
|
|
5916
6299
|
};
|
|
5917
6300
|
|
|
6301
|
+
// src/server/hono/middleware/auth.middleware.ts
|
|
6302
|
+
import { Context as Context35, Effect as Effect42, Layer as Layer37 } from "effect";
|
|
6303
|
+
import { getCookie } from "hono/cookie";
|
|
6304
|
+
import { createMiddleware } from "hono/factory";
|
|
6305
|
+
var generateSessionToken = (password) => {
|
|
6306
|
+
if (!password) return "";
|
|
6307
|
+
return Buffer.from(`ccv-session:${password}`).toString("base64");
|
|
6308
|
+
};
|
|
6309
|
+
var PUBLIC_API_ROUTES = [
|
|
6310
|
+
"/api/auth/login",
|
|
6311
|
+
"/api/auth/check",
|
|
6312
|
+
"/api/auth/logout",
|
|
6313
|
+
"/api/config",
|
|
6314
|
+
// Allow config access for theme/locale loading
|
|
6315
|
+
"/api/version"
|
|
6316
|
+
];
|
|
6317
|
+
var LayerImpl28 = Effect42.gen(function* () {
|
|
6318
|
+
const envService = yield* EnvService;
|
|
6319
|
+
const anthPassword = yield* envService.getEnv(
|
|
6320
|
+
"CLAUDE_CODE_VIEWER_AUTH_PASSWORD"
|
|
6321
|
+
) ?? void 0;
|
|
6322
|
+
const authEnabled = anthPassword !== void 0;
|
|
6323
|
+
const validSessionToken = generateSessionToken(anthPassword);
|
|
6324
|
+
const authMiddleware = createMiddleware(async (c, next) => {
|
|
6325
|
+
if (PUBLIC_API_ROUTES.includes(c.req.path)) {
|
|
6326
|
+
return next();
|
|
6327
|
+
}
|
|
6328
|
+
if (!c.req.path.startsWith("/api")) {
|
|
6329
|
+
return next();
|
|
6330
|
+
}
|
|
6331
|
+
if (!authEnabled) {
|
|
6332
|
+
return next();
|
|
6333
|
+
}
|
|
6334
|
+
const sessionToken = getCookie(c, "ccv-session");
|
|
6335
|
+
if (!sessionToken || sessionToken !== validSessionToken) {
|
|
6336
|
+
return c.json({ error: "Unauthorized" }, 401);
|
|
6337
|
+
}
|
|
6338
|
+
await next();
|
|
6339
|
+
});
|
|
6340
|
+
return {
|
|
6341
|
+
authEnabled,
|
|
6342
|
+
anthPassword,
|
|
6343
|
+
validSessionToken,
|
|
6344
|
+
authMiddleware
|
|
6345
|
+
};
|
|
6346
|
+
});
|
|
6347
|
+
var AuthMiddleware = class extends Context35.Tag("AuthMiddleware")() {
|
|
6348
|
+
static {
|
|
6349
|
+
this.Live = Layer37.effect(this, LayerImpl28);
|
|
6350
|
+
}
|
|
6351
|
+
};
|
|
6352
|
+
|
|
5918
6353
|
// src/server/hono/route.ts
|
|
5919
6354
|
import { zValidator } from "@hono/zod-validator";
|
|
5920
|
-
import { Effect as
|
|
5921
|
-
import { setCookie as setCookie2 } from "hono/cookie";
|
|
6355
|
+
import { Effect as Effect44, Runtime as Runtime3 } from "effect";
|
|
6356
|
+
import { deleteCookie, getCookie as getCookie3, setCookie as setCookie2 } from "hono/cookie";
|
|
5922
6357
|
import { streamSSE } from "hono/streaming";
|
|
5923
6358
|
import prexit from "prexit";
|
|
5924
6359
|
import { z as z28 } from "zod";
|
|
@@ -5926,7 +6361,7 @@ import { z as z28 } from "zod";
|
|
|
5926
6361
|
// package.json
|
|
5927
6362
|
var package_default = {
|
|
5928
6363
|
name: "@kimuson/claude-code-viewer",
|
|
5929
|
-
version: "0.4.
|
|
6364
|
+
version: "0.4.8",
|
|
5930
6365
|
type: "module",
|
|
5931
6366
|
license: "MIT",
|
|
5932
6367
|
repository: {
|
|
@@ -5963,15 +6398,21 @@ var package_default = {
|
|
|
5963
6398
|
e2e: "./scripts/e2e/exec_e2e.sh",
|
|
5964
6399
|
"e2e:start-server": "./scripts/e2e/start_server.sh",
|
|
5965
6400
|
"e2e:capture-snapshots": "./scripts/e2e/capture_snapshots.sh",
|
|
5966
|
-
"lingui:extract": "lingui extract --clean",
|
|
5967
|
-
"lingui:compile": "lingui compile --typescript"
|
|
6401
|
+
"lingui:extract": "lingui extract --clean && node ./scripts/lingui-sort.js",
|
|
6402
|
+
"lingui:compile": "lingui compile --typescript",
|
|
6403
|
+
postinstall: "lefthook install"
|
|
5968
6404
|
},
|
|
5969
6405
|
dependencies: {
|
|
5970
6406
|
"@anthropic-ai/claude-agent-sdk": "0.1.30",
|
|
5971
6407
|
"@anthropic-ai/claude-code": "2.0.24",
|
|
5972
6408
|
"@anthropic-ai/sdk": "0.67.0",
|
|
5973
|
-
"@effect/
|
|
5974
|
-
"@effect/
|
|
6409
|
+
"@effect/cluster": "0.55.0",
|
|
6410
|
+
"@effect/experimental": "0.57.11",
|
|
6411
|
+
"@effect/platform": "0.93.6",
|
|
6412
|
+
"@effect/platform-node": "0.103.0",
|
|
6413
|
+
"@effect/rpc": "0.72.2",
|
|
6414
|
+
"@effect/sql": "0.48.6",
|
|
6415
|
+
"@effect/workflow": "0.15.1",
|
|
5975
6416
|
"@hono/node-server": "1.19.5",
|
|
5976
6417
|
"@hono/zod-validator": "0.7.4",
|
|
5977
6418
|
"@lingui/core": "5.5.1",
|
|
@@ -5981,7 +6422,7 @@ var package_default = {
|
|
|
5981
6422
|
"@radix-ui/react-collapsible": "1.1.12",
|
|
5982
6423
|
"@radix-ui/react-dialog": "1.1.15",
|
|
5983
6424
|
"@radix-ui/react-hover-card": "1.1.15",
|
|
5984
|
-
"@radix-ui/react-popover": "
|
|
6425
|
+
"@radix-ui/react-popover": "1.1.15",
|
|
5985
6426
|
"@radix-ui/react-select": "2.2.6",
|
|
5986
6427
|
"@radix-ui/react-slot": "1.2.3",
|
|
5987
6428
|
"@radix-ui/react-tabs": "1.1.13",
|
|
@@ -5994,27 +6435,29 @@ var package_default = {
|
|
|
5994
6435
|
"class-variance-authority": "0.7.1",
|
|
5995
6436
|
clsx: "2.1.1",
|
|
5996
6437
|
"date-fns": "4.1.0",
|
|
5997
|
-
effect: "3.19.
|
|
6438
|
+
effect: "3.19.9",
|
|
5998
6439
|
"es-toolkit": "1.41.0",
|
|
5999
6440
|
hono: "4.10.3",
|
|
6000
6441
|
jotai: "2.15.0",
|
|
6001
6442
|
"lucide-react": "0.548.0",
|
|
6443
|
+
minisearch: "7.2.0",
|
|
6002
6444
|
"parse-git-diff": "0.0.19",
|
|
6003
6445
|
prexit: "2.3.0",
|
|
6004
6446
|
react: "19.2.0",
|
|
6005
6447
|
"react-dom": "19.2.0",
|
|
6006
6448
|
"react-error-boundary": "6.0.0",
|
|
6007
|
-
"react-helmet-async": "
|
|
6449
|
+
"react-helmet-async": "2.0.5",
|
|
6008
6450
|
"react-markdown": "10.1.0",
|
|
6009
6451
|
"react-syntax-highlighter": "15.6.6",
|
|
6010
6452
|
"remark-gfm": "4.0.1",
|
|
6011
6453
|
sonner: "2.0.7",
|
|
6012
6454
|
"tailwind-merge": "3.3.1",
|
|
6013
6455
|
ulid: "3.0.1",
|
|
6014
|
-
zod: "4.1.
|
|
6456
|
+
zod: "4.1.13"
|
|
6015
6457
|
},
|
|
6016
6458
|
devDependencies: {
|
|
6017
6459
|
"@biomejs/biome": "2.3.1",
|
|
6460
|
+
"@effect/language-service": "0.60.0",
|
|
6018
6461
|
"@lingui/cli": "5.5.1",
|
|
6019
6462
|
"@lingui/conf": "5.5.1",
|
|
6020
6463
|
"@lingui/format-json": "5.5.1",
|
|
@@ -6030,6 +6473,7 @@ var package_default = {
|
|
|
6030
6473
|
"@vitejs/plugin-react-swc": "4.2.0",
|
|
6031
6474
|
dotenv: "17.2.3",
|
|
6032
6475
|
esbuild: "0.25.11",
|
|
6476
|
+
lefthook: "2.0.8",
|
|
6033
6477
|
"npm-run-all2": "8.0.4",
|
|
6034
6478
|
playwright: "1.56.1",
|
|
6035
6479
|
"release-it": "19.0.5",
|
|
@@ -6191,16 +6635,16 @@ var userConfigSchema = z27.object({
|
|
|
6191
6635
|
var defaultUserConfig = userConfigSchema.parse({});
|
|
6192
6636
|
|
|
6193
6637
|
// src/server/lib/effect/toEffectResponse.ts
|
|
6194
|
-
import { Effect as
|
|
6638
|
+
import { Effect as Effect43 } from "effect";
|
|
6195
6639
|
var effectToResponse = async (ctx, effect) => {
|
|
6196
|
-
const result = await
|
|
6640
|
+
const result = await Effect43.runPromise(effect);
|
|
6197
6641
|
const result2 = ctx.json(result.response, result.status);
|
|
6198
6642
|
return result2;
|
|
6199
6643
|
};
|
|
6200
6644
|
|
|
6201
6645
|
// src/server/hono/middleware/config.middleware.ts
|
|
6202
|
-
import { getCookie, setCookie } from "hono/cookie";
|
|
6203
|
-
import { createMiddleware } from "hono/factory";
|
|
6646
|
+
import { getCookie as getCookie2, setCookie } from "hono/cookie";
|
|
6647
|
+
import { createMiddleware as createMiddleware2 } from "hono/factory";
|
|
6204
6648
|
|
|
6205
6649
|
// src/server/lib/config/parseUserConfig.ts
|
|
6206
6650
|
var parseUserConfig = (configJson) => {
|
|
@@ -6215,9 +6659,9 @@ var parseUserConfig = (configJson) => {
|
|
|
6215
6659
|
};
|
|
6216
6660
|
|
|
6217
6661
|
// src/server/hono/middleware/config.middleware.ts
|
|
6218
|
-
var configMiddleware =
|
|
6662
|
+
var configMiddleware = createMiddleware2(
|
|
6219
6663
|
async (c, next) => {
|
|
6220
|
-
const cookie =
|
|
6664
|
+
const cookie = getCookie2(c, "ccv-config");
|
|
6221
6665
|
const parsed = parseUserConfig(cookie);
|
|
6222
6666
|
if (cookie === void 0) {
|
|
6223
6667
|
const preferredLocale = detectLocaleFromAcceptLanguage(c.req.header("accept-language")) ?? DEFAULT_LOCALE;
|
|
@@ -6236,9 +6680,10 @@ var configMiddleware = createMiddleware(
|
|
|
6236
6680
|
);
|
|
6237
6681
|
|
|
6238
6682
|
// src/server/hono/route.ts
|
|
6239
|
-
var routes = (app) =>
|
|
6683
|
+
var routes = (app) => Effect44.gen(function* () {
|
|
6240
6684
|
const projectController = yield* ProjectController;
|
|
6241
6685
|
const sessionController = yield* SessionController;
|
|
6686
|
+
const agentSessionController = yield* AgentSessionController;
|
|
6242
6687
|
const gitController = yield* GitController;
|
|
6243
6688
|
const claudeCodeSessionProcessController = yield* ClaudeCodeSessionProcessController;
|
|
6244
6689
|
const claudeCodePermissionController = yield* ClaudeCodePermissionController;
|
|
@@ -6247,24 +6692,60 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6247
6692
|
const claudeCodeController = yield* ClaudeCodeController;
|
|
6248
6693
|
const schedulerController = yield* SchedulerController;
|
|
6249
6694
|
const featureFlagController = yield* FeatureFlagController;
|
|
6695
|
+
const searchController = yield* SearchController;
|
|
6250
6696
|
const envService = yield* EnvService;
|
|
6251
6697
|
const userConfigService = yield* UserConfigService;
|
|
6252
6698
|
const claudeCodeLifeCycleService = yield* ClaudeCodeLifeCycleService;
|
|
6253
6699
|
const initializeService = yield* InitializeService;
|
|
6254
|
-
const
|
|
6700
|
+
const { authMiddleware, validSessionToken, authEnabled, anthPassword } = yield* AuthMiddleware;
|
|
6701
|
+
const runtime = yield* Effect44.runtime();
|
|
6255
6702
|
if ((yield* envService.getEnv("NEXT_PHASE")) !== "phase-production-build") {
|
|
6256
6703
|
yield* initializeService.startInitialization();
|
|
6257
6704
|
prexit(async () => {
|
|
6258
6705
|
await Runtime3.runPromise(runtime)(initializeService.stopCleanup());
|
|
6259
6706
|
});
|
|
6260
6707
|
}
|
|
6261
|
-
return app.use(configMiddleware).use(async (c, next) => {
|
|
6262
|
-
await
|
|
6708
|
+
return app.use(configMiddleware).use(authMiddleware).use(async (c, next) => {
|
|
6709
|
+
await Effect44.runPromise(
|
|
6263
6710
|
userConfigService.setUserConfig({
|
|
6264
6711
|
...c.get("userConfig")
|
|
6265
6712
|
})
|
|
6266
6713
|
);
|
|
6267
6714
|
await next();
|
|
6715
|
+
}).post(
|
|
6716
|
+
"/api/auth/login",
|
|
6717
|
+
zValidator("json", z28.object({ password: z28.string() })),
|
|
6718
|
+
async (c) => {
|
|
6719
|
+
const { password } = c.req.valid("json");
|
|
6720
|
+
if (!authEnabled) {
|
|
6721
|
+
return c.json(
|
|
6722
|
+
{
|
|
6723
|
+
error: "Authentication not configured. Set CLAUDE_CODE_VIEWER_AUTH_PASSWORD environment variable."
|
|
6724
|
+
},
|
|
6725
|
+
500
|
|
6726
|
+
);
|
|
6727
|
+
}
|
|
6728
|
+
if (password !== anthPassword) {
|
|
6729
|
+
return c.json({ error: "Invalid password" }, 401);
|
|
6730
|
+
}
|
|
6731
|
+
setCookie2(c, "ccv-session", validSessionToken, {
|
|
6732
|
+
httpOnly: true,
|
|
6733
|
+
secure: false,
|
|
6734
|
+
// Set to true in production with HTTPS
|
|
6735
|
+
sameSite: "Lax",
|
|
6736
|
+
path: "/",
|
|
6737
|
+
maxAge: 60 * 60 * 24 * 7
|
|
6738
|
+
// 7 days
|
|
6739
|
+
});
|
|
6740
|
+
return c.json({ success: true });
|
|
6741
|
+
}
|
|
6742
|
+
).post("/api/auth/logout", async (c) => {
|
|
6743
|
+
deleteCookie(c, "ccv-session", { path: "/" });
|
|
6744
|
+
return c.json({ success: true });
|
|
6745
|
+
}).get("/api/auth/check", async (c) => {
|
|
6746
|
+
const sessionToken = getCookie3(c, "ccv-session");
|
|
6747
|
+
const isAuthenticated = authEnabled ? sessionToken === validSessionToken : true;
|
|
6748
|
+
return c.json({ authenticated: isAuthenticated, authEnabled });
|
|
6268
6749
|
}).get("/api/config", async (c) => {
|
|
6269
6750
|
return c.json({
|
|
6270
6751
|
config: c.get("userConfig")
|
|
@@ -6294,7 +6775,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6294
6775
|
projectController.getProject({
|
|
6295
6776
|
...c.req.param(),
|
|
6296
6777
|
...c.req.valid("query")
|
|
6297
|
-
}).pipe(
|
|
6778
|
+
}).pipe(Effect44.provide(runtime))
|
|
6298
6779
|
);
|
|
6299
6780
|
return response;
|
|
6300
6781
|
}
|
|
@@ -6311,7 +6792,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6311
6792
|
c,
|
|
6312
6793
|
projectController.createProject({
|
|
6313
6794
|
...c.req.valid("json")
|
|
6314
|
-
}).pipe(
|
|
6795
|
+
}).pipe(Effect44.provide(runtime))
|
|
6315
6796
|
);
|
|
6316
6797
|
return response;
|
|
6317
6798
|
}
|
|
@@ -6320,13 +6801,13 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6320
6801
|
c,
|
|
6321
6802
|
projectController.getProjectLatestSession({
|
|
6322
6803
|
...c.req.param()
|
|
6323
|
-
}).pipe(
|
|
6804
|
+
}).pipe(Effect44.provide(runtime))
|
|
6324
6805
|
);
|
|
6325
6806
|
return response;
|
|
6326
6807
|
}).get("/api/projects/:projectId/sessions/:sessionId", async (c) => {
|
|
6327
6808
|
const response = await effectToResponse(
|
|
6328
6809
|
c,
|
|
6329
|
-
sessionController.getSession({ ...c.req.param() }).pipe(
|
|
6810
|
+
sessionController.getSession({ ...c.req.param() }).pipe(Effect44.provide(runtime))
|
|
6330
6811
|
);
|
|
6331
6812
|
return response;
|
|
6332
6813
|
}).get(
|
|
@@ -6334,16 +6815,26 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6334
6815
|
async (c) => {
|
|
6335
6816
|
const response = await effectToResponse(
|
|
6336
6817
|
c,
|
|
6337
|
-
sessionController.exportSessionHtml({ ...c.req.param() }).pipe(
|
|
6818
|
+
sessionController.exportSessionHtml({ ...c.req.param() }).pipe(Effect44.provide(runtime))
|
|
6338
6819
|
);
|
|
6339
6820
|
return response;
|
|
6340
6821
|
}
|
|
6341
|
-
).get("/api/projects/:projectId/
|
|
6822
|
+
).get("/api/projects/:projectId/agent-sessions/:agentId", async (c) => {
|
|
6823
|
+
const { projectId, agentId } = c.req.param();
|
|
6824
|
+
const response = await effectToResponse(
|
|
6825
|
+
c,
|
|
6826
|
+
agentSessionController.getAgentSession({
|
|
6827
|
+
projectId,
|
|
6828
|
+
agentId
|
|
6829
|
+
}).pipe(Effect44.provide(runtime))
|
|
6830
|
+
);
|
|
6831
|
+
return response;
|
|
6832
|
+
}).get("/api/projects/:projectId/git/current-revisions", async (c) => {
|
|
6342
6833
|
const response = await effectToResponse(
|
|
6343
6834
|
c,
|
|
6344
6835
|
gitController.getCurrentRevisions({
|
|
6345
6836
|
...c.req.param()
|
|
6346
|
-
}).pipe(
|
|
6837
|
+
}).pipe(Effect44.provide(runtime))
|
|
6347
6838
|
);
|
|
6348
6839
|
return response;
|
|
6349
6840
|
}).post(
|
|
@@ -6361,7 +6852,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6361
6852
|
gitController.getGitDiff({
|
|
6362
6853
|
...c.req.param(),
|
|
6363
6854
|
...c.req.valid("json")
|
|
6364
|
-
}).pipe(
|
|
6855
|
+
}).pipe(Effect44.provide(runtime))
|
|
6365
6856
|
);
|
|
6366
6857
|
return response;
|
|
6367
6858
|
}
|
|
@@ -6374,7 +6865,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6374
6865
|
gitController.commitFiles({
|
|
6375
6866
|
...c.req.param(),
|
|
6376
6867
|
...c.req.valid("json")
|
|
6377
|
-
}).pipe(
|
|
6868
|
+
}).pipe(Effect44.provide(runtime))
|
|
6378
6869
|
);
|
|
6379
6870
|
return response;
|
|
6380
6871
|
}
|
|
@@ -6387,7 +6878,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6387
6878
|
gitController.pushCommits({
|
|
6388
6879
|
...c.req.param(),
|
|
6389
6880
|
...c.req.valid("json")
|
|
6390
|
-
}).pipe(
|
|
6881
|
+
}).pipe(Effect44.provide(runtime))
|
|
6391
6882
|
);
|
|
6392
6883
|
return response;
|
|
6393
6884
|
}
|
|
@@ -6400,7 +6891,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6400
6891
|
gitController.commitAndPush({
|
|
6401
6892
|
...c.req.param(),
|
|
6402
6893
|
...c.req.valid("json")
|
|
6403
|
-
}).pipe(
|
|
6894
|
+
}).pipe(Effect44.provide(runtime))
|
|
6404
6895
|
);
|
|
6405
6896
|
return response;
|
|
6406
6897
|
}
|
|
@@ -6409,7 +6900,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6409
6900
|
c,
|
|
6410
6901
|
claudeCodeController.getClaudeCommands({
|
|
6411
6902
|
...c.req.param()
|
|
6412
|
-
})
|
|
6903
|
+
}).pipe(Effect44.provide(runtime))
|
|
6413
6904
|
);
|
|
6414
6905
|
return response;
|
|
6415
6906
|
}).get("/api/projects/:projectId/mcp/list", async (c) => {
|
|
@@ -6417,19 +6908,19 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6417
6908
|
c,
|
|
6418
6909
|
claudeCodeController.getMcpListRoute({
|
|
6419
6910
|
...c.req.param()
|
|
6420
|
-
}).pipe(
|
|
6911
|
+
}).pipe(Effect44.provide(runtime))
|
|
6421
6912
|
);
|
|
6422
6913
|
return response;
|
|
6423
6914
|
}).get("/api/cc/meta", async (c) => {
|
|
6424
6915
|
const response = await effectToResponse(
|
|
6425
6916
|
c,
|
|
6426
|
-
claudeCodeController.getClaudeCodeMeta().pipe(
|
|
6917
|
+
claudeCodeController.getClaudeCodeMeta().pipe(Effect44.provide(runtime))
|
|
6427
6918
|
);
|
|
6428
6919
|
return response;
|
|
6429
6920
|
}).get("/api/cc/features", async (c) => {
|
|
6430
6921
|
const response = await effectToResponse(
|
|
6431
6922
|
c,
|
|
6432
|
-
claudeCodeController.getAvailableFeatures().pipe(
|
|
6923
|
+
claudeCodeController.getAvailableFeatures().pipe(Effect44.provide(runtime))
|
|
6433
6924
|
);
|
|
6434
6925
|
return response;
|
|
6435
6926
|
}).get("/api/cc/session-processes", async (c) => {
|
|
@@ -6473,7 +6964,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6473
6964
|
claudeCodeSessionProcessController.continueSessionProcess({
|
|
6474
6965
|
...c.req.param(),
|
|
6475
6966
|
...c.req.valid("json")
|
|
6476
|
-
}).pipe(
|
|
6967
|
+
}).pipe(Effect44.provide(runtime))
|
|
6477
6968
|
);
|
|
6478
6969
|
return response;
|
|
6479
6970
|
}
|
|
@@ -6482,7 +6973,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6482
6973
|
zValidator("json", z28.object({ projectId: z28.string() })),
|
|
6483
6974
|
async (c) => {
|
|
6484
6975
|
const { sessionProcessId } = c.req.param();
|
|
6485
|
-
void
|
|
6976
|
+
void Effect44.runFork(
|
|
6486
6977
|
claudeCodeLifeCycleService.abortTask(sessionProcessId)
|
|
6487
6978
|
);
|
|
6488
6979
|
return c.json({ message: "Task aborted" });
|
|
@@ -6510,7 +7001,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6510
7001
|
c,
|
|
6511
7002
|
async (rawStream) => {
|
|
6512
7003
|
await Runtime3.runPromise(runtime)(
|
|
6513
|
-
sseController.handleSSE(rawStream).pipe(
|
|
7004
|
+
sseController.handleSSE(rawStream).pipe(Effect44.provide(TypeSafeSSE.make(rawStream)))
|
|
6514
7005
|
);
|
|
6515
7006
|
},
|
|
6516
7007
|
async (err) => {
|
|
@@ -6520,7 +7011,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6520
7011
|
}).get("/api/scheduler/jobs", async (c) => {
|
|
6521
7012
|
const response = await effectToResponse(
|
|
6522
7013
|
c,
|
|
6523
|
-
schedulerController.getJobs().pipe(
|
|
7014
|
+
schedulerController.getJobs().pipe(Effect44.provide(runtime))
|
|
6524
7015
|
);
|
|
6525
7016
|
return response;
|
|
6526
7017
|
}).post(
|
|
@@ -6531,7 +7022,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6531
7022
|
c,
|
|
6532
7023
|
schedulerController.addJob({
|
|
6533
7024
|
job: c.req.valid("json")
|
|
6534
|
-
}).pipe(
|
|
7025
|
+
}).pipe(Effect44.provide(runtime))
|
|
6535
7026
|
);
|
|
6536
7027
|
return response;
|
|
6537
7028
|
}
|
|
@@ -6544,7 +7035,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6544
7035
|
schedulerController.updateJob({
|
|
6545
7036
|
id: c.req.param("id"),
|
|
6546
7037
|
job: c.req.valid("json")
|
|
6547
|
-
}).pipe(
|
|
7038
|
+
}).pipe(Effect44.provide(runtime))
|
|
6548
7039
|
);
|
|
6549
7040
|
return response;
|
|
6550
7041
|
}
|
|
@@ -6553,7 +7044,7 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6553
7044
|
c,
|
|
6554
7045
|
schedulerController.deleteJob({
|
|
6555
7046
|
id: c.req.param("id")
|
|
6556
|
-
}).pipe(
|
|
7047
|
+
}).pipe(Effect44.provide(runtime))
|
|
6557
7048
|
);
|
|
6558
7049
|
return response;
|
|
6559
7050
|
}).get(
|
|
@@ -6592,10 +7083,28 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6592
7083
|
);
|
|
6593
7084
|
return response;
|
|
6594
7085
|
}
|
|
7086
|
+
).get(
|
|
7087
|
+
"/api/search",
|
|
7088
|
+
zValidator(
|
|
7089
|
+
"query",
|
|
7090
|
+
z28.object({
|
|
7091
|
+
q: z28.string().min(2),
|
|
7092
|
+
limit: z28.string().optional().transform((val) => val ? parseInt(val, 10) : void 0),
|
|
7093
|
+
projectId: z28.string().optional()
|
|
7094
|
+
})
|
|
7095
|
+
),
|
|
7096
|
+
async (c) => {
|
|
7097
|
+
const { q, limit, projectId } = c.req.valid("query");
|
|
7098
|
+
const response = await effectToResponse(
|
|
7099
|
+
c,
|
|
7100
|
+
searchController.search({ query: q, limit, projectId }).pipe(Effect44.provide(runtime))
|
|
7101
|
+
);
|
|
7102
|
+
return response;
|
|
7103
|
+
}
|
|
6595
7104
|
).get("/api/flags", async (c) => {
|
|
6596
7105
|
const response = await effectToResponse(
|
|
6597
7106
|
c,
|
|
6598
|
-
featureFlagController.getFlags().pipe(
|
|
7107
|
+
featureFlagController.getFlags().pipe(Effect44.provide(runtime))
|
|
6599
7108
|
);
|
|
6600
7109
|
return response;
|
|
6601
7110
|
});
|
|
@@ -6603,13 +7112,13 @@ var routes = (app) => Effect38.gen(function* () {
|
|
|
6603
7112
|
|
|
6604
7113
|
// src/server/lib/effect/layers.ts
|
|
6605
7114
|
import { NodeContext } from "@effect/platform-node";
|
|
6606
|
-
import { Layer as
|
|
6607
|
-
var platformLayer =
|
|
7115
|
+
import { Layer as Layer38 } from "effect";
|
|
7116
|
+
var platformLayer = Layer38.mergeAll(
|
|
6608
7117
|
ApplicationContext.Live,
|
|
6609
7118
|
UserConfigService.Live,
|
|
6610
7119
|
EventBus.Live,
|
|
6611
7120
|
EnvService.Live
|
|
6612
|
-
).pipe(
|
|
7121
|
+
).pipe(Layer38.provide(EnvService.Live), Layer38.provide(NodeContext.layer));
|
|
6613
7122
|
|
|
6614
7123
|
// src/server/main.ts
|
|
6615
7124
|
var isDevelopment = process.env.NODE_ENV === "development";
|
|
@@ -6632,42 +7141,47 @@ if (!isDevelopment) {
|
|
|
6632
7141
|
}
|
|
6633
7142
|
var program = routes(honoApp).pipe(
|
|
6634
7143
|
/** Presentation */
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
7144
|
+
Effect45.provide(ProjectController.Live),
|
|
7145
|
+
Effect45.provide(SessionController.Live),
|
|
7146
|
+
Effect45.provide(AgentSessionController.Live),
|
|
7147
|
+
Effect45.provide(GitController.Live),
|
|
7148
|
+
Effect45.provide(ClaudeCodeController.Live),
|
|
7149
|
+
Effect45.provide(ClaudeCodeSessionProcessController.Live),
|
|
7150
|
+
Effect45.provide(ClaudeCodePermissionController.Live),
|
|
7151
|
+
Effect45.provide(FileSystemController.Live),
|
|
7152
|
+
Effect45.provide(SSEController.Live),
|
|
7153
|
+
Effect45.provide(SchedulerController.Live),
|
|
7154
|
+
Effect45.provide(FeatureFlagController.Live),
|
|
7155
|
+
Effect45.provide(SearchController.Live)
|
|
6645
7156
|
).pipe(
|
|
6646
7157
|
/** Application */
|
|
6647
|
-
|
|
6648
|
-
|
|
7158
|
+
Effect45.provide(InitializeService.Live),
|
|
7159
|
+
Effect45.provide(FileWatcherService.Live),
|
|
7160
|
+
Effect45.provide(AuthMiddleware.Live)
|
|
6649
7161
|
).pipe(
|
|
6650
7162
|
/** Domain */
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
7163
|
+
Effect45.provide(ClaudeCodeLifeCycleService.Live),
|
|
7164
|
+
Effect45.provide(ClaudeCodePermissionService.Live),
|
|
7165
|
+
Effect45.provide(ClaudeCodeSessionProcessService.Live),
|
|
7166
|
+
Effect45.provide(ClaudeCodeService.Live),
|
|
7167
|
+
Effect45.provide(GitService.Live),
|
|
7168
|
+
Effect45.provide(SchedulerService.Live),
|
|
7169
|
+
Effect45.provide(SchedulerConfigBaseDir.Live),
|
|
7170
|
+
Effect45.provide(SearchService.Live)
|
|
6658
7171
|
).pipe(
|
|
6659
7172
|
/** Infrastructure */
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
7173
|
+
Effect45.provide(ProjectRepository.Live),
|
|
7174
|
+
Effect45.provide(SessionRepository.Live),
|
|
7175
|
+
Effect45.provide(ProjectMetaService.Live),
|
|
7176
|
+
Effect45.provide(SessionMetaService.Live),
|
|
7177
|
+
Effect45.provide(VirtualConversationDatabase.Live),
|
|
7178
|
+
Effect45.provide(AgentSessionLayer)
|
|
6665
7179
|
).pipe(
|
|
6666
7180
|
/** Platform */
|
|
6667
|
-
|
|
6668
|
-
|
|
7181
|
+
Effect45.provide(platformLayer),
|
|
7182
|
+
Effect45.provide(NodeContext2.layer)
|
|
6669
7183
|
);
|
|
6670
|
-
await
|
|
7184
|
+
await Effect45.runPromise(program);
|
|
6671
7185
|
var port = isDevelopment ? (
|
|
6672
7186
|
// biome-ignore lint/style/noProcessEnv: allow only here
|
|
6673
7187
|
process.env.DEV_BE_PORT ?? "3401"
|