@ricsam/r5d-worker 0.0.44 → 0.0.46

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.44",
3
+ "version": "0.0.46",
4
4
  "type": "module"
5
5
  }
@@ -9,6 +9,9 @@ const MAX_REPORTED_WORKSPACE_PATHS = 2e3;
9
9
  const MAX_REPORTED_WORKSPACE_STATUS_BYTES = 256 * 1024;
10
10
  const MAX_MIRROR_COMPARISON_CACHE_ENTRIES = 2e5;
11
11
  const MIRROR_COMPARE_BUFFER_BYTES = 64 * 1024;
12
+ const DESTRUCTIVE_CHECKOUT_MIN_TRACKED_FILES = 20;
13
+ const DESTRUCTIVE_CHECKOUT_REMOVAL_RATIO = 0.8;
14
+ const ACTIVE_GIT_LOCK_PATHS = ["index.lock", "HEAD.lock", "packed-refs.lock", "shallow.lock"];
12
15
  const mirrorComparisonCache = /* @__PURE__ */ new Map();
13
16
  function gitArgs(input, args) {
14
17
  return input.authHeader ? ["git", "-c", `http.extraHeader=${input.authHeader}`, ...args] : ["git", ...args];
@@ -84,6 +87,36 @@ function listGitEligibleFiles(checkoutPath) {
84
87
  }
85
88
  }).sort();
86
89
  }
90
+ function checkoutGitSnapshot(checkoutPath) {
91
+ const gitPaths = Bun.spawnSync(
92
+ ["git", "rev-parse", "--git-path", "index", ...ACTIVE_GIT_LOCK_PATHS.flatMap((lock) => ["--git-path", lock])],
93
+ {
94
+ cwd: checkoutPath,
95
+ stdout: "pipe",
96
+ stderr: "ignore",
97
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
98
+ }
99
+ );
100
+ if (gitPaths.exitCode !== 0) return null;
101
+ const [indexPath, ...lockPaths] = gitPaths.stdout.toString().trim().split(/\r?\n/).map((gitPath) => path.resolve(checkoutPath, gitPath));
102
+ if (!indexPath || lockPaths.length !== ACTIVE_GIT_LOCK_PATHS.length || lockPaths.some((lockPath) => fs.existsSync(lockPath))) {
103
+ return null;
104
+ }
105
+ const head = Bun.spawnSync(["git", "rev-parse", "--verify", "HEAD"], {
106
+ cwd: checkoutPath,
107
+ stdout: "pipe",
108
+ stderr: "ignore",
109
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
110
+ });
111
+ let indexSignature = "missing";
112
+ try {
113
+ const stat = fs.statSync(indexPath);
114
+ indexSignature = entrySignature(stat);
115
+ } catch {
116
+ }
117
+ if (lockPaths.some((lockPath) => fs.existsSync(lockPath))) return null;
118
+ return `${head.exitCode === 0 ? head.stdout.toString().trim() : "unborn"}\0${indexSignature}`;
119
+ }
87
120
  function listShadowTrackedFiles(input, relativeRoot) {
88
121
  const normalizedRoot = relativeRoot.split(path.sep).join("/").replace(/^\/+|\/+$/g, "");
89
122
  const output = runGit(input, input.shadowRoot, ["ls-files", "-z", "--cached", "--", normalizedRoot], "list canonical workspace files");
@@ -213,11 +246,28 @@ function mirrorFileSet(sourceRoot, targetRoot, sourceFiles, targetFiles) {
213
246
  }
214
247
  removeEmptyDirectories(targetRoot);
215
248
  }
