@ferris1225/pi-subagents 4.2.4 → 4.2.5

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/src/runtime.ts CHANGED
@@ -258,7 +258,7 @@ export function createRuntime(pi: ExtensionAPI, configPath: string): SubagentRun
258
258
  // thread whose settlement finished during the wait above already
259
259
  // wrote (or removed) its own record; the lastResult-derived state
260
260
  // below matches it.
261
- const settledIds: number[] = [];
261
+ const settled: Array<{ runId: number; cwd: string }> = [];
262
262
  const records: ThreadRecord[] = [];
263
263
  for (const thread of runtime.threads.values()) {
264
264
  if (thread.retired) continue;
@@ -272,11 +272,11 @@ export function createRuntime(pi: ExtensionAPI, configPath: string): SubagentRun
272
272
  state = "parked";
273
273
  }
274
274
  if (state === "parked") records.push(threadRecordFromThread(thread, state));
275
- else settledIds.push(thread.id);
275
+ else settled.push({ runId: thread.id, cwd: thread.cwd });
276
276
  }
277
277
  await Promise.all([
278
278
  ...records.map((record) => upsertThreadRecord(runtime.configPath, record).catch(() => undefined)),
279
- ...settledIds.map((runId) => removeThreadRecord(runtime.configPath, runId).catch(() => undefined)),
279
+ ...settled.map(({ runId, cwd }) => removeThreadRecord(runtime.configPath, runId, cwd).catch(() => undefined)),
280
280
  ]);
281
281
  // Retained-failure recovery records are persisted by the finalization
282
282
  // itself; shutdown only drops sessions no record claims anymore.
@@ -27,6 +27,7 @@ import {
27
27
  } from "./config.ts";
28
28
  import {
29
29
  isCurrentBoot,
30
+ migrateLegacyThreadsManifest,
30
31
  readThreadRecords,
31
32
  referencedDurablePaths,
32
33
  removeThreadRecord,
@@ -225,7 +226,7 @@ export function persistThreadCheckpoint(
225
226
  ): void {
226
227
  const write = state === "parked"
227
228
  ? upsertThreadRecord(runtime.configPath, threadRecordFromThread(thread, state))
228
- : removeThreadRecord(runtime.configPath, thread.id);
229
+ : removeThreadRecord(runtime.configPath, thread.id, thread.cwd);
229
230
  void write.catch(() => undefined);
230
231
  }
231
232
 
@@ -1145,7 +1146,7 @@ async function discardRestoredRecord(runtime: SubagentRuntime, record: ThreadRec
1145
1146
  const worktree = await restoreWorktreeIsolation(record.worktree).catch(() => undefined);
1146
1147
  await worktree?.discard().catch(() => undefined);
1147
1148
  }
1148
- await removeThreadRecord(runtime.configPath, record.runId).catch(() => undefined);
1149
+ await removeThreadRecord(runtime.configPath, record.runId, record.cwd).catch(() => undefined);
1149
1150
  }
1150
1151
 
1151
1152
  /** Project-scoped <projectRoot>/results for a completion's artifacts. */
@@ -1273,6 +1274,9 @@ export async function restoreDurableThreads(runtime: SubagentRuntime): Promise<n
1273
1274
  export function bootstrapDurableState(runtime: SubagentRuntime): Promise<void> {
1274
1275
  const restore = (async () => {
1275
1276
  try {
1277
+ // Records from a pre-per-project manifest must land in their project
1278
+ // roots before restore reads anything.
1279
+ await migrateLegacyThreadsManifest(runtime.configPath);
1276
1280
  runtime.restoredRunIds = await restoreDurableThreads(runtime);
1277
1281
  } catch {
1278
1282
  /* restore is best-effort */
package/src/tools.ts CHANGED
@@ -344,7 +344,7 @@ export function registerLookupTools(pi: ExtensionAPI, runtime: SubagentRuntime):
344
344
  runtime.retireThreadSession(thread);
345
345
  // The destructive retire removes the durable record with the session;
346
346
  // an id never resurrects after subagent_stop.
347
- await removeThreadRecord(runtime.configPath, runId).catch(() => undefined);
347
+ await removeThreadRecord(runtime.configPath, runId, thread.cwd).catch(() => undefined);
348
348
  if (thread.lifecycleVersion === stopVersion && thread.lifecycleOperation === "stop") {
349
349
  thread.lifecycleOperation = undefined;
350
350
  }