lody 0.87.0 → 0.88.1

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/index.js CHANGED
@@ -37,7 +37,7 @@ import * as jt from "node:fs/promises";
37
37
  import jt__default, { mkdir as mkdir$1, realpath, symlink, mkdtemp, chmod, writeFile, rm, rename, readFile, readdir, stat, lstat, unlink, open, opendir } from "node:fs/promises";
38
38
  import zlib__default, { gzip, gunzip as gunzip$1, gunzipSync, brotliDecompressSync } from "node:zlib";
39
39
  import require$$1$8, { exec, execFile as execFile$1, spawn as spawn$2 } from "child_process";
40
- import { i as imports, _ as __wbg_set_wasm$1, r as rawWasm, L as LoroDoc, E as EphemeralStoreWasm, U as UndoManager, c as callPendingEvents$3, a as LoroTree, b as LoroText, d as LoroMovableList, e as LoroList, f as LoroMap, V as VersionVector, g as __vite__initWasm, h as decodeImportBlobMeta, __tla as __tla_0 } from "./chunks/loro_wasm_bg-BPNKba8n.js";
40
+ import { i as imports, _ as __wbg_set_wasm$1, r as rawWasm, L as LoroDoc, E as EphemeralStoreWasm, U as UndoManager, a as isValidContainerId, c as callPendingEvents$3, b as LoroTree, d as LoroText, e as LoroMovableList, f as LoroList, g as LoroMap, V as VersionVector, h as __vite__initWasm, j as decodeImportBlobMeta, __tla as __tla_0 } from "./chunks/loro_wasm_bg-Br-Fa9wV.js";
41
41
  import { performance as performance$1 } from "perf_hooks";
42
42
  import require$$0$9 from "net";
43
43
  import require$$4$2 from "tls";
@@ -4325,7 +4325,7 @@ Upgrade Node, then re-run: npx lody@latest`;
4325
4325
  }
4326
4326
  const name$2 = "lody";
4327
4327
  const name$1 = "@lody/cli-cloud";
4328
- const version$9 = "0.87.0";
4328
+ const version$9 = "0.88.1";
4329
4329
  const type$2 = "module";
4330
4330
  const scripts = {
4331
4331
  "dev": "node dev.mjs",
@@ -4664,7 +4664,7 @@ Upgrade Node, then re-run: npx lody@latest`;
4664
4664
  return "none";
4665
4665
  }
4666
4666
  const MODEL_THOUGHT_LEVEL_META_KEY = "lodyThoughtLevel";
4667
- const ACP_CAPABILITY_CACHE_VERSION = 5;
4667
+ const ACP_CAPABILITY_CACHE_VERSION = 6;
4668
4668
  const getAcpCapabilityCacheKey = (configId) => configId;
4669
4669
  const isBuiltinAgentType = (agentType) => BUILTIN_AGENTS.some((agent2) => agent2.agentType === agentType);
4670
4670
  const isManagedBuiltinAgentType = (agentType) => MANAGED_BUILTIN_RUNTIMES.some((runtime) => runtime.agentType === agentType);
@@ -6155,7 +6155,9 @@ Requirements:
6155
6155
  path2.add(value);
6156
6156
  }
6157
6157
  const keys2 = Object.keys(value);
6158
- const strippedValues = new Array(keys2.length);
6158
+ const strippedValues = Array.from({
6159
+ length: keys2.length
6160
+ });
6159
6161
  let changed = false;
6160
6162
  for (let i2 = 0; i2 < keys2.length; i2++) {
6161
6163
  const key2 = keys2[i2];
@@ -6459,7 +6461,7 @@ Requirements:
6459
6461
  function isContainerSchema(schema2) {
6460
6462
  return !!schema2 && (schema2.type === "loro-map" || schema2.type === "loro-list" || schema2.type === "loro-text" || schema2.type === "loro-movable-list" || schema2.type === "loro-tree");
6461
6463
  }
6462
- function validateSchema(schema2, value) {
6464
+ function validateSchema(schema2, value, options) {
6463
6465
  const errors2 = [];
6464
6466
  const actualType = schema2.type;
6465
6467
  if (schema2.options.required && (value === void 0 || value === null)) {
@@ -6474,7 +6476,8 @@ Requirements:
6474
6476
  valid: true
6475
6477
  };
6476
6478
  }
6477
- if (isSchemaValidated(schema2, value)) {
6479
+ const useCache = !options?.ignoreUnknownProperties;
6480
+ if (useCache && isSchemaValidated(schema2, value)) {
6478
6481
  return {
6479
6482
  valid: true
6480
6483
  };
@@ -6587,6 +6590,7 @@ Requirements:
6587
6590
  }
6588
6591
  for (const key2 in value) {
6589
6592
  if (!Object.prototype.hasOwnProperty.call(schema2.definition, key2)) {
6593
+ if (options?.ignoreUnknownProperties) continue;
6590
6594
  errors2.push(`Unknown property: ${key2}`);
6591
6595
  }
6592
6596
  }
@@ -6610,7 +6614,7 @@ Requirements:
6610
6614
  }
6611
6615
  }
6612
6616
  if (errors2.length === 0) {
6613
- markSchemaValidated(schema2, value);
6617
+ if (useCache) markSchemaValidated(schema2, value);
6614
6618
  return {
6615
6619
  valid: true
6616
6620
  };
@@ -7536,7 +7540,7 @@ Requirements:
7536
7540
  }
7537
7541
  finalize$1(instance.exports);
7538
7542
  } else {
7539
- const wkmod = wasmModuleOrExports instanceof WebAssembly.Module ? wasmModuleOrExports : await import("./chunks/loro_wasm_bg-BPNKba8n.js").then(async (m) => {
7543
+ const wkmod = wasmModuleOrExports instanceof WebAssembly.Module ? wasmModuleOrExports : await import("./chunks/loro_wasm_bg-Br-Fa9wV.js").then(async (m) => {
7540
7544
  await m.__tla;
7541
7545
  return m;
7542
7546
  }).then((n) => n.r);
@@ -7574,7 +7578,7 @@ Requirements:
7574
7578
  "Counter"
7575
7579
  ];
7576
7580
  function isContainerId(s) {
7577
- return s.startsWith("cid:");
7581
+ return isValidContainerId(s);
7578
7582
  }
7579
7583
  function isContainer(value) {
7580
7584
  if (typeof value !== "object" || value == null) {
@@ -9315,6 +9319,7 @@ Requirements:
9315
9319
  schema: options.schema,
9316
9320
  initialState: options.initialState || {},
9317
9321
  validateUpdates: options.validateUpdates !== false,
9322
+ ignoreUnknownProperties: options.ignoreUnknownProperties || false,
9318
9323
  debug: options.debug || false,
9319
9324
  checkStateConsistency: options.checkStateConsistency || false,
9320
9325
  inferOptions: options.inferOptions || {}
@@ -10473,7 +10478,9 @@ Requirements:
10473
10478
  }) : Object.assign({}, this.state, updater);
10474
10479
  hardenCidDescriptors(newState, this.state);
10475
10480
  if (this.options.validateUpdates) {
10476
- const validation2 = this.schema && validateSchema(this.schema, newState);
10481
+ const validation2 = this.schema && validateSchema(this.schema, newState, {
10482
+ ignoreUnknownProperties: this.options.ignoreUnknownProperties
10483
+ });
10477
10484
  if (validation2 && !validation2.valid) {
10478
10485
  const errorMessage2 = `State validation failed: ${validation2.errors?.join(", ")}`;
10479
10486
  throw new Error(errorMessage2);
@@ -10651,6 +10658,19 @@ Requirements:
10651
10658
  root[key2] = this.containerToMirrorState(container2, options);
10652
10659
  }
10653
10660
  }
10661
+ if (this.options.ignoreUnknownProperties) {
10662
+ const shallowDocState = this.doc.getShallowValue();
10663
+ for (const [key2, containerId] of Object.entries(shallowDocState)) {
10664
+ if (Object.prototype.hasOwnProperty.call(rootSchema.definition, key2)) {
10665
+ continue;
10666
+ }
10667
+ const container2 = this.doc.getContainerById(containerId);
10668
+ if (!container2) {
10669
+ throw new Error(`ContainerID not found: ${containerId}`);
10670
+ }
10671
+ root[key2] = normalizeContainerForJson(container2);
10672
+ }
10673
+ }
10654
10674
  return root;
10655
10675
  }
10656
10676
  registerContainerWithRegistry(containerId, schemaType) {
@@ -10702,15 +10722,16 @@ Requirements:
10702
10722
  return Array.from(this.containerRegistry.keys());
10703
10723
  }
10704
10724
  }
10705
- const CID_PLACEHOLDER_PREFIX = "\0mirror:cid\0";
10706
10725
  function toNormalizedJson(doc) {
10707
- const withEnumerableCid = doc.toJsonWithReplacer((_k, v) => {
10708
- if (isContainer(v)) {
10709
- return normalizeContainerForJson(v);
10726
+ const root = {};
10727
+ for (const [key2, id2] of Object.entries(doc.getShallowValue())) {
10728
+ const container2 = doc.getContainerById(id2);
10729
+ if (!container2) {
10730
+ throw new Error(`ContainerID not found: ${id2}`);
10710
10731
  }
10711
- return v;
10712
- });
10713
- return restoreCidDescriptors(withEnumerableCid);
10732
+ root[key2] = normalizeContainerForJson(container2);
10733
+ }
10734
+ return root;
10714
10735
  }
10715
10736
  function normalizeContainerForJson(c) {
10716
10737
  const kind = c.kind();
@@ -10724,10 +10745,11 @@ Requirements:
10724
10745
  const m = c;
10725
10746
  const obj = {};
10726
10747
  for (const key2 of m.keys()) {
10748
+ if (key2 === CID_KEY) continue;
10727
10749
  const child = m.get(key2);
10728
10750
  obj[key2] = isContainer(child) ? normalizeContainerForJson(child) : child;
10729
10751
  }
10730
- obj[CID_KEY] = CID_PLACEHOLDER_PREFIX + m.id;
10752
+ defineCidProperty(obj, m.id);
10731
10753
  return obj;
10732
10754
  }
10733
10755
  if (kind === "List" || kind === "MovableList") {
@@ -10741,33 +10763,6 @@ Requirements:
10741
10763
  }
10742
10764
  return c.toJSON();
10743
10765
  }