249
+ function restoreShadowProjectSnapshot(input, relativeRoot) {
250
+ const shadowRoot = path.join(input.shadowRoot, ...relativeRoot.split("/"));
251
+ const headFiles = runGitResult(input, input.shadowRoot, ["ls-tree", "-r", "--name-only", "-z", "HEAD", "--", relativeRoot]);
252
+ if (headFiles.exitCode === 0 && headFiles.stdout) {
253
+ runGit(input, input.shadowRoot, ["restore", "--source=HEAD", "--worktree", "--", relativeRoot], "restore deferred checkout scan");
254
+ runGit(input, input.shadowRoot, ["clean", "-fd", "--", relativeRoot], "clean deferred checkout scan");
255
+ return;
256
+ }
257
+ fs.rmSync(shadowRoot, { recursive: true, force: true });
258
+ }
216
259
  function mirrorVisibleProjectToShadow(input, manifest, branchName) {
217
260
  const visibleRoot = visibleProjectBranchPath(input.projectsRoot, manifest, branchName);
218
261
  if (!fs.existsSync(path.join(visibleRoot, ".git"))) return;
219
- const shadowRoot = path.join(input.shadowRoot, ...workspaceProjectBranchRelativePath(manifest.projectId, branchName).split("/"));
220
- mirrorFileSet(visibleRoot, shadowRoot, listGitEligibleFiles(visibleRoot), listFilesRecursively(shadowRoot));
262
+ const beforeSnapshot = checkoutGitSnapshot(visibleRoot);
263
+ if (!beforeSnapshot) return;
264
+ const visibleFiles = listGitEligibleFiles(visibleRoot);
265
+ const relativeRoot = workspaceProjectBranchRelativePath(manifest.projectId, branchName);
266
+ const shadowRoot = path.join(input.shadowRoot, ...relativeRoot.split("/"));
267
+ mirrorFileSet(visibleRoot, shadowRoot, visibleFiles, listFilesRecursively(shadowRoot));
268
+ if (checkoutGitSnapshot(visibleRoot) !== beforeSnapshot) {
269
+ restoreShadowProjectSnapshot(input, relativeRoot);
270
+ }
221
271
  }
222
272
  function mirrorShadowProjectToVisible(input, manifest, branchName) {
223
273
  const visibleRoot = visibleProjectBranchPath(input.projectsRoot, manifest, branchName);
@@ -246,29 +296,7 @@ function mirrorShadowPlansToLocal(input, manifest, branchName) {
246
296
  listFilesRecursively(targetRoot, planFilter)
247
297
  );
248
298
  }
