@pstdio/pocketcoder-cli 0.6.1 → 0.6.2

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.
Files changed (2) hide show
  1. package/dist/index.js +171 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5214,7 +5214,7 @@ function isYargsInstance(y) {
5214
5214
  var Yargs = YargsFactory(esm_default);
5215
5215
  var yargs_default = Yargs;
5216
5216
  // package.json
5217
- var version = "0.6.1";
5217
+ var version = "0.6.2";
5218
5218
 
5219
5219
  // src/cli-context.ts
5220
5220
  import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
@@ -40637,6 +40637,172 @@ class PocketCoderClient {
40637
40637
  return this.transport.raw(path, init);
40638
40638
  }
40639
40639
  }
40640
+ // ../sdk/src/workspace-turn-resolver.ts
40641
+ var ERROR_MESSAGES = {
40642
+ not_resumable: "workspace cannot be resumed",
40643
+ resume_handler_missing: "workspace resume handler is not configured",
40644
+ resume_failed: "workspace resume failed",
40645
+ invalid_resumed_workspace: "workspace resume returned an invalid workspace",
40646
+ readiness_failed: "resumed workspace did not become ready"
40647
+ };
40648
+
40649
+ class WorkspaceTurnResolutionError extends Error {
40650
+ code;
40651
+ constructor(code, cause) {
40652
+ super(ERROR_MESSAGES[code], cause === undefined ? undefined : { cause });
40653
+ this.name = "WorkspaceTurnResolutionError";
40654
+ this.code = code;
40655
+ }
40656
+ }
40657
+ var NON_RESUMABLE_STATES = new Set([
40658
+ "failed",
40659
+ "canceled",
40660
+ "expired",
40661
+ "succeeded",
40662
+ "terminating"
40663
+ ]);
40664
+ function aborted2(signal) {
40665
+ return signal.reason ?? new DOMException("The operation was aborted", "AbortError");
40666
+ }
40667
+ function waitForCaller(promise2, signal) {
40668
+ if (!signal)
40669
+ return promise2;
40670
+ if (signal.aborted)
40671
+ return Promise.reject(aborted2(signal));
40672
+ return new Promise((resolve6, reject) => {
40673
+ const onAbort = () => reject(aborted2(signal));
40674
+ signal.addEventListener("abort", onAbort, { once: true });
40675
+ promise2.then((value) => {
40676
+ signal.removeEventListener("abort", onAbort);
40677
+ resolve6(value);
40678
+ }, (error51) => {
40679
+ signal.removeEventListener("abort", onAbort);
40680
+ reject(error51);
40681
+ });
40682
+ });
40683
+ }
40684
+ function requireRemaining(deadline, failure) {
40685
+ const remaining = deadline - Date.now();
40686
+ if (remaining <= 0)
40687
+ throw new WorkspaceTurnResolutionError(failure);
40688
+ return remaining;
40689
+ }
40690
+
40691
+ class WorkspaceTurnResolver {
40692
+ client;
40693
+ resumeWorkspace;
40694
+ resumeTimeoutMs;
40695
+ attempts = new Map;
40696
+ constructor(options) {
40697
+ this.client = options.client;
40698
+ this.resumeWorkspace = options.resumeWorkspace;
40699
+ this.resumeTimeoutMs = options.resumeTimeoutMs ?? 300000;
40700
+ }
40701
+ async resolve(sourceWorkspaceId, options = {}) {
40702
+ if (options.signal?.aborted)
40703
+ throw aborted2(options.signal);
40704
+ const attempt = this.attempts.get(sourceWorkspaceId) ?? this.start(sourceWorkspaceId);
40705
+ attempt.waiters += 1;
40706
+ try {
40707
+ return await waitForCaller(attempt.promise, options.signal);
40708
+ } finally {
40709
+ attempt.waiters -= 1;
40710
+ if (attempt.waiters === 0 && !attempt.resumeStarted && !attempt.settled) {
40711
+ attempt.controller.abort(new DOMException("No callers remain", "AbortError"));
40712
+ }
40713
+ }
40714
+ }
40715
+ start(sourceWorkspaceId) {
40716
+ const attempt = {
40717
+ controller: new AbortController,
40718
+ promise: Promise.resolve(undefined),
40719
+ waiters: 0,
40720
+ resumeStarted: false,
40721
+ settled: false
40722
+ };
40723
+ this.attempts.set(sourceWorkspaceId, attempt);
40724
+ attempt.promise = this.run(sourceWorkspaceId, attempt).finally(() => {
40725
+ attempt.settled = true;
40726
+ if (this.attempts.get(sourceWorkspaceId) === attempt) {
40727
+ this.attempts.delete(sourceWorkspaceId);
40728
+ }
40729
+ });
40730
+ attempt.promise.catch(() => {});
40731
+ return attempt;
40732
+ }
40733
+ async run(sourceWorkspaceId, attempt) {
40734
+ const deadline = Date.now() + this.resumeTimeoutMs;
40735
+ let source = await this.client.workspaces.get(sourceWorkspaceId, {
40736
+ signal: attempt.controller.signal
40737
+ });
40738
+ if (source.state === "ready")
40739
+ return { workspace: source, resumed: false };
40740
+ if (source.state === "preserving") {
40741
+ source = await this.waitForPreserved(source, deadline, attempt.controller.signal);
40742
+ }
40743
+ this.assertResumable(source);
40744
+ if (!this.resumeWorkspace) {
40745
+ throw new WorkspaceTurnResolutionError("resume_handler_missing");
40746
+ }
40747
+ attempt.resumeStarted = true;
40748
+ const attemptId = crypto.randomUUID();
40749
+ let allocated;
40750
+ try {
40751
+ allocated = await this.resumeWorkspace({
40752
+ source,
40753
+ attemptId,
40754
+ signal: attempt.controller.signal
40755
+ });
40756
+ } catch (error51) {
40757
+ throw new WorkspaceTurnResolutionError("resume_failed", error51);
40758
+ }
40759
+ let fetched;
40760
+ try {
40761
+ fetched = await this.client.workspaces.get(allocated.id, {
40762
+ signal: attempt.controller.signal
40763
+ });
40764
+ } catch (error51) {
40765
+ throw new WorkspaceTurnResolutionError("invalid_resumed_workspace", error51);
40766
+ }
40767
+ this.assertLineage(source, fetched);
40768
+ try {
40769
+ const workspace = await this.client.workspaces.waitForReady(fetched, requireRemaining(deadline, "readiness_failed"), { signal: attempt.controller.signal });
40770
+ return { workspace, resumed: true };
40771
+ } catch (error51) {
40772
+ if (error51 instanceof WorkspaceTurnResolutionError)
40773
+ throw error51;
40774
+ throw new WorkspaceTurnResolutionError("readiness_failed", error51);
40775
+ }
40776
+ }
40777
+ async waitForPreserved(initial, deadline, signal) {
40778
+ let workspace = initial;
40779
+ while (workspace.state === "preserving") {
40780
+ const remaining = requireRemaining(deadline, "resume_failed");
40781
+ try {
40782
+ const change = await this.client.workspaces.change(workspace.id, workspace.change_cursor, Math.max(1, Math.min(30, Math.ceil(remaining / 1000))), { signal });
40783
+ workspace = change.workspace;
40784
+ } catch (error51) {
40785
+ if (signal.aborted)
40786
+ throw error51;
40787
+ throw new WorkspaceTurnResolutionError("resume_failed", error51);
40788
+ }
40789
+ }
40790
+ if (workspace.state === "failed") {
40791
+ throw new WorkspaceTurnResolutionError("resume_failed");
40792
+ }
40793
+ return workspace;
40794
+ }
40795
+ assertResumable(workspace) {
40796
+ if (workspace.state !== "preserved" || NON_RESUMABLE_STATES.has(workspace.state) || workspace.persistence.conversation_resume.status !== "supported" || !workspace.persistence.latest_checkpoint_id) {
40797
+ throw new WorkspaceTurnResolutionError("not_resumable");
40798
+ }
40799
+ }
40800
+ assertLineage(source, resumedWorkspace) {
40801
+ if (resumedWorkspace.id === source.id || resumedWorkspace.origin_workspace_id !== source.id || resumedWorkspace.restored_from_checkpoint_id !== source.persistence.latest_checkpoint_id) {
40802
+ throw new WorkspaceTurnResolutionError("invalid_resumed_workspace");
40803
+ }
40804
+ }
40805
+ }
40640
40806
  // src/cli-context.ts