10744
- function restoreCidDescriptors(value) {
10745
- if (Array.isArray(value)) {
10746
- for (let i2 = 0; i2 < value.length; i2++) {
10747
- value[i2] = restoreCidDescriptors(value[i2]);
10748
- }
10749
- return value;
10750
- }
10751
- if (isObject$3(value)) {
10752
- const obj = value;
10753
- for (const key2 of Object.keys(obj)) {
10754
- obj[key2] = restoreCidDescriptors(obj[key2]);
10755
- }
10756
- if (Object.prototype.hasOwnProperty.call(obj, CID_KEY)) {
10757
- const descriptor = Object.getOwnPropertyDescriptor(obj, CID_KEY);
10758
- if (!descriptor || descriptor.enumerable) {
10759
- const rawCid = obj[CID_KEY];
10760
- const cidValue = typeof rawCid === "string" && rawCid.startsWith(CID_PLACEHOLDER_PREFIX) ? rawCid.slice(CID_PLACEHOLDER_PREFIX.length) : rawCid;
10761
- delete obj[CID_KEY];
10762
- Object.defineProperty(obj, CID_KEY, {
10763
- value: cidValue
10764
- });
10765
- }
10766
- }
10767
- return obj;
10768
- }
10769
- return value;
10770
- }
10771
10766
  function normalizeInitialShapeShallow(input2) {
10772
10767
  const out = {};
10773
10768
  for (const [key2, value] of Object.entries(input2)) {
@@ -13247,6 +13242,13 @@ Requirements:
13247
13242
  localProjectId: LocalProjectIdSchema,
13248
13243
  requestedByUserId: string$1().trim().min(1).optional()
13249
13244
  }).strict();
13245
+ const LocalProjectRemovalPreflightRequestSchema = object$1({
13246
+ type: literal$1("local-project/removal-preflight"),
13247
+ machineId: MachineIdSchema$1,
13248
+ workspaceId: WorkspaceIdSchema,
13249
+ localProjectId: LocalProjectIdSchema,
13250
+ requestedByUserId: string$1().trim().min(1).optional()
13251
+ }).strict();
13250
13252
  const LocalProjectListRequestSchema = object$1({
13251
13253
  type: literal$1("local-project/list"),
13252
13254
  machineId: MachineIdSchema$1
@@ -13386,6 +13388,7 @@ Requirements:
13386
13388
  LocalProjectListRootsRequestSchema,
13387
13389
  LocalProjectBrowseDirRequestSchema,
13388
13390
  LocalProjectDeleteRequestSchema,
13391
+ LocalProjectRemovalPreflightRequestSchema,
13389
13392
  LocalProjectListRequestSchema,
13390
13393
  LocalProjectGitStateRequestSchema,
13391
13394
  LocalProjectListFilesRequestSchema,
@@ -13552,6 +13555,19 @@ Requirements:
13552
13555
  status: literal$1("resolved"),
13553
13556
  catalog: LocalProjectHistoryCatalogResultSchema
13554
13557
  }).strict();
13558
+ const LocalProjectWorktreeCleanupItemSchema = object$1({
13559
+ sessionId: SessionIdSchema$1,
13560
+ title: string$1(),
13561
+ path: string$1()
13562
+ }).strict();
13563
+ const LocalProjectWorktreeCleanupFailureSchema = LocalProjectWorktreeCleanupItemSchema.extend({
13564
+ message: string$1()
13565
+ }).strict();
13566
+ const LocalProjectWorktreeCleanupPreflightResultSchema = object$1({
13567
+ clean: array$2(LocalProjectWorktreeCleanupItemSchema),
13568
+ dirty: array$2(LocalProjectWorktreeCleanupItemSchema),
13569
+ failed: array$2(LocalProjectWorktreeCleanupFailureSchema)
13570
+ }).strict();
13555
13571
  const LocalProjectControlErrorCodeSchema = _enum$1([
13556
13572
  "invalid_request",
13557
13573
  "machine_mismatch",
@@ -13572,6 +13588,7 @@ Requirements:
13572
13588
  "local-project/list-roots",
13573
13589
  "local-project/browse-dir",
13574
13590
  "local-project/delete",
13591
+ "local-project/removal-preflight",
13575
13592
  "local-project/list",
13576
13593
  "local-project/git-state",
13577
13594
  "local-project/list-files",
@@ -13635,6 +13652,11 @@ Requirements:
13635
13652
  workspaceIds: array$2(WorkspaceIdSchema)
13636
13653
  }).strict()
13637
13654
  }).strict(),
