@standardagents/builder 0.27.4 → 0.27.6

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/dist/runtime.d.ts CHANGED
@@ -1003,7 +1003,9 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
1003
1003
  private currentExecutionOwnerId;
1004
1004
  /** Persist + cache the execution-owner record (null releases ownership). */
1005
1005
  private setExecutionOwner;
1006
- /** Whether the given client id has a live bridge socket (excluding `except`). */
1006
+ /** Whether the given client id has an open bridge socket (excluding `except`).
1007
+ * Idle bridge heartbeats are handled by Cloudflare without waking this object,
1008
+ * so timestamp liveness is intentionally enforced only for an in-flight call. */
1007
1009
  private hasLiveBridgeSocketForClient;
1008
1010
  /** Tell every other bridge socket that execution ownership moved. */
1009
1011
  private broadcastOwnerChanged;
@@ -1031,11 +1033,10 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
1031
1033
  private markBridgeDead;
1032
1034
  /**
1033
1035
  * Return the bridge socket a forwarded call should be dispatched to, pruning
1034
- * dead ones. A half-open client (idle NAT/proxy drop) keeps a
1035
- * `readyState === OPEN` socket that never fires close/error, so we also treat
1036
- * a socket we haven't heard from within {@link BRIDGE_LIVENESS_TIMEOUT_MS} as
1037
- * dead. The CLI heartbeats every few seconds, so this only trips on a truly
1038
- * gone client — and it means we won't dispatch a forwarded call into the void.
1036
+ * closed ones. Idle clients use Cloudflare's hibernation auto-response, so
1037
+ * their frames deliberately do not update `bridgeLastSeen`. Once a call is
1038
+ * dispatched, the client switches to application-visible pings and the
1039
+ * in-flight liveness timer above detects a half-open connection.
1039
1040
  *
1040
1041
  * With an execution owner recorded, only the owner's socket (or, as a
1041
1042
  * back-compat fallback, an unidentified legacy socket) is eligible; with no
package/dist/runtime.js CHANGED
@@ -16093,6 +16093,11 @@ var DurableThread = class _DurableThread extends DurableObject {
16093
16093
  codeExecutionBridges = /* @__PURE__ */ new Map();
16094
16094
  constructor(ctx, env) {
16095
16095
  super(ctx, env);
16096
+ if (typeof WebSocketRequestResponsePair !== "undefined") {
16097
+ ctx.setWebSocketAutoResponse(
16098
+ new WebSocketRequestResponsePair("stream_ping", "stream_pong")
16099
+ );
16100
+ }
16096
16101
  this.alarmQueue = new AlarmQueue(ctx);
16097
16102
  this.alarmQueue.setExecutor(
16098
16103
  async (method, args, itemId) => {
@@ -19457,14 +19462,13 @@ ${resultContent}${attachmentSummary}`;
19457
19462
  async setExecutionOwner(owner) {
19458
19463
  await this.setValue(EXECUTION_OWNER_KEY, owner);
19459
19464
  }
19460
- /** Whether the given client id has a live bridge socket (excluding `except`). */
19465
+ /** Whether the given client id has an open bridge socket (excluding `except`).
19466
+ * Idle bridge heartbeats are handled by Cloudflare without waking this object,
19467
+ * so timestamp liveness is intentionally enforced only for an in-flight call. */
19461
19468
  hasLiveBridgeSocketForClient(clientId, except) {
19462
- const now = Date.now();
19463
19469
  for (const ws of this.bridgeSockets) {
19464
19470
  if (ws === except) continue;
19465
19471
  if (ws.readyState !== WebSocket.OPEN) continue;
19466
- const lastSeen = this.bridgeLastSeen.get(ws) ?? 0;
19467
- if (now - lastSeen > BRIDGE_LIVENESS_TIMEOUT_MS) continue;
19468
19472
  if ((this.bridgeClientInfo.get(ws)?.clientId ?? null) === clientId) return true;
19469
19473
  }
19470
19474
  return false;
@@ -19625,22 +19629,19 @@ ${resultContent}${attachmentSummary}`;
19625
19629
  }
19626
19630
  /**
19627
19631
  * Return the bridge socket a forwarded call should be dispatched to, pruning
19628
- * dead ones. A half-open client (idle NAT/proxy drop) keeps a
19629
- * `readyState === OPEN` socket that never fires close/error, so we also treat
19630
- * a socket we haven't heard from within {@link BRIDGE_LIVENESS_TIMEOUT_MS} as
19631
- * dead. The CLI heartbeats every few seconds, so this only trips on a truly
19632
- * gone client — and it means we won't dispatch a forwarded call into the void.
19632
+ * closed ones. Idle clients use Cloudflare's hibernation auto-response, so
19633
+ * their frames deliberately do not update `bridgeLastSeen`. Once a call is
19634
+ * dispatched, the client switches to application-visible pings and the
19635
+ * in-flight liveness timer above detects a half-open connection.
19633
19636
  *
19634
19637
  * With an execution owner recorded, only the owner's socket (or, as a
19635
19638
  * back-compat fallback, an unidentified legacy socket) is eligible; with no
19636
19639
  * owner, the first live socket wins as it always has.
19637
19640
  */
19638
19641
  getOpenBridgeSocket(ownerClientId) {
19639
- const now = Date.now();
19640
19642
  const live = [];
19641
19643
  for (const ws of Array.from(this.bridgeSockets)) {
19642
- const lastSeen = this.bridgeLastSeen.get(ws) ?? 0;
19643
- if (ws.readyState === WebSocket.OPEN && now - lastSeen <= BRIDGE_LIVENESS_TIMEOUT_MS) {
19644
+ if (ws.readyState === WebSocket.OPEN) {
19644
19645
  live.push({ socket: ws, clientId: this.bridgeClientInfo.get(ws)?.clientId ?? null });
19645
19646
  continue;
19646
19647
  }
@@ -22314,6 +22315,11 @@ var DurableAgentBuilder = class extends DurableObject {
22314
22315
  eventSockets = /* @__PURE__ */ new Set();
22315
22316
  constructor(ctx, env) {
22316
22317
  super(ctx, env);
22318
+ if (typeof WebSocketRequestResponsePair !== "undefined") {
22319
+ ctx.setWebSocketAutoResponse(
22320
+ new WebSocketRequestResponsePair("stream_ping", "stream_pong")
22321
+ );
22322
+ }
22317
22323
  const sockets = ctx.getWebSockets();
22318
22324
  for (const ws of sockets) {
22319
22325
  const attachment = ws.deserializeAttachment();