lody 0.71.2 → 0.71.3

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.
@@ -3,7 +3,7 @@ import { readFile, mkdir, writeFile, rename } from "node:fs/promises";
3
3
  import os__default from "node:os";
4
4
  import path__default from "node:path";
5
5
  import process from "node:process";
6
- const reviewViewerVersion = "0.71.2";
6
+ const reviewViewerVersion = "0.71.3";
7
7
  const reviewViewerSha256 = "e395b367a7644fe83bc050d0c646810914a2844824fd2b5d11d24ae4f55b6893";
8
8
  const reviewViewerFileName = "standalone.html";
9
9
  const DEFAULT_CDN_BASES = ["https://cdn.jsdelivr.net/npm", "https://unpkg.com"];
package/dist/index.js CHANGED
@@ -4190,7 +4190,7 @@ let __tla = Promise.all([
4190
4190
  }
4191
4191
  }
4192
4192
  const name$1 = "lody";
4193
- const version$7 = "0.71.2";
4193
+ const version$7 = "0.71.3";
4194
4194
  const description$1 = "Lody Agent CLI tool for managing remote command execution";
4195
4195
  const type$2 = "module";
4196
4196
  const main$4 = "dist/index.js";
@@ -4204,7 +4204,7 @@ let __tla = Promise.all([
4204
4204
  "build": "pnpm run clean && pnpm run prepare:acp-adapters && pnpm run typecheck && pnpm run build:bundle && pnpm run check:published-bundle-imports && pnpm run copy:wasm",
4205
4205
  "build:watch": "pnpm run prepare:review-assets && vite build --watch",
4206
4206
  "build:bundle": "pnpm run prepare:review-assets && vite build",
4207
- "prepare:acp-adapters": "pnpm --dir ../.. --filter acp-extension-claude build && pnpm --dir ../.. --filter acp-extension-codex build",
4207
+ "prepare:acp-adapters": "corepack pnpm --dir ../.. --filter acp-extension-claude build && corepack pnpm --dir ../.. --filter acp-extension-codex build",
4208
4208
  "prepare:review-assets": "pnpm --dir ../.. --filter lody-code-review-viewer build",
4209
4209
  "check:published-bundle-imports": "node scripts/check-published-bundle-imports.js",
4210
4210
  "copy:wasm": "node scripts/copy-loro-wasm.js",
@@ -4516,7 +4516,7 @@ let __tla = Promise.all([
4516
4516
  displayName: "Codex"
4517
4517
  }
4518
4518
  ];
4519
- const usesAcpProvidedSessionTitle = (cliType, agentType) => cliType === "builtin" && (agentType === "claude" || agentType === "codex");
4519
+ const usesAcpProvidedSessionTitle = (cliType, agentType) => cliType === "builtin" && agentType === "claude";
4520
4520
  const isBuiltinRuntimeOverrides = (value) => {
4521
4521
  if (!value || typeof value !== "object" || Array.isArray(value)) {
4522
4522
  return false;
@@ -136226,6 +136226,32 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136226
136226
  };
136227
136227
  }
136228
136228
  }
136229
+ const isOperationStoreBusyError = (error2) => {
136230
+ if (!(error2 instanceof Error)) return false;
136231
+ const code2 = error2.code;
136232
+ return code2 === "SQLITE_BUSY" || code2 === "SQLITE_BUSY_SNAPSHOT";
136233
+ };
136234
+ const BUSY_RETRY_DELAYS_MS = [
136235
+ 100,
136236
+ 300,
136237
+ 900
136238
+ ];
136239
+ const runWithOperationStoreBusyRetry = async (run2, options = {}) => {
136240
+ const delays = options.delaysMs ?? BUSY_RETRY_DELAYS_MS;
136241
+ const sleep2 = options.sleep ?? ((ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2)));
136242
+ for (let attempt = 0; ; attempt += 1) {
136243
+ try {
136244
+ return run2();
136245
+ } catch (error2) {
136246
+ if (!isOperationStoreBusyError(error2)) throw error2;
136247
+ const delayMs = delays[attempt];
136248
+ if (delayMs === void 0) {
136249
+ throw new LodyOperationStoreError("STORE_BUSY", "The local Operation store is busy; retry the command.", true);
136250
+ }
136251
+ await sleep2(delayMs);
136252
+ }
136253
+ }
136254
+ };
136229
136255
  const parseJson = (text, schema2, label2) => {
136230
136256
  let parsed;
136231
136257
  try {
@@ -136361,7 +136387,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136361
136387
  const getOperationDeliveryId = (requesterSessionId, operationId) => `operation:${requesterSessionId}:${operationId}:completion`;
136362
136388
  const getOperationCompletionTurnId = (requesterSessionId, operationId) => `operation-completion:${requesterSessionId}:${operationId}`;
136363
136389
  class LodyOperationStore {
136364
- constructor(dbPath = getLodyOperationStorePath(), now2 = Date.now) {
136390
+ constructor(dbPath = getLodyOperationStorePath(), now2 = Date.now, options = {}) {
136365
136391
  this.now = now2;
136366
136392
  mkdirSync$2(path__default$1.dirname(dbPath), {
136367
136393
  recursive: true
@@ -136371,8 +136397,10 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136371
136397
  this.db.pragma("journal_mode = WAL");
136372
136398
  this.db.pragma("foreign_keys = ON");
136373
136399
  this.migrate();
136374
- this.repairTerminalDeliveries();
136375
- this.cleanupExpired(false);
136400
+ if (options.maintenance !== false) {
136401
+ this.repairTerminalDeliveries();
136402
+ this.cleanupExpired(false);
136403
+ }
136376
136404
  }
136377
136405
  db;
136378
136406
  close() {
@@ -136414,7 +136442,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136414
136442
  claimedItemIndexes
136415
136443
  };
136416
136444
  });
136417
- const accepted = transaction();
136445
+ const accepted = transaction.immediate();
136418
136446
  this.cleanupExpired(false);
136419
136447
  return accepted;
136420
136448
  }
@@ -136471,7 +136499,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136471
136499
  return {
136472
136500
  claimed: true
136473
136501
  };
136474
- })();
136502
+ }).immediate();
136475
136503
  }
