@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/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 Effect39 } from "effect";
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 FileSystem4, Path as Path6 } from "@effect/platform";
13
- import { Context as Context7, Effect as Effect9, Layer as Layer8 } from "effect";
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 Effect2, Context as EffectContext, Layer as Layer2 } from "effect";
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 = z.object({
26
- NODE_ENV: z.enum(["development", "production", "test"]).optional().default("development"),
27
- CLAUDE_CODE_VIEWER_CC_EXECUTABLE_PATH: z.string().optional(),
28
- GLOBAL_CLAUDE_DIR: z.string().optional(),
29
- NEXT_PHASE: z.string().optional(),
30
- PORT: z.string().optional().default("3000").transform((val) => parseInt(val, 10)),
31
- PATH: z.string().optional()
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 LayerImpl = Effect.gen(function* () {
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 Effect.gen(function* () {
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 Context.Tag("EnvService")() {
414
+ var EnvService = class extends Context3.Tag("EnvService")() {
67
415
  static {
68
- this.Live = Layer.effect(this, LayerImpl);
416
+ this.Live = Layer4.effect(this, LayerImpl3);
69
417
  }
70
418
  };
71
419
 
72
420
  // src/server/core/platform/services/ApplicationContext.ts
73
- var LayerImpl2 = Effect2.gen(function* () {
74
- const path = yield* Path.Path;
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
- Effect2.map(
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 = Layer2.effect(this, LayerImpl2);
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 FileSystem3, Path as Path4 } from "@effect/platform";
98
- import { Context as Context5, Effect as Effect6, Layer as Layer6, Option as Option2 } from "effect";
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 FileSystem2, Path as Path3 } from "@effect/platform";
114
- import { Context as Context4, Effect as Effect5, Layer as Layer5, Option, Ref as Ref3 } from "effect";
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 Context3, Effect as Effect4, Layer as Layer4, Ref as Ref2, Runtime } from "effect";
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 Path2 } from "@effect/platform";
122
- import { Context as Context2, Effect as Effect3, Layer as Layer3 } from "effect";
123
- import { z as z2 } from "zod";
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 = z2.array(z2.tuple([z2.string(), z2.unknown()]));
136
- var LayerImpl3 = Effect3.gen(function* () {
137
- const path = yield* Path2.Path;
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 Effect3.gen(function* () {
142
- const fs = yield* FileSystem.FileSystem;
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 Effect3.gen(function* () {
173
- const fs = yield* FileSystem.FileSystem;
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 Context2.Tag("PersistentService")() {
518
+ var PersistentService = class extends Context4.Tag("PersistentService")() {
183
519
  static {
184
- this.Live = Layer3.effect(this, LayerImpl3);
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 = () => Context3.GenericTag("FileCacheStorage");
190
- var makeFileCacheStorageLayer = (storageKey, schema) => Layer4.effect(
525
+ var FileCacheStorage = () => Context5.GenericTag("FileCacheStorage");
526
+ var makeFileCacheStorageLayer = (storageKey, schema) => Layer7.effect(
191
527
  FileCacheStorage(),
192
- Effect4.gen(function* () {
528
+ Effect6.gen(function* () {
193
529
  const persistentService = yield* PersistentService;
194
- const runtime = yield* Effect4.runtime();
195
- const storageRef = yield* Effect4.gen(function* () {
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) => Effect4.gen(function* () {
211
- const storage = yield* Ref2.get(storageRef);
212
- return storage.get(key);
213
- }),
214
- set: (key, value) => Effect4.gen(function* () {
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) => Effect4.gen(function* () {
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: () => Effect4.gen(function* () {
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 LayerImpl4 = Effect5.gen(function* () {
509
- const fs = yield* FileSystem2.FileSystem;
510
- const path = yield* Path3.Path;
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) => Effect5.gen(function* () {
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) => Effect5.gen(function* () {
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* Effect5.all(
619
+ const fileEntries = yield* Effect7.all(
543
620
  dirents.filter((name) => name.endsWith(".jsonl")).map(
544
- (name) => Effect5.gen(function* () {
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) => Effect5.gen(function* () {
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 Context4.Tag("ProjectMetaService")() {
666
+ var ProjectMetaService = class extends Context6.Tag("ProjectMetaService")() {
590
667
  static {
591
- this.Live = Layer5.effect(this, LayerImpl4).pipe(
592
- Layer5.provide(
668
+ this.Live = Layer8.effect(this, LayerImpl6).pipe(
669
+ Layer8.provide(
593
670
  makeFileCacheStorageLayer("project-path-cache", ProjectPathSchema)
594
671
  ),
595
- Layer5.provide(PersistentService.Live)
672
+ Layer8.provide(PersistentService.Live)
596
673
  );
597
674
  }
598
675
  };
599
676
 
600
677
  // src/server/core/project/infrastructure/ProjectRepository.ts
601
- var LayerImpl5 = Effect6.gen(function* () {
602
- const fs = yield* FileSystem3.FileSystem;
603
- const path = yield* Path4.Path;
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) => Effect6.gen(function* () {
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* Effect6.fail(new Error("Project not found"));
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 = () => Effect6.gen(function* () {
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) => Effect6.gen(function* () {
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* Effect6.tryPromise(
643
- () => fs.stat(fullPath).pipe(Effect6.runPromise)
644
- ).pipe(Effect6.catchAll(() => Effect6.succeed(null)));
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* Effect6.all(projectEffects, {
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 Context5.Tag("ProjectRepository")() {
751
+ var ProjectRepository = class extends Context7.Tag("ProjectRepository")() {
675
752
  static {
676
- this.Live = Layer6.effect(this, LayerImpl5);
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 Context6, Data as Data2, Effect as Effect8, Layer as Layer7 } from "effect";
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 Path5 } from "@effect/platform";
736
- import { Data, Effect as Effect7 } from "effect";
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 = Effect7.gen(function* () {
742
- const path = yield* Path5.Path;
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
- Effect7.map((output) => output.trim()),
760
- Effect7.map((output) => output === "" ? null : output),
881
+ Effect10.map((output) => output.trim()),
882
+ Effect10.map((output) => output === "" ? null : output),
761
883
  // 存在しない時、空文字になる模様
762
- Effect7.catchAll(() => Effect7.succeed(null))
884
+ Effect10.catchAll(() => Effect10.succeed(null))
763
885
  );
764
886
  if (whichClaude !== null) {
765
887
  return whichClaude;
766
888
  }
767
- const projectClaudeCode = yield* Effect7.try(() => {
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
- Effect7.catchAll(() => {
779
- return Effect7.fail(
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 = Effect7.gen(function* () {
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) => Effect7.gen(function* () {
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 Effect7.gen(function* () {
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 LayerImpl6 = Effect8.gen(function* () {
1010
+ var LayerImpl8 = Effect11.gen(function* () {
883
1011
  const projectRepository = yield* ProjectRepository;
884
- const getClaudeCodeMeta = () => Effect8.gen(function* () {
1012
+ const getClaudeCodeMeta = () => Effect11.gen(function* () {
885
1013
  const config = yield* Config;
886
1014
  return config;
887
1015
  });
888
- const getAvailableFeatures2 = () => Effect8.gen(function* () {
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) => Effect8.gen(function* () {
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* Effect8.fail(new ProjectPathNotFoundError({ projectId }));
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 Context6.Tag("ClaudeCodeService")() {
1039
+ var ClaudeCodeService = class extends Context8.Tag("ClaudeCodeService")() {
912
1040
  static {
913
- this.Live = Layer7.effect(this, LayerImpl6);
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 LayerImpl7 = Effect9.gen(function* () {
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
- const fs = yield* FileSystem4.FileSystem;
923
- const path = yield* Path6.Path;
924
- const getClaudeCommands = (options) => Effect9.gen(function* () {
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* fs.readDirectory(context.claudeCodePaths.claudeCommandsDirPath).pipe(
928
- Effect9.map(
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* fs.readDirectory(
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) => Effect9.gen(function* () {
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 = () => Effect9.gen(function* () {
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 = () => Effect9.gen(function* () {
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 Context7.Tag("ClaudeCodeController")() {
1110
+ var ClaudeCodeController = class extends Context9.Tag("ClaudeCodeController")() {
1003
1111
  static {
1004
- this.Live = Layer8.effect(this, LayerImpl7);
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 Context10, Effect as Effect12, Layer as Layer11 } from "effect";
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 Context9, Effect as Effect11, Layer as Layer10, Ref as Ref4 } from "effect";
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 Context8, Effect as Effect10, Layer as Layer9 } from "effect";
1017
- var layerImpl = Effect10.gen(function* () {
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) => Effect10.gen(function* () {
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) => Effect10.sync(() => {
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) => Effect10.sync(() => {
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 Context8.Tag("EventBus")() {
1155
+ var EventBus = class extends Context10.Tag("EventBus")() {
1048
1156
  static {
1049
- this.Live = Layer9.effect(this, layerImpl);
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 LayerImpl8 = Effect11.gen(function* () {
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) => Effect11.gen(function* () {
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* Effect11.sleep(1e3);
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 Effect11.gen(function* () {
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 Effect11.runPromise(
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) => Effect11.gen(function* () {
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 Context9.Tag(
1260
+ var ClaudeCodePermissionService = class extends Context11.Tag(
1153
1261
  "ClaudeCodePermissionService"
1154
1262
  )() {
1155
1263
  static {
1156
- this.Live = Layer10.effect(this, LayerImpl8);
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 LayerImpl9 = Effect12.gen(function* () {
1269
+ var LayerImpl11 = Effect15.gen(function* () {
1162
1270
  const claudeCodePermissionService = yield* ClaudeCodePermissionService;
1163
- const permissionResponse = (options) => Effect12.sync(() => {
1271
+ const permissionResponse = (options) => Effect15.sync(() => {
1164
1272
  const { permissionResponse: permissionResponse2 } = options;
1165
- Effect12.runFork(
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 Context10.Tag(
1289
+ var ClaudeCodePermissionController = class extends Context12.Tag(
1182
1290
  "ClaudeCodePermissionController"
1183
1291
  )() {
1184
1292
  static {
1185
- this.Live = Layer11.effect(this, LayerImpl9);
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 Context17, Effect as Effect20, Layer as Layer18 } from "effect";
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 Context11, Effect as Effect13, Layer as Layer12, Ref as Ref5 } from "effect";
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 LayerImpl10 = Effect13.gen(function* () {
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) => Effect13.gen(function* () {
1362
+ const setUserConfig = (newConfig) => Effect16.gen(function* () {
1255
1363
  yield* Ref5.update(configRef, () => newConfig);
1256
1364
  });
1257
- const getUserConfig = () => Effect13.gen(function* () {
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 Context11.Tag("UserConfigService")() {
1374
+ var UserConfigService = class extends Context13.Tag("UserConfigService")() {
1267
1375
  static {
1268
- this.Live = Layer12.effect(this, LayerImpl10);
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 Context16, Effect as Effect19, Layer as Layer17, Runtime as Runtime2 } from "effect";
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 FileSystem6, Path as Path7 } from "@effect/platform";
1304
- import { Context as Context14, Effect as Effect16, Layer as Layer15, Option as Option3 } from "effect";
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 Context12, Effect as Effect14, Layer as Layer13, Ref as Ref6 } from "effect";
1382
- var VirtualConversationDatabase = class extends Context12.Tag(
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 = Layer13.effect(
1497
+ this.Live = Layer16.effect(
1387
1498
  this,
1388
- Effect14.gen(function* () {
1499
+ Effect17.gen(function* () {
1389
1500
  const storageRef = yield* Ref6.make([]);
1390
- const getProjectVirtualConversations = (projectId) => Effect14.gen(function* () {
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) => Effect14.gen(function* () {
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) => Effect14.gen(function* () {
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) => Effect14.gen(function* () {
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 FileSystem5 } from "@effect/platform";
1439
- import { Context as Context13, Effect as Effect15, Layer as Layer14, Ref as Ref7 } from "effect";
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 Context13.Tag("SessionMetaService")() {
1696
+ var SessionMetaService = class extends Context15.Tag("SessionMetaService")() {
1586
1697
  static {
1587
- this.Live = Layer14.effect(
1698
+ this.Live = Layer17.effect(
1588
1699
  this,
1589
- Effect15.gen(function* () {
1590
- const fs = yield* FileSystem5.FileSystem;
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) => Effect15.gen(function* () {
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) => Effect15.gen(function* () {
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) => Effect15.gen(function* () {
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
- Layer14.provide(
1832
+ Layer17.provide(
1722
1833
  makeFileCacheStorageLayer(
1723
1834
  "first-user-message-cache",
1724
1835
  parsedUserMessageOrNullSchema
1725
1836
  )
1726
1837
  ),
1727
- Layer14.provide(PersistentService.Live)
1838
+ Layer17.provide(PersistentService.Live)
1728
1839
  );
1729
1840
  }
1730
1841
  };
1731
1842
 
1732
1843
  // src/server/core/session/infrastructure/SessionRepository.ts
1733
- var LayerImpl11 = Effect16.gen(function* () {
1734
- const fs = yield* FileSystem6.FileSystem;
1735
- const path = yield* Path7.Path;
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) => Effect16.gen(function* () {
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 ? Effect16.gen(function* () {
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 Effect16.succeed(null);
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 Effect16.succeed(virtualSession);
1923
+ return Effect19.succeed(virtualSession);
1813
1924
  })();
1814
1925
  return {
1815
1926
  session: sessionDetail
1816
1927
  };
1817
1928
  });
1818
- const getSessions = (projectId, options) => Effect16.gen(function* () {
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* Effect16.tryPromise({
1827
- try: () => fs.readDirectory(claudeProjectPath).pipe(Effect16.runPromise),
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(Effect16.catchAll(() => Effect16.succeed([])));
1836
- const sessionEffects = dirents.filter((entry) => entry.endsWith(".jsonl")).map(
1837
- (entry) => Effect16.gen(function* () {
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* Effect16.tryPromise(
1841
- () => fs.stat(fullPath).pipe(Effect16.runPromise)
1842
- ).pipe(Effect16.catchAll(() => Effect16.succeed(null)));
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* Effect16.all(sessionEffects, {
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* Effect16.all(
1979
+ const sessionsWithMeta2 = yield* Effect19.all(
1869
1980
  sessionsToReturn2.map(
1870
- (item) => Effect16.gen(function* () {
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* Effect16.all(
2044
+ const sessionsWithMeta = yield* Effect19.all(
1934
2045
  sessionsToReturn.map(
1935
- (item) => Effect16.gen(function* () {
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 Context14.Tag("SessionRepository")() {
2068
+ var SessionRepository = class extends Context16.Tag("SessionRepository")() {
1958
2069
  static {
1959
- this.Live = Layer15.effect(this, LayerImpl11);
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 Effect17 } from "effect";
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 Effect17.gen(function* () {
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 Context15, Data as Data3, Effect as Effect18, Layer as Layer16, Ref as Ref8 } from "effect";
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 LayerImpl12 = Effect18.gen(function* () {
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 Effect18.gen(function* () {
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 Effect18.gen(function* () {
2250
+ return Effect21.gen(function* () {
2140
2251
  const process2 = yield* getSessionProcess(sessionProcessId);
2141
2252
  if (process2.type !== "paused") {
2142
- return yield* Effect18.fail(
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* Effect18.fail(
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 Effect18.gen(function* () {
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* Effect18.fail(
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 Effect18.gen(function* () {
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 Effect18.gen(function* () {
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* Effect18.fail(new TaskNotFoundError({ taskId }));
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 Effect18.gen(function* () {
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 Effect18.gen(function* () {
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 Effect18.gen(function* () {
2383
+ return Effect21.gen(function* () {
2273
2384
  const currentProcess = yield* getSessionProcess(sessionProcessId);
2274
2385
  if (currentProcess.type !== "pending") {
2275
- return yield* Effect18.fail(
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 Effect18.gen(function* () {
2419
+ return Effect21.gen(function* () {
2309
2420
  const currentProcess = yield* getSessionProcess(sessionProcessId);
2310
2421
  if (currentProcess.type !== "not_initialized") {
2311
- return yield* Effect18.fail(
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 Effect18.gen(function* () {
2448
+ return Effect21.gen(function* () {
2338
2449
  const currentProcess = yield* getSessionProcess(sessionProcessId);
2339
2450
  if (currentProcess.type !== "initialized") {
2340
- return yield* Effect18.fail(
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 Effect18.gen(function* () {
2477
+ return Effect21.gen(function* () {
2367
2478
  const currentProcess = yield* getSessionProcess(sessionProcessId);
2368
2479
  if (currentProcess.type !== "file_created") {
2369
- return yield* Effect18.fail(
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 Effect18.gen(function* () {
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 Context15.Tag(
2567
+ var ClaudeCodeSessionProcessService = class extends Context17.Tag(
2457
2568
  "ClaudeCodeSessionProcessService"
2458
2569
  )() {
2459
2570
  static {
2460
- this.Live = Layer16.effect(this, LayerImpl12);
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 LayerImpl13 = Effect19.gen(function* () {
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* Effect19.runtime();
2582
+ const runtime = yield* Effect22.runtime();
2472
2583
  const continueTask = (options) => {
2473
2584
  const { sessionProcessId, baseSessionId, input } = options;
2474
- return Effect19.gen(function* () {
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 Effect19.gen(function* () {
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
- Effect19.runFork(
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) => Effect19.gen(function* () {
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* Effect19.die(
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
- Effect19.gen(function* () {
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
- Effect19.runFork(
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 Effect19.runPromise(
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
- Effect19.runFork(
2694
- Effect19.gen(function* () {
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: () => Effect19.promise(() => sessionInitializedPromise.promise),
2711
- yieldSessionFileCreated: () => Effect19.promise(() => sessionFileCreatedPromise.promise)
2821
+ yieldSessionInitialized: () => Effect22.promise(() => sessionInitializedPromise.promise),
2822
+ yieldSessionFileCreated: () => Effect22.promise(() => sessionFileCreatedPromise.promise)
2712
2823
  };
2713
2824
  });
2714
2825
  };
2715
- const getPublicSessionProcesses = () => Effect19.gen(function* () {
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) => Effect19.gen(function* () {
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 = () => Effect19.gen(function* () {
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 Context16.Tag(
2855
+ var ClaudeCodeLifeCycleService = class extends Context18.Tag(
2745
2856
  "ClaudeCodeLifeCycleService"
2746
2857
  )() {
2747
2858
  static {
2748
- this.Live = Layer17.effect(this, LayerImpl13);
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 LayerImpl14 = Effect20.gen(function* () {
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 = () => Effect20.gen(function* () {
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) => Effect20.gen(function* () {
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) => Effect20.gen(function* () {
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 Context17.Tag(
2946
+ var ClaudeCodeSessionProcessController = class extends Context19.Tag(
2836
2947
  "ClaudeCodeSessionProcessController"
2837
2948
  )() {
2838
2949
  static {
2839
- this.Live = Layer18.effect(this, LayerImpl14);
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 Context19, Effect as Effect22, Layer as Layer20 } from "effect";
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 Context18, Effect as Effect21, Layer as Layer19 } from "effect";
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 Context18.Tag("TypeSafeSSE")() {
2984
+ var TypeSafeSSE = class extends Context20.Tag("TypeSafeSSE")() {
2874
2985
  static {
2875
- this.make = (stream) => Layer19.succeed(this, {
2876
- writeSSE: (event, data) => Effect21.tryPromise({
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 LayerImpl15 = Effect22.gen(function* () {
3012
+ var LayerImpl17 = Effect25.gen(function* () {
2902
3013
  const eventBus = yield* EventBus;
2903
- const handleSSE = (rawStream) => Effect22.gen(function* () {
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
- Effect22.runFork(
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
- Effect22.runFork(
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
- Effect22.runFork(
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
- Effect22.runFork(
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
- Effect22.runFork(
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 Effect22.runPromise(
2953
- Effect22.gen(function* () {
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* Effect22.promise(() => connectionPromise);
3087
+ yield* Effect25.promise(() => connectionPromise);
2967
3088
  });
2968
3089
  return {
2969
3090
  handleSSE
2970
3091
  };
2971
3092
  });
2972
- var SSEController = class extends Context19.Tag("SSEController")() {
3093
+ var SSEController = class extends Context21.Tag("SSEController")() {
2973
3094
  static {
2974
- this.Live = Layer20.effect(this, LayerImpl15);
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 Path8 } from "@effect/platform";
2981
- import { Context as Context20, Effect as Effect23, Layer as Layer21, Ref as Ref9 } from "effect";
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 fileRegExp = /(?<projectId>.*?)\/(?<sessionId>.*?)\.jsonl/;
2984
- var fileRegExpGroupSchema = z22.object({
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 FileWatcherService = class extends Context20.Tag("FileWatcherService")() {
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 = Layer21.effect(
3141
+ this.Live = Layer24.effect(
2991
3142
  this,
2992
- Effect23.gen(function* () {
2993
- const path = yield* Path8.Path;
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 = () => Effect23.gen(function* () {
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* Effect23.tryPromise({
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 groups = fileRegExpGroupSchema.safeParse(
3018
- filename.match(fileRegExp)?.groups
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
- Effect23.runPromise(
3029
- Effect23.gen(function* () {
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
- Effect23.runFork(
3037
- eventBus.emit("sessionChanged", {
3038
- projectId: encodedProjectId,
3039
- sessionId
3040
- })
3041
- );
3042
- Effect23.runFork(
3043
- eventBus.emit("sessionListChanged", {
3044
- projectId: encodedProjectId
3045
- })
3046
- );
3047
- Effect23.runPromise(
3048
- Effect23.gen(function* () {
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 Effect23.runPromise(Ref9.set(watcherRef, watcher));
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
- Effect23.catchAll(() => Effect23.void)
3229
+ Effect26.catchAll(() => Effect26.void)
3073
3230
  );
3074
3231
  });
3075
- const stop = () => Effect23.gen(function* () {
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* Effect23.sync(() => watcher.close());
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* Effect23.sync(() => projectWatcher.close());
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 Context21, Effect as Effect24, Layer as Layer22 } from "effect";
3104
- var LayerImpl16 = Effect24.gen(function* () {
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 = () => Effect24.gen(function* () {
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 Context21.Tag("FeatureFlagController")() {
3289
+ var FeatureFlagController = class extends Context23.Tag("FeatureFlagController")() {
3129
3290
  static {
3130
- this.Live = Layer22.effect(this, LayerImpl16);
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 Context22, Effect as Effect25, Layer as Layer23 } from "effect";
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 LayerImpl17 = Effect25.gen(function* () {
3430
+ var LayerImpl19 = Effect28.gen(function* () {
3270
3431
  const projectRepository = yield* ProjectRepository;
3271
- const getFileCompletionRoute = (options) => Effect25.gen(function* () {
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* Effect25.promise(
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) => Effect25.promise(async () => {
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 Context22.Tag("FileSystemController")() {
3487
+ var FileSystemController = class extends Context24.Tag("FileSystemController")() {
3327
3488
  static {
3328
- this.Live = Layer23.effect(this, LayerImpl17);
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 Context24, Effect as Effect27, Either as Either2, Layer as Layer25 } from "effect";
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 FileSystem7, Path as Path9 } from "@effect/platform";
3673
- import { Context as Context23, Data as Data4, Duration, Effect as Effect26, Either, Layer as Layer24 } from "effect";
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 LayerImpl18 = Effect26.gen(function* () {
3751
- const fs = yield* FileSystem7.FileSystem;
3752
- const path = yield* Path9.Path;
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) => Effect26.gen(function* () {
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* Effect26.fail(
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* Effect26.either(Command2.string(command));
3928
+ const result = yield* Effect29.either(Command2.string(command));
3768
3929
  if (Either.isLeft(result)) {
3769
- return yield* Effect26.fail(
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) => Effect26.gen(function* () {
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) => Effect26.gen(function* () {
3943
+ const getCurrentBranch = (cwd) => Effect29.gen(function* () {
3783
3944
  const currentBranch = yield* execGitCommand(
3784
3945
  ["branch", "--show-current"],
3785
3946
  cwd
3786
- ).pipe(Effect26.map((result) => result.trim()));
3947
+ ).pipe(Effect29.map((result) => result.trim()));
3787
3948
  if (currentBranch === "") {
3788
- return yield* Effect26.fail(new DetachedHeadError({ cwd }));
3949
+ return yield* Effect29.fail(new DetachedHeadError({ cwd }));
3789
3950
  }
3790
3951
  return currentBranch;
3791
3952
  });
3792
- const branchExists = (cwd, branchName) => Effect26.gen(function* () {
3793
- const result = yield* Effect26.either(
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) => Effect26.gen(function* () {
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) => Effect26.gen(function* () {
3976
+ const stageFiles = (cwd, files) => Effect29.gen(function* () {
3816
3977
  if (files.length === 0) {
3817
- return yield* Effect26.fail(
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) => Effect26.gen(function* () {
3988
+ const commit = (cwd, message) => Effect29.gen(function* () {
3828
3989
  const trimmedMessage = message.trim();
3829
3990
  if (trimmedMessage.length === 0) {
3830
- return yield* Effect26.fail(
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) => Effect26.gen(function* () {
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* Effect26.either(
3877
- Command2.exitCode(command).pipe(Effect26.timeout(Duration.seconds(60)))
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* Effect26.fail(
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(Effect26.orElse(() => Effect26.succeed([])));
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* Effect26.fail(
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) => Effect26.gen(function* () {
4073
+ const getBranchHash = (cwd, branchName) => Effect29.gen(function* () {
3913
4074
  const result = yield* execGitCommand(["rev-parse", branchName], cwd).pipe(
3914
- Effect26.map((output) => output.trim().split("\n")[0] ?? null)
4075
+ Effect29.map((output) => output.trim().split("\n")[0] ?? null)
3915
4076
  );
3916
4077
  return result;
3917
4078
  });
3918
- const getBranchNamesByCommitHash = (cwd, hash) => Effect26.gen(function* () {
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) => Effect26.gen(function* () {
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) => Effect26.gen(function* () {
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) => Effect26.gen(function* () {
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) => Effect26.gen(function* () {
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 Context23.Tag("GitService")() {
4197
+ var GitService = class extends Context25.Tag("GitService")() {
4037
4198
  static {
4038
- this.Live = Layer24.effect(this, LayerImpl18);
4199
+ this.Live = Layer27.effect(this, LayerImpl20);
4039
4200
  }
4040
4201
  };
4041
4202
 
4042
4203
  // src/server/core/git/presentation/GitController.ts
4043
- var LayerImpl19 = Effect27.gen(function* () {
4204
+ var LayerImpl21 = Effect30.gen(function* () {
4044
4205
  const gitService = yield* GitService;
4045
4206
  const projectRepository = yield* ProjectRepository;
4046
- const getGitDiff = (options) => Effect27.gen(function* () {
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* Effect27.promise(
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) => Effect27.gen(function* () {
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* Effect27.either(
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* Effect27.either(
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) => Effect27.gen(function* () {
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* Effect27.either(gitService.push(projectPath));
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) => Effect27.gen(function* () {
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) => Effect27.gen(function* () {
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* Effect27.either(
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* Effect27.either(
4423
+ const baseBranchResult = yield* Effect30.either(
4263
4424
  gitService.findBaseBranch(projectPath, currentBranch)
4264
4425
  );
4265
- const allBranchesResult = yield* Effect27.either(
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* Effect27.either(
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 Context24.Tag("GitController")() {
4514
+ var GitController = class extends Context26.Tag("GitController")() {
4354
4515
  static {
4355
- this.Live = Layer25.effect(this, LayerImpl19);
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 FileSystem8, Path as Path11 } from "@effect/platform";
4361
- import { Context as Context25, Effect as Effect29, Layer as Layer26 } from "effect";
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 Path10 } from "@effect/platform";
4365
- import { Effect as Effect28 } from "effect";
4366
- var computeClaudeProjectFilePath = (options) => Effect28.gen(function* () {
4367
- const path = yield* Path10.Path;
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 LayerImpl20 = Effect29.gen(function* () {
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* FileSystem8.FileSystem;
4383
- const path = yield* Path11.Path;
4384
- const getProjects = () => Effect29.gen(function* () {
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) => Effect29.gen(function* () {
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) => Effect29.gen(function* () {
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) => Effect29.gen(function* () {
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 Context25.Tag("ProjectController")() {
4655
+ var ProjectController = class extends Context27.Tag("ProjectController")() {
4495
4656
  static {
4496
- this.Live = Layer26.effect(this, LayerImpl20);
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 FileSystem9, Path as Path12 } from "@effect/platform";
4503
- import { Context as Context26, Data as Data5, Effect as Effect30, Layer as Layer27 } from "effect";
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 Context26.Tag(
4725
+ var SchedulerConfigBaseDir = class extends Context28.Tag(
4565
4726
  "SchedulerConfigBaseDir"
4566
4727
  )() {
4567
4728
  static {
4568
- this.Live = Layer27.succeed(this, `${homedir4()}/.claude-code-viewer`);
4729
+ this.Live = Layer30.succeed(this, `${homedir4()}/.claude-code-viewer`);
4569
4730
  }
4570
4731
  };
4571
- var getConfigPath = Effect30.gen(function* () {
4572
- const path = yield* Path12.Path;
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 = Effect30.gen(function* () {
4577
- const fs = yield* FileSystem9.FileSystem;
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* Effect30.fail(
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* Effect30.try({
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* Effect30.fail(
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) => Effect30.gen(function* () {
4605
- const fs = yield* FileSystem9.FileSystem;
4606
- const path = yield* Path12.Path;
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 = Effect30.gen(function* () {
4774
+ var initializeConfig = Effect33.gen(function* () {
4614
4775
  const result = yield* readConfig.pipe(
4615
- Effect30.catchTags({
4616
- ConfigFileNotFoundError: () => Effect30.gen(function* () {
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: () => Effect30.gen(function* () {
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 Context27,
4794
+ Context as Context29,
4634
4795
  Cron,
4635
4796
  Data as Data6,
4636
4797
  Duration as Duration2,
4637
- Effect as Effect32,
4798
+ Effect as Effect35,
4638
4799
  Fiber,
4639
- Layer as Layer28,
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 Effect31 } from "effect";
4647
- var executeJob = (job) => Effect31.gen(function* () {
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* Effect31.fail(
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 LayerImpl21 = Effect32.gen(function* () {
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) => Effect32.gen(function* () {
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* Effect32.fail(
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* Effect32.gen(function* () {
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* Effect32.sleep(Duration2.millis(nextDelay));
4709
- yield* Effect32.repeat(runJobWithConcurrencyControl(job), cronSchedule);
4710
- }).pipe(Effect32.forkDaemon);
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* Effect32.delay(
4882
+ const fiber = yield* Effect35.delay(
4722
4883
  runJobWithConcurrencyControl(job),
4723
4884
  delayDuration
4724
- ).pipe(Effect32.forkDaemon);
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) => Effect32.gen(function* () {
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
- Effect32.matchEffect({
4742
- onSuccess: () => Effect32.void,
4743
- onFailure: () => Effect32.void
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
- Effect32.catchAll((error) => {
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 Effect32.void;
4918
+ return Effect35.void;
4758
4919
  })
4759
4920
  );
4760
4921
  return result2;
4761
4922
  }
4762
4923
  const result = yield* executeJob(job).pipe(
4763
- Effect32.matchEffect({
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) => Effect32.gen(function* () {
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) => Effect32.gen(function* () {
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 = Effect32.gen(function* () {
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 = Effect32.gen(function* () {
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 = () => Effect32.gen(function* () {
4980
+ const getJobs = () => Effect35.gen(function* () {
4820
4981
  const config = yield* readConfig.pipe(
4821
- Effect32.catchTags({
4822
- ConfigFileNotFoundError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] }))),
4823
- ConfigParseError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] })))
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) => Effect32.gen(function* () {
4989
+ const addJob = (newJob) => Effect35.gen(function* () {
4829
4990
  const config = yield* readConfig.pipe(
4830
- Effect32.catchTags({
4831
- ConfigFileNotFoundError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] }))),
4832
- ConfigParseError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] })))
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) => Effect32.gen(function* () {
5012
+ const updateJob = (jobId, updates) => Effect35.gen(function* () {
4852
5013
  const config = yield* readConfig.pipe(
4853
- Effect32.catchTags({
4854
- ConfigFileNotFoundError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] }))),
4855
- ConfigParseError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] })))
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* Effect32.fail(new SchedulerJobNotFoundError({ jobId }));
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) => Effect32.gen(function* () {
5037
+ const deleteJobFromConfig = (jobId) => Effect35.gen(function* () {
4877
5038
  const config = yield* readConfig.pipe(
4878
- Effect32.catchTags({
4879
- ConfigFileNotFoundError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] }))),
4880
- ConfigParseError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] })))
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* Effect32.fail(new SchedulerJobNotFoundError({ jobId }));
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) => Effect32.gen(function* () {
5053
+ const deleteJob = (jobId) => Effect35.gen(function* () {
4893
5054
  const config = yield* readConfig.pipe(
4894
- Effect32.catchTags({
4895
- ConfigFileNotFoundError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] }))),
4896
- ConfigParseError: () => initializeConfig.pipe(Effect32.map(() => ({ jobs: [] })))
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* Effect32.fail(new SchedulerJobNotFoundError({ jobId }));
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 Context27.Tag("SchedulerService")() {
5076
+ var SchedulerService = class extends Context29.Tag("SchedulerService")() {
4916
5077
  static {
4917
- this.Live = Layer28.effect(this, LayerImpl21);
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 Context28, Effect as Effect33, Layer as Layer29 } from "effect";
4923
- var LayerImpl22 = Effect33.gen(function* () {
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 = () => Effect33.gen(function* () {
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) => Effect33.gen(function* () {
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) => Effect33.gen(function* () {
5101
+ const updateJob = (options) => Effect36.gen(function* () {
4941
5102
  const { id, job } = options;
4942
5103
  const result = yield* schedulerService.updateJob(id, job).pipe(
4943
- Effect33.catchTag(
5104
+ Effect36.catchTag(
4944
5105
  "SchedulerJobNotFoundError",
4945
- () => Effect33.succeed(null)
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) => Effect33.gen(function* () {
5120
+ const deleteJob = (options) => Effect36.gen(function* () {
4960
5121
  const { id } = options;
4961
5122
  const result = yield* schedulerService.deleteJob(id).pipe(
4962
- Effect33.catchTag(
5123
+ Effect36.catchTag(
4963
5124
  "SchedulerJobNotFoundError",
4964
- () => Effect33.succeed(false)
5125
+ () => Effect36.succeed(false)
4965
5126
  ),
4966
- Effect33.map(() => true)
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 Context28.Tag("SchedulerController")() {
5147
+ var SchedulerController = class extends Context30.Tag("SchedulerController")() {
4987
5148
  static {
4988
- this.Live = Layer29.effect(this, LayerImpl22);
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 Context29, Effect as Effect35, Layer as Layer30 } from "effect";
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 Effect34 } from "effect";
5379
+ import { Effect as Effect39 } from "effect";
4997
5380
  var escapeHtml = (text) => {
4998
5381
  const map = {
4999
5382
  "&": "&amp;",
@@ -5252,7 +5635,7 @@ var renderGroupedAssistantEntries = (entries) => {
5252
5635
  </div>
5253
5636
  `;
5254
5637
  };
5255
- var generateSessionHtml = (session, projectId) => Effect34.gen(function* () {
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 LayerImpl23 = Effect35.gen(function* () {
6158
+ var LayerImpl27 = Effect40.gen(function* () {
5776
6159
  const sessionRepository = yield* SessionRepository;
5777
- const getSession = (options) => Effect35.gen(function* () {
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) => Effect35.gen(function* () {
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 Context29.Tag("SessionController")() {
6194
+ var SessionController = class extends Context33.Tag("SessionController")() {
5812
6195
  static {
5813
- this.Live = Layer30.effect(this, LayerImpl23);
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 Context30, Effect as Effect36, Layer as Layer31, Ref as Ref11, Schedule as Schedule2 } from "effect";
5823
- var InitializeService = class extends Context30.Tag("InitializeService")() {
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 = Layer31.effect(
6208
+ this.Live = Layer36.effect(
5826
6209
  this,
5827
- Effect36.gen(function* () {
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* Ref11.make({});
6218
+ const listenersRef = yield* Ref12.make({});
5836
6219
  const startInitialization = () => {
5837
- return Effect36.gen(function* () {
6220
+ return Effect41.gen(function* () {
5838
6221
  yield* fileWatcher.startWatching();
5839
- const daemon = Effect36.repeat(
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* Effect36.forkDaemon(daemon);
6227
+ yield* Effect41.forkDaemon(daemon);
5845
6228
  console.log("after starting heartbeat fork");
5846
6229
  const onSessionChanged = (event) => {
5847
- Effect36.runFork(
6230
+ Effect41.runFork(
5848
6231
  projectMetaService.invalidateProject(event.projectId)
5849
6232
  );
5850
- Effect36.runFork(
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
- Effect36.runFork(
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* Ref11.set(listenersRef, {
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* Effect36.gen(function* () {
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* Effect36.all(
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
- Effect36.catchAll(() => Effect36.void),
5891
- Effect36.withSpan("initialize-cache")
6273
+ Effect41.catchAll(() => Effect41.void),
6274
+ Effect41.withSpan("initialize-cache")
5892
6275
  );
5893
- }).pipe(Effect36.withSpan("start-initialization"));
6276
+ }).pipe(Effect41.withSpan("start-initialization"));
5894
6277
  };
5895
- const stopCleanup = () => Effect36.gen(function* () {
5896
- const listeners = yield* Ref11.get(listenersRef);
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* Ref11.set(listenersRef, {});
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 Effect38, Runtime as Runtime3 } from "effect";
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.5",
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/platform": "0.93.2",
5974
- "@effect/platform-node": "0.100.0",
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": "^1.1.15",
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.3",
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": "^2.0.5",
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.12"
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 Effect37 } from "effect";
6638
+ import { Effect as Effect43 } from "effect";
6195
6639
  var effectToResponse = async (ctx, effect) => {
6196
- const result = await Effect37.runPromise(effect);
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 = createMiddleware(
6662
+ var configMiddleware = createMiddleware2(
6219
6663
  async (c, next) => {
6220
- const cookie = getCookie(c, "ccv-config");
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) => Effect38.gen(function* () {
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 runtime = yield* Effect38.runtime();
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 Effect38.runPromise(
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
6818
+ sessionController.exportSessionHtml({ ...c.req.param() }).pipe(Effect44.provide(runtime))
6338
6819
  );
6339
6820
  return response;
6340
6821
  }
6341
- ).get("/api/projects/:projectId/git/current-revisions", async (c) => {
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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 Effect38.runFork(
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(Effect38.provide(TypeSafeSSE.make(rawStream)))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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(Effect38.provide(runtime))
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 Layer32 } from "effect";
6607
- var platformLayer = Layer32.mergeAll(
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(Layer32.provide(EnvService.Live), Layer32.provide(NodeContext.layer));
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
- Effect39.provide(ProjectController.Live),
6636
- Effect39.provide(SessionController.Live),
6637
- Effect39.provide(GitController.Live),
6638
- Effect39.provide(ClaudeCodeController.Live),
6639
- Effect39.provide(ClaudeCodeSessionProcessController.Live),
6640
- Effect39.provide(ClaudeCodePermissionController.Live),
6641
- Effect39.provide(FileSystemController.Live),
6642
- Effect39.provide(SSEController.Live),
6643
- Effect39.provide(SchedulerController.Live),
6644
- Effect39.provide(FeatureFlagController.Live)
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
- Effect39.provide(InitializeService.Live),
6648
- Effect39.provide(FileWatcherService.Live)
7158
+ Effect45.provide(InitializeService.Live),
7159
+ Effect45.provide(FileWatcherService.Live),
7160
+ Effect45.provide(AuthMiddleware.Live)
6649
7161
  ).pipe(
6650
7162
  /** Domain */
6651
- Effect39.provide(ClaudeCodeLifeCycleService.Live),
6652
- Effect39.provide(ClaudeCodePermissionService.Live),
6653
- Effect39.provide(ClaudeCodeSessionProcessService.Live),
6654
- Effect39.provide(ClaudeCodeService.Live),
6655
- Effect39.provide(GitService.Live),
6656
- Effect39.provide(SchedulerService.Live),
6657
- Effect39.provide(SchedulerConfigBaseDir.Live)
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
- Effect39.provide(ProjectRepository.Live),
6661
- Effect39.provide(SessionRepository.Live),
6662
- Effect39.provide(ProjectMetaService.Live),
6663
- Effect39.provide(SessionMetaService.Live),
6664
- Effect39.provide(VirtualConversationDatabase.Live)
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
- Effect39.provide(platformLayer),
6668
- Effect39.provide(NodeContext2.layer)
7181
+ Effect45.provide(platformLayer),
7182
+ Effect45.provide(NodeContext2.layer)
6669
7183
  );
6670
- await Effect39.runPromise(program);
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"