lalph 0.3.72 → 0.3.74

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.mjs CHANGED
@@ -181199,7 +181199,7 @@ var ji = Bt, Ii = Object.assign(Qe, { sync: Bt }), zi = Ut, Bi = Object.assign(e
181199
181199
  });
181200
181200
  Ze.glob = Ze;
181201
181201
  //#endregion
181202
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/ApplyPatch.js
181202
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/ApplyPatch.js
181203
181203
  /**
181204
181204
  * @since 1.0.0
181205
181205
  */
@@ -196072,7 +196072,7 @@ var StreamableHTTPClientTransport = class {
196072
196072
  }
196073
196073
  };
196074
196074
  //#endregion
196075
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/McpClient.js
196075
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/McpClient.js
196076
196076
  /**
196077
196077
  * @since 1.0.0
196078
196078
  */
@@ -196117,7 +196117,7 @@ const layer$13 = effect$1(McpClient, gen(function* () {
196117
196117
  });
196118
196118
  }));
196119
196119
  //#endregion
196120
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/ExaSearch.js
196120
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/ExaSearch.js
196121
196121
  /**
196122
196122
  * @since 1.0.0
196123
196123
  */
@@ -211067,7 +211067,7 @@ var require_lib = /* @__PURE__ */ __commonJSMin$1(((exports) => {
211067
211067
  exports.impl = impl;
211068
211068
  }));
211069
211069
  //#endregion
211070
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/WebToMarkdown.js
211070
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/WebToMarkdown.js
211071
211071
  /**
211072
211072
  * @since 1.0.0
211073
211073
  */
@@ -214684,7 +214684,7 @@ const mapProviderResults = (inputLength, results) => {
214684
214684
  return succeed$3(embeddings);
214685
214685
  };
214686
214686
  //#endregion
214687
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/ChunkRepo.js
214687
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/ChunkRepo.js
214688
214688
  /**
214689
214689
  * @since 1.0.0
214690
214690
  * @category Models
@@ -214807,11 +214807,12 @@ const layer$10 = effect$1(ChunkRepo, gen(function* () {
214807
214807
  }),
214808
214808
  quantize: maybeQuantize,
214809
214809
  setSyncId: (chunkId, syncId) => sql`update chunks set syncId = ${syncId} where id = ${chunkId}`.pipe(mapError$2((reason) => new ChunkRepoError({ reason }))),
214810
+ deleteByPath: (path) => sql`delete from chunks where path = ${path}`.pipe(mapError$2((reason) => new ChunkRepoError({ reason }))),
214810
214811
  deleteForSyncId: (syncId) => sql`delete from chunks where syncId != ${syncId}`.pipe(mapError$2((reason) => new ChunkRepoError({ reason })))
214811
214812
  });
214812
214813
  }));
214813
214814
  //#endregion
214814
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/CodeChunker.js
214815
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/CodeChunker.js
214815
214816
  /**
214816
214817
  * @since 1.0.0
214817
214818
  */
@@ -214908,7 +214909,7 @@ const ignoredDirectories = new Set([
214908
214909
  "node_modules",
214909
214910
  "target"
214910
214911
  ]);
214911
- const normalizePath = (path) => path.replace(/\\/g, "/");
214912
+ const normalizePath$1 = (path) => path.replace(/\\/g, "/");
214912
214913
  const normalizeText = (content) => content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
214913
214914
  const hashContent = (content) => createHash("sha256").update(content).digest("hex");
214914
214915
  const meaningfulLinePattern = /[^\s\p{P}]/u;
@@ -214931,7 +214932,7 @@ const isProbablyMinified = (content) => {
214931
214932
  * @category Predicates
214932
214933
  */
214933
214934
  const isMeaningfulFile = (path) => {
214934
- const parts = normalizePath(path).toLowerCase().split("/");
214935
+ const parts = normalizePath$1(path).toLowerCase().split("/");
214935
214936
  const fileName = parts.at(-1);
214936
214937
  if (fileName === void 0 || fileName.length === 0) return false;
214937
214938
  if (parts.some((part) => ignoredDirectories.has(part))) return false;
@@ -214957,7 +214958,7 @@ const resolveChunkSettings = (options) => {
214957
214958
  */
214958
214959
  const chunkFileContent = (path, content, options) => {
214959
214960
  if (content.trim().length === 0 || isProbablyMinified(content)) return [];
214960
- const normalizedPath = normalizePath(path);
214961
+ const normalizedPath = normalizePath$1(path);
214961
214962
  const lines = normalizeText(content).split("\n");
214962
214963
  if (lines.at(-1) === "") lines.pop();
214963
214964
  if (lines.length === 0) return [];
@@ -215005,20 +215006,37 @@ const layer$9 = effect$1(CodeChunker, gen(function* () {
215005
215006
  ], {
215006
215007
  cwd: root,
215007
215008
  stdin: "ignore"
215008
- })), runCollect, map$9(fromIterable$5), map$9((entries) => entries.map((entry) => normalizePath(entry.trim())).filter((entry) => entry.length > 0 && isMeaningfulFile(entry)).sort((left, right) => left.localeCompare(right))), orDie$2);
215009
+ })), runCollect, map$9(fromIterable$5), map$9((entries) => entries.map((entry) => normalizePath$1(entry.trim())).filter((entry) => entry.length > 0 && isMeaningfulFile(entry)).sort((left, right) => left.localeCompare(right))), orDie$2);
215009
215010
  });