136476
136504
  markItemInputDurable(requesterSessionId, operationId, itemIndex, claimToken) {
136477
136505
  return this.db.transaction(() => {
@@ -136492,7 +136520,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136492
136520
  this.db.prepare(`DELETE FROM operation_item_materializations
136493
136521
  WHERE requester_session_id = ? AND operation_id = ? AND item_index = ?`).run(requesterSessionId, operationId, itemIndex);
136494
136522
  return this.get(requesterSessionId, operationId);
136495
- })();
136523
+ }).immediate();
136496
136524
  }
136497
136525
  finish(requesterSessionId, operationId, completion, finishedAt = new Date(this.now()).toISOString()) {
136498
136526
  const bounded = this.assertCompletionBound(completion);
@@ -136518,7 +136546,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136518
136546
  }
136519
136547
  return updated;
136520
136548
  });
136521
- return transaction();
136549
+ return transaction.immediate();
136522
136550
  }
136523
136551
  cancel(requesterSessionId, operationId) {
136524
136552
  const transaction = this.db.transaction(() => {
@@ -136542,7 +136570,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136542
136570
  didCancel: true
136543
136571
  };
136544
136572
  });
136545
- return transaction();
136573
+ return transaction.immediate();
136546
136574
  }
136547
136575
  listPendingDeliveries(workspaceId, requesterSessionId) {
136548
136576
  const rows = requesterSessionId ? this.db.prepare(`SELECT * FROM deliveries
@@ -136690,7 +136718,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136690
136718
  )`).run(cutoff);
136691
136719
  this.db.prepare(`INSERT INTO orchestration_meta (key, value) VALUES ('last_cleanup_at_ms', ?)
136692
136720
  ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(String(nowMs2));
136693
- })();
136721
+ }).immediate();
136694
136722
  }
136695
136723
  migrate() {
136696
136724
  this.db.exec(`
@@ -136774,7 +136802,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
136774
136802
  WHERE deliveries.requester_session_id = operations.requester_session_id
136775
136803
  AND deliveries.operation_id = operations.operation_id
136776
136804
  )`).run();
136777
- })();
136805
+ }).immediate();
136778
136806
  }
136779
136807
  }
136780
136808
  const terminalAssistantFor = (history, userTurnId) => history.find((entry) => entry.role === "assistant" && entry.userTurnId === userTurnId && (entry.finished === true || typeof entry.endedAt === "number"));
@@ -141000,12 +141028,6 @@ ${entry.text}`).join("\n\n");
141000
141028
  } : {}
141001
141029
  };
141002
141030
  }
