@cookielab.io/klovi 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -58,6 +58,110 @@ var init_plugin_errors = __esm(() => {
58
58
  };
59
59
  });
60
60
 
61
+ // ../../packages/plugin-core/src/resolve-worktree.ts
62
+ import { join } from "node:path";
63
+ import { FileSystem } from "@effect/platform";
64
+ import { Effect } from "effect";
65
+ function stripT3CodeSuffix(path) {
66
+ if (!T3CODE_SUFFIX_REGEX.test(path))
67
+ return null;
68
+ const parentPath = path.replace(T3CODE_SUFFIX_REGEX, "");
69
+ const lastSlash = parentPath.lastIndexOf("/");
70
+ const projectName = lastSlash === -1 ? parentPath : parentPath.slice(lastSlash + 1);
71
+ return { path: parentPath, projectName };
72
+ }
73
+ function resolveGitWorktree(worktreePath) {
74
+ return Effect.gen(function* () {
75
+ const fs = yield* FileSystem.FileSystem;
76
+ const dotGitPath = join(worktreePath, ".git");
77
+ const info = yield* fs.stat(dotGitPath).pipe(Effect.catchAll(() => Effect.succeed(null)));
78
+ if (!info || info.type !== "File")
79
+ return worktreePath;
80
+ const content = yield* fs.readFileString(dotGitPath).pipe(Effect.catchAll(() => Effect.succeed("")));
81
+ if (!content)
82
+ return worktreePath;
83
+ const match = GITDIR_WORKTREE_REGEX.exec(content);
84
+ if (!match?.[1])
85
+ return worktreePath;
86
+ const gitdir = match[1];
87
+ const worktreeIdx = gitdir.indexOf(GIT_WORKTREES_SEGMENT);
88
+ if (worktreeIdx === -1)
89
+ return worktreePath;
90
+ return gitdir.slice(0, worktreeIdx);
91
+ });
92
+ }
93
+ function lastSegment(path) {
94
+ const lastSlash = path.lastIndexOf("/");
95
+ return lastSlash === -1 ? path : path.slice(lastSlash + 1);
96
+ }
97
+ function collectT3CodeEntries(projects) {
98
+ const entries = [];
99
+ for (const project of projects) {
100
+ const stripped = stripT3CodeSuffix(project.resolvedPath);
101
+ if (stripped) {
102
+ entries.push({
103
+ project,
104
+ originalPath: project.resolvedPath,
105
+ projectName: stripped.projectName
106
+ });
107
+ project.resolvedPath = stripped.path;
108
+ }
109
+ }
110
+ return entries;
111
+ }
112
+ function buildNameMap(projects, t3codeProjects) {
113
+ const nameToResolvedPaths = new Map;
114
+ for (const project of projects) {
115
+ if (t3codeProjects.has(project))
116
+ continue;
117
+ const name = lastSegment(project.resolvedPath);
118
+ if (!name)
119
+ continue;
120
+ const existing = nameToResolvedPaths.get(name);
121
+ if (existing) {
122
+ if (!existing.includes(project.resolvedPath))
123
+ existing.push(project.resolvedPath);
124
+ } else {
125
+ nameToResolvedPaths.set(name, [project.resolvedPath]);
126
+ }
127
+ }
128
+ return nameToResolvedPaths;
129
+ }
130
+ function resolveEntry(entry, nameMap) {
131
+ return Effect.gen(function* () {
132
+ const candidates = nameMap.get(entry.projectName);
133
+ if (!candidates || candidates.length === 0)
134
+ return;
135
+ if (candidates.length === 1) {
136
+ const resolvedPath = candidates[0];
137
+ if (resolvedPath)
138
+ entry.project.resolvedPath = resolvedPath;
139
+ return;
140
+ }
141
+ const resolved = yield* resolveGitWorktree(entry.originalPath);
142
+ if (candidates.includes(resolved)) {
143
+ entry.project.resolvedPath = resolved;
144
+ }
145
+ });
146
+ }
147
+ function resolveT3CodePaths(projects) {
148
+ return Effect.gen(function* () {
149
+ const t3codeEntries = collectT3CodeEntries(projects);
150
+ if (t3codeEntries.length === 0)
151
+ return;
152
+ const t3codeProjects = new Set(t3codeEntries.map((e) => e.project));
153
+ const nameMap = buildNameMap(projects, t3codeProjects);
154
+ for (const entry of t3codeEntries) {
155
+ yield* resolveEntry(entry, nameMap);
156
+ }
157
+ });
158
+ }
159
+ var T3CODE_SUFFIX_REGEX, GITDIR_WORKTREE_REGEX, GIT_WORKTREES_SEGMENT = "/.git/worktrees/";
160
+ var init_resolve_worktree = __esm(() => {
161
+ T3CODE_SUFFIX_REGEX = /\/t3code-[a-f0-9]+$/;
162
+ GITDIR_WORKTREE_REGEX = /^gitdir:\s*(.+?)\s*$/;
163
+ });
164
+
61
165
  // ../../packages/plugin-core/src/session-id.ts