40641
40807
  var import_dotenv = __toESM(require_main(), 1);
40642
40808
  function need(flags, key) {
@@ -43101,9 +43267,9 @@ class FilesystemStorageDriver {
43101
43267
  }
43102
43268
  }
43103
43269
  async initRoots() {
43104
- await mkdir3(this.workspaceRoot, { recursive: true, mode: 448 });
43270
+ await mkdir3(this.workspaceRoot, { recursive: true, mode: 457 });
43105
43271
  await mkdir3(this.checkpointRoot, { recursive: true, mode: 448 });
43106
- await chmod3(this.workspaceRoot, 448);
43272
+ await chmod3(this.workspaceRoot, 457);
43107
43273
  await chmod3(this.checkpointRoot, 448);
43108
43274
  }
43109
43275
  storageRef(ref) {
@@ -43123,8 +43289,8 @@ class FilesystemStorageDriver {
43123
43289
  async allocate(input) {
43124
43290
  await this.initRoots();
43125
43291
  const root = childOf2(this.workspaceRoot, input.storageId);
43126
- await mkdir3(root, { recursive: true, mode: 448 });
43127
- await chmod3(root, 448);
43292
+ await mkdir3(root, { recursive: true, mode: 457 });
43293
+ await chmod3(root, 457);
43128
43294
  for (const mount of input.mounts) {
43129
43295
  const path = join7(root, mount.name);
43130
43296
  await mkdir3(path, { recursive: true, mode: 504 });
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "type:app"
7
7
  ]
8
8
  },
9
- "version": "0.6.1",
9
+ "version": "0.6.2",
10
10
  "private": false,
11
11
  "description": "Operator and diagnostics CLI for PocketCoder.",
12
12
  "type": "module",