141003
- async function ensureSessionDocSynced(sessionDoc, reason) {
141004
- const synced = await sessionDoc.waitUntilSynced();
141005
- if (!synced) {
141006
- throw new Error(`Session document changes were not confirmed by Loro Streams (${reason}). Retry the command after checking network connectivity.`);
141007
- }
141008
- }
141009
141031
  function buildCliHistoryInputConfig(args2) {
141010
141032
  return {
141011
141033
  prompt: args2.prompt,
@@ -141420,13 +141442,24 @@ ${entry.text}`).join("\n\n");
141420
141442
  } catch {
141421
141443
  }
141422
141444
  }
141423
- async function writeDispatchPointerAndSync(args2) {
141445
+ async function writeDispatchPointer(args2) {
141424
141446
  await args2.manager.repo.upsertDocMeta(getSessionRoomId(args2.sessionId), {
141425
141447
  latestUserMsgId: args2.userTurnId,
141426
141448
  lastMissingHistoryUserMsgId: void 0
141427
141449
  });
141428
- await ensureSessionDocSynced(args2.sessionDoc, `${args2.reason}:doc`);
141429
- await ensureWorkspaceMetaSynced(args2.manager, `${args2.reason}:meta`);
141450
+ }
141451
+ async function confirmDispatchSyncedBestEffort(args2) {
141452
+ const logger2 = args2.logger ?? getLogger("session");
141453
+ try {
141454
+ const synced = await args2.sessionDoc.waitUntilSynced();
141455
+ if (!synced) {
141456
+ logger2.warn(`Session dispatch not yet confirmed by Loro Streams (${args2.reason}:doc); the durable dispatch pointer will converge on reconnect.`);
141457
+ return;
141458
+ }
141459
+ await ensureWorkspaceMetaSynced(args2.manager, `${args2.reason}:meta`);
141460
+ } catch (error2) {
141461
+ logger2.warn(`Session dispatch confirmation did not complete (${args2.reason}); the durable dispatch pointer will converge on reconnect: ${formatErrorMessage(error2)}`);
141462
+ }
141430
141463
  }
141431
141464
  async function listMachineMetasForWorkspace(manager) {
141432
141465
  return (await listAliveDocMetas(manager, isMachineDocRoomId)).map((entry) => entry.meta);
@@ -141954,6 +141987,7 @@ ${entry.text}`).join("\n\n");
141954
141987
  });
141955
141988
  let completionAbortController;
141956
141989
  let completionPromise;
141990
+ let dispatched = false;
141957
141991
  try {
141958
141992
  const modeId = effectiveDispatchConfig.modeId;
141959
141993
  const modelId = effectiveDispatchConfig.modelId;
@@ -141981,11 +142015,15 @@ ${entry.text}`).join("\n\n");
141981
142015
  await manager.repo.upsertDocMeta(sessionRoomId, {
141982
142016
  status: SessionStatusFactory.idle()
141983
142017
  });
141984
- await writeDispatchPointerAndSync({
142018
+ await writeDispatchPointer({
141985
142019
  manager,
141986
- sessionDoc,
141987
142020
  sessionId,
141988
- userTurnId,
142021
+ userTurnId
142022
+ });
142023
+ dispatched = true;
142024
+ await confirmDispatchSyncedBestEffort({
142025
+ manager,
142026
+ sessionDoc,
141989
142027
  reason: `session.create:${sessionId}`
141990
142028
  });
141991
142029
  await dispatchTurnFastPath({
@@ -142018,7 +142056,9 @@ ${entry.text}`).join("\n\n");
142018
142056
  } catch (error2) {
142019
142057
  completionAbortController?.abort();
142020
142058
  await completionPromise?.catch(() => void 0);
142021
- await rollbackPendingSessionCreate(manager, sessionId);
142059
+ if (!dispatched) {
142060
+ await rollbackPendingSessionCreate(manager, sessionId);
142061
+ }
142022
142062
  throw error2;
142023
142063
  }
142024
142064
  }
