@standardagents/builder 0.26.0 → 0.27.1

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
@@ -204,6 +204,8 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
204
204
  private messageSockets;
205
205
  private bridgeSockets;
206
206
  private bridgeLastSeen;
207
+ private bridgeClientInfo;
208
+ private executionOwnerCache;
207
209
  private pendingClientCalls;
208
210
  private alarmQueue;
209
211
  private alarmQueueRearmed;
@@ -992,6 +994,29 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
992
994
  * user's own machine.
993
995
  */
994
996
  private handleBridgeWebSocketUpgrade;
997
+ /** Parse a raw KV value into an {@link ExecutionOwner}, or null. */
998
+ private parseExecutionOwner;
999
+ /** Load (and cache) the thread's persisted execution-owner record. */
1000
+ private getExecutionOwner;
1001
+ /** Owner id from the in-memory mirror only (for sync paths); null when
1002
+ * unloaded or unowned — both degrade to the historical any-socket rule. */
1003
+ private currentExecutionOwnerId;
1004
+ /** Persist + cache the execution-owner record (null releases ownership). */
1005
+ private setExecutionOwner;
1006
+ /** Whether the given client id has a live bridge socket (excluding `except`). */
1007
+ private hasLiveBridgeSocketForClient;
1008
+ /** Tell every other bridge socket that execution ownership moved. */
1009
+ private broadcastOwnerChanged;
1010
+ /** Whether any forwarded call is mid-flight (blocking await or parked). */
1011
+ hasInFlightClientCalls(): Promise<boolean>;
1012
+ /**
1013
+ * Ownership moved away from a dead client: settle everything that was
1014
+ * dispatched to it. In-memory blocking calls fail immediately; parked
1015
+ * durable calls get an error result and the turn resumes — re-sending them
1016
+ * to the NEW owner would silently re-run the operation on a different
1017
+ * machine's filesystem, which is worse than an honest retryable error.
1018
+ */
1019
+ private failStalePendingWork;
995
1020
  /**
996
1021
  * Forward a tool operation to a connected bridge client and await its result.
997
1022
  *
@@ -1005,23 +1030,31 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
1005
1030
  /** Close and forget a bridge socket we've deemed dead, failing remaining calls. */
1006
1031
  private markBridgeDead;
1007
1032
  /**
1008
- * Return the first bridge socket that is open AND still proving liveness,
1009
- * pruning dead ones. A half-open client (idle NAT/proxy drop) keeps a
1033
+ * 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
1010
1035
  * `readyState === OPEN` socket that never fires close/error, so we also treat
1011
1036
  * a socket we haven't heard from within {@link BRIDGE_LIVENESS_TIMEOUT_MS} as
1012
1037
  * dead. The CLI heartbeats every few seconds, so this only trips on a truly
1013
1038
  * gone client — and it means we won't dispatch a forwarded call into the void.
1039
+ *
1040
+ * With an execution owner recorded, only the owner's socket (or, as a
1041
+ * back-compat fallback, an unidentified legacy socket) is eligible; with no
1042
+ * owner, the first live socket wins as it always has.
1014
1043
  */
1015
1044
  private getOpenBridgeSocket;
1016
1045
  /** Resolve an in-flight forwarded tool call from a client `tool_response`. */
1017
1046
  private resolveClientCall;
1018
1047
  /**
1019
- * When the last bridge client disconnects, fail any in-flight forwarded tool
1020
- * calls so the agent loop doesn't hang waiting on a client that is gone.
1048
+ * When the last bridge client that could serve forwarded calls disconnects,
1049
+ * fail any in-flight ones so the agent loop doesn't hang waiting on a client
1050
+ * that is gone. Uses the in-memory owner mirror (sync path); when the mirror
1051
+ * isn't loaded this degrades to the historical any-socket check, and the
1052
+ * per-call liveness interval still catches a dead dispatch target.
1021
1053
  */
1022
1054
  private failPendingClientCallsIfNoBridge;
1023
- /** Whether a bridge client is connected right now (used to decide durable park). */
1024
- hasBridge(): boolean;
1055
+ /** Whether a bridge client that can execute forwarded calls is connected
1056
+ * right now (used to decide durable park). */
1057
+ hasBridge(): Promise<boolean>;
1025
1058
  private ensurePendingClientTable;
1026
1059
  /**
1027
1060
  * Durably dispatch a forwarded tool call WITHOUT blocking the agent loop.
@@ -1032,7 +1065,13 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
1032
1065
  dispatchClientTool(request: ClientToolRequest, toolCallId: string, side: "a" | "b"): Promise<{
1033
1066
  dispatched: boolean;
1034
1067
  }>;
1035
- /** Send one durable `tool_request` frame to the bridge if a client is connected. */
1068
+ /**
1069
+ * Send one durable `tool_request` frame to the bridge if a client is
1070
+ * connected — and stamp the pending row with the identity+generation it was
1071
+ * dispatched to, fencing the eventual HTTP delivery to that client. A
1072
+ * legacy (unidentified) executor leaves the row unstamped, keeping the
1073
+ * historical accept-anything delivery for old CLIs.
1074
+ */
1036
1075
  private sendClientToolRequest;
1037
1076
  /** Still-pending durable forwarded calls (for re-sending after a reconnect). */
1038
1077
  getPendingClientCalls(): Promise<Array<{
@@ -1050,7 +1089,7 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
1050
1089
  * call resolved. Returns the side to continue, or null if there is no pending
1051
1090
  * call (unknown id or already resolved — the delivery is idempotent).
1052
1091
  */
1053
- deliverClientToolResult(toolCallId: string, ok: boolean, result?: string, error?: string): Promise<{
1092
+ deliverClientToolResult(toolCallId: string, ok: boolean, result?: string, error?: string, deliveredByClientId?: string, deliveredGeneration?: number): Promise<{
1054
1093
  side: "a" | "b";
1055
1094
  } | null>;
1056
1095
  /**
@@ -1855,6 +1894,27 @@ declare class DurableAgentBuilder<Env extends AgentBuilderEnv = AgentBuilderEnv>
1855
1894
  env_type_patch?: Record<string, unknown> | null;
1856
1895
  env_delete?: string[] | null;
1857
1896
  }): Promise<void>;
1897
+ private assertValidUserValueKey;
1898
+ private assertValidUserValueUserId;
1899
+ /** Read one JSON value from a user's account-wide key-value store. */
1900
+ getUserValue(userId: string, key: string): Promise<unknown | null>;
1901
+ /** Write one JSON value to a user's account-wide store; null/undefined deletes. */
1902
+ setUserValue(userId: string, key: string, value: unknown): Promise<void>;
1903
+ /** List a user's account-wide values, optionally filtered by key prefix. */
1904
+ listUserValues(userId: string, options?: {
1905
+ prefix?: string | null;
1906
+ limit?: number;
1907
+ offset?: number;
1908
+ }): Promise<{
1909
+ entries: Array<{
1910
+ key: string;
1911
+ value: unknown;
1912
+ updated_at: number;
1913
+ }>;
1914
+ total: number;
1915
+ limit: number;
1916
+ offset: number;
1917
+ }>;
1858
1918
  getMissingRequiredScopedSubagentEnv(params: {
1859
1919
  parent_thread_id: string;
1860
1920
  agent_name: string;