@standardagents/builder 0.28.1 → 0.29.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/dist/runtime.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { e as ThreadEnv, A as Agent, r as ThreadMetadata, t as ToolResult, M as Message, k as ClientToolRequest, l as ClientToolResponse, m as ClientStreamRequest, n as ClientStreamResponse, w as FileRecord, F as FlowState, y as FileStats, G as GrepResult, x as AttachmentRef, J as MessageContent, E as Env, q as ThreadInstance } from './index-BzXyIJPA.js';
2
- export { f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, B as Controller, a as ControllerContext, u as FlowResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, T as ToolCall, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-BzXyIJPA.js';
1
+ import { e as ThreadEnv, A as Agent, r as ThreadMetadata, t as ToolResult, M as Message, k as ClientToolRequest, l as ClientToolResponse, m as ClientStreamRequest, n as ClientStreamResponse, w as FileRecord, F as FlowState, y as FileStats, G as GrepResult, x as AttachmentRef, J as MessageContent, E as Env, q as ThreadInstance } from './index-Cp_Zcrhy.js';
2
+ export { f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, B as Controller, a as ControllerContext, u as FlowResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, T as ToolCall, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-Cp_Zcrhy.js';
3
3
  import { CodeExecutionOptions, CodeExecutionResult, SubagentRegistryEntry, InjectMessageInput, QueueMessageInput, SkillMetadata, SkillFileInput, ModelDefinition as ModelDefinition$1, ToolArgs, PromptTextPart, PromptEnvPart, VariableDefinition, SubpromptConfig as SubpromptConfig$1, PromptToolConfig as PromptToolConfig$1, SubagentToolConfig as SubagentToolConfig$1, ReasoningConfig, SideConfig as SideConfig$1, LLMProviderInterface, ContentPart, TextPart, ImagePart, FilePart, ThreadState, NamespaceContext, DefinitionLoader } from '@standardagents/spec';
4
4
  export { AgentType, DefinitionLoader, GlobalNamespaceContext, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, PromptInput, PromptTextPart, ProviderAssistantMessage, ProviderError, ProviderErrorCode, ProviderFactory, ProviderFactoryConfig, ProviderFinishReason, ProviderGeneratedImage, ProviderMessage, ProviderMessageContent, ModelCapabilities as ProviderModelCapabilities, ProviderReasoningDetail, ProviderRequest, ProviderResponse, ProviderStreamChunk, ProviderSystemMessage, ProviderTool, ProviderToolCallPart, ProviderToolMessage, ProviderToolResultContent, ProviderUsage, ProviderUserMessage, ReasoningConfig, StructuredPrompt, TextContent, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHook, defineModel, definePrompt, defineTool, isPacked, isVisibleInNamespace, mapReasoningLevel } from '@standardagents/spec';
5
5
  import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
@@ -1120,6 +1120,7 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
1120
1120
  id?: string;
1121
1121
  error?: string;
1122
1122
  noClient?: boolean;
1123
+ code?: 'unsupported' | 'unavailable' | 'refused' | 'timeout';
1123
1124
  }>;
1124
1125
  proxyStreamWrite(id: string, dataB64: string): Promise<void>;
1125
1126
  proxyStreamPull(id: string): Promise<{
package/dist/runtime.js CHANGED
@@ -47,6 +47,30 @@ function callClient(state, request) {
47
47
  return s.callClient(request);
48
48
  }
49
49
  function callClientStream(state, request) {
50
+ if (state.runtimeStreams) {
51
+ return state.runtimeStreams.open({
52
+ capability: request.tool,
53
+ metadata: request.meta,
54
+ timeoutMs: request.timeoutMs
55
+ }).then(
56
+ (opened) => opened.ok ? {
57
+ ok: true,
58
+ duplex: {
59
+ readable: opened.stream.readable,
60
+ writable: opened.stream.writable,
61
+ close: (reason) => opened.stream.close(reason),
62
+ done: opened.stream.closed
63
+ }
64
+ } : {
65
+ ok: false,
66
+ error: opened.error,
67
+ data: opened.code ? {
68
+ code: opened.code,
69
+ noClient: opened.code === "unavailable" ? true : void 0
70
+ } : void 0
71
+ }
72
+ );
73
+ }
50
74
  const s = asForwarding(state);
51
75
  if (typeof s.callClientStream !== "function") {
52
76
  return Promise.resolve({
@@ -56,6 +80,39 @@ function callClientStream(state, request) {
56
80
  }
57
81
  return s.callClientStream(request);
58
82
  }
83
+ function createRuntimeStreams(openClientStream) {
84
+ return {
85
+ async open(request) {
86
+ const opened = await openClientStream({
87
+ tool: request.capability,
88
+ meta: request.metadata,
89
+ timeoutMs: request.timeoutMs
90
+ });
91
+ if (!opened.ok) {
92
+ const failureData = opened.data;
93
+ return {
94
+ ok: false,
95
+ error: opened.error,
96
+ code: failureData?.code
97
+ };
98
+ }
99
+ let closed = false;
100
+ return {
101
+ ok: true,
102
+ stream: {
103
+ readable: opened.duplex.readable,
104
+ writable: opened.duplex.writable,
105
+ closed: opened.duplex.done,
106
+ close: (reason) => {
107
+ if (closed) return;
108
+ closed = true;
109
+ opened.duplex.close(reason);
110
+ }
111
+ }
112
+ };
113
+ }
114
+ };
115
+ }
59
116
  function encodeStreamChunk(bytes) {
60
117
  let binary = "";
61
118
  const step = 32768;
@@ -12930,6 +12987,14 @@ var init_ThreadStateImpl = __esm({
12930
12987
  }
12931
12988
  return this.getMetadataArguments();
12932
12989
  }
12990
+ /**
12991
+ * Optional spec byte streams backed by the execution owner's existing
12992
+ * bridge. Streams are live resources: they proxy through ancestors when a
12993
+ * subagent opens one, but they never park or outlive a bridge disconnect.
12994
+ */
12995
+ get runtimeStreams() {
12996
+ return createRuntimeStreams((request) => this.callClientStream(request));
12997
+ }
12933
12998
  getMetadataArguments() {
12934
12999
  const value = this._metadata.properties?.[SUBAGENT_INITIAL_ARGUMENTS_THREAD_PROPERTY];
12935
13000
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -13506,11 +13571,9 @@ var init_ThreadStateImpl = __esm({
13506
13571
  return local;
13507
13572
  }
13508
13573
  /**
13509
- * Open a bidirectional byte stream to the connected client (e.g. a raw TCP
13510
- * tunnel for Worker-side TLS termination). Streams require a LIVE bridge on
13511
- * this thread and never park — a stream is only meaningful while the client
13512
- * is attached. Subagents must not call this directly; they proxy whole
13513
- * requests up to the root thread instead (request-up / stream-down).
13574
+ * Legacy bridge implementation used by `runtimeStreams`. Streams require a
13575
+ * live execution owner and never park. A child thread proxies the complete
13576
+ * request to the nearest bridge-holding ancestor (request-up/stream-down).
13514
13577
  */
13515
13578
  async callClientStream(request) {
13516
13579
  const instance = this._threadInstance;
@@ -13536,7 +13599,11 @@ var init_ThreadStateImpl = __esm({
13536
13599
  return { ok: true, duplex: this.buildProxyDuplex(stub, opened.id) };
13537
13600
  }
13538
13601
  if (opened.error && !opened.noClient) {
13539
- return { ok: false, error: opened.error };
13602
+ return {
13603
+ ok: false,
13604
+ error: opened.error,
13605
+ data: opened.code ? { code: opened.code } : void 0
13606
+ };
13540
13607
  }
13541
13608
  }
13542
13609
  } catch {
@@ -13555,6 +13622,12 @@ var init_ThreadStateImpl = __esm({
13555
13622
  let settleDone;
13556
13623
  const done = new Promise((r) => settleDone = r);
13557
13624
  let closed = false;
13625
+ let settled = false;
13626
+ const settle = (result) => {
13627
+ if (settled) return;
13628
+ settled = true;
13629
+ settleDone(result);
13630
+ };
13558
13631
  const readable = new ReadableStream({
13559
13632
  async pull(controller) {
13560
13633
  while (!closed) {
@@ -13563,7 +13636,7 @@ var init_ThreadStateImpl = __esm({
13563
13636
  res = await stub.proxyStreamPull(id);
13564
13637
  } catch (error) {
13565
13638
  controller.error(error instanceof Error ? error : new Error(String(error)));
13566
- settleDone({ ok: false, error: "proxy stream pull failed" });
13639
+ settle({ ok: false, error: "proxy stream pull failed" });
13567
13640
  return;
13568
13641
  }
13569
13642
  for (const chunk of res.chunks) {
@@ -13571,7 +13644,7 @@ var init_ThreadStateImpl = __esm({
13571
13644
  }
13572
13645
  if (res.done) {
13573
13646
  controller.close();
13574
- settleDone(res.error ? { ok: false, error: res.error } : { ok: true });
13647
+ settle(res.error ? { ok: false, error: res.error } : { ok: true });
13575
13648
  return;
13576
13649
  }
13577
13650
  if (res.chunks.length > 0) return;
@@ -13582,6 +13655,7 @@ var init_ThreadStateImpl = __esm({
13582
13655
  closed = true;
13583
13656
  void stub.proxyStreamAbort(id).catch(() => {
13584
13657
  });
13658
+ settle({ ok: false, error: "proxy stream reader canceled" });
13585
13659
  }
13586
13660
  });
13587
13661
  const writable = new WritableStream({
@@ -13596,16 +13670,18 @@ var init_ThreadStateImpl = __esm({
13596
13670
  closed = true;
13597
13671
  void stub.proxyStreamAbort(id).catch(() => {
13598
13672
  });
13673
+ settle({ ok: false, error: "proxy stream writer aborted" });
13599
13674
  }
13600
13675
  });
13601
13676
  return {
13602
13677
  readable,
13603
13678
  writable,
13604
13679
  close: (error) => {
13680
+ if (closed) return;
13605
13681
  closed = true;
13606
13682
  void stub.proxyStreamAbort(id).catch(() => {
13607
13683
  });
13608
- settleDone(error ? { ok: false, error } : { ok: true });
13684
+ settle(error ? { ok: false, error } : { ok: true });
13609
13685
  },
13610
13686
  done
13611
13687
  };
@@ -20247,12 +20323,10 @@ ${resultContent}${attachmentSummary}`;
20247
20323
  }
20248
20324
  return { side };
20249
20325
  }
20250
- // ─── Client byte streams (Worker-side TLS tunnels) ─────────────────────────
20251
- // A stream is a bidirectional byte pipe over the bridge WebSocket: the
20252
- // client opens a raw TCP socket per the stream's `meta` and shuttles bytes
20253
- // both ways; the Worker terminates TLS over those bytes (node:tls over the
20254
- // duplex), so the client only ever relays ciphertext. Streams are bound to a
20255
- // live socket and never park.
20326
+ // ─── Runtime byte streams ──────────────────────────────────────────────────
20327
+ // The existing bridge frames carry opaque capability metadata and bytes
20328
+ // between the runtime and its execution owner. Streams are live resources:
20329
+ // they are bound to one bridge socket and never park.
20256
20330
  /** Default time to wait for the client to accept a stream open. */
20257
20331
  static CLIENT_STREAM_OPEN_TIMEOUT_MS = 3e4;
20258
20332
  /** Open a bidirectional byte stream to the connected owner client. */
@@ -20263,7 +20337,7 @@ ${resultContent}${attachmentSummary}`;
20263
20337
  return {
20264
20338
  ok: false,
20265
20339
  error: "The workspace is not available right now. Try again in a moment.",
20266
- data: { noClient: true }
20340
+ data: { noClient: true, code: "unavailable" }
20267
20341
  };
20268
20342
  }
20269
20343
  const id = crypto.randomUUID();
@@ -20296,7 +20370,8 @@ ${resultContent}${attachmentSummary}`;
20296
20370
  state.openTimer = setTimeout(() => {
20297
20371
  resolve({
20298
20372
  ok: false,
20299
- error: `The client did not accept the ${request.tool} stream within ${Math.round(timeoutMs / 1e3)}s.`
20373
+ error: `The client did not accept the ${request.tool} stream within ${Math.round(timeoutMs / 1e3)}s.`,
20374
+ code: "timeout"
20300
20375
  });
20301
20376
  }, timeoutMs);
20302
20377
  try {
@@ -20311,7 +20386,8 @@ ${resultContent}${attachmentSummary}`;
20311
20386
  } catch (error) {
20312
20387
  resolve({
20313
20388
  ok: false,
20314
- error: `Failed to reach the client: ${error instanceof Error ? error.message : String(error)}`
20389
+ error: `Failed to reach the client: ${error instanceof Error ? error.message : String(error)}`,
20390
+ code: "unavailable"
20315
20391
  });
20316
20392
  }
20317
20393
  });
@@ -20324,7 +20400,11 @@ ${resultContent}${attachmentSummary}`;
20324
20400
  this.clientStreams.delete(id);
20325
20401
  state.settled = true;
20326
20402
  settleDone({ ok: false, error: openResult.error });
20327
- return { ok: false, error: openResult.error ?? "Stream open failed." };
20403
+ return {
20404
+ ok: false,
20405
+ error: openResult.error ?? "Stream open failed.",
20406
+ data: openResult.code ? { code: openResult.code } : void 0
20407
+ };
20328
20408
  }
20329
20409
  const sendChunked = (bytes) => {
20330
20410
  for (let i = 0; i < bytes.length; i += CLIENT_STREAM_CHUNK_BYTES) {
@@ -20368,8 +20448,14 @@ ${resultContent}${attachmentSummary}`;
20368
20448
  async proxyStreamOpen(request) {
20369
20449
  const opened = await this.openClientStream(request);
20370
20450
  if (!opened.ok) {
20371
- const noClient = !!(opened.data && opened.data.noClient);
20372
- return { ok: false, error: opened.error, noClient };
20451
+ const failureData = opened.data;
20452
+ const noClient = failureData?.noClient === true;
20453
+ return {
20454
+ ok: false,
20455
+ error: opened.error,
20456
+ noClient,
20457
+ code: failureData?.code
20458
+ };
20373
20459
  }
20374
20460
  const id = crypto.randomUUID();
20375
20461
  const duplex = opened.duplex;
@@ -20440,12 +20526,12 @@ ${resultContent}${attachmentSummary}`;
20440
20526
  }
20441
20527
  }
20442
20528
  /** Settle and remove a client stream exactly once. */
20443
- settleClientStream(id, result) {
20529
+ settleClientStream(id, result, openCode) {
20444
20530
  const state = this.clientStreams.get(id);
20445
20531
  if (!state) return;
20446
20532
  this.clientStreams.delete(id);
20447
20533
  if (state.openTimer) clearTimeout(state.openTimer);
20448
- if (state.opened) state.opened({ ok: false, error: result.error ?? "Stream closed." });
20534
+ if (state.opened) state.opened({ ok: false, error: result.error ?? "Stream closed.", code: openCode });
20449
20535
  if (!state.settled) {
20450
20536
  state.settled = true;
20451
20537
  try {
@@ -20489,7 +20575,7 @@ ${resultContent}${attachmentSummary}`;
20489
20575
  }
20490
20576
  case "stream_error": {
20491
20577
  const error = typeof parsed.error === "string" ? parsed.error : "Client stream error.";
20492
- this.settleClientStream(id, { ok: false, error });
20578
+ this.settleClientStream(id, { ok: false, error }, "refused");
20493
20579
  return;
20494
20580
  }
20495
20581
  case "stream_data": {
@@ -20516,7 +20602,7 @@ ${resultContent}${attachmentSummary}`;
20516
20602
  failClientStreamsForSocket(ws) {
20517
20603
  for (const [id, state] of Array.from(this.clientStreams.entries())) {
20518
20604
  if (state.socket === ws) {
20519
- this.settleClientStream(id, { ok: false, error: "The client connection was lost." });
20605
+ this.settleClientStream(id, { ok: false, error: "The client connection was lost." }, "unavailable");
20520
20606
  }
20521
20607
  }
20522
20608
  }