@@ -142085,13 +142125,18 @@ ${entry.text}`).join("\n\n");
142085
142125
  signal: completionAbortController?.signal,
142086
142126
  onEvent: structuredOutput.onEvent
142087
142127
  }) : void 0;
142128
+ let dispatched = false;
142088
142129
  try {
142089
142130
  await updateSessionActivityTimestampsBestEffort(manager, sessionId);
142090
- await writeDispatchPointerAndSync({
142131
+ await writeDispatchPointer({
142091
142132
  manager,
142092
- sessionDoc,
142093
142133
  sessionId,
142094
- userTurnId,
142134
+ userTurnId
142135
+ });
142136
+ dispatched = true;
142137
+ await confirmDispatchSyncedBestEffort({
142138
+ manager,
142139
+ sessionDoc,
142095
142140
  reason: `session.chat:${sessionId}:${userTurnId}`
142096
142141
  });
142097
142142
  await dispatchTurnFastPath({
@@ -142114,11 +142159,13 @@ ${entry.text}`).join("\n\n");
142114
142159
  } catch (error2) {
142115
142160
  completionAbortController?.abort();
142116
142161
  await completionPromise?.catch(() => void 0);
142117
- await removeHistoryEntryById(sessionDoc, userTurnId);
142118
- await manager.repo.upsertDocMeta(getSessionRoomId(sessionId), {
142119
- latestUserMsgId: void 0,
142120
- lastMissingHistoryUserMsgId: void 0
142121
- }).catch(() => void 0);
142162
+ if (!dispatched) {
142163
+ await removeHistoryEntryById(sessionDoc, userTurnId);
142164
+ await manager.repo.upsertDocMeta(getSessionRoomId(sessionId), {
142165
+ latestUserMsgId: void 0,
142166
+ lastMissingHistoryUserMsgId: void 0
142167
+ }).catch(() => void 0);
142168
+ }
142122
142169
  throw error2;
142123
142170
  }
142124
142171
  }
@@ -144451,11 +144498,11 @@ ${entry.text}`).join("\n\n");
144451
144498
  });
144452
144499
  }
144453
144500
  const workspaceRoot = path__default$1.resolve(resolvedWorkspace.workspaceRoot);
144454
- const workspacePath = normalizeWorkspacePath(requestedPath, options);
144501
+ const workspacePath = normalizeWorkspacePath(resolveWorkspaceRelativeRequestPath(workspaceRoot, requestedPath), options);
144455
144502
  const requestedAbsolutePath = path__default$1.resolve(workspaceRoot, workspacePath);
144456
144503
  const absolutePath = await resolveExistingPathWithoutConflicts(workspaceRoot, workspacePath, requestedPath) ?? requestedAbsolutePath;
144457
144504
  const relative2 = path__default$1.relative(workspaceRoot, absolutePath);
144458
- if (relative2.startsWith("..") || path__default$1.isAbsolute(relative2)) {
144505
+ if (isPathOutsideRoot(relative2)) {
144459
144506
  throw new CodeCollabV2ServiceError("invalid_path", "Path escapes workspace root.", {
144460
144507
  path: requestedPath
144461
144508
  });
@@ -145140,6 +145187,21 @@ ${entry.text}`).join("\n\n");
145140
145187
  }
145141
145188
  return normalized;
145142
145189
  }
145190
+ function resolveWorkspaceRelativeRequestPath(workspaceRoot, input2) {
145191
+ if (!path__default$1.isAbsolute(input2)) {
145192
+ return input2;
145193
+ }
145194
+ const relative2 = path__default$1.relative(workspaceRoot, path__default$1.resolve(input2));
145195
+ if (isPathOutsideRoot(relative2)) {
145196
+ throw new CodeCollabV2ServiceError("invalid_path", "Path escapes workspace root.", {
145197
+ path: input2
145198
+ });
145199
+ }
145200
+ return relative2.split(path__default$1.sep).join("/");
145201
+ }
145202
+ function isPathOutsideRoot(relativePath) {
145203
+ return relativePath === ".." || relativePath.startsWith(`..${path__default$1.sep}`) || path__default$1.isAbsolute(relativePath);
145204
+ }
145143
145205
  async function stableReadFile(resolved, maxBytes) {
145144
145206
  let lastTransientError;
145145
145207
  for (let attempt = 0; attempt < 3; attempt += 1) {
@@ -145256,7 +145318,7 @@ ${entry.text}`).join("\n\n");
145256
145318
  throw mapNodeReadError(error2, resolved.workspacePath);
145257
145319
  });
145258
145320
  const relative2 = path__default$1.relative(rootRealpath, fileRealpath);
145259
- if (relative2.startsWith("..") || path__default$1.isAbsolute(relative2)) {
145321
+ if (isPathOutsideRoot(relative2)) {
145260
145322
  throw new CodeCollabV2ServiceError("invalid_path", "Resolved path escapes workspace root.", {
145261
145323
  path: resolved.workspacePath
145262
145324
  });
@@ -155590,7 +155652,9 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
155590
155652
  this.logger.debug(`[${sessionId}] Failed to delete session doc (may already be deleted): ${formatErrorMessage(error2)}`);
155591
155653
  }
155592
155654
  try {
155593
- const operationStore = new LodyOperationStore(getLodyOperationStorePath(this.machineId));
155655
+ const operationStore = new LodyOperationStore(getLodyOperationStorePath(this.machineId), void 0, {
155656
+ maintenance: false
155657
+ });
155594
155658
  try {
155595
155659
  operationStore.deleteRequesterSession(sessionId);
155596
155660
  } finally {
@@ -203332,7 +203396,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
203332
203396
  data = createReviewBundleSnapshot(bundle);
203333
203397
  }
203334
203398
  const { injectReviewSnapshot } = await import("./chunks/index-VoI6Ds2-.js");
203335
- const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-CP4bkTWs.js");
203399
+ const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-S-XYMgL_.js");
203336
203400
  const template = await resolveReviewViewerTemplate();
203337
203401
  const html = injectReviewSnapshot(template, data);
203338
203402
  const outputPath = options.output ? path__default$1.resolve(options.output) : defaultHtmlOutputPath(inputPath);
@@ -221230,14 +221294,14 @@ ${result.stderr}`;
221230
221294
  localControlSocketPath: readOptionalEnv("LODY_MCP_SOCKET_PATH", "LODY_PREVIEW_MCP_SOCKET_PATH"),
221231
221295
  workdir: readOptionalEnv("LODY_MCP_WORKDIR", "LODY_PREVIEW_MCP_WORKDIR") ?? process.cwd()
221232
221296
  });