62
166
  function encodeSessionId(pluginId, rawSessionId) {
63
167
  return `${pluginId}${SESSION_ID_SEPARATOR}${rawSessionId}`;
@@ -75,7 +179,7 @@ function parseSessionId(sessionId) {
75
179
  var SESSION_ID_SEPARATOR = "::";
76
180
 
77
181
  // ../../packages/plugin-core/src/plugin-registry.ts
78
- import { Effect, Layer } from "effect";
182
+ import { Effect as Effect2, Layer } from "effect";
79
183
  function encodeResolvedPath(resolvedPath) {
80
184
  if (resolvedPath.startsWith("/")) {
81
185
  return resolvedPath.replace(/\//g, "-");
@@ -112,12 +216,13 @@ class PluginRegistry {
112
216
  return [...this.plugins.values()].map((entry) => entry.plugin);
113
217
  }
114
218
  discoverAllProjects() {
115
- return Effect.gen(this, function* () {
219
+ return Effect2.gen(this, function* () {
116
220
  const allProjects = [];
117
221
  for (const { plugin, configLayer } of this.plugins.values()) {
118
- const projects = yield* plugin.discoverProjects.pipe(Effect.provide(configLayer), Effect.catchAll(() => Effect.succeed([])));
222
+ const projects = yield* plugin.discoverProjects.pipe(Effect2.provide(configLayer), Effect2.catchAll(() => Effect2.succeed([])));
119
223
  allProjects.push(...projects);
120
224
  }
225
+ yield* resolveT3CodePaths(allProjects);
121
226
  const projectsByPath = new Map;
122
227
  for (const project of allProjects) {
123
228
  const current = projectsByPath.get(project.resolvedPath);
@@ -147,13 +252,13 @@ class PluginRegistry {
147
252
  });
148
253
  }
149
254
  listAllSessions(project) {
150
- return Effect.gen(this, function* () {
255
+ return Effect2.gen(this, function* () {
151
256
  const allSessions = [];
152
257
  for (const source of project.sources) {
153
258
  const entry = this.plugins.get(source.pluginId);
154
259
  if (!entry)
155
260
  continue;
156
- const sessions = yield* entry.plugin.listSessions(source.nativeId).pipe(Effect.provide(entry.configLayer), Effect.catchAll(() => Effect.succeed([])));
261
+ const sessions = yield* entry.plugin.listSessions(source.nativeId).pipe(Effect2.provide(entry.configLayer), Effect2.catchAll(() => Effect2.succeed([])));
157
262
  allSessions.push(...sessions.map((session) => ({
158
263
  ...session,
159
264
  sessionId: this.sessionIdEncoder(source.pluginId, session.sessionId),
@@ -167,6 +272,7 @@ class PluginRegistry {
167
272
  }
168
273
  var init_plugin_registry = __esm(() => {
169
274
  init_plugin_config();
275
+ init_resolve_worktree();
170
276
  });
171
277
 
172
278
  // ../../packages/plugin-core/src/plugin-runtime.ts
@@ -197,19 +303,19 @@ var init_src = __esm(() => {
197
303
  });
198
304
 
199
305
  // ../../packages/plugin-opencode/src/db.ts
200
- import { join } from "node:path";
201
- import { FileSystem } from "@effect/platform";
202
- import { Effect as Effect2 } from "effect";
306
+ import { join as join2 } from "node:path";
307
+ import { FileSystem as FileSystem2 } from "@effect/platform";
308
+ import { Effect as Effect3 } from "effect";
203
309
  function getOpenCodeDbPath() {
204
- return Effect2.gen(function* () {
310
+ return Effect3.gen(function* () {
205
311
  const config = yield* PluginConfig;
206
- return join(config.dataDir, "opencode.db");
312
+ return join2(config.dataDir, "opencode.db");
207
313
  });
208
314
  }
209
315
  function openOpenCodeDb() {
210
- return Effect2.gen(function* () {
316
+ return Effect3.gen(function* () {
211
317
  const dbPath = yield* getOpenCodeDbPath();
212
- const fs = yield* FileSystem.FileSystem;
318
+ const fs = yield* FileSystem2.FileSystem;
213
319
  const exists = yield* fs.exists(dbPath);
214
320
  if (!exists)
215
321
  return null;
@@ -231,7 +337,7 @@ function tryParseJson(value) {
231
337
  }
232
338
 
233
339
  // ../../packages/plugin-opencode/src/discovery.ts
234
- import { Effect as Effect3 } from "effect";
340
+ import { Effect as Effect4 } from "effect";
235
341
  function getColumns(db, tableName) {
236
342
  const rows = db.query(`PRAGMA table_info(${tableName})`).all();
237
343
  return new Set(rows.map((r) => r.name));
@@ -252,7 +358,7 @@ function inspectSchema(db) {
252
358
  };
253
359
  }
254
360
  function discoverOpenCodeProjects() {
255
- return Effect3.gen(function* () {
361
+ return Effect4.gen(function* () {
256
362
  const db = yield* openOpenCodeDb();
257
363
  if (!db)
258
364
  return [];
@@ -340,7 +446,7 @@ function sessionRowToSummary(db, row) {
340
446
  };
341
447
  }
342
448
  function listOpenCodeSessions(nativeId) {
343
- return Effect3.gen(function* () {
449
+ return Effect4.gen(function* () {
344
450
  const db = yield* openOpenCodeDb();
345
451
  if (!db)
346
452
  return [];
@@ -400,7 +506,7 @@ var init_discovery = __esm(() => {
400
506
  });
401
507
 
402
508
  // ../../packages/plugin-opencode/src/parser.ts
403
- import { Effect as Effect4 } from "effect";
509
+ import { Effect as Effect5 } from "effect";
404
510
  function partToContentBlock(partData, nextToolUseId) {
405
511
  switch (partData.type) {
406
512
  case "text": {
@@ -595,7 +701,7 @@ function loadSessionFromDb(db, nativeId, sessionId) {
595
701
  return { sessionId, project, turns, pluginId: "opencode" };
596
702
  }
597
703
  function loadOpenCodeSession(nativeId, sessionId) {
598
- return Effect4.gen(function* () {
704
+ return Effect5.gen(function* () {
599
705
  const db = yield* openOpenCodeDb();
600
706
  if (!db) {
601
707
  return emptySession(nativeId, sessionId);
@@ -623,19 +729,19 @@ var init_parser = __esm(() => {
623
729
  });
624
730
 
625
731
  // ../../packages/plugin-opencode/src/config.ts
626
- import { join as join2 } from "node:path";
732
+ import { join as join3 } from "node:path";
627
733
  var DEFAULT_OPENCODE_DIR;
628
734
  var init_config = __esm(() => {
629
- DEFAULT_OPENCODE_DIR = join2(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".local", "share", "opencode");
735
+ DEFAULT_OPENCODE_DIR = join3(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".local", "share", "opencode");
630
736
  });
631
737
 
632
738
  // ../../packages/plugin-opencode/src/runtime/bun-sqlite.ts
633
- import { Effect as Effect5, Layer as Layer3 } from "effect";
739
+ import { Effect as Effect6, Layer as Layer3 } from "effect";
634
740
  var bunSqliteClient, BunSqliteLayer;
635
741
  var init_bun_sqlite = __esm(() => {
636
742
  init_src();
637
743
  bunSqliteClient = {
638
- open: (dbPath, options) => Effect5.try({
744
+ open: (dbPath, options) => Effect6.try({
639
745
  try: () => {
640
746
  const sqlite = __require("bun:sqlite");
641
747
  return new sqlite.Database(dbPath, {
@@ -643,18 +749,18 @@ var init_bun_sqlite = __esm(() => {
643
749
  });
644
750
  },
645
751
  catch: () => null
646
- }).pipe(Effect5.catchAll(() => Effect5.succeed(null)))
752
+ }).pipe(Effect6.catchAll(() => Effect6.succeed(null)))
647
753
  };
648
754
  BunSqliteLayer = Layer3.succeed(SqliteClientTag, bunSqliteClient);
649
755
  });
650
756
 
651
757
  // ../../packages/plugin-opencode/src/runtime/node-sqlite.ts
652
- import { Effect as Effect6, Layer as Layer4 } from "effect";
758
+ import { Effect as Effect7, Layer as Layer4 } from "effect";
653
759
  var nodeSqliteClient, NodeSqliteLayer;
654
760
  var init_node_sqlite = __esm(() => {
655
761
  init_src();
656
762
  nodeSqliteClient = {
657
- open: (dbPath, options) => Effect6.tryPromise({
763
+ open: (dbPath, options) => Effect7.tryPromise({
658
764
  try: async () => {
659
765
  const sqlite = await import("node:sqlite");
660
766
  const db = new sqlite.DatabaseSync(dbPath, {
@@ -679,15 +785,15 @@ var init_node_sqlite = __esm(() => {
679
785
  };
680
786
  },
681
787
  catch: () => null
682
- }).pipe(Effect6.catchAll(() => Effect6.succeed(null)))
788
+ }).pipe(Effect7.catchAll(() => Effect7.succeed(null)))
683
789
  };
684
790
  NodeSqliteLayer = Layer4.succeed(SqliteClientTag, nodeSqliteClient);
685
791
  });
686
792
 
687
793
  // ../../packages/plugin-opencode/src/index.ts
688
- import { join as join3 } from "node:path";
689
- import { FileSystem as FileSystem2 } from "@effect/platform";
690
- import { Effect as Effect7 } from "effect";
794
+ import { join as join4 } from "node:path";
795
+ import { FileSystem as FileSystem3 } from "@effect/platform";
796
+ import { Effect as Effect8 } from "effect";
691
797
  var openCodePlugin;
692
798
  var init_src2 = __esm(() => {
693
799
  init_src();
@@ -700,24 +806,24 @@ var init_src2 = __esm(() => {
700
806
  id: "opencode",
701
807
  displayName: "OpenCode",
702
808
  getDefaultDataDir: () => null,
703
- isDataAvailable: Effect7.gen(function* () {
809
+ isDataAvailable: Effect8.gen(function* () {
704
810
  const config = yield* PluginConfig;
705
- const fs = yield* FileSystem2.FileSystem;
706
- return yield* fs.exists(join3(config.dataDir, "opencode.db")).pipe(Effect7.catchAll(() => Effect7.succeed(false)));
811
+ const fs = yield* FileSystem3.FileSystem;
812
+ return yield* fs.exists(join4(config.dataDir, "opencode.db")).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
707
813
  }),
708
- discoverProjects: discoverOpenCodeProjects().pipe(Effect7.catchAll((err) => Effect7.fail(new PluginError({
814
+ discoverProjects: discoverOpenCodeProjects().pipe(Effect8.catchAll((err) => Effect8.fail(new PluginError({
709
815
  pluginId: "opencode",
710
816
  operation: "discoverProjects",
711
817
  message: String(err),
712
818
  cause: err
713
819
  })))),
714
- listSessions: (nativeId) => listOpenCodeSessions(nativeId).pipe(Effect7.catchAll((err) => Effect7.fail(new PluginError({
820
+ listSessions: (nativeId) => listOpenCodeSessions(nativeId).pipe(Effect8.catchAll((err) => Effect8.fail(new PluginError({
715
821
  pluginId: "opencode",
716
822
  operation: "listSessions",
717
823
  message: String(err),
718
824
  cause: err
719
825
  })))),
720
- loadSession: (nativeId, sessionId) => loadOpenCodeSession(nativeId, sessionId).pipe(Effect7.catchAll((err) => Effect7.fail(new PluginError({
826
+ loadSession: (nativeId, sessionId) => loadOpenCodeSession(nativeId, sessionId).pipe(Effect8.catchAll((err) => Effect8.fail(new PluginError({
721
827
  pluginId: "opencode",
722
828
  operation: "loadSession",
723
829
  message: String(err),
@@ -745,9 +851,9 @@ var init_platform_node = __esm(() => {
745
851
  import { execFile } from "node:child_process";
746
852
 
747
853
  // ../../packages/server/src/effect/bootstrap.ts
748
- import { join as join11 } from "node:path";
854
+ import { join as join12 } from "node:path";
749
855
  import { HttpServer } from "@effect/platform";
750
- import { Cause, Effect as Effect19, Fiber, Layer as Layer8 } from "effect";
856
+ import { Cause, Effect as Effect20, Fiber, Layer as Layer8 } from "effect";
751
857
 
752
858
  // ../../packages/server/src/effect/platform-bun.ts
753
859
  init_src2();
@@ -759,7 +865,7 @@ var makeBunServerLayer = (options) => Layer5.merge(BunHttpServer.layer(options),
759
865
  // ../../packages/server/src/effect/plugin-runtime.ts
760
866
  init_src();
761
867
  import {
762
- Effect as Effect8,
868
+ Effect as Effect9,
763
869
  ManagedRuntime
764
870
  } from "effect";
765
871
  var pluginRuntime = ManagedRuntime.make(BunPluginLayer);
@@ -767,7 +873,7 @@ function setPluginLayer(layer) {
767
873
  pluginRuntime = ManagedRuntime.make(layer);
768
874
  }
769
875
  function runPluginEffect(effect, config) {
770
- const provided = effect.pipe(Effect8.provide(makePluginConfigLayer(config)));
876
+ const provided = effect.pipe(Effect9.provide(makePluginConfigLayer(config)));
771
877
  return pluginRuntime.runPromise(provided);
772
878
  }
773
879
  function runRegistryEffect(effect) {
@@ -781,7 +887,7 @@ class ServerConfig extends Context3.Tag("@klovi/ServerConfig")() {
781
887
  }
782
888
 
783
889
  // ../../packages/server/src/effect/server-services.ts
784
- import { Context as Context4, Effect as Effect18, Layer as Layer6 } from "effect";
890
+ import { Context as Context4, Effect as Effect19, Layer as Layer6 } from "effect";
785
891
 
786
892
  // ../../packages/server/src/services/app-services.ts
787
893
  init_src();
@@ -789,12 +895,12 @@ import { access, rm } from "node:fs/promises";
789
895
 
790
896
  // ../../packages/plugin-claude-code/src/index.ts
791
897
  init_src();
792
- import { Effect as Effect12 } from "effect";
898
+ import { Effect as Effect13 } from "effect";
793
899
 
794
900
  // ../../packages/plugin-claude-code/src/discovery.ts
795
901
  init_src();
796
- import { join as join5 } from "node:path";
797
- import { Effect as Effect10 } from "effect";
902
+ import { join as join6 } from "node:path";
903
+ import { Effect as Effect11 } from "effect";
798
904
 
799
905
  // ../../packages/plugin-claude-code/src/command-message.ts
800
906
  var COMMAND_ARGS_REGEX = /<command-args>([\s\S]*?)<\/command-args>/;
@@ -826,17 +932,17 @@ function parseCommandMessage(text) {
826
932
 
827
933
  // ../../packages/plugin-claude-code/src/shared/discovery-utils.ts
828
934
  init_src();
829
- import { join as join4 } from "node:path";
830
- import { FileSystem as FileSystem3 } from "@effect/platform";
831
- import { Effect as Effect9 } from "effect";
935
+ import { join as join5 } from "node:path";
936
+ import { FileSystem as FileSystem4 } from "@effect/platform";
937
+ import { Effect as Effect10 } from "effect";
832
938
  var WINDOWS_DRIVE_LETTER_REGEX = /^[A-Za-z]\//;
833
939
  function readDirEntriesSafe(dir) {
834
- return Effect9.gen(function* () {
835
- const fs = yield* FileSystem3.FileSystem;
836
- const names = yield* fs.readDirectory(dir).pipe(Effect9.catchAll(() => Effect9.succeed([])));
940
+ return Effect10.gen(function* () {
941
+ const fs = yield* FileSystem4.FileSystem;
942
+ const names = yield* fs.readDirectory(dir).pipe(Effect10.catchAll(() => Effect10.succeed([])));
837
943
  const entries = [];
838
944
  for (const name of names) {
839
- const info = yield* fs.stat(join4(dir, name)).pipe(Effect9.catchAll(() => Effect9.succeed(null)));
945
+ const info = yield* fs.stat(join5(dir, name)).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
840
946
  if (info) {
841
947
  entries.push({ name, isDirectory: info.type === "Directory" });
842
948
  }
@@ -845,19 +951,19 @@ function readDirEntriesSafe(dir) {
845
951
  });
846
952
  }
847
953
  function listFilesBySuffix(dir, suffix) {
848
- return Effect9.gen(function* () {
849
- const fs = yield* FileSystem3.FileSystem;
850
- const names = yield* fs.readDirectory(dir).pipe(Effect9.catchAll(() => Effect9.succeed([])));
954
+ return Effect10.gen(function* () {
955
+ const fs = yield* FileSystem4.FileSystem;
956
+ const names = yield* fs.readDirectory(dir).pipe(Effect10.catchAll(() => Effect10.succeed([])));
851
957
  return names.filter((name) => name.endsWith(suffix));
852
958
  });
853
959
  }
854
960
  function listFilesWithMtime(dir, suffix) {
855
- return Effect9.gen(function* () {
856
- const fs = yield* FileSystem3.FileSystem;
961
+ return Effect10.gen(function* () {
962
+ const fs = yield* FileSystem4.FileSystem;
857
963
  const names = yield* listFilesBySuffix(dir, suffix);
858
964
  const results = [];
859
965
  for (const fileName of names) {
860
- const info = yield* fs.stat(join4(dir, fileName)).pipe(Effect9.catchAll(() => Effect9.succeed(null)));
966
+ const info = yield* fs.stat(join5(dir, fileName)).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
861
967
  if (info?.mtime._tag === "Some") {
862
968
  results.push({ fileName, mtime: info.mtime.value.toISOString() });
863
969
  }
@@ -867,22 +973,22 @@ function listFilesWithMtime(dir, suffix) {
867
973
  });
868
974
  }
869
975
  function readTextPrefix(filePath, maxBytes) {
870
- return Effect9.gen(function* () {
871
- const fs = yield* FileSystem3.FileSystem;
976
+ return Effect10.gen(function* () {
977
+ const fs = yield* FileSystem4.FileSystem;
872
978
  const bytes = yield* fs.readFile(filePath);
873
979
  const slice = bytes.subarray(0, maxBytes);
874
980
  return new TextDecoder().decode(slice);
875
981
  });
876
982
  }
877
983
  function readFileText(filePath) {
878
- return Effect9.gen(function* () {
879
- const fs = yield* FileSystem3.FileSystem;
984
+ return Effect10.gen(function* () {
985
+ const fs = yield* FileSystem4.FileSystem;
880
986
  return yield* fs.readFileString(filePath);
881
987
  });
882
988
  }
883
989
  function fileExists(filePath) {
884
- return Effect9.gen(function* () {
885
- const fs = yield* FileSystem3.FileSystem;
990
+ return Effect10.gen(function* () {
991
+ const fs = yield* FileSystem4.FileSystem;
886
992
  return yield* fs.exists(filePath);
887
993
  });
888
994
  }
@@ -928,11 +1034,11 @@ var CWD_SCAN_BYTES = 64 * 1024;
928
1034
  var SESSION_META_SCAN_BYTES = 1024 * 1024;
929
1035
  var BRACKETED_TEXT_REGEX = /^\[.+\]$/;
930
1036
  function inspectProjectSessions(projectDir, sessionFiles) {
931
- return Effect10.gen(function* () {
1037
+ return Effect11.gen(function* () {
932
1038
  const lastActivity = sessionFiles[0]?.mtime || "";
933
1039
  let resolvedPath = "";
934
1040
  for (const sessionFile of sessionFiles) {
935
- const filePath = join5(projectDir, sessionFile.fileName);
1041
+ const filePath = join6(projectDir, sessionFile.fileName);
936
1042
  if (!resolvedPath) {
937
1043
  resolvedPath = yield* extractCwd(filePath);
938
1044
  }
@@ -941,15 +1047,15 @@ function inspectProjectSessions(projectDir, sessionFiles) {
941
1047
  });
942
1048
  }
943
1049
  function discoverClaudeProjects() {
944
- return Effect10.gen(function* () {
1050
+ return Effect11.gen(function* () {
945
1051
  const config = yield* PluginConfig;
946
- const projectsDir = join5(config.dataDir, "projects");
1052
+ const projectsDir = join6(config.dataDir, "projects");
947
1053
  const entries = yield* readDirEntriesSafe(projectsDir);
948
1054
  const projects = [];
949
1055
  for (const entry of entries) {
950
1056
  if (!entry.isDirectory)
951
1057
  continue;
952
- const projectDir = join5(projectsDir, entry.name);
1058
+ const projectDir = join6(projectsDir, entry.name);
953
1059
  const sessionFiles = yield* listFilesWithMtime(projectDir, ".jsonl");
954
1060
  if (sessionFiles.length === 0)
955
1061
  continue;
@@ -970,13 +1076,13 @@ function discoverClaudeProjects() {
970
1076
  }
971
1077
  var PLAN_PREFIX = "Implement the following plan";
972
1078
  function listClaudeSessions(nativeId) {
973
- return Effect10.gen(function* () {
1079
+ return Effect11.gen(function* () {
974
1080
  const config = yield* PluginConfig;
975
- const projectDir = join5(config.dataDir, "projects", nativeId);
1081
+ const projectDir = join6(config.dataDir, "projects", nativeId);
976
1082
  const files = yield* listFilesBySuffix(projectDir, ".jsonl");
977
1083
  const sessions = [];
978
1084
  for (const file of files) {
979
- const filePath = join5(projectDir, file);
1085
+ const filePath = join6(projectDir, file);
980
1086
  const sessionId = file.replace(".jsonl", "");
981
1087
  const meta = yield* extractSessionMeta(filePath);
982
1088
  if (meta)
@@ -1003,8 +1109,8 @@ function classifySessionTypes(sessions) {
1003
1109
  }
1004
1110
  }
1005
1111
  function extractCwd(filePath) {
1006
- return Effect10.gen(function* () {
1007
- const text = yield* readTextPrefix(filePath, CWD_SCAN_BYTES).pipe(Effect10.catchAll(() => Effect10.succeed("")));
1112
+ return Effect11.gen(function* () {
1113
+ const text = yield* readTextPrefix(filePath, CWD_SCAN_BYTES).pipe(Effect11.catchAll(() => Effect11.succeed("")));
1008
1114
  if (!text)
1009
1115
  return "";
1010
1116
  let cwd = "";
@@ -1053,8 +1159,8 @@ function processMetaLine(obj, meta) {
1053
1159
  }
1054
1160
  }
1055
1161
  function extractSessionMeta(filePath) {
1056
- return Effect10.gen(function* () {
1057
- const text = yield* readTextPrefix(filePath, SESSION_META_SCAN_BYTES).pipe(Effect10.catchAll(() => Effect10.succeed("")));
1162
+ return Effect11.gen(function* () {
1163
+ const text = yield* readTextPrefix(filePath, SESSION_META_SCAN_BYTES).pipe(Effect11.catchAll(() => Effect11.succeed("")));
1058
1164
  if (!text)
1059
1165
  return null;
1060
1166
  const meta = {
@@ -1088,12 +1194,12 @@ function extractSessionMeta(filePath) {
1088
1194
 
1089
1195
  // ../../packages/plugin-claude-code/src/parser.ts
1090
1196
  init_src();
1091
- import { join as join6 } from "node:path";
1092
- import { Effect as Effect11 } from "effect";
1197
+ import { join as join7 } from "node:path";
1198
+ import { Effect as Effect12 } from "effect";
1093
1199
  function loadClaudeSession(nativeId, sessionId) {
1094
- return Effect11.gen(function* () {
1200
+ return Effect12.gen(function* () {
1095
1201
  const config = yield* PluginConfig;
1096
- const filePath = join6(config.dataDir, "projects", nativeId, `${sessionId}.jsonl`);
1202
+ const filePath = join7(config.dataDir, "projects", nativeId, `${sessionId}.jsonl`);
1097
1203
  const { rawLines, parseErrors } = yield* readJsonlLines(filePath);
1098
1204
  const subAgentMap = extractSubAgentMap(rawLines);
1099
1205
  const slug = extractSlug(rawLines);
@@ -1122,10 +1228,10 @@ function loadClaudeSession(nativeId, sessionId) {
1122
1228
  });
1123
1229
  }
1124
1230
  function parseSubAgentSession(sessionId, encodedPath, agentId) {
1125
- return Effect11.gen(function* () {
1231
+ return Effect12.gen(function* () {
1126
1232
  const config = yield* PluginConfig;
1127
- const filePath = join6(config.dataDir, "projects", encodedPath, sessionId, "subagents", `agent-${agentId}.jsonl`);
1128
- const parsed = yield* readJsonlLines(filePath).pipe(Effect11.catchAll(() => Effect11.succeed({ rawLines: [], parseErrors: [] })));
1233
+ const filePath = join7(config.dataDir, "projects", encodedPath, sessionId, "subagents", `agent-${agentId}.jsonl`);
1234
+ const parsed = yield* readJsonlLines(filePath).pipe(Effect12.catchAll(() => Effect12.succeed({ rawLines: [], parseErrors: [] })));
1129
1235
  const subAgentMap = extractSubAgentMap(parsed.rawLines);
1130
1236
  const turns = buildTurns(parsed.rawLines, parsed.parseErrors);
1131
1237
  for (const turn of turns) {
@@ -1203,7 +1309,7 @@ function findImplSessionId(slug, sessions, currentSessionId) {
1203
1309
  return match?.sessionId;
1204
1310
  }
1205
1311
  function readJsonlLines(filePath) {
1206
- return Effect11.gen(function* () {
1312
+ return Effect12.gen(function* () {
1207
1313
  const text = yield* readFileText(filePath);
1208
1314
  const rawLines = [];
1209
1315
  const parseErrors = [];
@@ -1349,7 +1455,7 @@ function buildToolCall2(block, toolResults) {
1349
1455
  return toolCall;
1350
1456
  }
1351
1457
  function processContentBlock(block, current, toolResults) {
1352
- if (block.type === "thinking" && "thinking" in block) {
1458
+ if (block.type === "thinking" && "thinking" in block && block.thinking.trim()) {
1353
1459
  current.contentBlocks.push({ type: "thinking", block: { text: block.thinking } });
1354
1460
  } else if (block.type === "text" && "text" in block && block.text.trim()) {
1355
1461
  current.contentBlocks.push({ type: "text", text: block.text });
@@ -1484,27 +1590,27 @@ function extractToolResult(tr) {
1484
1590
  }
1485
1591
 
1486
1592
  // ../../packages/plugin-claude-code/src/config.ts
1487
- import { join as join7 } from "node:path";
1488
- var DEFAULT_CLAUDE_CODE_DIR = join7(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".claude");
1593
+ import { join as join8 } from "node:path";
1594
+ var DEFAULT_CLAUDE_CODE_DIR = join8(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".claude");
1489
1595
  // ../../packages/plugin-claude-code/src/index.ts
1490
1596
  var claudeCodePlugin = {
1491
1597
  id: "claude-code",
1492
1598
  displayName: "Claude Code",
1493
1599
  getDefaultDataDir: () => null,
1494
- isDataAvailable: Effect12.gen(function* () {
1600
+ isDataAvailable: Effect13.gen(function* () {
1495
1601
  const config = yield* PluginConfig;
1496
- return yield* fileExists(config.dataDir).pipe(Effect12.catchAll(() => Effect12.succeed(false)));
1602
+ return yield* fileExists(config.dataDir).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
1497
1603
  }),
1498
1604
  discoverProjects: discoverClaudeProjects(),
1499
1605
  listSessions: (nativeId) => listClaudeSessions(nativeId),
1500
- loadSession: (nativeId, sessionId) => loadClaudeSession(nativeId, sessionId).pipe(Effect12.map((r) => r.session), Effect12.catchAll((err) => Effect12.fail(new PluginError({
1606
+ loadSession: (nativeId, sessionId) => loadClaudeSession(nativeId, sessionId).pipe(Effect13.map((r) => r.session), Effect13.catchAll((err) => Effect13.fail(new PluginError({
1501
1607
  pluginId: "claude-code",
1502
1608
  operation: "loadSession",
1503
1609
  message: String(err),
1504
1610
  cause: err
1505
1611
  })))),
1506
- loadSessionDetail: (nativeId, sessionId) => Effect12.gen(function* () {
1507
- const [{ session, slug }, sessions] = yield* Effect12.all([
1612
+ loadSessionDetail: (nativeId, sessionId) => Effect13.gen(function* () {
1613
+ const [{ session, slug }, sessions] = yield* Effect13.all([
1508
1614
  loadClaudeSession(nativeId, sessionId),
1509
1615
  listClaudeSessions(nativeId)
1510
1616
  ]);
@@ -1513,7 +1619,7 @@ var claudeCodePlugin = {
1513
1619
  planSessionId: findPlanSessionId(session.turns, slug, sessions, sessionId),
1514
1620
  implSessionId: findImplSessionId(slug, sessions, sessionId)
1515
1621
  };
1516
- }).pipe(Effect12.catchAll((err) => Effect12.fail(new PluginError({
1622
+ }).pipe(Effect13.catchAll((err) => Effect13.fail(new PluginError({
1517
1623
  pluginId: "claude-code",
1518
1624
  operation: "loadSessionDetail",
1519
1625
  message: String(err),
@@ -1525,38 +1631,38 @@ var claudeCodePlugin = {
1525
1631
 
1526
1632
  // ../../packages/plugin-codex/src/index.ts
1527
1633
  init_src();
1528
- import { Effect as Effect17 } from "effect";
1634
+ import { Effect as Effect18 } from "effect";
1529
1635
 
1530
1636
  // ../../packages/plugin-codex/src/discovery.ts
1531
1637
  init_src();
1532
- import { Effect as Effect15 } from "effect";
1638
+ import { Effect as Effect16 } from "effect";
1533
1639
 
1534
1640
  // ../../packages/plugin-codex/src/session-index.ts
1535
1641
  init_src();
1536
- import { join as join8 } from "node:path";
1537
- import { FileSystem as FileSystem5 } from "@effect/platform";
1538
- import { Effect as Effect14 } from "effect";
1642
+ import { join as join9 } from "node:path";
1643
+ import { FileSystem as FileSystem6 } from "@effect/platform";
1644
+ import { Effect as Effect15 } from "effect";
1539
1645
 
1540
1646
  // ../../packages/plugin-codex/src/shared/discovery-utils.ts
1541
- import { FileSystem as FileSystem4 } from "@effect/platform";
1542
- import { Effect as Effect13 } from "effect";
1647
+ import { FileSystem as FileSystem5 } from "@effect/platform";
1648
+ import { Effect as Effect14 } from "effect";
1543
1649
  function readTextPrefix2(filePath, maxBytes) {
1544
- return Effect13.gen(function* () {
1545
- const fs = yield* FileSystem4.FileSystem;
1650
+ return Effect14.gen(function* () {
1651
+ const fs = yield* FileSystem5.FileSystem;
1546
1652
  const bytes = yield* fs.readFile(filePath);
1547
1653
  const slice = bytes.subarray(0, maxBytes);
1548
1654
  return new TextDecoder().decode(slice);
1549
1655
  });
1550
1656
  }
1551
1657
  function readFileText2(filePath) {
1552
- return Effect13.gen(function* () {
1553
- const fs = yield* FileSystem4.FileSystem;
1658
+ return Effect14.gen(function* () {
1659
+ const fs = yield* FileSystem5.FileSystem;
1554
1660
  return yield* fs.readFileString(filePath);
1555
1661
  });
1556
1662
  }
1557
1663
  function fileExists2(filePath) {
1558
- return Effect13.gen(function* () {
1559
- const fs = yield* FileSystem4.FileSystem;
1664
+ return Effect14.gen(function* () {
1665
+ const fs = yield* FileSystem5.FileSystem;
1560
1666
  return yield* fs.exists(filePath);
1561
1667
  });
1562
1668
  }
@@ -1637,8 +1743,8 @@ function inferModelFromPrefix(prefixText) {
1637
1743
  return model;
1638
1744
  }
1639
1745
  function parseSessionMeta(filePath, fileMtimeEpoch) {
1640
- return Effect14.gen(function* () {
1641
- const prefix = yield* readTextPrefix2(filePath, FIRST_LINE_SCAN_BYTES).pipe(Effect14.catchAll(() => Effect14.succeed("")));
1746
+ return Effect15.gen(function* () {
1747
+ const prefix = yield* readTextPrefix2(filePath, FIRST_LINE_SCAN_BYTES).pipe(Effect15.catchAll(() => Effect15.succeed("")));
1642
1748
  if (!prefix)
1643
1749
  return null;
1644
1750
  const firstNewline = prefix.indexOf(`
@@ -1665,12 +1771,12 @@ function parseSessionMeta(filePath, fileMtimeEpoch) {
1665
1771
  });
1666
1772
  }
1667
1773
  function walkJsonlFiles(dir, visit) {
1668
- return Effect14.gen(function* () {
1669
- const fs = yield* FileSystem5.FileSystem;
1670
- const names = yield* fs.readDirectory(dir).pipe(Effect14.catchAll(() => Effect14.succeed([])));
1774
+ return Effect15.gen(function* () {
1775
+ const fs = yield* FileSystem6.FileSystem;
1776
+ const names = yield* fs.readDirectory(dir).pipe(Effect15.catchAll(() => Effect15.succeed([])));
1671
1777
  for (const name of names) {
1672
- const fullPath = join8(dir, name);
1673
- const info = yield* fs.stat(fullPath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1778
+ const fullPath = join9(dir, name);
1779
+ const info = yield* fs.stat(fullPath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1674
1780
  if (!info)
1675
1781
  continue;
1676
1782
  if (info.type === "Directory") {
@@ -1684,13 +1790,13 @@ function walkJsonlFiles(dir, visit) {
1684
1790
  });
1685
1791
  }
1686
1792
  function scanCodexSessions() {
1687
- return Effect14.gen(function* () {
1793
+ return Effect15.gen(function* () {
1688
1794
  const config = yield* PluginConfig;
1689
- const fs = yield* FileSystem5.FileSystem;
1690
- const sessionsDir = join8(config.dataDir, "sessions");
1795
+ const fs = yield* FileSystem6.FileSystem;
1796
+ const sessionsDir = join9(config.dataDir, "sessions");
1691
1797
  const sessions = [];
1692
- yield* walkJsonlFiles(sessionsDir, (filePath, _fileName) => Effect14.gen(function* () {
1693
- const info = yield* fs.stat(filePath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1798
+ yield* walkJsonlFiles(sessionsDir, (filePath, _fileName) => Effect15.gen(function* () {
1799
+ const info = yield* fs.stat(filePath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1694
1800
  const fileMtimeEpoch = info?.mtime._tag === "Some" ? info.mtime.value.getTime() / 1000 : undefined;
1695
1801
  const meta = yield* parseSessionMeta(filePath, fileMtimeEpoch);
1696
1802
  if (!meta)
@@ -1707,12 +1813,12 @@ function scanCodexSessions() {
1707
1813
  });
1708
1814
  }
1709
1815
  function walkForFile(dir, match) {
1710
- return Effect14.gen(function* () {
1711
- const fs = yield* FileSystem5.FileSystem;
1712
- const names = yield* fs.readDirectory(dir).pipe(Effect14.catchAll(() => Effect14.succeed([])));
1816
+ return Effect15.gen(function* () {
1817
+ const fs = yield* FileSystem6.FileSystem;
1818
+ const names = yield* fs.readDirectory(dir).pipe(Effect15.catchAll(() => Effect15.succeed([])));
1713
1819
  for (const name of names) {
1714
- const fullPath = join8(dir, name);
1715
- const info = yield* fs.stat(fullPath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1820
+ const fullPath = join9(dir, name);
1821
+ const info = yield* fs.stat(fullPath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1716
1822
  if (!info)
1717
1823
  continue;
1718
1824
  if (info.type !== "Directory" && match(name))
@@ -1727,16 +1833,16 @@ function walkForFile(dir, match) {
1727
1833
  });
1728
1834
  }
1729
1835
  function findCodexSessionFileById(sessionId) {
1730
- return Effect14.gen(function* () {
1836
+ return Effect15.gen(function* () {
1731
1837
  const config = yield* PluginConfig;
1732
- const fs = yield* FileSystem5.FileSystem;
1733
- const sessionsDir = join8(config.dataDir, "sessions");
1838
+ const fs = yield* FileSystem6.FileSystem;
1839
+ const sessionsDir = join9(config.dataDir, "sessions");
1734
1840
  const exactName = `${sessionId}.jsonl`;
1735
1841
  const suffix = `-${sessionId}.jsonl`;
1736
1842
  const filePath = yield* walkForFile(sessionsDir, (name) => name === exactName || name.endsWith(suffix));
1737
1843
  if (!filePath)
1738
1844
  return null;
1739
- const info = yield* fs.stat(filePath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1845
+ const info = yield* fs.stat(filePath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1740
1846
  return info?.type === "File" ? filePath : null;
1741
1847
  });
1742
1848
  }
@@ -1744,7 +1850,7 @@ function findCodexSessionFileById(sessionId) {
1744
1850
  // ../../packages/plugin-codex/src/discovery.ts
1745
1851
  var SESSION_TITLE_SCAN_BYTES = 256 * 1024;
1746
1852
  function discoverCodexProjects() {
1747
- return Effect15.gen(function* () {
1853
+ return Effect16.gen(function* () {
1748
1854
  const sessions = yield* scanCodexSessions();
1749
1855
  const byCwd = new Map;
1750
1856
  for (const session of sessions) {
@@ -1795,17 +1901,17 @@ function extractFirstUserMessage(text) {
1795
1901
  return message;
1796
1902
  }
1797
1903
  function listCodexSessions(nativeId) {
1798
- return Effect15.gen(function* () {
1904
+ return Effect16.gen(function* () {
1799
1905
  const allSessions = yield* scanCodexSessions();
1800
1906
  const matching = allSessions.filter((s) => s.meta.cwd === nativeId);
1801
1907
  const sessions = [];
1802
1908
  for (const s of matching) {
1803
1909
  let firstMessage = s.meta.name || "";
1804
1910
  if (!firstMessage) {
1805
- const prefix = yield* readTextPrefix2(s.filePath, SESSION_TITLE_SCAN_BYTES).pipe(Effect15.catchAll(() => Effect15.succeed("")));
1911
+ const prefix = yield* readTextPrefix2(s.filePath, SESSION_TITLE_SCAN_BYTES).pipe(Effect16.catchAll(() => Effect16.succeed("")));
1806
1912
  firstMessage = extractFirstUserMessage(prefix) || "";
1807
1913
  if (!firstMessage) {
1808
- const fullText = yield* readFileText2(s.filePath).pipe(Effect15.catchAll(() => Effect15.succeed("")));
1914
+ const fullText = yield* readFileText2(s.filePath).pipe(Effect16.catchAll(() => Effect16.succeed("")));
1809
1915
  firstMessage = extractFirstUserMessage(fullText) || "";
1810
1916
  }
1811
1917
  firstMessage ||= "Codex session";
@@ -1828,7 +1934,7 @@ function listCodexSessions(nativeId) {
1828
1934
 
1829
1935
  // ../../packages/plugin-codex/src/parser.ts
1830
1936
  init_src();
1831
- import { Effect as Effect16 } from "effect";
1937
+ import { Effect as Effect17 } from "effect";
1832
1938
  function isKnownModel2(model) {
1833
1939
  return typeof model === "string" && model.length > 0 && model !== "unknown";
1834
1940
  }
@@ -2139,7 +2245,7 @@ function buildCodexTurns(events, model, timestamp) {
2139
2245
  return state.turns;
2140
2246
  }
2141
2247
  function loadCodexSession(_nativeId, sessionId) {
2142
- return Effect16.gen(function* () {
2248
+ return Effect17.gen(function* () {
2143
2249
  const filePath = yield* findCodexSessionFileById(sessionId);
2144
2250
  if (!filePath) {
2145
2251
  return {
@@ -2186,20 +2292,20 @@ function loadCodexSession(_nativeId, sessionId) {
2186
2292
  }
2187
2293
 
2188
2294
  // ../../packages/plugin-codex/src/config.ts
2189
- import { join as join9 } from "node:path";
2190
- var DEFAULT_CODEX_CLI_DIR = join9(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".codex");
2295
+ import { join as join10 } from "node:path";
2296
+ var DEFAULT_CODEX_CLI_DIR = join10(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".codex");
2191
2297
  // ../../packages/plugin-codex/src/index.ts
2192
2298
  var codexCliPlugin = {
2193
2299
  id: "codex-cli",
2194
2300
  displayName: "Codex",
2195
2301
  getDefaultDataDir: () => null,
2196
- isDataAvailable: Effect17.gen(function* () {
2302
+ isDataAvailable: Effect18.gen(function* () {
2197
2303
  const config = yield* PluginConfig;
2198
- return yield* fileExists2(config.dataDir).pipe(Effect17.catchAll(() => Effect17.succeed(false)));
2304
+ return yield* fileExists2(config.dataDir).pipe(Effect18.catchAll(() => Effect18.succeed(false)));
2199
2305
  }),
2200
2306
  discoverProjects: discoverCodexProjects(),
2201
2307
  listSessions: (nativeId) => listCodexSessions(nativeId),
2202
- loadSession: (nativeId, sessionId) => loadCodexSession(nativeId, sessionId).pipe(Effect17.catchAll((err) => Effect17.fail(new PluginError({
2308
+ loadSession: (nativeId, sessionId) => loadCodexSession(nativeId, sessionId).pipe(Effect18.catchAll((err) => Effect18.fail(new PluginError({
2203
2309
  pluginId: "codex-cli",
2204
2310
  operation: "loadSession",
2205
2311
  message: String(err),
@@ -2229,7 +2335,7 @@ var BUILTIN_PLUGIN_ID_SET = new Set(BUILTIN_PLUGIN_DESCRIPTORS.map((descriptor)
2229
2335
  // ../../packages/server/src/services/settings.ts
2230
2336
  init_src();
2231
2337
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
2232
- import { dirname, join as join10 } from "node:path";
2338
+ import { dirname, join as join11 } from "node:path";
2233
2339
  function createDefaultPluginStates() {
2234
2340
  return Object.fromEntries(BUILTIN_KLOVI_PLUGIN_IDS.map((pluginId) => [pluginId, { enabled: true, dataDir: null }]));
2235
2341
  }
@@ -2262,7 +2368,7 @@ async function loadSettings(path) {
2262
2368
  async function saveSettings(path, settings) {
2263
2369
  const dir = dirname(path);
2264
2370
  await mkdir(dir, { recursive: true });
2265
- const tmpPath = join10(dir, `.settings-${Date.now()}.tmp`);
2371
+ const tmpPath = join11(dir, `.settings-${Date.now()}.tmp`);
2266
2372
  await writeFile(tmpPath, JSON.stringify(settings, null, 2));
2267
2373
  await rename(tmpPath, path);
2268
2374
  }
@@ -2598,12 +2704,12 @@ async function createRegistry(settings) {
2598
2704
  // ../../packages/server/src/effect/server-services.ts
2599
2705
  class KloviServices extends Context4.Tag("@klovi/KloviServices")() {
2600
2706
  }
2601
- var KloviServicesLive = Layer6.effect(KloviServices, Effect18.gen(function* () {
2707
+ var KloviServicesLive = Layer6.effect(KloviServices, Effect19.gen(function* () {
2602
2708
  const config = yield* ServerConfig;
2603
2709
  const { settingsPath } = config;
2604
2710
  const version = config.version === "0.0.0" ? "dev" : config.version;
2605
- const settings = yield* Effect18.promise(() => loadSettings(settingsPath));
2606
- let registry = yield* Effect18.promise(() => createRegistry(settings));
2711
+ const settings = yield* Effect19.promise(() => loadSettings(settingsPath));
2712
+ let registry = yield* Effect19.promise(() => createRegistry(settings));
2607
2713
  async function refreshRegistry() {
2608
2714
  const freshSettings = await loadSettings(settingsPath);
2609
2715
  registry = await createRegistry(freshSettings);
@@ -2641,7 +2747,7 @@ var KloviServicesLive = Layer6.effect(KloviServices, Effect18.gen(function* () {
2641
2747
  // ../../packages/server/src/effect/bootstrap.ts
2642
2748
  function getDefaultSettingsPath() {
2643
2749
  const home = process.env["HOME"] ?? process.env["USERPROFILE"] ?? "";
2644
- return join11(home, ".klovi", "settings.json");
2750
+ return join12(home, ".klovi", "settings.json");
2645
2751
  }
2646
2752
  function detectRuntime(requested = "auto") {
2647
2753
  if (requested !== "auto")
@@ -2677,26 +2783,26 @@ async function bootstrapServer(options, makeServe) {
2677
2783
  resolveAddress = resolve;
2678
2784
  rejectAddress = reject;
2679
2785
  });
2680
- const addressCapture = Layer8.effectDiscard(HttpServer.addressWith((address) => Effect19.sync(() => {
2786
+ const addressCapture = Layer8.effectDiscard(HttpServer.addressWith((address) => Effect20.sync(() => {
2681
2787
  const addr = address;
2682
2788
  resolveAddress(`http://${addr.hostname}:${addr.port}`);
2683
2789
  })));
2684
2790
  const serveLayer = makeServe();
2685
2791
  const fullLayer = Layer8.merge(serveLayer, addressCapture).pipe(Layer8.provide(servicesLayer), Layer8.provide(configLayer), Layer8.provide(platformLayer));
2686
- const fiber = Effect19.runFork(Layer8.launch(fullLayer));
2687
- Effect19.runFork(Fiber.join(fiber).pipe(Effect19.catchAllCause((cause) => Effect19.sync(() => rejectAddress(Cause.squash(cause))))));
2792
+ const fiber = Effect20.runFork(Layer8.launch(fullLayer));
2793
+ Effect20.runFork(Fiber.join(fiber).pipe(Effect20.catchAllCause((cause) => Effect20.sync(() => rejectAddress(Cause.squash(cause))))));
2688
2794
  const url = await addressPromise;
2689
2795
  return {
2690
2796
  url,
2691
2797
  stop() {
2692
- Effect19.runFork(Fiber.interrupt(fiber));
2798
+ Effect20.runFork(Fiber.interrupt(fiber));
2693
2799
  }
2694
2800
  };
2695
2801
  }
2696
2802
 
2697
2803
  // ../../packages/server/src/effect/http-app.ts
2698
2804
  import { HttpRouter, HttpServer as HttpServer2, HttpServerRequest, HttpServerResponse } from "@effect/platform";
2699
- import { Effect as Effect20 } from "effect";
2805
+ import { Effect as Effect21 } from "effect";
2700
2806
 
2701
2807
  // ../../packages/server/src/rpc-error.ts
2702
2808
  class RPCError extends Error {
@@ -2712,7 +2818,7 @@ var NON_RPC_KEYS = new Set(["getRegistry", "settingsPath"]);
2712
2818
  function isRPCMethod(method, services) {
2713
2819
  return Object.hasOwn(services, method) && !NON_RPC_KEYS.has(method);
2714
2820
  }
2715
- var rpcHandler = Effect20.gen(function* () {
2821
+ var rpcHandler = Effect21.gen(function* () {
2716
2822
  const services = yield* KloviServices;
2717
2823
  const routeParams = yield* HttpRouter.params;
2718
2824
  const req = yield* HttpServerRequest.HttpServerRequest;
@@ -2721,7 +2827,7 @@ var rpcHandler = Effect20.gen(function* () {
2721
2827
  return HttpServerResponse.unsafeJson({ error: "Method name required" }, { status: 400 });
2722
2828
  }
2723
2829
  if (!isRPCMethod(method, services)) {
2724
- return yield* Effect20.fail(new RPCError(404, `Unknown method: ${method}`));
2830
+ return yield* Effect21.fail(new RPCError(404, `Unknown method: ${method}`));
2725
2831
  }
2726
2832
  let params = {};
2727
2833
  const bodyText = yield* req.text;
@@ -2733,44 +2839,44 @@ var rpcHandler = Effect20.gen(function* () {
2733
2839
  }
2734
2840
  }
2735
2841
  const handler = services[method];
2736
- return yield* Effect20.tryPromise({
2842
+ return yield* Effect21.tryPromise({
2737
2843
  try: async () => {
2738
2844
  const result = await Promise.resolve(handler(params));
2739
2845
  return HttpServerResponse.unsafeJson(result);
2740
2846
  },
2741
2847
  catch: (err) => err
2742
2848
  });
2743
- }).pipe(Effect20.catchAll((err) => {
2849
+ }).pipe(Effect21.catchAll((err) => {
2744
2850
  if (err instanceof RPCError) {
2745
- return Effect20.succeed(HttpServerResponse.unsafeJson({ error: err.message }, { status: err.status }));
2851
+ return Effect21.succeed(HttpServerResponse.unsafeJson({ error: err.message }, { status: err.status }));
2746
2852
  }
2747
2853
  const message = err instanceof Error ? err.message : "Internal server error";
2748
- return Effect20.succeed(HttpServerResponse.unsafeJson({ error: message }, { status: 500 }));
2854
+ return Effect21.succeed(HttpServerResponse.unsafeJson({ error: message }, { status: 500 }));
2749
2855
  }));
2750
- var emptyMethodHandler = Effect20.succeed(HttpServerResponse.unsafeJson({ error: "Method name required" }, { status: 400 }));
2856
+ var emptyMethodHandler = Effect21.succeed(HttpServerResponse.unsafeJson({ error: "Method name required" }, { status: 400 }));
2751
2857
  var makeRpcRouter = () => HttpRouter.empty.pipe(HttpRouter.post("/api/rpc/", emptyMethodHandler), HttpRouter.post("/api/rpc/:method", rpcHandler));
2752
- var notFoundHandler = Effect20.succeed(HttpServerResponse.unsafeJson({ error: "Not found" }, { status: 404 }));
2753
- var makeHttpApp = () => makeRpcRouter().pipe(Effect20.catchTag("RouteNotFound", () => notFoundHandler));
2858
+ var notFoundHandler = Effect21.succeed(HttpServerResponse.unsafeJson({ error: "Not found" }, { status: 404 }));
2859
+ var makeHttpApp = () => makeRpcRouter().pipe(Effect21.catchTag("RouteNotFound", () => notFoundHandler));
2754
2860
  var makeServeLayer = () => makeHttpApp().pipe(HttpServer2.serve());
2755
2861
 
2756
2862
  // src/http-app.ts
2757
2863
  import { HttpServer as HttpServer3 } from "@effect/platform";
2758
- import { Effect as Effect22 } from "effect";
2864
+ import { Effect as Effect23 } from "effect";
2759
2865
 
2760
2866
  // src/static-handler.ts
2761
2867
  import { HttpServerRequest as HttpServerRequest2, HttpServerResponse as HttpServerResponse2 } from "@effect/platform";
2762
- import { Effect as Effect21 } from "effect";
2763
- var makeStaticHandler = (staticDir) => Effect21.gen(function* () {
2868
+ import { Effect as Effect22 } from "effect";
2869
+ var makeStaticHandler = (staticDir) => Effect22.gen(function* () {
2764
2870
  const req = yield* HttpServerRequest2.HttpServerRequest;
2765
2871
  const url = new URL(req.url, "http://localhost");
2766
2872
  const filePath = url.pathname === "/" ? "/index.html" : url.pathname;
2767
- return yield* HttpServerResponse2.file(`${staticDir}${filePath}`).pipe(Effect21.orElse(() => HttpServerResponse2.file(`${staticDir}/index.html`)), Effect21.orElse(() => Effect21.succeed(HttpServerResponse2.unsafeJson({ error: "Not found" }, { status: 404 }))));
2873
+ return yield* HttpServerResponse2.file(`${staticDir}${filePath}`).pipe(Effect22.orElse(() => HttpServerResponse2.file(`${staticDir}/index.html`)), Effect22.orElse(() => Effect22.succeed(HttpServerResponse2.unsafeJson({ error: "Not found" }, { status: 404 }))));
2768
2874
  });
2769
2875
 
2770
2876
  // src/http-app.ts
2771
2877
  var makePackageHttpApp = (staticDir) => {
2772
2878
  const router = makeRpcRouter();
2773
- return router.pipe(Effect22.catchTag("RouteNotFound", () => makeStaticHandler(staticDir)));
2879
+ return router.pipe(Effect23.catchTag("RouteNotFound", () => makeStaticHandler(staticDir)));
2774
2880
  };
2775
2881
  var makePackageServeLayer = (staticDir) => {
2776
2882
  if (!staticDir) {