249
- function pruneDirectoryChildren(root, allowedNames) {
250
- if (!fs.existsSync(root)) return;
251
- for (const entry of fs.readdirSync(root)) {
252
- if (allowedNames.has(entry)) continue;
253
- const target = path.resolve(root, entry);
254
- assertInside(root, target, "Workspace manifest prune path");
255
- fs.rmSync(target, { recursive: true, force: true });
256
- }
257
- }
258
- function pruneShadowToManifest(input) {
259
- const projectIds = new Set(input.projects.map((project) => project.projectId));
260
- const projectsRoot = path.join(input.shadowRoot, "projects");
261
- const plansRoot = path.join(input.shadowRoot, "plans");
262
- pruneDirectoryChildren(projectsRoot, projectIds);
263
- pruneDirectoryChildren(plansRoot, projectIds);
264
- for (const manifest of input.projects) {
265
- const encodedBranches = new Set(manifest.branches.map(encodeWorkspaceBranch));
266
- pruneDirectoryChildren(path.join(projectsRoot, manifest.projectId, "branches"), encodedBranches);
267
- pruneDirectoryChildren(path.join(plansRoot, manifest.projectId), encodedBranches);
268
- }
269
- }
270
299
  function mirrorVisibleWorkspaceToShadow(input, excludedCheckouts = /* @__PURE__ */ new Set()) {
271
- pruneShadowToManifest(input);
272
300
  for (const manifest of [...input.projects].sort((left, right) => left.projectId.localeCompare(right.projectId))) {
273
301
  for (const branchName of [...new Set(manifest.branches)].sort()) {
274
302
  if (excludedCheckouts.has(`${manifest.projectId}\0${branchName}`)) continue;
@@ -282,13 +310,13 @@ function reconcileNewVisibleCheckouts(input) {
282
310
  const manifest = input.projects.find((project) => project.projectId === target.projectId);
283
311
  if (!manifest || !manifest.branches.includes(target.branchName)) continue;
284
312
  const projectRoot = workspaceProjectBranchRelativePath(target.projectId, target.branchName);
285
- if (listShadowTrackedFiles(input, projectRoot).length > 0) {
313
+ if (listShadowTrackedFiles(input, projectRoot).length > 0 || restoreShadowRootFromRemote(input, projectRoot)) {
286
314
  mirrorShadowProjectToVisible(input, manifest, target.branchName);
287
315
  } else {
288
316
  mirrorVisibleProjectToShadow(input, manifest, target.branchName);
289
317
  }
290
318
  const plansRoot = workspacePlansRelativePath(target.projectId, target.branchName);
291
- if (listShadowTrackedFiles(input, plansRoot).length > 0) {
319
+ if (listShadowTrackedFiles(input, plansRoot).length > 0 || restoreShadowRootFromRemote(input, plansRoot)) {
292
320
  mirrorShadowPlansToLocal(input, manifest, target.branchName);
293
321
  } else {
294
322
  mirrorLocalPlansToShadow(input, manifest, target.branchName);
@@ -335,11 +363,103 @@ function revParse(input, revision) {
335
363
  function gitStatus(input) {
336
364
  return runGit(input, input.shadowRoot, ["status", "--porcelain=v1", "--untracked-files=all"], "read workspace status");
337
365
  }
338
- function stagedPaths(input) {
339
- return runGit(input, input.shadowRoot, ["diff", "--cached", "--name-only", "-z"], "list workspace changes").split("\0").filter(Boolean).sort();
366
+ function resetUncommittedShadowSnapshot(input) {
367
+ if (!gitStatus(input)) return;
368
+ if (tryGit(input, input.shadowRoot, ["rev-parse", "--verify", "HEAD"])) {
369
+ runGit(input, input.shadowRoot, ["reset", "--hard", "HEAD"], "reset interrupted workspace snapshot");
370
+ } else {
371
+ runGit(input, input.shadowRoot, ["read-tree", "--empty"], "reset interrupted unborn workspace snapshot");
372
+ }
373
+ runGit(input, input.shadowRoot, ["clean", "-fd"], "clean interrupted workspace snapshot");
374
+ }
375
+ function fastForwardCleanShadowForNewCheckouts(input) {
376
+ if (!input.newVisibleCheckouts?.length) return;
377
+ runGit(input, input.shadowRoot, ["add", "-A"], "stage existing workspace changes before checkout hydration");
378
+ if (gitStatus(input)) return;
379
+ const localHead = revParse(input, "HEAD");
380
+ const remoteHead = revParse(input, `origin/${WORKSPACE_BRANCH}`);
381
+ if (!localHead || !remoteHead || localHead === remoteHead) return;
382
+ if (!tryGit(input, input.shadowRoot, ["merge-base", "--is-ancestor", localHead, remoteHead])) return;
383
+ runGit(input, input.shadowRoot, ["reset", "--hard", remoteHead], "fast-forward before checkout hydration");
384
+ }
385
+ function restoreShadowRootFromRemote(input, relativeRoot) {
386
+ const remoteRevision = `origin/${WORKSPACE_BRANCH}`;
387
+ const remoteFiles = runGitResult(input, input.shadowRoot, ["ls-tree", "-r", "--name-only", "-z", remoteRevision, "--", relativeRoot]);
388
+ if (remoteFiles.exitCode !== 0 || !remoteFiles.stdout) return false;
389
+ runGit(
390
+ input,
391
+ input.shadowRoot,
392
+ ["restore", `--source=${remoteRevision}`, "--staged", "--worktree", "--", relativeRoot],
393
+ `hydrate ${relativeRoot} from canonical workspace`
394
+ );
395
+ return true;
340
396
  }
341
- async function stagedDiffSizeBytes(input) {
342
- const subprocess = Bun.spawn(gitArgs(input, ["diff", "--cached", "--binary", "--no-ext-diff"]), {
397
+ function candidateBaseRevision(input) {
398
+ const localHead = revParse(input, "HEAD");
399
+ if (!localHead) return null;
400
+ const remoteHead = revParse(input, `origin/${WORKSPACE_BRANCH}`);
401
+ if (!remoteHead) {
402
+ const emptyTree = Bun.spawnSync(gitArgs(input, ["mktree"]), {
403
+ cwd: input.shadowRoot,
404
+ stdin: Buffer.alloc(0),
405
+ stdout: "pipe",
406
+ stderr: "pipe",
407
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
408
+ });
409
+ if (emptyTree.exitCode !== 0) {
410
+ throw new Error(
411
+ `create empty workspace comparison tree: ${emptyTree.stderr.toString().trim() || `git exited ${emptyTree.exitCode}`}`
412
+ );
413
+ }
414
+ return emptyTree.stdout.toString().trim();
415
+ }
416
+ const mergeBase = runGitResult(input, input.shadowRoot, ["merge-base", localHead, remoteHead]);
417
+ return mergeBase.exitCode === 0 && mergeBase.stdout ? mergeBase.stdout : remoteHead;
418
+ }
419
+ function stagedPaths(input, baseRevision) {
420
+ return runGit(
421
+ input,
422
+ input.shadowRoot,
423
+ ["diff", "--cached", "--name-only", "-z", ...baseRevision ? [baseRevision] : []],
424
+ "list workspace changes"
425
+ ).split("\0").filter(Boolean).sort();
426
+ }
427
+ function stagedDeletedPaths(input, baseRevision) {
428
+ return runGit(
429
+ input,
430
+ input.shadowRoot,
431
+ ["diff", "--cached", "--diff-filter=D", "--name-only", "-z", ...baseRevision ? [baseRevision] : []],
432
+ "list workspace deletions"
433
+ ).split("\0").filter(Boolean).sort();
434
+ }
435
+ function managedCheckoutRoot(filePath) {
436
+ const projectMatch = /^projects\/([^/]+)\/branches\/([^/]+)\//.exec(filePath);
437
+ return projectMatch ? `projects/${projectMatch[1]}/branches/${projectMatch[2]}` : null;
438
+ }
439
+ function revisionTrackedFileCount(input, revision, relativeRoot) {
440
+ if (!revision) return 0;
441
+ const result = runGitResult(input, input.shadowRoot, ["ls-tree", "-r", "--name-only", "-z", revision, "--", relativeRoot]);
442
+ if (result.exitCode !== 0) return 0;
443
+ return result.stdout.split("\0").filter(Boolean).length;
444
+ }
445
+ function destructiveCheckoutReductions(input, baseRevision) {
446
+ const roots = new Set(
447
+ stagedDeletedPaths(input, baseRevision).map(managedCheckoutRoot).filter((root) => Boolean(root))
448
+ );
449
+ const destructive = [];
450
+ for (const root of roots) {
451
+ const trackedBefore = revisionTrackedFileCount(input, baseRevision, root);
452
+ if (trackedBefore === 0) continue;
453
+ const trackedAfter = listShadowTrackedFiles(input, root).length;
454
+ const removedRatio = (trackedBefore - trackedAfter) / trackedBefore;
455
+ if (trackedAfter === 0 || trackedBefore >= DESTRUCTIVE_CHECKOUT_MIN_TRACKED_FILES && removedRatio >= DESTRUCTIVE_CHECKOUT_REMOVAL_RATIO) {
456
+ destructive.push({ root, trackedBefore, trackedAfter });
457
+ }
458
+ }
459
+ return destructive.sort((left, right) => left.root.localeCompare(right.root));
460
+ }
461
+ async function stagedDiffSizeBytes(input, baseRevision) {
462
+ const subprocess = Bun.spawn(gitArgs(input, ["diff", "--cached", "--binary", "--no-ext-diff", ...baseRevision ? [baseRevision] : []]), {
343
463
  cwd: input.shadowRoot,
344
464
  stdout: "pipe",
345
465
  stderr: "pipe",
@@ -442,13 +562,17 @@ async function synchronizeWorkspace(rawInput) {
442
562
  };
443
563
  }
444
564
  if (!input.skipVisibleMirror) {
565
+ resetUncommittedShadowSnapshot(input);
445
566
  const newCheckoutKeys = new Set((input.newVisibleCheckouts ?? []).map((target) => `${target.projectId}\0${target.branchName}`));
446
567
  mirrorVisibleWorkspaceToShadow(input, newCheckoutKeys);
568
+ fastForwardCleanShadowForNewCheckouts(input);
447
569
  reconcileNewVisibleCheckouts(input);
448
570
  }
449
571
  runGit(input, input.shadowRoot, ["add", "-A"], "stage workspace changes");
450
- const paths = stagedPaths(input);
451
- const diffSizeBytes = await stagedDiffSizeBytes(input);
572
+ const stagedWorkingPaths = stagedPaths(input);
573
+ const baseRevision = candidateBaseRevision(input);
574
+ const paths = stagedPaths(input, baseRevision);
575
+ const diffSizeBytes = await stagedDiffSizeBytes(input, baseRevision);
452
576
  const statusBeforeCommit = reportedStatus(gitStatus(input));
453
577
  const observed = {
454
578
  ...result,
@@ -457,10 +581,23 @@ async function synchronizeWorkspace(rawInput) {
457
581
  affectedPaths: reportedPaths(paths),
458
582
  affectedProjects: affectedProjects(paths)
459
583
  };
584
+ const destructiveReductions = destructiveCheckoutReductions(input, baseRevision);
585
+ if (destructiveReductions.length > 0 && !input.confirmedLargeDiff) {
586
+ const summary = destructiveReductions.map(({ root, trackedBefore, trackedAfter }) => `${root} (${trackedBefore} -> ${trackedAfter} tracked files)`).join(", ");
587
+ return {
588
+ ...observed,
589
+ outcome: "large_diff_blocked",
590
+ error: `Workspace safety guard blocked a destructive checkout reduction: ${summary}`
591
+ };
592
+ }
460
593
  if (paths.length > 0 && diffSizeBytes > MAX_WORKSPACE_SYNC_DIFF_BYTES && !input.confirmedLargeDiff) {
461
- return { ...observed, outcome: "large_diff_blocked" };
594
+ return {
595
+ ...observed,
596
+ outcome: "large_diff_blocked",
597
+ error: `Workspace safety guard blocked a ${diffSizeBytes}-byte diff above the ${MAX_WORKSPACE_SYNC_DIFF_BYTES}-byte automatic publication limit.`
598
+ };
462
599
  }
463
- if (paths.length > 0) {
600
+ if (stagedWorkingPaths.length > 0) {
464
601
  runGit(input, input.shadowRoot, ["commit", "-m", commitMessage(input)], "commit workspace changes");
465
602
  }
466
603
  const candidateHead = revParse(input, "HEAD");
@@ -553,7 +690,10 @@ async function synchronizeWorkspace(rawInput) {
553
690
  }
554
691
  function calculateWorkspaceDiffFingerprint(input) {
555
692
  ensureShadowWorkspace(input);
556
- if (!input.skipVisibleMirror) mirrorVisibleWorkspaceToShadow(input);
693
+ if (!input.skipVisibleMirror) {
694
+ resetUncommittedShadowSnapshot(input);
695
+ mirrorVisibleWorkspaceToShadow(input);
696
+ }
557
697
  runGit(input, input.shadowRoot, ["add", "-A"], "stage workspace fingerprint");
558
698
  const stagedTree = runGit(input, input.shadowRoot, ["write-tree"], "write workspace fingerprint tree");
559
699
  const headTree = revParse(input, "HEAD^{tree}");
@@ -566,27 +706,25 @@ function calculateWorkspaceDiffFingerprint(input) {
566
706
  }
567
707
  class WorkspaceSyncSingleFlight {
568
708
  queue = Promise.resolve();
569
- run(input) {
570
- const queued = this.queue.then(
571
- () => synchronizeWorkspace(input),
572
- () => synchronizeWorkspace(input)
573
- );
709
+ enqueue(task) {
710
+ const queued = this.queue.then(task, task);
574
711
  this.queue = queued.then(
575
712
  () => void 0,
576
713
  () => void 0
577
714
  );
578
715
  return queued;
579
716
  }
717
+ run(input) {
718
+ return this.enqueue(() => synchronizeWorkspace(input));
719
+ }
720
+ runPrepared(prepare) {
721
+ return this.enqueue(() => synchronizeWorkspace(prepare()));
722
+ }
580
723
  fingerprint(input) {
581
- const queued = this.queue.then(
582
- () => calculateWorkspaceDiffFingerprint(input),
583
- () => calculateWorkspaceDiffFingerprint(input)
584
- );
585
- this.queue = queued.then(
586
- () => void 0,
587
- () => void 0
588
- );
589
- return queued;
724
+ return this.enqueue(() => calculateWorkspaceDiffFingerprint(input));
725
+ }
726
+ fingerprintPrepared(prepare) {
727
+ return this.enqueue(() => calculateWorkspaceDiffFingerprint(prepare()));
590
728
  }
591
729
  afterCurrent() {
592
730
  return this.queue;
@@ -49,6 +49,11 @@ type WorkerViewFileBytesResult = {
49
49
  width: number;
50
50
  height: number;
51
51
  };
52
+ export type WorkerBuiltInToolPaths = {
53
+ artifactsDir?: string;
54
+ plansDir?: string;
55
+ activePlanFile?: string;
56
+ };
52
57
  export declare function isArtifactEnvPath(filePath: string): boolean;
53
58
  export declare function syncSessionArtifacts(input: {
54
59
  baseUrl: string;
@@ -86,8 +91,14 @@ type ResolvedWorkerFilePath = {
86
91
  displayPath: string;
87
92
  repoRelativePath: null;
88
93
  scope: "host";
94
+ } | {
95
+ absolutePath: string;
96
+ displayPath: string;
97
+ repoRelativePath: null;
98
+ scope: "virtual";
99
+ virtualRootPath: string;
89
100
  };
90
- export declare function resolveWorkerFilePath(branchPath: string, inputPath: string): ResolvedWorkerFilePath;
101
+ export declare function resolveWorkerFilePath(branchPath: string, inputPath: string, builtInPaths?: WorkerBuiltInToolPaths): ResolvedWorkerFilePath;
91
102
  export declare function githubCliEnv(token: string | null | undefined): Record<string, string>;
92
103
  export declare function ensureVisibleGitCheckout(input: {
93
104
  projectRoot: string;
@@ -98,27 +109,27 @@ export declare function ensureVisibleGitCheckout(input: {
98
109
  defaultBranch: string;
99
110
  reconcileExistingOrigin?: boolean;
100
111
  }): string;
101
- export declare function readWorkerTextFile(branchPath: string, filePath: string, offset?: number, limit?: number): WorkerReadFileResult;
102
- export declare function writeWorkerTextFile(branchPath: string, filePath: string, content: string): WorkerWriteFileResult;
112
+ export declare function readWorkerTextFile(branchPath: string, filePath: string, offset?: number, limit?: number, builtInPaths?: WorkerBuiltInToolPaths): WorkerReadFileResult;
113
+ export declare function writeWorkerTextFile(branchPath: string, filePath: string, content: string, builtInPaths?: WorkerBuiltInToolPaths): WorkerWriteFileResult;
103
114
  export declare function editWorkerTextFile(branchPath: string, filePath: string, edits: Array<{
104
115
  oldText: string;
105
116
  newText: string;
106
- }>): WorkerEditFileResult;
117
+ }>, builtInPaths?: WorkerBuiltInToolPaths): WorkerEditFileResult;
107
118
  export declare function grepWorkerFiles(branchPath: string, input: {
108
119
  pattern: string;
109
120
  path?: string;
110
121
  glob?: string;
111
122
  caseSensitive?: boolean;
112
123
  limit?: number;
113
- }): WorkerGrepResult;
124
+ }, builtInPaths?: WorkerBuiltInToolPaths): WorkerGrepResult;
114
125
  export declare function findWorkerFiles(branchPath: string, input: {
115
126
  pattern?: string;
116
127
  path?: string;
117
128
  entryType?: string;
118
129
  limit?: number;
119
- }): WorkerFindResult;
120
- export declare function listWorkerDirectory(branchPath: string, inputPath?: string, inputLimit?: number): WorkerLsResult;
121
- export declare function readWorkerImageFile(branchPath: string, filePath: string): WorkerViewFileBytesResult;
130
+ }, builtInPaths?: WorkerBuiltInToolPaths): WorkerFindResult;
131
+ export declare function listWorkerDirectory(branchPath: string, inputPath?: string, inputLimit?: number, builtInPaths?: WorkerBuiltInToolPaths): WorkerLsResult;
132
+ export declare function readWorkerImageFile(branchPath: string, filePath: string, builtInPaths?: WorkerBuiltInToolPaths): WorkerViewFileBytesResult;
122
133
  export declare function resolveHostShell(command?: string, platform?: NodeJS.Platform): {
123
134
  file: string;
124
135
  args: string[];
@@ -68,7 +68,10 @@ export declare function synchronizeWorkspace(rawInput: WorkspaceSyncInput): Prom
68
68
  export declare function calculateWorkspaceDiffFingerprint(input: WorkspaceSyncInput): string;
69
69
  export declare class WorkspaceSyncSingleFlight {
70
70
  private queue;
71
+ private enqueue;
71
72
  run(input: WorkspaceSyncInput): Promise<WorkspaceSyncResult>;
73
+ runPrepared(prepare: () => WorkspaceSyncInput): Promise<WorkspaceSyncResult>;
72
74
  fingerprint(input: WorkspaceSyncInput): Promise<string>;
75
+ fingerprintPrepared(prepare: () => WorkspaceSyncInput): Promise<string>;
73
76
  afterCurrent(): Promise<void>;
74
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.44",
3
+ "version": "0.0.46",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/main.cjs",
6
6
  "module": "./dist/mjs/main.mjs",