221233
- const withOperationStore = (fn) => {
221234
- const store = new LodyOperationStore();
221235
- try {
221236
- return fn(store);
221237
- } finally {
221238
- store.close();
221239
- }
221297
+ let sharedOperationStore;
221298
+ const getSharedOperationStore = () => {
221299
+ sharedOperationStore ??= new LodyOperationStore(void 0, void 0, {
221300
+ maintenance: false
221301
+ });
221302
+ return sharedOperationStore;
221240
221303
  };
221304
+ const withOperationStore = (fn) => runWithOperationStoreBusyRetry(() => fn(getSharedOperationStore()));
221241
221305
  const assertBatchSize = (length2, maximum) => {
221242
221306
  if (length2 < 1 || length2 > maximum) {
221243
221307
  throw new LodyOperationStoreError("BATCH_TOO_LARGE", `Batch item count must be between 1 and ${maximum}; received ${length2}.`, false);
@@ -222074,8 +222138,8 @@ ${result.stderr}`;
222074
222138
  deadlineSeconds: args2.deadlineSeconds
222075
222139
  } : {}
222076
222140
  };
222077
- const retry2 = withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_create", canonicalCommand));
222078
- if (retry2) return withOperationStore((store) => store.snapshot(retry2));
222141
+ const retry2 = await withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_create", canonicalCommand));
222142
+ if (retry2) return await withOperationStore((store) => store.snapshot(retry2));
222079
222143
  const targetMachineId = args2.machineId ?? currentSession.machineId;
222080
222144
  await assertMachineOnlineForSingleCommand(manager, targetMachineId, ctx);
222081
222145
  const createOptions = buildMcpCreateOptions(args2, ctx);
@@ -222096,7 +222160,7 @@ ${result.stderr}`;
222096
222160
  const preallocatedUserTurnId = randomUUID();
222097
222161
  const materializationClaimToken = randomUUID();
222098
222162
  const timing = operationDeadline(args2.deadlineSeconds);
222099
- const accepted = withOperationStore((store) => store.accept({
222163
+ const accepted = await withOperationStore((store) => store.accept({
222100
222164
  workspaceId: workspace.id,
222101
222165
  ownerMachineId: ctx.machineId,
222102
222166
  requesterSessionId: ctx.sessionId,
@@ -222119,7 +222183,7 @@ ${result.stderr}`;
222119
222183
  materializationClaimToken
222120
222184
  }));
222121
222185
  if (accepted.operation.state === "finished") {
222122
- return withOperationStore((store) => store.snapshot(accepted.operation));
222186
+ return await withOperationStore((store) => store.snapshot(accepted.operation));
222123
222187
  }
222124
222188
  const pendingItem = accepted.operation.items[0];
222125
222189
  if (!pendingItem || pendingItem.status !== "active") {
@@ -222133,7 +222197,7 @@ ${result.stderr}`;
222133
222197
  if (result.sessionId !== pendingItem.target.sessionId || result.userTurnId !== pendingItem.target.userTurnId) {
222134
222198
  throw new Error("Create result did not preserve preallocated target ids.");
222135
222199
  }
222136
- withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, 0, materializationClaimToken));
222200
+ await withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, 0, materializationClaimToken));
222137
222201
  }
222138
222202
  return snapshotOperation(ctx.sessionId, args2.operationId);
222139
222203
  });
@@ -222158,8 +222222,8 @@ ${result.stderr}`;
222158
222222
  deadlineSeconds: args2.deadlineSeconds
222159
222223
  } : {}
222160
222224
  };
222161
- const retry2 = withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_chat", canonicalCommand));
222162
- if (retry2) return withOperationStore((store) => store.snapshot(retry2));
222225
+ const retry2 = await withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_chat", canonicalCommand));
222226
+ if (retry2) return await withOperationStore((store) => store.snapshot(retry2));
222163
222227
  const targetSession = await readCurrentSessionMeta(manager, args2.sessionId);
222164
222228
  if (!targetSession) {
222165
222229
  throw new LodyOperationStoreError("SESSION_NOT_FOUND", `Target Session not found: ${args2.sessionId}`, false);
@@ -222181,7 +222245,7 @@ ${result.stderr}`;
222181
222245
  const preallocatedUserTurnId = randomUUID();
222182
222246
  const materializationClaimToken = randomUUID();
222183
222247
  const timing = operationDeadline(args2.deadlineSeconds);
222184
- const accepted = withOperationStore((store) => store.accept({
222248
+ const accepted = await withOperationStore((store) => store.accept({
222185
222249
  workspaceId: workspace.id,
222186
222250
  ownerMachineId: ctx.machineId,
222187
222251
  requesterSessionId: ctx.sessionId,
@@ -222204,7 +222268,7 @@ ${result.stderr}`;
222204
222268
  materializationClaimToken
222205
222269
  }));
222206
222270
  if (accepted.operation.state === "finished") {
222207
- return withOperationStore((store) => store.snapshot(accepted.operation));
222271
+ return await withOperationStore((store) => store.snapshot(accepted.operation));
222208
222272
  }
222209
222273
  const pendingItem = accepted.operation.items[0];
222210
222274
  if (!pendingItem || pendingItem.status !== "active") {
@@ -222218,7 +222282,7 @@ ${result.stderr}`;
222218
222282
  if (result.userTurnId !== pendingItem.target.userTurnId) {
222219
222283
  throw new Error("Chat result did not preserve the preallocated target turn id.");
222220
222284
  }
222221
- withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, 0, materializationClaimToken));
222285
+ await withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, 0, materializationClaimToken));
222222
222286
  }
222223
222287
  return snapshotOperation(ctx.sessionId, args2.operationId);
222224
222288
  });
@@ -222261,11 +222325,11 @@ ${result.stderr}`;
222261
222325
  } : {},
222262
222326
  error: makeLodyError(code2, message, retryable)
222263
222327
  });
222264
- const finishOperationWhenEveryItemIsTerminal = (requesterSessionId, operationId, items2) => {
222328
+ const finishOperationWhenEveryItemIsTerminal = async (requesterSessionId, operationId, items2) => {
222265
222329
  if (items2.some((item) => item.status === "active")) {
222266
222330
  return;
222267
222331
  }
222268
- withOperationStore((store) => store.finish(requesterSessionId, operationId, {
222332
+ await withOperationStore((store) => store.finish(requesterSessionId, operationId, {
222269
222333
  type: "result",
222270
222334
  value: {
222271
222335
  items: items2
@@ -222293,8 +222357,8 @@ ${result.stderr}`;
222293
222357
  deadlineSeconds: args2.deadlineSeconds
222294
222358
  } : {}
