@byok-sdk/cloud-do 0.26.1 → 0.27.0

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/README.md CHANGED
@@ -4,26 +4,33 @@ This package hosts a pi-durable session in a Cloudflare Durable Object.
4
4
  It provides native SQLite storage, inline tools, wake and inbox processing,
5
5
  usage limits, settlement hooks, and transcript reads.
6
6
 
7
- The prepared stable candidate is 0.26.1, with keys 0.11.1. It is not
8
- published. See the [candidate release notes](../../docs/releases/v0.26.1.md).
9
-
10
- The current `latest` release is 0.26.0, in the nine-package release set with
11
- keys 0.11.0. Registry readback passed on 2026-10-11; see the
12
- [publication record](../../docs/releases/v0.26.0-publication.md).
13
- The published 0.26.0-rc.4 (see the
7
+ The current source prepares stable 0.27.0, in the nine-package release set
8
+ with keys 0.12.0, for the npm dist-tag `latest`. Publication remains pending.
9
+ The published `rc` train remains 0.27.0-rc.2 / keys 0.12.0-rc.2; see the
10
+ [rc.2 publication record](../../docs/releases/v0.27.0-rc.2-publication.md).
11
+ See the [release notes](../../docs/releases/v0.27.0.md) for the stable plan
12
+ and the open Host acceptance gap (#195).
13
+
14
+ The current `latest` release is 0.26.1, in the nine-package release set with
15
+ keys 0.11.1. Registry readback and isolated installation passed on 2026-10-12.
16
+ See the [publication record](../../docs/releases/v0.26.1-publication.md).
17
+ The previous stable release was 0.26.0 / keys 0.11.0; its
18
+ [publication record](../../docs/releases/v0.26.0-publication.md) remains historical.
19
+ The earlier published 0.26.0-rc.4 (see the
14
20
  [rc.4 publication record](../../docs/releases/v0.26.0-rc.4-publication.md))
15
- stays on `rc`; rc.1 to rc.3 are superseded. See the
16
- [release notes](../../docs/releases/v0.26.0.md#version-set-and-channel).
21
+ is superseded by 0.27.0-rc.2; 0.26.0-rc.1 to rc.3 are superseded. See the
22
+ [release notes](../../docs/releases/v0.26.1.md#version-set-and-channel).
17
23
  Live Host acceptance remains separate.
18
24
  The package needs Node 24.15.0 or later for build tooling.
19
25
 
20
26
  ## Install and subclass
21
27
 
22
- The following install example names the prepared stable candidate. Publish
23
- it before installation. Use an installed package to verify the consumer path.
28
+ The following install example names the 0.27.0 candidate. It works only
29
+ after publication and exact registry readback. Use an installed package to
30
+ verify the consumer path.
24
31
 
25
32
  ~~~sh
26
- npm install @byok-sdk/cloud-do@0.26.1
33
+ npm install @byok-sdk/cloud-do@0.27.0
27
34
  npm install --save-dev @cloudflare/workers-types
28
35
  ~~~
29
36
 
@@ -109,13 +116,13 @@ openDurableObjectStorage has the local structural factory type
109
116
  (location: DurableObjectStorage) => Promise<Storage>.
110
117
  Storage is pi-durable's native interface. The package does not import client
111
118
  source or keys types. Its three runtime dependencies are pi-durable, pi-ai,
112
- and chord, each pinned to 1.1.0.
119
+ and chord, each pinned to 1.2.0.
113
120
 
114
121
  The Durable Object owns the physical connection. Closing the adapter
115
122
  invalidates that adapter. It does not close the Durable Object database.
116
123
 
117
124
  This follows the async adapter in [Cloudflare Agents d6656161](https://github.com/cloudflare/agents/blob/d6656161/packages/agents/src/harness/pi/session-store.ts).
118
- Current upstream uses a different synchronous pi contract. Pinned pi 1.1.0 takes
125
+ Current upstream uses a different synchronous pi contract. Pinned pi 1.2.0 takes
119
126
  async callbacks, so `transactionSync()` cannot host its transaction callback.
120
127
  Cloudflare documents async SQL transactions on the
121
128
  [SQLite storage API](https://developers.cloudflare.com/durable-objects/api/sqlite-storage-api/).
@@ -128,11 +135,13 @@ under the SDK's pre-1.0 policy.
128
135
  ## Package checks
129
136
 
130
137
  The library build emits dist/index.js and a local declaration closure.
131
- The dist check rejects Node builtins, missing or escaped declaration paths,
132
- and undeclared external type imports. A separate Wrangler dry run writes
138
+ The dist check rejects missing or escaped declaration paths and undeclared
139
+ external type imports. The entry dependency contract enforces runtime builtin policy. A separate Wrangler dry run writes
133
140
  dist-worker. That Worker output is not in the npm package.
134
141
 
135
142
  Release verification installs a real tarball in a temporary consumer.
136
143
  It typechecks the subclass, bundles it with Wrangler, and runs its hook,
137
144
  Durable Object RPC, identity helper, and SQLite adapter in real workerd.
138
145
  The same smoke runs in the Linux, macOS, and Windows release-pack jobs.
146
+
147
+ Runtime dependencies and size budgets: [entry dependency contract](../../README.md#entry-dependencies).
package/dist/index.js CHANGED
@@ -2271,6 +2271,8 @@ var SessionRuntime = class {
2271
2271
  #initializing = false;
2272
2272
  #deferredSettlements = [];
2273
2273
  #opened;
2274
+ /** Pi 1.2: the cached Harness's Session failed and closed. The next open() replaces it from Storage. */
2275
+ #sessionFailed = false;
2274
2276
  #recovery;
2275
2277
  #recovered = false;
2276
2278
  #config;
@@ -2345,14 +2347,23 @@ var SessionRuntime = class {
2345
2347
  });
2346
2348
  }
2347
2349
  open(selected) {
2348
- if (!this.#opened) {
2350
+ if (!this.#opened || this.#sessionFailed) {
2351
+ this.#sessionFailed = false;
2352
+ let openGuard;
2353
+ const disposeOpenGuard = () => {
2354
+ openGuard?.dispose();
2355
+ if (this.#recoveryGuard === openGuard) this.#recoveryGuard = void 0;
2356
+ };
2349
2357
  const initialized = prepareCloudGuard(this.env, selected).then((guard) => {
2358
+ openGuard = guard;
2350
2359
  this.#recoveryGuard = guard;
2351
2360
  this.#initializing = true;
2352
2361
  return this.state.blockConcurrencyWhile(async () => {
2353
2362
  this.ledger.ensureSchema();
2354
2363
  this.cloud.ensureSchema();
2355
2364
  this.#sessionSchema();
2365
+ this.#dispatcher = void 0;
2366
+ this.#bootstrapFailure = void 0;
2356
2367
  this.#config = this.#storedConfig();
2357
2368
  if (!this.#config && this.ledger.pending().length) this.#bootstrapFailure = "CLOUD_TOOL_NOT_AVAILABLE";
2358
2369
  if (this.#config) {
@@ -2428,20 +2439,22 @@ var SessionRuntime = class {
2428
2439
  return { harness, replay };
2429
2440
  });
2430
2441
  });
2431
- this.#opened = initialized.then(({ harness, replay }) => {
2442
+ const opened = initialized.then(({ harness, replay }) => {
2432
2443
  this.#flushSettlements();
2433
- this.#recovery = this.#recover(harness, replay).finally(() => {
2434
- this.#recoveryGuard?.dispose();
2435
- this.#recoveryGuard = void 0;
2444
+ void harness.closed.then((end) => {
2445
+ if (end.reason !== "failed" || this.#opened !== opened) return;
2446
+ this.#recovered = false;
2447
+ this.#sessionFailed = true;
2436
2448
  });
2449
+ this.#recovery = this.#recover(harness, replay).finally(disposeOpenGuard);
2437
2450
  void this.#recovery.catch(() => void 0);
2438
2451
  return harness;
2439
2452
  }, (error) => {
2440
2453
  this.#flushSettlements();
2441
- this.#recoveryGuard?.dispose();
2442
- this.#recoveryGuard = void 0;
2454
+ disposeOpenGuard();
2443
2455
  throw error;
2444
2456
  });
2457
+ this.#opened = opened;
2445
2458
  }
2446
2459
  return this.#opened;
2447
2460
  }
@@ -2638,7 +2651,7 @@ var SessionRuntime = class {
2638
2651
  this.#repairing = false;
2639
2652
  guard?.dispose();
2640
2653
  previousGuard?.dispose();
2641
- this.#recoveryGuard = void 0;
2654
+ if (this.#recoveryGuard === guard) this.#recoveryGuard = void 0;
2642
2655
  if (this.#active) this.#active.guard = void 0;
2643
2656
  }
2644
2657
  }
@@ -2881,11 +2894,13 @@ var SessionRuntime = class {
2881
2894
  await this.#runInvocation(row2, void 0, true).catch(() => void 0);
2882
2895
  }
2883
2896
  await this.#adjudicateRuns(harness);
2897
+ if (this.#active && !this.#active.liveOwner) {
2898
+ clearTimeout(this.#active.timer);
2899
+ this.#active = void 0;
2900
+ }
2884
2901
  await this.#backfillTurns(harness);
2885
2902
  await this.cloud.rearmAlarm({ busy: false, repairRetrying: false });
2886
2903
  this.#recovered = true;
2887
- this.#recoveryGuard?.dispose();
2888
- this.#recoveryGuard = void 0;
2889
2904
  }
2890
2905
  async #backfillTurns(harness) {
2891
2906
  let before = Number.MAX_SAFE_INTEGER;
@@ -2966,20 +2981,20 @@ var SessionRuntime = class {
2966
2981
  const error = result.error;
2967
2982
  if (Object.hasOwn(result, "modelView")) return {
2968
2983
  isError: result.ok === false,
2969
- content: [{ type: "text", text: JSON.stringify(result.modelView) }]
2984
+ output: [{ type: "text", text: JSON.stringify(result.modelView) }]
2970
2985
  };
2971
2986
  if (result.ok === false) {
2972
2987
  if (this.#dispatcher?.domainErrors?.includes(error.code)) return {
2973
2988
  isError: true,
2974
- content: [{ type: "text", text: JSON.stringify({ ok: false, error }) }]
2989
+ output: [{ type: "text", text: JSON.stringify({ ok: false, error }) }]
2975
2990
  };
2976
2991
  return this.#errorResult(error.code);
2977
2992
  }
2978
- return { content: [{ type: "text", text: JSON.stringify(result) }] };
2993
+ return { output: [{ type: "text", text: JSON.stringify(result) }] };
2979
2994
  }
2980
2995
  #errorResult(code) {
2981
2996
  const fixed = safeCloudError(new Error(typeof code === "string" ? code : "CLOUD_TOOL_FAILED")).code;
2982
- return { isError: true, content: [{ type: "text", text: JSON.stringify({ ok: false, error: { code: fixed } }) }] };
2997
+ return { isError: true, output: [{ type: "text", text: JSON.stringify({ ok: false, error: { code: fixed } }) }] };
2983
2998
  }
2984
2999
  #toolErrorCode(error) {
2985
3000
  const code = safeCloudError(error).code;
@@ -3016,7 +3031,7 @@ var SessionRuntime = class {
3016
3031
  let removeAbort;
3017
3032
  try {
3018
3033
  deadline = Math.min(row2.deadlineAt, this.ledger.execution(row2.conversationId)?.deadlineAt ?? row2.deadlineAt);
3019
- if (Date.now() >= deadline) throw new CloudDoError("CLOUD_TOOL_TIMEOUT");
3034
+ if (Date.now() >= deadline) throw new CloudDoError(this.#timeoutCode(row2.conversationId));
3020
3035
  if (!this.#config || !this.#dispatcher) throw new CloudDoError("CLOUD_EXECUTION_INTERRUPTED");
3021
3036
  if (!recovery && this.fatal(row2.conversationId)) throw new CloudDoError(this.fatal(row2.conversationId));
3022
3037
  const args = JSON.parse(row2.argsJson);