13655
+ object$1({
13656
+ ok: literal$1(true),
13657
+ type: literal$1("local-project/removal-preflight"),
13658
+ result: LocalProjectWorktreeCleanupPreflightResultSchema
13659
+ }).strict(),
13638
13660
  object$1({
13639
13661
  ok: literal$1(true),
13640
13662
  type: literal$1("local-project/list"),
@@ -14531,12 +14553,12 @@ Requirements:
14531
14553
  {
14532
14554
  id: "auggie",
14533
14555
  name: "Auggie CLI",
14534
- version: "0.35.0",
14556
+ version: "0.36.0",
14535
14557
  description: "Augment Code's powerful software agent, backed by industry-leading context engine",
14536
14558
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/auggie.svg",
14537
14559
  distribution: {
14538
14560
  npx: {
14539
- package: "@augmentcode/auggie@0.35.0",
14561
+ package: "@augmentcode/auggie@0.36.0",
14540
14562
  args: [
14541
14563
  "--acp"
14542
14564
  ],
@@ -14561,12 +14583,12 @@ Requirements:
14561
14583
  {
14562
14584
  id: "cline",
14563
14585
  name: "Cline",
14564
- version: "3.0.55",
14586
+ version: "3.0.60",
14565
14587
  description: "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
14566
14588
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/cline.svg",
14567
14589
  distribution: {
14568
14590
  npx: {
14569
- package: "cline@3.0.55",
14591
+ package: "cline@3.0.60",
14570
14592
  args: [
14571
14593
  "--acp"
14572
14594
  ]
@@ -14576,12 +14598,12 @@ Requirements:
14576
14598
  {
14577
14599
  id: "codebuddy-code",
14578
14600
  name: "Codebuddy Code",
14579
- version: "2.137.1",
14601
+ version: "2.140.0",
14580
14602
  description: "Tencent Cloud's official intelligent coding tool",
14581
14603
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/codebuddy-code.svg",
14582
14604
  distribution: {
14583
14605
  npx: {
14584
- package: "@tencent-ai/codebuddy-code@2.137.1",
14606
+ package: "@tencent-ai/codebuddy-code@2.140.0",
14585
14607
  args: [
14586
14608
  "--acp"
14587
14609
  ]
@@ -14753,48 +14775,48 @@ Requirements:
14753
14775
  {
14754
14776
  id: "devin",
14755
14777
  name: "Devin",
14756
- version: "3000.4.25",
14778
+ version: "3000.6.2",
14757
14779
  description: "Devin CLI coding agent by Cognition",
14758
14780
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/devin.svg",
14759
14781
  distribution: {
14760
14782
  binary: {
14761
14783
  "darwin-aarch64": {
14762
- archive: "https://static.devin.ai/cli/3000.4.25/devin-3000.4.25-aarch64-apple-darwin.tar.gz",
14784
+ archive: "https://static.devin.ai/cli/3000.6.2/devin-3000.6.2-aarch64-apple-darwin.tar.gz",
14763
14785
  cmd: "./bin/devin",
14764
14786
  args: [
14765
14787
  "acp"
14766
14788
  ]
14767
14789
  },
14768
14790
  "darwin-x86_64": {
14769
- archive: "https://static.devin.ai/cli/3000.4.25/devin-3000.4.25-x86_64-apple-darwin.tar.gz",
14791
+ archive: "https://static.devin.ai/cli/3000.6.2/devin-3000.6.2-x86_64-apple-darwin.tar.gz",
14770
14792
  cmd: "./bin/devin",
14771
14793
  args: [
14772
14794
  "acp"
14773
14795
  ]
14774
14796
  },
14775
14797
  "linux-aarch64": {
14776
- archive: "https://static.devin.ai/cli/3000.4.25/devin-3000.4.25-aarch64-unknown-linux.tar.gz",
14798
+ archive: "https://static.devin.ai/cli/3000.6.2/devin-3000.6.2-aarch64-unknown-linux.tar.gz",
14777
14799
  cmd: "./bin/devin",
14778
14800
  args: [
14779
14801
  "acp"
14780
14802
  ]
14781
14803
  },
14782
14804
  "linux-x86_64": {
14783
- archive: "https://static.devin.ai/cli/3000.4.25/devin-3000.4.25-x86_64-unknown-linux.tar.gz",
14805
+ archive: "https://static.devin.ai/cli/3000.6.2/devin-3000.6.2-x86_64-unknown-linux.tar.gz",
14784
14806
  cmd: "./bin/devin",
14785
14807
  args: [
14786
14808
  "acp"
14787
14809
  ]
14788
14810
  },
14789
14811
  "windows-aarch64": {
14790
- archive: "https://static.devin.ai/cli/3000.4.25/devin-3000.4.25-aarch64-pc-windows.zip",
14812
+ archive: "https://static.devin.ai/cli/3000.6.2/devin-3000.6.2-aarch64-pc-windows.zip",
14791
14813
  cmd: "./bin\\devin.exe",
14792
14814
  args: [
14793
14815
  "acp"
14794
14816
  ]
14795
14817
  },
14796
14818
  "windows-x86_64": {
14797
- archive: "https://static.devin.ai/cli/3000.4.25/devin-3000.4.25-x86_64-pc-windows.zip",
14819
+ archive: "https://static.devin.ai/cli/3000.6.2/devin-3000.6.2-x86_64-pc-windows.zip",
14798
14820
  cmd: "./bin\\devin.exe",
14799
14821
  args: [
14800
14822
  "acp"
@@ -14806,12 +14828,12 @@ Requirements:
14806
14828
  {
14807
14829
  id: "dimcode",
14808
14830
  name: "DimCode",
14809
- version: "0.3.17",
14831
+ version: "0.3.21",
14810
14832
  description: "A coding agent that puts leading models at your command.",
14811
14833
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/dimcode.svg",
14812
14834
  distribution: {
14813
14835
  npx: {
14814
- package: "dimcode@0.3.17",
14836
+ package: "dimcode@0.3.21",
14815
14837
  args: [
14816
14838
  "acp"
14817
14839
  ]
@@ -14821,12 +14843,12 @@ Requirements:
14821
14843
  {
14822
14844
  id: "dirac",
14823
14845
  name: "Dirac",
14824
- version: "0.4.37",
14846
+ version: "0.5.1",
14825
14847
  description: "Reduces API costs by more than 50%, produces better and faster work. Uses Hash anchored parallel edits, AST manipulation and a whole lot of neat optimizations. Fully Open Source.",
14826
14848
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/dirac.svg",
14827
14849
  distribution: {
14828
14850
  npx: {
14829
- package: "dirac-cli@0.4.37",
14851
+ package: "dirac-cli@0.5.1",
14830
14852
  args: [
14831
14853
  "--acp"
14832
14854
  ]
@@ -14836,12 +14858,12 @@ Requirements:
14836
14858
  {
14837
14859
  id: "factory-droid",
14838
14860
  name: "Factory Droid",
14839
- version: "0.200.0",
14861
+ version: "0.205.1",
14840
14862
  description: "Factory Droid - AI coding agent powered by Factory AI",
14841
14863
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/factory-droid.svg",
14842
14864
  distribution: {
14843
14865
  npx: {
14844
- package: "droid@0.200.0",
14866
+ package: "droid@0.205.1",
14845
14867
  args: [
14846
14868
  "exec",
14847
14869
  "--output-format",
@@ -14875,12 +14897,12 @@ Requirements:
14875
14897
  {
14876
14898
  id: "gemini",
14877
14899
  name: "Gemini CLI",
14878
- version: "0.56.0",
14900
+ version: "0.57.0",
14879
14901
  description: "Google's official CLI for Gemini",
14880
14902
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/gemini.svg",
14881
14903
  distribution: {
14882
14904
  npx: {
14883
- package: "@google/gemini-cli@0.56.0",
14905
+ package: "@google/gemini-cli@0.57.0",
14884
14906
  args: [
14885
14907
  "--acp"
14886
14908
  ]
@@ -14890,12 +14912,12 @@ Requirements:
14890
14912
  {
14891
14913
  id: "github-copilot-cli",
14892
14914
  name: "GitHub Copilot",
14893
- version: "1.0.80",
14915
+ version: "1.0.81",
14894
14916
  description: "GitHub's AI pair programmer",
14895
14917
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/github-copilot-cli.svg",
14896
14918
  distribution: {
14897
14919
  npx: {
14898
- package: "@github/copilot@1.0.80",
14920
+ package: "@github/copilot@1.0.81",
14899
14921
  args: [
14900
14922
  "--acp"
14901
14923
  ]
@@ -14905,19 +14927,19 @@ Requirements:
14905
14927
  {
14906
14928
  id: "glm-acp-agent",
14907
14929
  name: "GLM Agent",
14908
- version: "1.6.0",
14930
+ version: "1.6.1",
14909
14931
  description: "ACP agent powered by Zhipu AI's GLM Coding Plan models (glm-5.1, glm-5-turbo, glm-4.7, glm-4.5-air). Supports streaming, tool calls, mid-session model switching, image input via Z.AI Coding Plan Vision MCP, and session load/fork/resume with on-disk persistence.",
14910
14932
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/glm-acp-agent.svg",
14911
14933
  distribution: {
14912
14934
  npx: {
14913
- package: "glm-acp-agent@1.6.0"
14935
+ package: "glm-acp-agent@1.6.1"
14914
14936
  }
14915
14937
  }
14916
14938
  },
14917
14939
  {
14918
14940
  id: "goose",
14919
14941
  name: "goose",
14920
- version: "1.46.0",
14942
+ version: "1.48.0",
14921
14943
  description: "A local, extensible, open source AI agent that automates engineering tasks",
14922
14944
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/goose.svg",
14923
14945
  distribution: {
@@ -14935,13 +14957,13 @@ Requirements:
14935
14957
  {
14936
14958
  id: "harn",
14937
14959
  name: "Harn",
14938
- version: "0.10.108",
14960
+ version: "0.10.118",
14939
14961
  description: "Harn runs .harn agent pipelines as a native ACP coding agent over stdio.",
14940
14962
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/harn.svg",
14941
14963
  distribution: {
14942
14964
  binary: {
14943
14965
  "darwin-aarch64": {
14944
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.108/harn-aarch64-apple-darwin.tar.gz",
14966
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.118/harn-aarch64-apple-darwin.tar.gz",
14945
14967
  cmd: "./harn",
14946
14968
  args: [
14947
14969
  "serve",
@@ -14949,7 +14971,7 @@ Requirements:
14949
14971
  ]
14950
14972
  },
14951
14973
  "darwin-x86_64": {
14952
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.108/harn-x86_64-apple-darwin.tar.gz",
14974
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.118/harn-x86_64-apple-darwin.tar.gz",
14953
14975
  cmd: "./harn",
14954
14976
  args: [
14955
14977
  "serve",
@@ -14957,7 +14979,7 @@ Requirements:
14957
14979
  ]
14958
14980
  },
14959
14981
  "linux-aarch64": {
14960
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.108/harn-aarch64-unknown-linux-gnu.tar.gz",
14982
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.118/harn-aarch64-unknown-linux-gnu.tar.gz",
14961
14983
  cmd: "./harn",
14962
14984
  args: [
14963
14985
  "serve",
@@ -14965,7 +14987,7 @@ Requirements:
14965
14987
  ]
14966
14988
  },
14967
14989
  "linux-x86_64": {
14968
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.108/harn-x86_64-unknown-linux-gnu.tar.gz",
14990
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.118/harn-x86_64-unknown-linux-gnu.tar.gz",
14969
14991
  cmd: "./harn",
14970
14992
  args: [
14971
14993
  "serve",
@@ -14973,7 +14995,7 @@ Requirements:
14973
14995
  ]
14974
14996
  },
14975
14997
  "windows-x86_64": {
14976
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.108/harn-x86_64-pc-windows-msvc.zip",
14998
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.118/harn-x86_64-pc-windows-msvc.zip",
14977
14999
  cmd: "harn.exe",
14978
15000
  args: [
14979
15001
  "serve",
@@ -14986,7 +15008,7 @@ Requirements:
14986
15008
  {
14987
15009
  id: "junie",
14988
15010
  name: "Junie",
14989
- version: "2913.6.0",
15011
+ version: "3032.2.0",
14990
15012
  description: "AI Coding Agent by JetBrains",
14991
15013
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/junie.svg",
14992
15014
  distribution: {
@@ -15004,47 +15026,47 @@ Requirements:
15004
15026
  {
15005
15027
  id: "kilo",
15006
15028
  name: "Kilo",
15007
- version: "7.4.23",
15029
+ version: "7.5.5",
15008
15030
  description: "The open source coding agent",
15009
15031
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/kilo.svg",
15010
15032
  distribution: {
15011
15033
  npx: {
15012
- package: "@kilocode/cli@7.4.23",
15034
+ package: "@kilocode/cli@7.5.5",
15013
15035
  args: [
15014
15036
  "acp"
15015
15037
  ]
15016
15038
  },
15017
15039
  binary: {
15018
15040
  "darwin-aarch64": {
15019
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/kilo-darwin-arm64.zip",
15041
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.5.5/kilo-darwin-arm64.zip",
15020
15042
  cmd: "./kilo",
15021
15043
  args: [
15022
15044
  "acp"
15023
15045
  ]
15024
15046
  },
15025
15047
  "darwin-x86_64": {
15026
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/kilo-darwin-x64.zip",
15048
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.5.5/kilo-darwin-x64.zip",
15027
15049
  cmd: "./kilo",
15028
15050
  args: [
15029
15051
  "acp"
15030
15052
  ]
15031
15053
  },
15032
15054
  "linux-aarch64": {
15033
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/kilo-linux-arm64.tar.gz",
15055
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.5.5/kilo-linux-arm64.tar.gz",
15034
15056
  cmd: "./kilo",
15035
15057
  args: [
15036
15058
  "acp"
15037
15059
  ]
15038
15060
  },
15039
15061
  "linux-x86_64": {
15040
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/kilo-linux-x64.tar.gz",
15062
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.5.5/kilo-linux-x64.tar.gz",
15041
15063
  cmd: "./kilo",
15042
15064
  args: [
15043
15065
  "acp"
15044
15066
  ]
15045
15067
  },
15046
15068
  "windows-x86_64": {
15047
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/kilo-windows-x64.zip",
15069
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.5.5/kilo-windows-x64.zip",
15048
15070
  cmd: "./kilo.exe",
15049
15071
  args: [
15050
15072
  "acp"
@@ -15126,12 +15148,12 @@ Requirements:
15126
15148
  {
15127
15149
  id: "nova",
15128
15150
  name: "Nova",
15129
- version: "1.1.35",
15151
+ version: "1.1.37",
15130
15152
  description: "Nova by Compass AI - a fully-fledged software engineer at your command",
15131
15153
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/nova.svg",
15132
15154
  distribution: {
15133
15155
  npx: {
15134
- package: "@compass-ai/nova@1.1.35",
15156
+ package: "@compass-ai/nova@1.1.37",
15135
15157
  args: [
15136
15158
  "acp"
15137
15159
  ]
@@ -15141,7 +15163,7 @@ Requirements:
15141
15163
  {
15142
15164
  id: "opencode",
15143
15165
  name: "OpenCode",
15144
- version: "1.18.19",
15166
+ version: "1.18.23",
15145
15167
  description: "The open source coding agent",
15146
15168
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/opencode.svg",
15147
15169
  distribution: {
@@ -15239,12 +15261,12 @@ Requirements:
15239
15261
  {
15240
15262
  id: "qwen-code",
15241
15263
  name: "Qwen Code",
15242
- version: "0.21.15",
15264
+ version: "0.22.2",
15243
15265
  description: "Alibaba's Qwen coding assistant",
15244
15266
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/qwen-code.svg",
15245
15267
  distribution: {
15246
15268
  npx: {
15247
- package: "@qwen-code/qwen-code@0.21.15",
15269
+ package: "@qwen-code/qwen-code@0.22.2",
15248
15270
  args: [
15249
15271
  "--acp",
15250
15272
  "--experimental-skills"
@@ -17920,14 +17942,29 @@ ${outputTail}` : blockTail.output;
17920
17942
  };
17921
17943
  function extractAskUserQuestionAnswersFromOutcome(meta, outcome) {
17922
17944
  if (!outcome || !isRecord$b(outcome._meta)) return null;
17923
- const rawAnswers = meta.source === "lody" ? getLodyOutcomeAnswers(outcome._meta) : meta.source === "codex" ? getCodexOutcomeAnswers(outcome._meta) : getClaudeOutcomeAnswers(outcome._meta);
17924
- if (!rawAnswers) return null;
17945
+ const answerSources = [
17946
+ {
17947
+ source: "lody",
17948
+ answers: getLodyOutcomeAnswers(outcome._meta)
17949
+ },
17950
+ {
17951
+ source: "codex",
17952
+ answers: getCodexOutcomeAnswers(outcome._meta)
17953
+ },
17954
+ {
17955
+ source: "claude",
17956
+ answers: getClaudeOutcomeAnswers(outcome._meta)
17957
+ }
17958
+ ];
17959
+ const answerSource = answerSources.find(({ answers }) => answers !== null);
17960
+ if (!answerSource?.answers) return null;
17925
17961
  const result = {};
17926
17962
  for (const [index, question] of meta.questions.entries()) {
17927
17963
  const key2 = getAskUserQuestionAnswerKey(meta.questions, index);
17928
- const raw2 = rawAnswers[key2];
17964
+ const sourceKey = answerSource.source === "claude" ? getAskUserQuestionAnswerKey(meta.questions.map(({ id: _id, ...item }) => item), index) : key2;
17965
+ const raw2 = answerSource.answers[sourceKey];
17929
17966
  if (raw2 === void 0) continue;
17930
- if (meta.source === "codex") {
17967
+ if (answerSource.source === "codex") {
17931
17968
  if (!isRecord$b(raw2)) continue;
17932
17969
  const inner = raw2.answers;
17933
17970
  if (!Array.isArray(inner)) continue;
@@ -20609,10 +20646,13 @@ ${tailedOutput}` : null;
20609
20646
  return parsed;
20610
20647
  };
20611
20648
  const MACHINE_PROTOCOL_CAPABILITIES = {
20649
+ localProjectRemoval: "localProjectRemoval",
20612
20650
  providerSetup: "providerSetup"
20613
20651
  };
20652
+ const LOCAL_PROJECT_REMOVAL_PROTOCOL_VERSION = 1;
20614
20653
  const PROVIDER_SETUP_PROTOCOL_VERSION = 1;
20615
20654
  const CURRENT_MACHINE_PROTOCOL_CAPABILITIES = {
20655
+ [MACHINE_PROTOCOL_CAPABILITIES.localProjectRemoval]: LOCAL_PROJECT_REMOVAL_PROTOCOL_VERSION,
20616
20656
  [MACHINE_PROTOCOL_CAPABILITIES.providerSetup]: PROVIDER_SETUP_PROTOCOL_VERSION
20617
20657
  };
20618
20658
  const isLoroRepoDocDeleted = (value) => {
@@ -23875,8 +23915,65 @@ ${context2.authorReply.trim()}
23875
23915
  }
23876
23916
  command2.requestedBy = value.requestedBy;
23877
23917
  }
23918
+ if (!isMissing(value.projectName)) {
23919
+ if (typeof value.projectName !== "string") return void 0;
23920
+ command2.projectName = value.projectName;
23921
+ }
23922
+ if (!isMissing(value.originalRootPath)) {
23923
+ if (typeof value.originalRootPath !== "string") return void 0;
23924
+ command2.originalRootPath = value.originalRootPath;
23925
+ }
23926
+ if (!isMissing(value.cleanupWorktrees)) {
23927
+ if (value.cleanupWorktrees !== true) return void 0;
23928
+ command2.cleanupWorktrees = true;
23929
+ }
23930
+ if (!isMissing(value.status)) {
23931
+ if (value.status !== "completed") return void 0;
23932
+ command2.status = "completed";
23933
+ }
23934
+ if (!isMissing(value.cleanupResult)) {
23935
+ const result = normalizeLocalProjectWorktreeCleanupResult(value.cleanupResult);
23936
+ if (!result) return void 0;
23937
+ command2.cleanupResult = result;
23938
+ }
23878
23939
  return command2;
23879
23940
  };
23941
+ const normalizeLocalProjectWorktreeCleanupItem = (value) => {
23942
+ if (!isRecord$8(value)) return void 0;
23943
+ if (typeof value.sessionId !== "string") return void 0;
23944
+ if (typeof value.title !== "string") return void 0;
23945
+ if (typeof value.path !== "string") return void 0;
23946
+ return {
23947
+ sessionId: value.sessionId,
23948
+ title: value.title,
23949
+ path: value.path
23950
+ };
23951
+ };
23952
+ const normalizeLocalProjectWorktreeCleanupResult = (value) => {
23953
+ if (!isRecord$8(value) || typeof value.completedAt !== "number") return void 0;
23954
+ if (!Array.isArray(value.deleted)) return void 0;
23955
+ if (!Array.isArray(value.skippedDirty)) return void 0;
23956
+ if (!Array.isArray(value.failed)) return void 0;
23957
+ const deleted = value.deleted.map(normalizeLocalProjectWorktreeCleanupItem);
23958
+ const skippedDirty = value.skippedDirty.map(normalizeLocalProjectWorktreeCleanupItem);
23959
+ const failed = value.failed.map((entry) => {
23960
+ const item = normalizeLocalProjectWorktreeCleanupItem(entry);
23961
+ if (!item || !isRecord$8(entry) || typeof entry.message !== "string") return void 0;
23962
+ return {
23963
+ ...item,
23964
+ message: entry.message
23965
+ };
23966
+ });
23967
+ if (deleted.includes(void 0)) return void 0;
23968
+ if (skippedDirty.includes(void 0)) return void 0;
23969
+ if (failed.includes(void 0)) return void 0;
23970
+ return {
23971
+ completedAt: value.completedAt,
23972
+ deleted,
23973
+ skippedDirty,
23974
+ failed
23975
+ };
23976
+ };
23880
23977
  const normalizeLocalProjectMeta = (value) => {
23881
23978
  if (!isRecord$8(value) || !isNonEmptyString$2(value.id) || !isNonEmptyString$2(value.name) || !isNonEmptyString$2(value.rootPath) || typeof value.createdAtMs !== "number") {
23882
23979
  return void 0;
@@ -74126,6 +74223,7 @@ ${val.stack}`;
74126
74223
  return repo;
74127
74224
  }
74128
74225
  async ready() {
74226
+ await this.syncRunner.ensureMetaLiveMonitor();
74129
74227
  if (this.metaPersister) {
74130
74228
  const version2 = this.metaFlock.version();
74131
74229
  this.metaPersister.start(version2);
@@ -104223,14 +104321,14 @@ ${value}`;
104223
104321
  }
104224
104322
  await this.machine.updateRateLimits(cliType, limits);
104225
104323
  }
104226
- async updateAcpCapabilities(machineId, configId, cliType, agentType, modes, models, configOptions, availableCommands, sessionFork, sourceVersion, modelReasoningEfforts, options = {}) {
104324
+ async updateAcpCapabilities(machineId, configId, cliType, agentType, modes, models, configOptions, availableCommands, sessionFork, sourceVersion, modelReasoningEfforts, acknowledgedSteer = false, options = {}) {
104227
104325
  options.signal?.throwIfAborted();
104228
104326
  if (!this.machine) {
104229
104327
  this.machine = this.createMachineDocument(machineId);
104230
104328
  await this.machine.init();
104231
104329
  }
104232
104330
  options.signal?.throwIfAborted();
104233
- await this.machine.updateAcpCapabilities(configId, cliType, agentType, modes, models, configOptions, availableCommands, sessionFork, sourceVersion, modelReasoningEfforts, options);
104331
+ await this.machine.updateAcpCapabilities(configId, cliType, agentType, modes, models, configOptions, availableCommands, sessionFork, sourceVersion, modelReasoningEfforts, acknowledgedSteer, options);
104234
104332
  }
104235
104333
  async getAcpCapabilities(machineId, configId) {
104236
104334
  if (!this.machine) {
@@ -104410,6 +104508,7 @@ ${value}`;
104410
104508
  this.mirror = new Mirror({
104411
104509
  doc: handle.doc,
104412
104510
  schema: sessionDocSchema,
104511
+ ignoreUnknownProperties: true,
104413
104512
  initialState: merged
104414
104513
  });
104415
104514
  this.historyAutoReadHandle = attachAutoMarkLatestUserHistoryAsRead(this.mirror);
@@ -105336,6 +105435,7 @@ ${value}`;
105336
105435
  configOptions: entry.configOptions,
105337
105436
  availableCommands: entry.availableCommands,
105338
105437
  sessionFork: entry.sessionFork,
105438
+ acknowledgedSteer: entry.acknowledgedSteer,
105339
105439
  sessionForkWorktree: entry.sessionForkWorktree
105340
105440
  });
105341
105441
  class MachineDocument {
@@ -105391,7 +105491,7 @@ ${value}`;
105391
105491
  }
105392
105492
  });
105393
105493
  }
105394
- async updateAcpCapabilities(configId, cliType, agentType, modes, models, configOptions, availableCommands, sessionFork, sourceVersion, modelReasoningEfforts, options = {}) {
105494
+ async updateAcpCapabilities(configId, cliType, agentType, modes, models, configOptions, availableCommands, sessionFork, sourceVersion, modelReasoningEfforts, acknowledgedSteer = false, options = {}) {
105395
105495
  options.signal?.throwIfAborted();
105396
105496
  const normalizedModes = modes.map((mode2) => ({
105397
105497
  id: mode2.id,
@@ -105414,6 +105514,7 @@ ${value}`;
105414
105514
  configOptions: configOptions?.length ? configOptions : void 0,
105415
105515
  availableCommands: availableCommands?.length ? availableCommands : void 0,
105416
105516
  sessionFork,
105517
+ acknowledgedSteer,
105417
105518
  sessionForkWorktree: sessionFork,
105418
105519
  modelReasoningEfforts: modelReasoningEfforts && Object.keys(modelReasoningEfforts).length > 0 ? modelReasoningEfforts : void 0,
105419
105520
  fetchedAt: getServerNow()
@@ -113545,6 +113646,7 @@ ${incoming}`).output;
113545
113646
  configOptions,
113546
113647
  availableCommands,
113547
113648
  sessionFork: lifecycleCapabilities.sessionFork === true,
113649
+ acknowledgedSteer: lifecycleCapabilities.acknowledgedSteer === true,
113548
113650
  ...modelReasoningEfforts ? {
113549
113651
  modelReasoningEfforts
113550
113652
  } : {}
@@ -114648,7 +114750,8 @@ ${incoming}`).output;
114648
114750
  const toolCallId = typeof params.toolCallId === "string" ? params.toolCallId : void 0;
114649
114751
  const requestId = randomUUID$1();
114650
114752
  const firstQuestion = elicitation.meta.questions[0];
114651
- const autoResolveAtEpochSeconds = typeof elicitation.autoResolutionMs === "number" && Number.isFinite(elicitation.autoResolutionMs) ? Math.floor((getServerNow() + Math.max(0, elicitation.autoResolutionMs)) / 1e3) : void 0;
114753
+ const autoResolveAt = typeof elicitation.autoResolutionMs === "number" && Number.isFinite(elicitation.autoResolutionMs) ? getServerNow() + Math.max(0, elicitation.autoResolutionMs) : void 0;
114754
+ const autoResolveAtEpochSeconds = autoResolveAt === void 0 ? void 0 : Math.floor(autoResolveAt / 1e3);
114652
114755
  const lodyElicitation = {
114653
114756
  version: 1,
114654
114757
  questions: elicitation.meta.questions,
@@ -114656,6 +114759,27 @@ ${incoming}`).output;
114656
114759
  autoResolveAtEpochSeconds
114657
114760
  } : {}
114658
114761
  };
114762
+ const legacyQuestionMeta = this.options.agentConfig?.agentType === "codex" ? {
114763
+ codex: {
114764
+ requestUserInput: {
114765
+ version: 1,
114766
+ allowCustomAnswer: elicitation.meta.allowCustomAnswer,
114767
+ questions: elicitation.meta.questions,
114768
+ ...autoResolveAt !== void 0 ? {
114769
+ autoResolveAt
114770
+ } : {}
114771
+ }
114772
+ }
114773
+ } : this.options.agentConfig?.agentType === "claude" ? {
114774
+ claudeCode: {
114775
+ requestType: "askUserQuestion",
114776
+ askUserQuestion: {
114777
+ version: 1,
114778
+ allowCustomAnswer: elicitation.meta.allowCustomAnswer,
114779
+ questions: elicitation.meta.questions
114780
+ }
114781
+ }
114782
+ } : {};
114659
114783
  const syntheticRequest = {
114660
114784
  sessionId,
114661
114785
  toolCall: {
@@ -114682,7 +114806,8 @@ ${incoming}`).output;
114682
114806
  _meta: {
114683
114807
  lody: {
114684
114808
  elicitation: lodyElicitation
114685
- }
114809
+ },
114810
+ ...legacyQuestionMeta
114686
114811
  }
114687
114812
  };
114688
114813
  this.logger.debug(`[${this.options.sessionId}] Bridging AskUserQuestion elicitation (toolCallId=${toolCallId ?? "<none>"}, questions=${elicitation.meta.questions.length})`);
@@ -129191,7 +129316,8 @@ ${fallbackStderrTail}` : errorMessage2;
129191
129316
  try {
129192
129317
  return {
129193
129318
  ...normalizeAcpSessionCapabilities(sessionResponse, {
129194
- sessionFork: client2.supportsSessionFork?.() === true
129319
+ sessionFork: client2.supportsSessionFork?.() === true,
129320
+ acknowledgedSteer: client2.supportsAcknowledgedSteer()
129195
129321
  }),
129196
129322
  capabilitySourceVersion
129197
129323
  };
@@ -131453,6 +131579,32 @@ path=/${options.repoFullName}.git
131453
131579
  isClean
131454
131580
  };
131455
131581
  }
131582
+ async inspectWorktree(sessionId) {
131583
+ return withRepoLock(this.repoId, async () => {
131584
+ assertSafeSessionId(sessionId);
131585
+ const worktreePath = this.getWorktreeHostPath(sessionId);
131586
+ if (!fs.existsSync(worktreePath)) {
131587
+ return {
131588
+ state: "missing",
131589
+ path: worktreePath
131590
+ };
131591
+ }
131592
+ try {
131593
+ const info = await this.getWorktreeInfo(sessionId);
131594
+ return {
131595
+ state: info.isClean ? "clean" : "dirty",
131596
+ path: worktreePath,
131597
+ info
131598
+ };
131599
+ } catch (error2) {
131600
+ return {
131601
+ state: "failed",
131602
+ path: worktreePath,
131603
+ message: error2 instanceof Error ? error2.message : String(error2)
131604
+ };
131605
+ }
131606
+ });
131607
+ }
131456
131608
  async removeWorktree(sessionId, force = false, branchName, options) {
131457
131609
  return withRepoLock(this.repoId, async () => {
131458
131610
  const resolvedBranchName = await this.removeWorktreeInternal(sessionId, {
@@ -131552,7 +131704,10 @@ path=/${options.repoFullName}.git
131552
131704
  ];
131553
131705
  if (options.force) args2.splice(2, 0, "--force");
131554
131706
  await this.runGit(args2, this.getGitAdminCwd());
131555
- } catch {
131707
+ } catch (error2) {
131708
+ if (!options.force) {
131709
+ throw error2;
131710
+ }
131556
131711
  this.logger.debug(`[${this.repoId}] git worktree remove failed, removing directory manually`);
131557
131712
  fs.rmSync(worktreePath, {
131558
131713
  recursive: true,
@@ -132895,6 +133050,9 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
132895
133050
  function shouldApplyMachineDeleteLocalProjectCommand(project, command2) {
132896
133051
  return project.createdAtMs <= command2.requestedAt;
132897
133052
  }
133053
+ function isSessionInLocalProjectRemovalScope(session2, target) {
133054
+ return session2.machineId === target.machineId && session2.project?.kind === "local" && session2.project.localProjectId === target.localProjectId;
133055
+ }
132898
133056
  function readLegacyMachineLocalProjects(machineMeta) {
132899
133057
  const localProjects = machineMeta?.localProjects;
132900
133058
  if (!localProjects || typeof localProjects !== "object") {
@@ -136258,7 +136416,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136258
136416
  });
136259
136417
  const existing = await this.deps.workspaceDocument.getAcpCapabilities(this.deps.machineId, agentConfigId);
136260
136418
  const availableCommands = capabilities.availableCommands !== void 0 ? capabilities.availableCommands : existing?.sourceVersion === sourceVersion ? existing.availableCommands : void 0;
136261
- await this.deps.workspaceDocument.updateAcpCapabilities(this.deps.machineId, agentConfigId, config2.agentCliType, config2.agentType, capabilities.modes, capabilities.models, capabilities.configOptions, availableCommands, capabilities.sessionFork, sourceVersion, capabilities.modelReasoningEfforts);
136419
+ await this.deps.workspaceDocument.updateAcpCapabilities(this.deps.machineId, agentConfigId, config2.agentCliType, config2.agentType, capabilities.modes, capabilities.models, capabilities.configOptions, availableCommands, capabilities.sessionFork, sourceVersion, capabilities.modelReasoningEfforts, capabilities.acknowledgedSteer);
136262
136420
  })().catch((error2) => {
136263
136421
  this.deps.logger.debug(`[${session2.sessionId}] Failed to update ACP capabilities from created session: ${formatErrorMessage(error2)}`);
136264
136422
  });
@@ -136432,7 +136590,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136432
136590
  options.signal?.throwIfAborted();
136433
136591
  await this.emitBuiltinRuntimeStatusForRefresh(message, options.onAcpBinaryProgress);
136434
136592
  options.signal?.throwIfAborted();
136435
- const { modes, models, configOptions, availableCommands, sessionFork, modelReasoningEfforts, capabilitySourceVersion } = await this.deps.fetchAcpCapabilities(message.cliType, message.agentType, message.env, message.customAcp, message.runtimeOverrides, {
136593
+ const { modes, models, configOptions, availableCommands, sessionFork, acknowledgedSteer, modelReasoningEfforts, capabilitySourceVersion } = await this.deps.fetchAcpCapabilities(message.cliType, message.agentType, message.env, message.customAcp, message.runtimeOverrides, {
136436
136594
  signal: options.signal,
136437
136595
  onManagedRuntimeProgress: (event) => {
136438
136596
  if (options.signal?.aborted) return;
@@ -136445,7 +136603,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136445
136603
  agentType: message.agentType,
136446
136604
  customAcp: message.customAcp,
136447
136605
  runtimeOverrides: message.runtimeOverrides
136448
- }), modelReasoningEfforts, {
136606
+ }), modelReasoningEfforts, acknowledgedSteer, {
136449
136607
  signal: options.signal
136450
136608
  });
136451
136609
  return {
@@ -137254,18 +137412,21 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
137254
137412
  }
137255
137413
  }
137256
137414
  }
137257
- peekStashedRpcTurn(sessionId, meta) {
137415
+ peekStashedRpcTurn(sessionId, meta, history = []) {
137258
137416
  const stash = this.rpcTurnStash.get(sessionId);
137259
137417
  if (!stash) {
137260
137418
  return null;
137261
137419
  }
137262
137420
  const now2 = Date.now();
137263
137421
  for (const [userTurnId, stashed] of stash) {
137264
- const isTerminal2 = meta.lastHandledUserMsgId === userTurnId || this.deps.executionService.getTerminalUserTurnStatusWithoutEntry?.(sessionId, userTurnId) !== void 0;
137422
+ const isTerminal2 = meta.lastHandledUserMsgId === userTurnId || this.deps.executionService.getTerminalUserTurnStatusWithoutEntry?.(sessionId, userTurnId) !== void 0 || history.some((entry) => entry.id === userTurnId && entry.role === "user" && (entry.status === "handled" || entry.status === "failed" || entry.status === "canceled"));
137265
137423
  if (stashed.expiresAtMs <= now2 || isTerminal2) {
137266
137424
  stash.delete(userTurnId);
137267
137425
  continue;
137268
137426
  }
137427
+ if (userTurnId === meta.lastMissingHistoryUserMsgId) {
137428
+ continue;
137429
+ }
137269
137430
  this.turnSourceHints.set(`${sessionId}:${userTurnId}`, "rpc");
137270
137431
  return stashed.entry;
137271
137432
  }
@@ -137508,7 +137669,8 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
137508
137669
  if (!isActive()) {
137509
137670
  return;
137510
137671
  }
137511
- const meta = isLoroRepoDocDeleted(record2) ? void 0 : record2?.meta;
137672
+ const docDeleted = isLoroRepoDocDeleted(record2);
137673
+ const meta = docDeleted ? void 0 : record2?.meta;
137512
137674
  phase = "evaluate-ownership";
137513
137675
  const isOwned = meta?.machineId === this.deps.machineId && !meta?.isArchived;
137514
137676
  if (!isOwned) {
@@ -137517,7 +137679,9 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
137517
137679
  this.watchedSessions.delete(sessionId);
137518
137680
  this.cancelCheckChains.delete(sessionId);
137519
137681
  this.cancelSeenTurn.delete(sessionId);
137520
- this.rpcTurnStash.delete(sessionId);
137682
+ if (meta || docDeleted) {
137683
+ this.rpcTurnStash.delete(sessionId);
137684
+ }
137521
137685
  this.interruptAccessRetry(sessionId);
137522
137686
  return;
137523
137687
  }
@@ -138219,7 +138383,8 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
138219
138383
  if (!isActive()) {
138220
138384
  return null;
138221
138385
  }
138222
- this.deps.logger.debug(`[${sessionId}] Pending user turn metadata is visible but history is missing it; waiting up to ${SessionDispatchWatcher.HISTORY_SYNC_WAIT_TIMEOUT_MS / 1e3}s for history CRDT sync`);
138386
+ const pendingUserTurnId = getPendingUserTurnActivationId(meta);
138387
+ this.deps.logger.debug(`[${sessionId}] Pending user turn ${getPendingUserTurnActivationId(meta) ?? "unknown"} metadata is visible but history is missing it; waiting up to ${SessionDispatchWatcher.HISTORY_SYNC_WAIT_TIMEOUT_MS / 1e3}s for history CRDT sync (pendingUserMsgId=${pendingUserTurnId ?? "unknown"})`);
138223
138388
  return await new Promise((resolve2) => {
138224
138389
  let settled = false;
138225
138390
  let currentMeta = meta;
@@ -138349,7 +138514,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
138349
138514
  }
138350
138515
  };
138351
138516
  timer2 = SessionDispatchWatcher.setUnrefTimeout(() => {
138352
- this.deps.logger.warn(`[${sessionId}] User turn did not arrive in history after ${SessionDispatchWatcher.HISTORY_SYNC_WAIT_TIMEOUT_MS / 1e3}s; entering dispatch recovery`);
138517
+ this.deps.logger.warn(`[${sessionId}] User turn ${pendingUserTurnId ?? "unknown"} did not arrive in history after ${SessionDispatchWatcher.HISTORY_SYNC_WAIT_TIMEOUT_MS / 1e3}s; entering dispatch recovery`);
138353
138518
  finish(null);
138354
138519
  }, SessionDispatchWatcher.HISTORY_SYNC_WAIT_TIMEOUT_MS);
138355
138520
  progressTimer = setInterval(() => {
@@ -138359,7 +138524,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
138359
138524
  }
138360
138525
  return;
138361
138526
  }
138362
- this.deps.logger.warn(`[${sessionId}] Still waiting for pending user turn history sync (elapsed=${Date.now() - waitStartedAt}ms docRoom=${sessionDoc.getDocRoomStatus() ?? "unknown"})`);
138527
+ this.deps.logger.warn(`[${sessionId}] Still waiting for pending user turn history sync (pendingUserMsgId=${pendingUserTurnId ?? "unknown"} elapsed=${Date.now() - waitStartedAt}ms docRoom=${sessionDoc.getDocRoomStatus() ?? "unknown"})`);
138363
138528
  }, SessionDispatchWatcher.HISTORY_SYNC_PROGRESS_LOG_MS);
138364
138529
  progressTimer.unref?.();
138365
138530
  if (!isActive()) {
@@ -138437,7 +138602,9 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
138437
138602
  if (pendingUserMsgId) {
138438
138603
  recoveryPatch.lastMissingHistoryUserMsgId = pendingUserMsgId;
138439
138604
  }
138605
+ this.deps.logger.warn(`[${sessionId}] Marking missing-history recovery for user turn ${pendingUserMsgId ?? "unknown"} (message_delivery_failed)`);
138440
138606
  await this.deps.workspaceDocument.repo.upsertDocMeta?.(roomId, recoveryPatch);
138607
+ this.deps.logger.info(`[${sessionId}] Recorded missing-history recovery for user turn ${pendingUserMsgId ?? "unknown"}; the turn stays undispatchable until the user explicitly redelivers it`);
138441
138608
  if (this.deps.recordChatFailure) {
138442
138609
  try {
138443
138610
  await this.deps.recordChatFailure(sessionDoc, "message_delivery_failed", "The user message could not be delivered because its history payload did not sync to this machine. Please resend it after sync recovers.");
@@ -138477,7 +138644,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
138477
138644
  this.turnSourceHints.set(`${meta.id}:${promoted.id}`, "queue");
138478
138645
  return promoted;
138479
138646
  }
138480
- return this.peekStashedRpcTurn(meta.id, meta);
138647
+ return this.peekStashedRpcTurn(meta.id, meta, history);
138481
138648
  }
138482
138649
  async maybeRepairAlreadyHandledTurn(sessionDoc, meta, turn, history) {
138483
138650
  const sessionId = meta.id;
@@ -139876,6 +140043,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
139876
140043
  string$1(),
139877
140044
  boolean()
139878
140045
  ])).optional(),
140046
+ taskToolsEnabled: boolean().optional(),
139879
140047
  inheritSessionDefaults: literal$1(false).optional()
139880
140048
  }).strict().nullable()).optional()
139881
140049
  }).strict();
@@ -151717,6 +151885,7 @@ ${part.truncated ? TRUNCATION_MARKER : ""}${part.content}`).join("\n\n");
151717
151885
  const mirror = new Mirror({
151718
151886
  doc: handle.doc,
151719
151887
  schema: taskDocSchema,
151888
+ ignoreUnknownProperties: true,
151720
151889
  ...options?.seedEmptyDocument ? {
151721
151890
  initialState: emptyTaskDocState(taskId)
151722
151891
  } : {}
@@ -166018,7 +166187,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166018
166187
  "local-project/set-worktree-cleanup"
166019
166188
  ]);
166020
166189
  function isRemoteLocalProjectControlRequest(request2) {
166021
- return HISTORY_REQUEST_TYPES.has(request2.type) || SETUP_REQUEST_TYPES.has(request2.type);
166190
+ return request2.type === "local-project/removal-preflight" || HISTORY_REQUEST_TYPES.has(request2.type) || SETUP_REQUEST_TYPES.has(request2.type);
166022
166191
  }
166023
166192
  function precheckLocalProjectHistoryRequest(args2) {
166024
166193
  const { request: request2, expectedMachineId, expectedWorkspaceId } = args2;
@@ -166057,6 +166226,91 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166057
166226
  requesterUserId
166058
166227
  };
166059
166228
  }
166229
+ function getTargetSessions(target) {
166230
+ return target.sessions.filter((session2) => session2.machineId === target.machineId && !session2.parentSessionId && session2.isWorktree === true && session2.project?.kind === "local" && session2.project.localProjectId === target.localProjectId);
166231
+ }
166232
+ function toCleanupItem(session2, path2) {
166233
+ return {
166234
+ sessionId: session2.id,
166235
+ title: session2.title?.trim() || session2.id,
166236
+ path: path2
166237
+ };
166238
+ }
166239
+ function getManager(target) {
166240
+ return getWorktreeManager({
166241
+ repoId: deriveRepoIdFromLocalProjectPath(target.originalRootPath),
166242
+ source: {
166243
+ kind: "local-shared",
166244
+ originalRootPath: target.originalRootPath
166245
+ },
166246
+ logger: target.logger
166247
+ });
166248
+ }
166249
+ async function preflightLocalProjectWorktreeRemoval(target) {
166250
+ const result = {
166251
+ clean: [],
166252
+ dirty: [],
166253
+ failed: []
166254
+ };
166255
+ const manager = getManager(target);
166256
+ for (const session2 of getTargetSessions(target)) {
166257
+ const inspection = await manager.inspectWorktree(session2.id);
166258
+ if (inspection.state === "missing") continue;
166259
+ const item = toCleanupItem(session2, inspection.path);
166260
+ if (inspection.state === "clean") result.clean.push(item);
166261
+ if (inspection.state === "dirty") result.dirty.push(item);
166262
+ if (inspection.state === "failed") {
166263
+ result.failed.push({
166264
+ ...item,
166265
+ message: inspection.message
166266
+ });
166267
+ }
166268
+ }
166269
+ return result;
166270
+ }
166271
+ async function cleanupLocalProjectWorktrees(target) {
166272
+ const result = {
166273
+ completedAt: getServerNow(),
166274
+ deleted: [],
166275
+ skippedDirty: [],
166276
+ failed: []
166277
+ };
166278
+ const manager = getManager(target);
166279
+ for (const session2 of getTargetSessions(target)) {
166280
+ const inspection = await manager.inspectWorktree(session2.id);
166281
+ if (inspection.state === "missing") continue;
166282
+ const item = toCleanupItem(session2, inspection.path);
166283
+ if (inspection.state === "dirty") {
166284
+ result.skippedDirty.push(item);
166285
+ continue;
166286
+ }
166287
+ if (inspection.state === "failed") {
166288
+ result.failed.push({
166289
+ ...item,
166290
+ message: inspection.message
166291
+ });
166292
+ continue;
166293
+ }
166294
+ try {
166295
+ await manager.removeWorktree(session2.id, false, session2.branchName, {
166296
+ baseBranchName: session2.baseBranch
166297
+ });
166298
+ result.deleted.push(item);
166299
+ } catch (error2) {
166300
+ const latest2 = await manager.inspectWorktree(session2.id);
166301
+ if (latest2.state === "dirty") {
166302
+ result.skippedDirty.push(toCleanupItem(session2, latest2.path));
166303
+ } else if (latest2.state !== "missing") {
166304
+ result.failed.push({
166305
+ ...item,
166306
+ message: formatErrorMessage(error2)
166307
+ });
166308
+ }
166309
+ }
166310
+ }
166311
+ result.completedAt = getServerNow();
166312
+ return result;
166313
+ }
166060
166314
  const SESSION_IMAGE_DOWNLOAD_RETRY_DELAYS_MS = [
166061
166315
  250,
166062
166316
  750,
@@ -168787,7 +169041,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
168787
169041
  }
168788
169042
  void this.processDeleteLocalProjectRequests();
168789
169043
  }
168790
- async archiveSessionResources(sessionId) {
169044
+ async archiveSessionResources(sessionId, options) {
168791
169045
  this.logger.debug(`[${sessionId}] Archiving session resources`);
168792
169046
  this.clearSessionActivePresence(sessionId);
168793
169047
  this.closeSessionTerminals?.(sessionId);
@@ -168808,55 +169062,58 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
168808
169062
  this.logger.debug(`[${sessionId}] Terminating active session`);
168809
169063
  await this.sessionManager.terminateSession(sessionId, true);
168810
169064
  }
168811
- const cleanupTarget = this.resolveWorktreeCleanupTarget({
168812
- sessionMeta,
168813
- machineMeta: archiveMachineMeta
168814
- });
168815
- if (cleanupTarget) {
168816
- const worktreeManager = getWorktreeManager(this.buildWorktreeManagerConfig(cleanupTarget));
168817
- const worktreePath = worktreeManager.getWorktreeHostPath(sessionId);
168818
- if (fs__default.existsSync(worktreePath)) {
168819
- const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
168820
- await runWorktreeCleanup({
168821
- config: await resolveSessionWorktreeCleanupConfig({
168822
- token: this.token,
168823
- workspaceId: this.workspaceId,
168824
- machineId: this.machineId,
168825
- sessionId,
168826
- sessionMeta,
168827
- workspaceDocument: this.workspaceDocument,
168828
- logger: this.logger
168829
- }),
168830
- sessionId,
168831
- workspaceId: this.workspaceId,
168832
- workdir: worktreePath,
168833
- branch: cleanupTarget.branchName ?? sessionMeta?.branchName?.trim() ?? "",
168834
- repoFullName: sessionMeta?.project?.kind === "local" ? void 0 : sessionMeta?.repoFullName,
168835
- localProjectId: sessionMeta?.project?.kind === "local" ? sessionMeta.project.localProjectId : void 0,
168836
- logger: this.logger,
168837
- events: createWorktreeScriptHistoryRecorder({
168838
- sessionDoc,
169065
+ if (!options?.preserveWorktree) {
169066
+ const cleanupTarget = this.resolveWorktreeCleanupTarget({
169067
+ sessionMeta,
169068
+ machineMeta: archiveMachineMeta
169069
+ });
169070
+ if (cleanupTarget) {
169071
+ const worktreeManager = getWorktreeManager(this.buildWorktreeManagerConfig(cleanupTarget));
169072
+ const worktreePath = worktreeManager.getWorktreeHostPath(sessionId);
169073
+ if (fs__default.existsSync(worktreePath)) {
169074
+ const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
169075
+ await runWorktreeCleanup({
169076
+ config: await resolveSessionWorktreeCleanupConfig({
169077
+ token: this.token,
169078
+ workspaceId: this.workspaceId,
169079
+ machineId: this.machineId,
169080
+ sessionId,
169081
+ sessionMeta,
169082
+ workspaceDocument: this.workspaceDocument,
169083
+ logger: this.logger
169084
+ }),
168839
169085
  sessionId,
168840
- phase: "cleanup",
168841
- logger: this.logger
168842
- })
168843
- });
168844
- }
168845
- try {
168846
- const archiveResult = await worktreeManager.archiveWorktree(sessionId);
168847
- if (archiveResult.branchName && archiveResult.branchName !== sessionMeta?.branchName?.trim()) {
168848
- await this.workspaceDocument.repo.upsertDocMeta(sessionRoomId, {
168849
- branchName: archiveResult.branchName
169086
+ workspaceId: this.workspaceId,
169087
+ workdir: worktreePath,
169088
+ branch: cleanupTarget.branchName ?? sessionMeta?.branchName?.trim() ?? "",
169089
+ repoFullName: sessionMeta?.project?.kind === "local" ? void 0 : sessionMeta?.repoFullName,
169090
+ localProjectId: sessionMeta?.project?.kind === "local" ? sessionMeta.project.localProjectId : void 0,
169091
+ logger: this.logger,
169092
+ events: createWorktreeScriptHistoryRecorder({
169093
+ sessionDoc,
169094
+ sessionId,
169095
+ phase: "cleanup",
169096
+ logger: this.logger
169097
+ })
168850
169098
  });
168851
169099
  }
168852
- } catch (error2) {
168853
- this.logger.debug(`[${sessionId}] Failed to archive worktree: ${formatErrorMessage(error2)}`);
169100
+ try {
169101
+ const archiveResult = await worktreeManager.archiveWorktree(sessionId);
169102
+ if (archiveResult.branchName && archiveResult.branchName !== sessionMeta?.branchName?.trim()) {
169103
+ await this.workspaceDocument.repo.upsertDocMeta(sessionRoomId, {
169104
+ branchName: archiveResult.branchName
169105
+ });
169106
+ }
169107
+ } catch (error2) {
169108
+ this.logger.debug(`[${sessionId}] Failed to archive worktree: ${formatErrorMessage(error2)}`);
169109
+ }
168854
169110
  }
168855
169111
  }
168856
169112
  await this.sessionManager.archiveSession(sessionId);
168857
169113
  this.logger.debug(`[${sessionId}] Session doc cleaned`);
168858
169114
  await this.workspaceDocument.repo.upsertDocMeta(sessionRoomId, {
168859
- isArchived: true
169115
+ isArchived: true,
169116
+ status: SessionStatusFactory.idle()
168860
169117
  });
168861
169118
  this.logger.debug(`[${sessionId}] Session meta archived`);
168862
169119
  this.store.get(sessionId).logger = null;
@@ -168916,14 +169173,28 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
168916
169173
  }
168917
169174
  this.logger.debug(`[local-project] Processing ${localProjectEntries.length} delete request(s)`);
168918
169175
  for (const [localProjectId, command2] of localProjectEntries) {
169176
+ if (command2.status === "completed") {
169177
+ continue;
169178
+ }
168919
169179
  if (this.deleteLocalProjectInFlight.has(localProjectId)) {
168920
169180
  this.logger.debug(`[local-project] ${localProjectId} already in progress`);
168921
169181
  continue;
168922
169182
  }
168923
169183
  this.deleteLocalProjectInFlight.add(localProjectId);
168924
169184
  try {
168925
- await this.deleteLocalProjectResources(localProjectId, command2);
168926
- await this.removeDeleteLocalProjectRequest(localProjectId);
169185
+ const cleanupResult = await this.deleteLocalProjectResources(localProjectId, command2);
169186
+ if (command2.cleanupWorktrees && cleanupResult) {
169187
+ await this.writeMachineFlockRow({
169188
+ key: machineFlockKeys.deleteLocalProjectCommand(localProjectId),
169189
+ value: {
169190
+ ...command2,
169191
+ status: "completed",
169192
+ cleanupResult
169193
+ }
169194
+ });
169195
+ } else {
169196
+ await this.removeDeleteLocalProjectRequest(localProjectId);
169197
+ }
168927
169198
  } catch (error2) {
168928
169199
  this.logger.error(`[local-project] Failed to delete ${localProjectId}: ${formatErrorMessage(error2)}`);
168929
169200
  } finally {
@@ -168941,56 +169212,68 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
168941
169212
  this.logger.debug(`[local-project] Failed to cleanup worktree setup for ${localProjectId}: ${formatErrorMessage(error2)}`);
168942
169213
  }
168943
169214
  }
168944
- async stopActiveLocalProjectSessions(localProjectId) {
168945
- const sessionIds = [
168946
- ...this.workspaceDocument.sessions.keys()
168947
- ];
168948
- if (sessionIds.length === 0) return;
168949
- let stoppedCount = 0;
168950
- for (const sessionId of sessionIds) {
168951
- try {
168952
- const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
168953
- const meta = await sessionDoc.getMetaState();
168954
- if (!meta) continue;
168955
- if (meta.machineId !== this.machineId) continue;
168956
- if (meta.project?.kind !== "local") continue;
168957
- if (meta.project.localProjectId !== localProjectId) continue;
168958
- const hasRunningProcess = this.sessionManager.hasSession(sessionId);
168959
- if (!hasRunningProcess && !isActiveSessionStatus(meta.status)) continue;
168960
- this.clearSessionActivePresence(sessionId);
168961
- this.closeSessionTerminals?.(sessionId);
168962
- await this.finalizeACPState(sessionId);
168963
- if (hasRunningProcess) {
168964
- await this.sessionManager.terminateSession(sessionId, true);
168965
- }
168966
- await sessionDoc.setStatus(SessionStatusFactory.idle());
168967
- stoppedCount += 1;
168968
- } catch (error2) {
168969
- this.logger.debug(`[${sessionId}] Failed to stop active session before local project removal: ${formatErrorMessage(error2)}`);
168970
- }
169215
+ async archiveLocalProjectSessions(localProjectId) {
169216
+ const sessions = (await listAliveSessionMetas(this.workspaceDocument)).filter(({ meta }) => isSessionInLocalProjectRemovalScope(meta, {
169217
+ machineId: this.machineId,
169218
+ localProjectId
169219
+ }));
169220
+ if (sessions.length === 0) return;
169221
+ const rootSessions = sessions.filter(({ meta }) => meta.isArchived !== true && !meta.parentSessionId);
169222
+ const archivedRootSessionIds = new Set(rootSessions.map(({ meta }) => meta.id));
169223
+ for (const { meta } of rootSessions) {
169224
+ await this.archiveSessionResources(meta.id, {
169225
+ preserveWorktree: true
169226
+ });
168971
169227
  }
168972
- if (stoppedCount > 0) {
168973
- this.logger.debug(`[local-project] Stopped ${stoppedCount} active session(s) before removing ${localProjectId}`);
169228
+ for (const { roomId, meta } of sessions) {
169229
+ if (archivedRootSessionIds.has(meta.id)) continue;
169230
+ if (this.sessionManager.hasSession(meta.id)) {
169231
+ await this.archiveSessionResources(meta.id, {
169232
+ preserveWorktree: true
169233
+ });
169234
+ continue;
169235
+ }
169236
+ if (meta.isArchived === true) continue;
169237
+ await this.workspaceDocument.repo.upsertDocMeta(roomId, {
169238
+ isArchived: true,
169239
+ status: SessionStatusFactory.idle()
169240
+ });
168974
169241
  }
169242
+ this.logger.debug(`[local-project] Processed ${sessions.length} session(s) before removing ${localProjectId}`);
168975
169243
  }
168976
169244
  async deleteLocalProjectResources(localProjectId, command2) {
168977
169245
  const existingProject = await resolveWorkspaceLocalProject(this.workspaceDocument.repo, this.workspaceId, this.machineId, localProjectId);
168978
- if (!existingProject) {
169246
+ if (!existingProject && !command2.cleanupWorktrees) {
168979
169247
  this.logger.debug(`[local-project] ${localProjectId} already removed`);
168980
169248
  await this.cleanupLocalProjectWorktreeSetup(localProjectId);
168981
- return;
169249
+ return void 0;
168982
169250
  }
168983
- if (!shouldApplyMachineDeleteLocalProjectCommand(existingProject, command2)) {
169251
+ if (existingProject && !shouldApplyMachineDeleteLocalProjectCommand(existingProject, command2)) {
168984
169252
  this.logger.debug(`[local-project] Skipping stale delete request for ${localProjectId}; project was created after the request`);
168985
- return;
169253
+ return void 0;
169254
+ }
169255
+ await this.archiveLocalProjectSessions(localProjectId);
169256
+ let cleanupResult;
169257
+ const originalRootPath = existingProject?.rootPath ?? command2.originalRootPath;
169258
+ if (command2.cleanupWorktrees && originalRootPath) {
169259
+ const sessions = (await listAliveSessionMetas(this.workspaceDocument)).map(({ meta }) => meta);
169260
+ cleanupResult = await cleanupLocalProjectWorktrees({
169261
+ machineId: this.machineId,
169262
+ localProjectId,
169263
+ originalRootPath,
169264
+ sessions,
169265
+ logger: this.logger
169266
+ });
169267
+ }
169268
+ if (existingProject) {
169269
+ await removeMachineLocalProject(this.workspaceDocument.repo, this.workspaceId, this.machineId, localProjectId, void 0, {
169270
+ sync: this.workspaceDocument,
169271
+ reason: "local-project-delete-command"
169272
+ });
169273
+ this.logger.debug(`[local-project] Removed ${existingProject.name} (${existingProject.rootPath})`);
168986
169274
  }
168987
- await this.stopActiveLocalProjectSessions(localProjectId);
168988
- await removeMachineLocalProject(this.workspaceDocument.repo, this.workspaceId, this.machineId, localProjectId, void 0, {
168989
- sync: this.workspaceDocument,
168990
- reason: "local-project-delete-command"
168991
- });
168992
- this.logger.debug(`[local-project] Removed ${existingProject.name} (${existingProject.rootPath})`);
168993
169275
  await this.cleanupLocalProjectWorktreeSetup(localProjectId);
169276
+ return cleanupResult;
168994
169277
  }
168995
169278
  toDeleteRequestRecord(request2) {
168996
169279
  if (!request2 || typeof request2 !== "object") {
@@ -172723,6 +173006,20 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
172723
173006
  return authorized.response;
172724
173007
  }
172725
173008
  const { rootPath } = authorized;
173009
+ if (request2.type === "local-project/removal-preflight") {
173010
+ const sessions = (await listAliveSessionMetas(this.workspaceDocument)).map(({ meta }) => meta);
173011
+ return {
173012
+ ok: true,
173013
+ type: "local-project/removal-preflight",
173014
+ result: await preflightLocalProjectWorktreeRemoval({
173015
+ machineId: this.machineId,
173016
+ localProjectId: request2.localProjectId,
173017
+ originalRootPath: rootPath,
173018
+ sessions,
173019
+ logger: this.logger
173020
+ })
173021
+ };
173022
+ }
172726
173023
  if (isLocalProjectWorktreeConfigRequest(request2)) {
172727
173024
  return await handleLocalProjectWorktreeConfigRequest(request2);
172728
173025
  }
@@ -181876,7 +182173,8 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181876
182173
  client2 = started.client;
181877
182174
  acpSessionId = started.acpSessionId;
181878
182175
  acpCapabilities = normalizeAcpSessionCapabilities(started.sessionResponse, {
181879
- sessionFork: started.client.supportsSessionFork()
182176
+ sessionFork: started.client.supportsSessionFork(),
182177
+ acknowledgedSteer: started.client.supportsAcknowledgedSteer()
181880
182178
  });
181881
182179
  } catch (error2) {
181882
182180
  if (error2 instanceof AcpStartupProcessExitError || error2 instanceof AcpStartupProcessError) {
@@ -185400,9 +185698,13 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
185400
185698
  const BEL = String.fromCharCode(7);
185401
185699
  const OSC_TITLE_REGEX = new RegExp(`${ESC}\\](?:0|2);([^${BEL}${ESC}]*)(?:${BEL}|${ESC}\\\\)`, "g");
185402
185700
  const TERMINAL_ENV_BLOCKLIST = /* @__PURE__ */ new Set([
185701
+ "ELECTRON_RUN_AS_NODE",
185403
185702
  "LODY_CLI_TOKEN",
185703
+ "LODY_ELECTRON_BOOTSTRAP",
185404
185704
  "LODY_ELECTRON_SESSION_TOKEN",
185705
+ "LODY_GIT_CRED_BROKER_STATE_FILE",
185405
185706
  "LODY_GIT_CRED_BROKER_TOKEN",
185707
+ "LODY_GIT_CRED_BROKER_URL",
185406
185708
  LODY_GIT_CRED_CONTEXT_TOKEN_ENV,
185407
185709
  LODY_MANAGED_GH_TOKEN_SHA256_ENV
185408
185710
  ]);
@@ -191403,6 +191705,22 @@ ${trimmed2}${closing}`;
191403
191705
  }
191404
191706
  };
191405
191707
  }
191708
+ if (message.type === "local-project/removal-preflight") {
191709
+ const runtime = await this.resolveWorkspaceRuntime(message.workspaceId);
191710
+ const rootPath = await this.resolveWorkspaceProjectRootPath(runtime, message.localProjectId);
191711
+ const sessions = (await listAliveSessionMetas(runtime.lody.documentManager)).map(({ meta }) => meta);
191712
+ return {
191713
+ ok: true,
191714
+ type: "local-project/removal-preflight",
191715
+ result: await preflightLocalProjectWorktreeRemoval({
191716
+ machineId: this.machineId,
191717
+ localProjectId: message.localProjectId,
191718
+ originalRootPath: rootPath,
191719
+ sessions,
191720
+ logger: this.logger
191721
+ })
191722
+ };
191723
+ }
191406
191724
  if (message.type === "local-project/list") {
191407
191725
  return {
191408
191726
  ok: true,
@@ -220311,7 +220629,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
220311
220629
  data = createReviewBundleSnapshot(bundle);
220312
220630
  }
220313
220631
  const { injectReviewSnapshot } = await import("./chunks/index-VoI6Ds2-.js");
220314
- const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-BetqYmAc.js").then(async (m) => {
220632
+ const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-GDxDN5px.js").then(async (m) => {
220315
220633
  await m.__tla;
220316
220634
  return m;
220317
220635
  });