222295
222359
  };
222296
- const retry2 = withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_create_many", canonicalCommand));
222297
- if (retry2) return withOperationStore((store) => store.snapshot(retry2));
222360
+ const retry2 = await withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_create_many", canonicalCommand));
222361
+ if (retry2) return await withOperationStore((store) => store.snapshot(retry2));
222298
222362
  const invoking = await resolveInvokingTurnContext(manager, requester);
222299
222363
  const initialItems = await mapWithConcurrency(expanded, 5, async (item) => {
222300
222364
  const label2 = item.label;
@@ -222341,7 +222405,7 @@ ${result.stderr}`;
222341
222405
  });
222342
222406
  const materializationClaimToken = randomUUID();
222343
222407
  const timing = operationDeadline(args2.deadlineSeconds);
222344
- const accepted = withOperationStore((store) => store.accept({
222408
+ const accepted = await withOperationStore((store) => store.accept({
222345
222409
  workspaceId: workspace.id,
222346
222410
  ownerMachineId: ctx.machineId,
222347
222411
  requesterSessionId: ctx.sessionId,
@@ -222362,7 +222426,7 @@ ${result.stderr}`;
222362
222426
  materializationClaimToken
222363
222427
  }));
222364
222428
  if (accepted.operation.state === "finished") {
222365
- return withOperationStore((store) => store.snapshot(accepted.operation));
222429
+ return await withOperationStore((store) => store.snapshot(accepted.operation));
222366
222430
  }