215011
+ const chunkFile = fn("CodeChunker.chunkFile")(function* (options) {
215012
+ const root = pathService.resolve(options.root);
215013
+ const absolutePath = pathService.resolve(root, options.path);
215014
+ const path = normalizePath$1(pathService.relative(root, absolutePath));
215015
+ if (path.length === 0 || path === ".." || path.startsWith("../") || !isMeaningfulFile(path)) return [];
215016
+ return yield* pipe$1(fs.readFileString(absolutePath), map$9((content) => chunkFileContent(path, content, options)), catch_$2(() => succeed$3([])));
215017
+ });
215018
+ const chunkFiles = (options) => fromArray(options.paths).pipe(flatMap$2((path) => pipe$1(chunkFile({
215019
+ root: options.root,
215020
+ path,
215021
+ chunkSize: options.chunkSize,
215022
+ chunkOverlap: options.chunkOverlap
215023
+ }), fromArrayEffect), { concurrency: 5 }));
215010
215024
  const chunkCodebase = fnUntraced(function* (options) {
215011
215025
  const root = pathService.resolve(options.root);
215012
- return fromArray(yield* listFiles({
215026
+ return chunkFiles({
215013
215027
  root,
215014
- ...options.maxFileSize === void 0 ? {} : { maxFileSize: options.maxFileSize }
215015
- })).pipe(flatMap$2((path) => {
215016
- const absolutePath = pathService.resolve(root, path);
215017
- return pipe$1(fs.readFileString(absolutePath), map$9((content) => chunkFileContent(path, content, options)), catch_$2(() => succeed$3([])), fromArrayEffect);
215018
- }, { concurrency: 5 }));
215028
+ paths: yield* listFiles({
215029
+ root,
215030
+ ...options.maxFileSize === void 0 ? {} : { maxFileSize: options.maxFileSize }
215031
+ }),
215032
+ chunkSize: options.chunkSize,
215033
+ chunkOverlap: options.chunkOverlap
215034
+ });
215019
215035
  }, unwrap);
215020
215036
  return CodeChunker.of({
215021
215037
  listFiles,
215038
+ chunkFile,
215039
+ chunkFiles,
215022
215040
  chunkCodebase
215023
215041
  });
215024
215042
  }));
@@ -215172,7 +215190,7 @@ const run$1 = /* @__PURE__ */ make$25({});
215172
215190
  */
215173
215191
  const layer$7 = (options) => effectDiscard(run$1(options));
215174
215192
  //#endregion
215175
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/internal/sqlite-vector.js
215193
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/internal/sqlite-vector.js
215176
215194
  /**
215177
215195
  * Binary extension for each platform
215178
215196
  */
@@ -215289,7 +215307,7 @@ function getExtensionPath() {
215289
215307
  throw new ExtensionNotFoundError(`SQLite Vector extension not found for platform: ${getCurrentPlatform()}\n\nThe platform-specific package "${getPlatformPackageName()}" is not installed.\nThis usually happens when:\n 1. Your platform is not supported\n 2. npm failed to install optional dependencies\n 3. You're installing with --no-optional flag\n\nTry running: npm install --force`);
215290
215308
  }
215291
215309
  //#endregion
215292
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/Sqlite.js
215310
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/Sqlite.js
215293
215311
  /**
215294
215312
  * @since 1.0.0
215295
215313
  */
@@ -215319,10 +215337,15 @@ const SqliteLayer = (database) => layer$7({ loader: fromRecord({ "0001_create_ch
215319
215337
  yield* fs.makeDirectory(directory, { recursive: true });
215320
215338
  }))));
215321
215339
  //#endregion
215322
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/SemanticSearch.js
215340
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/SemanticSearch.js
215323
215341
  /**
215324
215342
  * @since 1.0.0
215325
215343
  */