222367
222431
  const nextItems = await mapWithConcurrency(accepted.operation.items, 5, async (storedItem, index) => {
222368
222432
  if (storedItem.status !== "active" || storedItem.inputDurable || !accepted.claimedItemIndexes.includes(index)) {
@@ -222396,13 +222460,13 @@ ${result.stderr}`;
222396
222460
  options.userTurnId = storedItem.target.userTurnId;
222397
222461
  options.chainDepth = invoking.chainDepth + 1;
222398
222462
  await createSessionResult(auth, workspace, manager, expandedItem.prompt, options, resolveTurnDispatchConfig({}));
222399
- withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, index, materializationClaimToken));
222463
+ await withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, index, materializationClaimToken));
222400
222464
  return markOperationItemInputDurable(storedItem);
222401
222465
  } catch {
222402
222466
  return storedItem;
222403
222467
  }
222404
222468
  });
222405
- finishOperationWhenEveryItemIsTerminal(ctx.sessionId, args2.operationId, nextItems);
222469
+ await finishOperationWhenEveryItemIsTerminal(ctx.sessionId, args2.operationId, nextItems);
222406
222470
  return snapshotOperation(ctx.sessionId, args2.operationId);
222407
222471
  });
222408
222472
  };
@@ -222427,8 +222491,8 @@ ${result.stderr}`;
222427
222491
  deadlineSeconds: args2.deadlineSeconds
222428
222492
  } : {}
222429
222493
  };
222430
- const retry2 = withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_chat_many", canonicalCommand));
222431
- if (retry2) return withOperationStore((store) => store.snapshot(retry2));
222494
+ const retry2 = await withOperationStore((store) => store.findMatchingRetry(ctx.sessionId, args2.operationId, "session_chat_many", canonicalCommand));
222495
+ if (retry2) return await withOperationStore((store) => store.snapshot(retry2));
222432
222496
  const invoking = await resolveInvokingTurnContext(manager, requester);
222433
222497
  const initialItems = await mapWithConcurrency(expanded, 5, async (item) => {
222434
222498
  if (!item.sessionId || !item.prompt) {
@@ -222459,7 +222523,7 @@ ${result.stderr}`;
222459
222523
  });
222460
222524
  const materializationClaimToken = randomUUID();
222461
222525
  const timing = operationDeadline(args2.deadlineSeconds);
222462
- const accepted = withOperationStore((store) => store.accept({
222526
+ const accepted = await withOperationStore((store) => store.accept({
222463
222527
  workspaceId: workspace.id,
222464
222528
  ownerMachineId: ctx.machineId,
222465
222529
  requesterSessionId: ctx.sessionId,
@@ -222480,7 +222544,7 @@ ${result.stderr}`;
222480
222544
  materializationClaimToken
222481
222545
  }));
222482
222546
  if (accepted.operation.state === "finished") {
222483
- return withOperationStore((store) => store.snapshot(accepted.operation));
222547
+ return await withOperationStore((store) => store.snapshot(accepted.operation));
222484
222548
  }
222485
222549
  const nextItems = await mapWithConcurrency(accepted.operation.items, 5, async (storedItem, index) => {
222486
222550
  if (storedItem.status !== "active" || storedItem.inputDurable || !accepted.claimedItemIndexes.includes(index)) {
@@ -222495,13 +222559,13 @@ ${result.stderr}`;
222495
222559
  userTurnId: storedItem.target.userTurnId,
222496
222560
  chainDepth: invoking.chainDepth + 1
222497
222561
  });
222498
- withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, index, materializationClaimToken));
222562
+ await withOperationStore((store) => store.markItemInputDurable(ctx.sessionId, args2.operationId, index, materializationClaimToken));
222499
222563
  return markOperationItemInputDurable(storedItem);
222500
222564
  } catch {
222501
222565
  return storedItem;
222502
222566
  }
222503
222567
  });
222504
- finishOperationWhenEveryItemIsTerminal(ctx.sessionId, args2.operationId, nextItems);
222568
+ await finishOperationWhenEveryItemIsTerminal(ctx.sessionId, args2.operationId, nextItems);
222505
222569
  return snapshotOperation(ctx.sessionId, args2.operationId);
222506
222570
  });
222507
222571
  };
@@ -222783,7 +222847,7 @@ ${lines2.join("\n")}` : ""}${suffix}`);
222783
222847
  }, async (args2) => {
222784
222848
  try {
222785
222849
  const ctx = getSessionContext();
222786
- return jsonTextResult(snapshotOperation(ctx.sessionId, args2.operationId));
222850
+ return jsonTextResult(await snapshotOperation(ctx.sessionId, args2.operationId));
222787
222851
  } catch (error2) {
222788
222852
  return mcpErrorResult(error2);
222789
222853
  }
@@ -222796,13 +222860,13 @@ ${lines2.join("\n")}` : ""}${suffix}`);
222796
222860
  try {
222797
222861
  const ctx = getSessionContext();
222798
222862
  const requesterSessionId = ctx.sessionId;
222799
- const before = withOperationStore((store) => store.get(requesterSessionId, args2.operationId));
222800
- const cancellation = withOperationStore((store) => store.cancel(requesterSessionId, args2.operationId));
222863
+ const before = await withOperationStore((store) => store.get(requesterSessionId, args2.operationId));
222864
+ const cancellation = await withOperationStore((store) => store.cancel(requesterSessionId, args2.operationId));
222801
222865
  if (cancellation.didCancel && before.state === "active") {
222802
222866
  const startedTargets = before.items.filter((item) => item.status === "active" && item.inputDurable);
222803
222867
  await Promise.allSettled(startedTargets.map((item) => item.status === "active" ? runLodyCliJson(buildOperationTargetCancelArgs(getMcpWorkspaceId(ctx), item)) : Promise.resolve()));
222804
222868
  }
222805
- return jsonTextResult(withOperationStore((store) => store.snapshot(cancellation.operation)));
222869
+ return jsonTextResult(await withOperationStore((store) => store.snapshot(cancellation.operation)));
222806
222870
  } catch (error2) {
222807
222871
  return mcpErrorResult(error2);
222808
222872
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lody",
3
- "version": "0.71.2",
3
+ "version": "0.71.3",
4
4
  "description": "Lody Agent CLI tool for managing remote command execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -75,15 +75,15 @@
75
75
  "ws": "^8.18.3",
76
76
  "zod": "^4.1.5",
77
77
  "zstd-stream": "^1.1.0",
78
- "@lody/cli-supervisor": "0.0.1",
79
- "@lody/code-review-helper": "0.0.0",
80
- "@lody/shared": "0.0.1",
81
78
  "@lody/convex": "0.0.1",
82
79
  "@lody/loro-streams-rpc": "0.0.1",
83
80
  "acp-extension-claude": "0.59.0",
81
+ "@lody/code-review-helper": "0.0.0",
82
+ "@lody/cli-supervisor": "0.0.1",
83
+ "@lody/shared": "0.0.1",
84
84
  "acp-extension-core": "0.0.5",
85
- "acp-extension-codex": "1.2.1",
86
- "lody-code-review-viewer": "0.71.2"
85
+ "lody-code-review-viewer": "0.71.3",
86
+ "acp-extension-codex": "1.2.1"
87
87
  },
88
88
  "files": [
89
89
  "dist",
@@ -106,7 +106,7 @@
106
106
  "build": "pnpm run clean && pnpm run prepare:acp-adapters && pnpm run typecheck && pnpm run build:bundle && pnpm run check:published-bundle-imports && pnpm run copy:wasm",
107
107
  "build:watch": "pnpm run prepare:review-assets && vite build --watch",
108
108
  "build:bundle": "pnpm run prepare:review-assets && vite build",
109
- "prepare:acp-adapters": "pnpm --dir ../.. --filter acp-extension-claude build && pnpm --dir ../.. --filter acp-extension-codex build",
109
+ "prepare:acp-adapters": "corepack pnpm --dir ../.. --filter acp-extension-claude build && corepack pnpm --dir ../.. --filter acp-extension-codex build",
110
110
  "prepare:review-assets": "pnpm --dir ../.. --filter lody-code-review-viewer build",
111
111
  "check:published-bundle-imports": "node scripts/check-published-bundle-imports.js",
112
112
  "copy:wasm": "node scripts/copy-loro-wasm.js",