215344
+ const normalizePath = (path) => path.replace(/\\/g, "/");
215345
+ const chunkConfig = {
215346
+ chunkSize: 20,
215347
+ chunkOverlap: 5
215348
+ };
215326
215349
  /**
215327
215350
  * @since 1.0.0
215328
215351
  * @category Services
@@ -215336,44 +215359,60 @@ const layer$6 = (options) => effect$1(SemanticSearch, gen(function* () {
215336
215359
  const chunker = yield* CodeChunker;
215337
215360
  const repo = yield* ChunkRepo;
215338
215361
  const embeddings = yield* EmbeddingModel;
215362
+ const pathService = yield* Path$1;
215363
+ const root = pathService.resolve(options.directory);
215339
215364
  const resolver = embeddings.resolver.pipe(setDelay(options.embeddingBatchSize ?? millis(50)), batchN(options.embeddingBatchSize ?? 500));
215365
+ const concurrency = options.concurrency ?? 2e3;
215340
215366
  const indexHandle = yield* make$56();
215341
215367
  const console = yield* Console$1;
215342
- const runIndex = run$4(indexHandle, gen(function* () {
215343
- const syncId = SyncId.makeUnsafe(crypto.randomUUID());
215344
- yield* logInfo("Starting SemanticSearch index");
215345
- yield* pipe$1(chunker.chunkCodebase({
215346
- root: options.directory,
215347
- chunkSize: 20,
215348
- chunkOverlap: 5
215349
- }), tap(fnUntraced(function* (chunk) {
215368
+ const resolveIndexedPath = (path) => {
215369
+ const absolutePath = pathService.resolve(root, path);
215370
+ const relativePath = normalizePath(pathService.relative(root, absolutePath));
215371
+ if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith("../")) return none$4();
215372
+ return some$2(relativePath);
215373
+ };
215374
+ const processChunk = fnUntraced(function* (options) {
215375
+ if (options.checkExisting) {
215350
215376
  const id = yield* repo.exists({
215351
- path: chunk.path,
215352
- startLine: chunk.startLine,
215353
- hash: chunk.contentHash
215377
+ path: options.chunk.path,
215378
+ startLine: options.chunk.startLine,
215379
+ hash: options.chunk.contentHash
215354
215380
  });
215355
215381
  if (isSome(id)) {
215356
- yield* repo.setSyncId(id.value, syncId);
215382
+ yield* repo.setSyncId(id.value, options.syncId);
215357
215383
  return;
215358
215384
  }
215359
- const result = yield* request$2(new EmbeddingRequest({ input: `File: ${chunk.path}
215360
- Lines: ${chunk.startLine}-${chunk.endLine}
215385
+ }
215386
+ const result = yield* request$2(new EmbeddingRequest({ input: `File: ${options.chunk.path}
215387
+ Lines: ${options.chunk.startLine}-${options.chunk.endLine}
215361
215388
 
215362
- ${chunk.content}` }), resolver);
215363
- const vector = new Float32Array(result.vector);
215364
- yield* repo.insert(Chunk.insert.makeUnsafe({
215365
- path: chunk.path,
215366
- startLine: chunk.startLine,
215367
- endLine: chunk.endLine,
215368
- hash: chunk.contentHash,
215369
- content: chunk.content,
215370
- vector,
215371
- syncId
215372
- }));
215373
- }, ignore$1({
215374
- log: "Warn",
215375
- message: "Failed to process chunk for embedding"
215376
- }), (effect, chunk) => annotateLogs(effect, { chunk: `${chunk.path}/${chunk.startLine}` })), { concurrency: options.concurrency ?? 2e3 }), runDrain);
215389
+ ${options.chunk.content}` }), resolver);
215390
+ const vector = new Float32Array(result.vector);
215391
+ yield* repo.insert(Chunk.insert.makeUnsafe({
215392
+ path: options.chunk.path,
215393
+ startLine: options.chunk.startLine,
215394
+ endLine: options.chunk.endLine,
215395
+ hash: options.chunk.contentHash,
215396
+ content: options.chunk.content,
215397
+ vector,
215398
+ syncId: options.syncId
215399
+ }));
215400
+ }, ignore$1({
215401
+ log: "Warn",
215402
+ message: "Failed to process chunk for embedding"
215403
+ }), (effect, options) => annotateLogs(effect, { chunk: `${options.chunk.path}/${options.chunk.startLine}` }));
215404
+ const runIndex = run$4(indexHandle, gen(function* () {
215405
+ const syncId = SyncId.makeUnsafe(crypto.randomUUID());
215406
+ yield* logInfo("Starting SemanticSearch index");
215407
+ yield* pipe$1(chunker.chunkCodebase({
215408
+ root,
215409
+ ...chunkConfig
215410
+ }), tap((chunk) => processChunk({
215411
+ chunk,
215412
+ syncId,
215413
+ checkExisting: true
215414
+ }), { concurrency }), runDrain);
215415
+ yield* repo.deleteForSyncId(syncId);
215377
215416
  yield* logInfo("Finished SemanticSearch index");
215378
215417
  }).pipe(withSpan$1("SemanticSearch.index"), withLogSpan("SemanticSearch.index"), provideService$2(Console$1, console)), { onlyIfMissing: true });
215379
215418
  const initialIndex = yield* runIndex;
@@ -215388,19 +215427,50 @@ ${chunk.content}` }), resolver);
215388
215427
  limit: options.limit
215389
215428
  })).map((r) => r.format()).join("\n\n");
215390
215429
  }, orDie$2),
215391
- reindex: asVoid(runIndex)
215430
+ updateFile: fn("SemanticSearch.updateFile")(function* (path) {
215431
+ yield* join$2(initialIndex);
215432
+ const indexedPath = resolveIndexedPath(path);
215433
+ if (isNone(indexedPath)) return;
215434
+ yield* repo.deleteByPath(indexedPath.value);
215435
+ const chunks = yield* chunker.chunkFile({
215436
+ root,
215437
+ path: indexedPath.value,
215438
+ ...chunkConfig
215439
+ });
215440
+ if (chunks.length === 0) return;
215441
+ const syncId = SyncId.makeUnsafe(crypto.randomUUID());
215442
+ yield* pipe$1(fromArray(chunks), tap((chunk) => processChunk({
215443
+ chunk,
215444
+ syncId,
215445
+ checkExisting: false
215446
+ }), { concurrency }), runDrain);
215447
+ }, orDie$2),
215448
+ removeFile: fn("SemanticSearch.removeFile")(function* (path) {
215449
+ yield* join$2(initialIndex);
215450
+ const indexedPath = resolveIndexedPath(path);
215451
+ if (isNone(indexedPath)) return;
215452
+ yield* repo.deleteByPath(indexedPath.value);
215453
+ }, orDie$2)
215392
215454
  });
215393
215455
  })).pipe(provide$3([layer$9, layer$10.pipe(provide$3(SqliteLayer(options.database ?? ".clanka/search.sqlite")))]));
215394
215456
  /**
215395
215457
  * @since 1.0.0
215396
215458
  * @category Utils
215397
215459
  */
215398
- const maybeReindex = serviceOption(SemanticSearch).pipe(flatMap$4(match$10({
215460
+ const maybeUpdateFile = (path) => serviceOption(SemanticSearch).pipe(flatMap$4(match$10({
215461
+ onNone: () => void_$2,
215462
+ onSome: (service) => service.updateFile(path)
215463
+ })));
215464
+ /**
215465
+ * @since 1.0.0
215466
+ * @category Utils
215467
+ */
215468
+ const maybeRemoveFile = (path) => serviceOption(SemanticSearch).pipe(flatMap$4(match$10({
215399
215469
  onNone: () => void_$2,
215400
- onSome: (service) => service.reindex
215470
+ onSome: (service) => service.removeFile(path)
215401
215471
  })));
215402
215472
  //#endregion
215403
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/AgentTools.js
215473
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/AgentTools.js
215404
215474
  /**
215405
215475
  * @since 1.0.0
215406
215476
  */
@@ -215559,12 +215629,14 @@ const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(gen(function* () {
215559
215629
  const path = pathService.resolve(cwd, options.path);
215560
215630
  yield* fs.makeDirectory(pathService.dirname(path), { recursive: true });
215561
215631
  yield* fs.writeFileString(path, options.content);
215562
- yield* maybeReindex;
215632
+ yield* maybeUpdateFile(pathService.relative(cwd, path));
215563
215633
  }, orDie$2),
215564
215634
  removeFile: fn("AgentTools.removeFile")(function* (path) {
215565
215635
  yield* logInfo(`Calling "removeFile"`).pipe(annotateLogs({ path }));
215566
215636
  const cwd = yield* CurrentDirectory;
215567
- return yield* fs.remove(pathService.resolve(cwd, path), { force: true });
215637
+ const absolutePath = pathService.resolve(cwd, path);
215638
+ yield* fs.remove(absolutePath, { force: true });
215639
+ yield* maybeRemoveFile(pathService.relative(cwd, absolutePath));
215568
215640
  }, orDie$2),
215569
215641
  renameFile: fn("AgentTools.renameFile")(function* (options) {
215570
215642
  yield* logInfo(`Calling "renameFile"`).pipe(annotateLogs(options));
@@ -215572,7 +215644,9 @@ const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(gen(function* () {
215572
215644
  const from = pathService.resolve(cwd, options.from);
215573
215645
  const to = pathService.resolve(cwd, options.to);
215574
215646
  yield* fs.makeDirectory(pathService.dirname(to), { recursive: true });
215575
- return yield* fs.rename(from, to);
215647
+ yield* fs.rename(from, to);
215648
+ yield* maybeRemoveFile(pathService.relative(cwd, from));
215649
+ yield* maybeUpdateFile(pathService.relative(cwd, to));
215576
215650
  }, orDie$2),
215577
215651
  mkdir: fn("AgentTools.mkdir")(function* (path) {
215578
215652
  yield* logInfo(`Calling "mkdir"`).pipe(annotateLogs({ path }));
@@ -215659,7 +215733,7 @@ const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(gen(function* () {
215659
215733
  const state = /* @__PURE__ */ new Map();
215660
215734
  const steps = [];
215661
215735
  const out = [];
215662
- const rel = (path) => pathService.relative(cwd, path).replaceAll("\\", "/");
215736
+ const rel = (path) => pathService.relative(cwd, path);
215663
215737
  const load = fn("AgentTools.applyPatch.load")(function* (path, reason) {
215664
215738
  if (state.has(path)) {
215665
215739
  const input = state.get(path);
@@ -215724,17 +215798,20 @@ const AgentToolHandlersNoDeps = AgentToolsWithSearch.toLayer(gen(function* () {
215724
215798
  case "update":
215725
215799
  yield* fs.makeDirectory(pathService.dirname(step.path), { recursive: true });
215726
215800
  yield* fs.writeFileString(step.path, step.next);
215801
+ yield* maybeUpdateFile(rel(step.path));
215727
215802
  break;
215728
215803
  case "move":
215729
215804
  yield* fs.makeDirectory(pathService.dirname(step.movePath), { recursive: true });
215730
215805
  yield* fs.writeFileString(step.movePath, step.next);
215731
215806
  yield* fs.remove(step.path);
215807
+ yield* maybeRemoveFile(rel(step.path));
215808
+ yield* maybeUpdateFile(rel(step.movePath));
215732
215809
  break;
215733
215810
  case "delete":
215734
215811
  yield* fs.remove(step.path);
215812
+ yield* maybeRemoveFile(rel(step.path));
215735
215813
  break;
215736
215814
  }
215737
- yield* maybeReindex;
215738
215815
  return `Success. Updated the following files:\n${out.join("\n")}`;
215739
215816
  }, orDie$2),
215740
215817
  delegate: fn("AgentTools.delegate")(function* (prompt) {
@@ -215756,7 +215833,7 @@ const AgentToolHandlers = AgentToolHandlersNoDeps.pipe(provide$3([layer$12, laye
215756
215833
  AgentToolHandlersNoDeps.pipe(provide$3([mock(ExaSearch)({}), mock(WebToMarkdown)({})]));
215757
215834
  var ApplyPatchError = class extends TaggedClass$2("ApplyPatchError") {};
215758
215835
  //#endregion
215759
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/TypeBuilder.js
215836
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/TypeBuilder.js
215760
215837
  const resolveDocumentation = resolveAt("documentation");
215761
215838
  const identifierPattern = /^[$A-Z_a-z][$0-9A-Z_a-z]*$/u;
215762
215839
  const Precedence = {
@@ -216029,7 +216106,7 @@ const render = (schema, options) => {
216029
216106
  return printNode({ text: documentation === void 0 ? rendered.text : `${renderJsDoc(documentation, 0, printerOptions)}${printerOptions.newLine}${rendered.text}` }, printerOptions);
216030
216107
  };
216031
216108
  //#endregion
216032
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/ToolkitRenderer.js
216109
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/ToolkitRenderer.js
216033
216110
  /**
216034
216111
  * @since 1.0.0
216035
216112
  */
@@ -216051,7 +216128,7 @@ declare function ${name}(${params}): Promise<${render(tool.successSchema)}>`);
216051
216128
  }) });
216052
216129
  };
216053
216130
  //#endregion
216054
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/AgentExecutor.js
216131
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/AgentExecutor.js
216055
216132
  /**
216056
216133
  * @since 1.0.0
216057
216134
  */
@@ -216220,7 +216297,7 @@ var QueueWriteStream = class extends Writable {
216220
216297
  }
216221
216298
  };
216222
216299
  //#endregion
216223
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/ScriptExtraction.js
216300
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/ScriptExtraction.js
216224
216301
  const stripWrappingCodeFence = (script) => {
216225
216302
  const lines = script.split(/\r?\n/);
216226
216303
  if (lines.length < 2) return script;
@@ -217753,7 +217830,7 @@ const applySpanTransformer = (transformer, response, options) => {
217753
217830
  });
217754
217831
  };
217755
217832
  //#endregion
217756
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/Agent.js
217833
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/Agent.js
217757
217834
  /**
217758
217835
  * @since 1.0.0
217759
217836
  */
@@ -218417,7 +218494,7 @@ var Retry = class Retry extends TaggedClass$2("Retry") {
218417
218494
  }
218418
218495
  };
218419
218496
  //#endregion
218420
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/Generated.js
218497
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/Generated.js
218421
218498
  /**
218422
218499
  * @since 1.0.0
218423
218500
  */ const AdminApiKey = /* @__PURE__ */ Struct$2({
@@ -226485,7 +226562,7 @@ const OpenAiClientError = (tag, cause, response) => new OpenAiClientErrorImpl({
226485
226562
  request: response.request
226486
226563
  });
226487
226564
  //#endregion
226488
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/internal/errors.js
226565
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/internal/errors.js
226489
226566
  /** @internal */
226490
226567
  const OpenAiErrorBody$1 = /* @__PURE__ */ Struct$2({ error: /* @__PURE__ */ Struct$2({
226491
226568
  message: String$1,
@@ -226698,7 +226775,7 @@ const mapStatusCodeToReason$1 = ({ status, headers, message, metadata, http }) =
226698
226775
  }
226699
226776
  };
226700
226777
  //#endregion
226701
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/OpenAiConfig.js
226778
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/OpenAiConfig.js
226702
226779
  /**
226703
226780
  * @since 1.0.0
226704
226781
  */
@@ -226713,7 +226790,7 @@ var OpenAiConfig$1 = class OpenAiConfig$1 extends Service$1()("@effect/ai-openai
226713
226790
  static getOrUndefined = /* @__PURE__ */ map$9(/* @__PURE__ */ services(), (context) => context.mapUnsafe.get(OpenAiConfig$1.key));
226714
226791
  };
226715
226792
  //#endregion
226716
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/OpenAiClient.js
226793
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/OpenAiClient.js
226717
226794
  /**
226718
226795
  * OpenAI Client module for interacting with OpenAI's API.
226719
226796
  *
@@ -226836,17 +226913,30 @@ const makeSocket = /* @__PURE__ */ gen(function* () {
226836
226913
  try {
226837
226914
  const event = decodeEvent(text);
226838
226915
  if (event.type === "error") tracker.clearUnsafe();
226839
- if (event.type === "error" && "status" in event) return fail$4(currentQueue, make$15({
226840
- module: "OpenAiClient",
226841
- method: "createResponseStream",
226842
- reason: reasonFromHttpStatus({
226843
- status: event.status,
226844
- metadata: {
226845
- ...event.error,
226846
- description: event.error.message
226847
- }
226848
- })
226849
- }));
226916
+ if (event.type === "error" && "status" in event) {
226917
+ const json = JSON.stringify(event.error);
226918
+ return fail$4(currentQueue, make$15({
226919
+ module: "OpenAiClient",
226920
+ method: "createResponseStream",
226921
+ reason: reasonFromHttpStatus({
226922
+ status: event.status,
226923
+ metadata: {
226924
+ ...event.error,
226925
+ description: json
226926
+ },
226927
+ http: {
226928
+ body: json,
226929
+ request: {
226930
+ method: "POST",
226931
+ url: request.url,
226932
+ urlParams: [],
226933
+ hash: void 0,
226934
+ headers: request.headers
226935
+ }
226936
+ }
226937
+ })
226938
+ }));
226939
+ }
226850
226940
  offerUnsafe(currentQueue, event);
226851
226941
  } catch {}
226852
226942
  }).pipe(catchCause$1((cause) => {
@@ -226919,7 +227009,7 @@ const decodeEvent = /* @__PURE__ */ decodeUnknownSync(/* @__PURE__ */ fromJsonSt
226919
227009
  */
226920
227010
  const layerWebSocketMode = /* @__PURE__ */ effectServices(makeSocket);
226921
227011
  //#endregion
226922
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/OpenAiEmbeddingModel.js
227012
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/OpenAiEmbeddingModel.js
226923
227013
  /**
226924
227014
  * OpenAI Embedding Model implementation.
226925
227015
  *
@@ -227304,7 +227394,7 @@ const formats = [
227304
227394
  "uuid"
227305
227395
  ];
227306
227396
  //#endregion
227307
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/internal/utilities.js
227397
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/internal/utilities.js
227308
227398
  const finishReasonMap$1 = {
227309
227399
  content_filter: "content-filter",
227310
227400
  function_call: "tool-calls",
@@ -227322,7 +227412,7 @@ const resolveFinishReason$1 = (finishReason, hasToolCalls) => {
227322
227412
  return reason;
227323
227413
  };
227324
227414
  //#endregion
227325
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/OpenAiTelemetry.js
227415
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/OpenAiTelemetry.js
227326
227416
  /**
227327
227417
  * OpenAI telemetry attributes for OpenTelemetry integration.
227328
227418
  *
@@ -227351,7 +227441,7 @@ const addGenAIAnnotations$1 = /* @__PURE__ */ dual(2, (span, options) => {
227351
227441
  }
227352
227442
  });
227353
227443
  //#endregion
227354
- //#region node_modules/.pnpm/@effect+ai-openai@4.0.0-beta.34_effect@4.0.0-beta.34/node_modules/@effect/ai-openai/dist/OpenAiLanguageModel.js
227444
+ //#region node_modules/.pnpm/@effect+ai-openai@https+++pkg.pr.new+Effect-TS+effect-smol+@effect+ai-openai@34082eb_ef_4e07b24e446e85b2c061a82cdecc4c61/node_modules/@effect/ai-openai/dist/OpenAiLanguageModel.js
227355
227445
  /**
227356
227446
  * OpenAI Language Model implementation.
227357
227447
  *
@@ -229066,7 +229156,7 @@ const transformToolCallParams = /* @__PURE__ */ fnUntraced(function* (tools, too
229066
229156
  })));
229067
229157
  });
229068
229158
  //#endregion
229069
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/CodexAuth.js
229159
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/CodexAuth.js
229070
229160
  /**
229071
229161
  * @since 1.0.0
229072
229162
  */
@@ -229286,7 +229376,7 @@ var CodexAuth = class CodexAuth extends Service$1()("clanka/CodexAuth") {
229286
229376
  static layerClient = this.layerClientNoDeps.pipe(provide$3(CodexAuth.layer));
229287
229377
  };
229288
229378
  //#endregion
229289
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/Codex.js
229379
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/Codex.js
229290
229380
  /**
229291
229381
  * @since 1.0.0
229292
229382
  */
@@ -230598,7 +230688,7 @@ const getUsageDetailNumber = (details, field) => {
230598
230688
  return typeof value === "number" ? value : void 0;
230599
230689
  };
230600
230690
  //#endregion
230601
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/CopilotAuth.js
230691
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/CopilotAuth.js
230602
230692
  /**
230603
230693
  * @since 1.0.0
230604
230694
  */
@@ -230789,7 +230879,7 @@ var GithubCopilotAuth = class GithubCopilotAuth extends Service$1()("clanka/Gith
230789
230879
  static layerClient = this.layerClientNoDeps.pipe(provide$3(GithubCopilotAuth.layer));
230790
230880
  };
230791
230881
  //#endregion
230792
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/Copilot.js
230882
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/Copilot.js
230793
230883
  /**
230794
230884
  * @since 1.0.0
230795
230885
  */
@@ -231209,7 +231299,7 @@ Object.defineProperties(createChalk.prototype, styles);
231209
231299
  const chalk = createChalk();
231210
231300
  createChalk({ level: stderrColor ? stderrColor.level : 0 });
231211
231301
  //#endregion
231212
- //#region node_modules/.pnpm/clanka@0.1.22_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-o_7a4026aab05a714a14be1d2fa397b573/node_modules/clanka/dist/OutputFormatter.js
231302
+ //#region node_modules/.pnpm/clanka@0.2.0_@effect+ai-openai-compat@4.0.0-beta.34_effect@4.0.0-beta.34__@effect+ai-op_460c830319f7edba0f4ce6b977c1844d/node_modules/clanka/dist/OutputFormatter.js
231213
231303
  /**
231214
231304
  * @since 1.0.0
231215
231305
  */
@@ -239344,6 +239434,8 @@ var Worktree = class extends Service$1()("lalph/Worktree", { make: gen(function*
239344
239434
  };
239345
239435
  }
239346
239436
  const directory = yield* fs.makeTempDirectory();
239437
+ const shared = pathService.resolve(".lalph", "shared");
239438
+ const worktreeShared = pathService.join(directory, ".lalph", "shared");
239347
239439
  yield* addFinalizer(fnUntraced(function* () {
239348
239440
  yield* execIgnore(spawner, make$45`git worktree remove --force ${directory}`);
239349
239441
  }));
@@ -239352,8 +239444,16 @@ var Worktree = class extends Service$1()("lalph/Worktree", { make: gen(function*
239352
239444
  const execHelpers = yield* makeExecHelpers({ directory });
239353
239445
  yield* setupWorktree({
239354
239446
  directory,
239355
- exec: execHelpers.exec
239447
+ exec: execHelpers.exec,
239448
+ shared,
239449
+ worktreeShared
239356
239450
  });
239451
+ yield* addFinalizer(fnUntraced(function* () {
239452
+ yield* copySharedBack({
239453
+ shared,
239454
+ worktreeShared
239455
+ }).pipe(catchCause$1(logWarning));
239456
+ }));
239357
239457
  return {
239358
239458
  directory,
239359
239459
  inExisting,
@@ -239394,9 +239494,8 @@ const setupWorktree = fnUntraced(function* (options) {
239394
239494
  yield* options.exec`git push -u ${parsed.remote} ${parsed.branch}`;
239395
239495
  }
239396
239496
  }
239397
- const shared = pathService.resolve(".lalph", "shared");
239398
- yield* fs.makeDirectory(shared, { recursive: true });
239399
- yield* fs.symlink(shared, pathService.join(options.directory, ".lalph", "shared"));
239497
+ yield* fs.makeDirectory(options.shared, { recursive: true });
239498
+ yield* fs.copy(options.shared, options.worktreeShared, { overwrite: true });
239400
239499
  const cwdSetupPath = pathService.resolve("scripts", "worktree-setup.sh");
239401
239500
  const worktreeSetupPath = pathService.join(options.directory, "scripts", "worktree-setup.sh");
239402
239501
  yield* seedSetupScript(cwdSetupPath);
@@ -239408,6 +239507,17 @@ const setupWorktree = fnUntraced(function* (options) {
239408
239507
  stdout: "inherit"
239409
239508
  })`${setupPath}`.pipe(spawner.exitCode);
239410
239509
  });
239510
+ const copySharedBack = fnUntraced(function* (options) {
239511
+ const fs = yield* FileSystem;
239512
+ const pathService = yield* Path$1;
239513
+ if (!(yield* fs.exists(options.worktreeShared))) return;
239514
+ yield* fs.makeDirectory(pathService.dirname(options.shared), { recursive: true });
239515
+ yield* fs.remove(options.shared, {
239516
+ recursive: true,
239517
+ force: true
239518
+ });
239519
+ yield* fs.copy(options.worktreeShared, options.shared);
239520
+ });
239411
239521
  const getTargetBranch = gen(function* () {
239412
239522
  const project = yield* projectById(yield* CurrentProjectId);
239413
239523
  if (isNone(project)) return none$4();
@@ -240567,7 +240677,7 @@ const commandEdit = make$58("edit").pipe(withDescription("Open the selected proj
240567
240677
  const commandSource = make$58("source").pipe(withDescription("Select the issue source to use (e.g. GitHub Issues or Linear). This applies to all projects."), withHandler(() => selectIssueSource), provide(Settings.layer));
240568
240678
  //#endregion
240569
240679
  //#region package.json
240570
- var version = "0.3.72";
240680
+ var version = "0.3.74";
240571
240681
  //#endregion
240572
240682
  //#region src/commands/projects/ls.ts
240573
240683
  const commandProjectsLs = make$58("ls").pipe(withDescription("List configured projects and how they run (enabled state, concurrency, branch, git flow, review agent)."), withHandler(fnUntraced(function* () {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lalph",
3
3
  "type": "module",
4
- "version": "0.3.72",
4
+ "version": "0.3.74",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -34,7 +34,7 @@
34
34
  "devDependencies": {
35
35
  "@changesets/changelog-github": "^0.6.0",
36
36
  "@changesets/cli": "^2.30.0",
37
- "@effect/ai-openai": "4.0.0-beta.34",
37
+ "@effect/ai-openai": "https://pkg.pr.new/Effect-TS/effect-smol/@effect/ai-openai@34082eb",
38
38
  "@effect/ai-openai-compat": "4.0.0-beta.34",
39
39
  "@effect/language-service": "^0.80.0",
40
40
  "@effect/platform-node": "4.0.0-beta.34",
@@ -42,7 +42,7 @@
42
42
  "@octokit/plugin-rest-endpoint-methods": "^17.0.0",
43
43
  "@octokit/types": "^16.0.0",
44
44
  "@typescript/native-preview": "7.0.0-dev.20260317.1",
45
- "clanka": "^0.1.22",
45
+ "clanka": "^0.2.0",
46
46
  "concurrently": "^9.2.1",
47
47
  "effect": "4.0.0-beta.34",
48
48
  "husky": "^9.1.7",
package/src/Worktree.ts CHANGED
@@ -40,6 +40,8 @@ export class Worktree extends ServiceMap.Service<Worktree>()("lalph/Worktree", {
40
40
  }
41
41
 
42
42
  const directory = yield* fs.makeTempDirectory()
43
+ const shared = pathService.resolve(".lalph", "shared")
44
+ const worktreeShared = pathService.join(directory, ".lalph", "shared")
43
45
 
44
46
  yield* Effect.addFinalizer(
45
47
  Effect.fnUntraced(function* () {
@@ -62,8 +64,19 @@ export class Worktree extends ServiceMap.Service<Worktree>()("lalph/Worktree", {
62
64
  yield* setupWorktree({
63
65
  directory,
64
66
  exec: execHelpers.exec,
67
+ shared,
68
+ worktreeShared,
65
69
  })
66
70
 
71
+ yield* Effect.addFinalizer(
72
+ Effect.fnUntraced(function* () {
73
+ yield* copySharedBack({
74
+ shared,
75
+ worktreeShared,
76
+ }).pipe(Effect.catchCause(Effect.logWarning))
77
+ }),
78
+ )
79
+
67
80
  return {
68
81
  directory,
69
82
  inExisting,
@@ -109,6 +122,8 @@ const seedSetupScript = Effect.fnUntraced(function* (setupPath: string) {
109
122
 
110
123
  const setupWorktree = Effect.fnUntraced(function* (options: {
111
124
  readonly directory: string
125
+ readonly shared: string
126
+ readonly worktreeShared: string
112
127
  readonly exec: (
113
128
  template: TemplateStringsArray,
114
129
  ...args: Array<string | number | boolean>
@@ -129,12 +144,10 @@ const setupWorktree = Effect.fnUntraced(function* (options: {
129
144
  }
130
145
  }
131
146
 
132
- const shared = pathService.resolve(".lalph", "shared")
133
- yield* fs.makeDirectory(shared, { recursive: true })
134
- yield* fs.symlink(
135
- shared,
136
- pathService.join(options.directory, ".lalph", "shared"),
137
- )
147
+ yield* fs.makeDirectory(options.shared, { recursive: true })
148
+ yield* fs.copy(options.shared, options.worktreeShared, {
149
+ overwrite: true,
150
+ })
138
151
 
139
152
  const cwdSetupPath = pathService.resolve("scripts", "worktree-setup.sh")
140
153
  const worktreeSetupPath = pathService.join(
@@ -158,6 +171,24 @@ const setupWorktree = Effect.fnUntraced(function* (options: {
158
171
  })`${setupPath}`.pipe(spawner.exitCode)
159
172
  })
160
173
 
174
+ const copySharedBack = Effect.fnUntraced(function* (options: {
175
+ readonly shared: string
176
+ readonly worktreeShared: string
177
+ }) {
178
+ const fs = yield* FileSystem.FileSystem
179
+ const pathService = yield* Path.Path
180
+
181
+ if (!(yield* fs.exists(options.worktreeShared))) {
182
+ return
183
+ }
184
+
185
+ yield* fs.makeDirectory(pathService.dirname(options.shared), {
186
+ recursive: true,
187
+ })
188
+ yield* fs.remove(options.shared, { recursive: true, force: true })
189
+ yield* fs.copy(options.worktreeShared, options.shared)
190
+ })
191
+
161
192
  const getTargetBranch = Effect.gen(function* () {
162
193
  const projectId = yield* CurrentProjectId
163
194
  const project = yield* projectById(projectId)