@runtypelabs/sdk 4.19.2 → 4.21.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/index.cjs CHANGED
@@ -89,6 +89,7 @@ __export(index_exports, {
89
89
  ToolEnsureConflictError: () => ToolEnsureConflictError,
90
90
  ToolsEndpoint: () => ToolsEndpoint,
91
91
  ToolsNamespace: () => ToolsNamespace,
92
+ UNIFIED_EVENTS_QUERY: () => UNIFIED_EVENTS_QUERY,
92
93
  UsersEndpoint: () => UsersEndpoint,
93
94
  applyGeneratedRuntimeToolProposalToDispatchRequest: () => applyGeneratedRuntimeToolProposalToDispatchRequest,
94
95
  attachRuntimeToolsToDispatchRequest: () => attachRuntimeToolsToDispatchRequest,
@@ -105,8 +106,10 @@ __export(index_exports, {
105
106
  computeSkillContentHash: () => computeSkillContentHash,
106
107
  computeSurfaceContentHash: () => computeSurfaceContentHash,
107
108
  computeToolContentHash: () => computeToolContentHash,
109
+ createAgentEventTranslator: () => createAgentEventTranslator,
108
110
  createClient: () => createClient,
109
111
  createExternalTool: () => createExternalTool,
112
+ createFlowEventTranslator: () => createFlowEventTranslator,
110
113
  defaultWorkflow: () => defaultWorkflow,
111
114
  defaultWorkflowConfig: () => defaultWorkflowConfig,
112
115
  defineAgent: () => defineAgent,
@@ -129,6 +132,7 @@ __export(index_exports, {
129
132
  isDiscoveryToolName: () => isDiscoveryToolName,
130
133
  isMarathonArtifactPath: () => isMarathonArtifactPath,
131
134
  isPreservationSensitiveTask: () => isPreservationSensitiveTask,
135
+ isUnifiedEventType: () => isUnifiedEventType,
132
136
  isWorkflowHookRef: () => isWorkflowHookRef,
133
137
  listWorkflowHooks: () => listWorkflowHooks,
134
138
  normalizeAgentDefinition: () => normalizeAgentDefinition,
@@ -143,6 +147,7 @@ __export(index_exports, {
143
147
  parseOffloadedOutputId: () => parseOffloadedOutputId,
144
148
  parseSSEChunk: () => parseSSEChunk,
145
149
  processStream: () => processStream,
150
+ pullFpo: () => pullFpo,
146
151
  registerWorkflowHook: () => registerWorkflowHook,
147
152
  resolveStallStopAfter: () => resolveStallStopAfter,
148
153
  resolveWorkflowHook: () => resolveWorkflowHook,
@@ -150,10 +155,511 @@ __export(index_exports, {
150
155
  shouldInjectEmptySessionNudge: () => shouldInjectEmptySessionNudge,
151
156
  shouldRequestModelEscalation: () => shouldRequestModelEscalation,
152
157
  streamEvents: () => streamEvents,
153
- unregisterWorkflowHook: () => unregisterWorkflowHook
158
+ unregisterWorkflowHook: () => unregisterWorkflowHook,
159
+ withUnifiedEvents: () => withUnifiedEvents
154
160
  });
155
161
  module.exports = __toCommonJS(index_exports);
156
162
 
163
+ // src/unified-stream-adapter.ts
164
+ var UNIFIED_EVENTS_QUERY = "events=unified";
165
+ function withUnifiedEvents(path) {
166
+ return path.includes("?") ? `${path}&${UNIFIED_EVENTS_QUERY}` : `${path}?${UNIFIED_EVENTS_QUERY}`;
167
+ }
168
+ var UNIFIED_ONLY_EVENT_TYPES = /* @__PURE__ */ new Set([
169
+ "execution_start",
170
+ "execution_complete",
171
+ "execution_error",
172
+ "turn_start",
173
+ "turn_complete",
174
+ "text_start",
175
+ "text_delta",
176
+ "text_complete",
177
+ "reasoning_start",
178
+ "reasoning_delta",
179
+ "reasoning_complete",
180
+ "media_start",
181
+ "media_delta",
182
+ "media_complete",
183
+ "tool_output_delta",
184
+ "await"
185
+ ]);
186
+ function isUnifiedEventType(type) {
187
+ return typeof type === "string" && UNIFIED_ONLY_EVENT_TYPES.has(type);
188
+ }
189
+ function str(value) {
190
+ return typeof value === "string" ? value : void 0;
191
+ }
192
+ function num(value) {
193
+ return typeof value === "number" ? value : void 0;
194
+ }
195
+ function compact(event) {
196
+ const out = { type: event.type };
197
+ for (const [k, v] of Object.entries(event)) {
198
+ if (k !== "type" && v !== void 0) out[k] = v;
199
+ }
200
+ return out;
201
+ }
202
+ var LEGACY_FLOW_PASSTHROUGH = /* @__PURE__ */ new Set([
203
+ "flow_start",
204
+ "flow_complete",
205
+ "flow_error",
206
+ "flow_await",
207
+ "step_await",
208
+ "step_delta"
209
+ ]);
210
+ function createFlowEventTranslator() {
211
+ let currentStepId;
212
+ let currentStepName;
213
+ return (raw) => {
214
+ if (!raw || typeof raw !== "object") return [];
215
+ const data = raw;
216
+ const type = str(data.type);
217
+ if (!type) return [];
218
+ const executionId = str(data.executionId);
219
+ const seq = num(data.seq);
220
+ if (LEGACY_FLOW_PASSTHROUGH.has(type)) return [data];
221
+ switch (type) {
222
+ case "execution_start":
223
+ if (data.kind !== "flow") return [];
224
+ return [
225
+ compact({
226
+ type: "flow_start",
227
+ executionId,
228
+ seq,
229
+ flowId: data.flowId,
230
+ flowName: data.flowName,
231
+ totalSteps: data.totalSteps,
232
+ startedAt: data.startedAt,
233
+ source: data.source
234
+ })
235
+ ];
236
+ case "step_start": {
237
+ const id = str(data.id) ?? str(data.stepId);
238
+ const name = str(data.name) ?? str(data.stepName);
239
+ currentStepId = id;
240
+ currentStepName = name;
241
+ return [
242
+ compact({
243
+ type: "step_start",
244
+ executionId,
245
+ seq,
246
+ stepId: id,
247
+ name,
248
+ stepName: name,
249
+ stepType: data.stepType,
250
+ index: data.index,
251
+ totalSteps: data.totalSteps,
252
+ startedAt: data.startedAt,
253
+ outputVariable: data.outputVariable
254
+ })
255
+ ];
256
+ }
257
+ case "text_delta":
258
+ return [
259
+ compact({
260
+ type: "step_delta",
261
+ executionId,
262
+ seq,
263
+ delta: str(data.delta) ?? "",
264
+ text: str(data.delta) ?? "",
265
+ stepId: currentStepId,
266
+ name: currentStepName,
267
+ stepName: currentStepName
268
+ })
269
+ ];
270
+ case "step_complete": {
271
+ const id = str(data.id) ?? str(data.stepId);
272
+ const name = str(data.name) ?? str(data.stepName);
273
+ const out = compact({
274
+ type: "step_complete",
275
+ executionId,
276
+ seq,
277
+ stepId: id,
278
+ name,
279
+ stepName: name,
280
+ stepType: data.stepType,
281
+ result: data.result,
282
+ success: data.success,
283
+ executionTime: num(data.durationMs) ?? num(data.executionTime),
284
+ stopReason: data.stopReason,
285
+ completedAt: data.completedAt,
286
+ unresolvedVariables: data.unresolvedVariables,
287
+ error: data.error
288
+ });
289
+ currentStepId = void 0;
290
+ currentStepName = void 0;
291
+ return [out];
292
+ }
293
+ case "execution_complete":
294
+ if (data.kind !== "flow") return [];
295
+ return [
296
+ compact({
297
+ type: "flow_complete",
298
+ executionId,
299
+ seq,
300
+ success: data.success,
301
+ totalSteps: data.totalSteps,
302
+ successfulSteps: data.successfulSteps,
303
+ failedSteps: data.failedSteps,
304
+ executionTime: data.durationMs,
305
+ finalOutput: data.finalOutput,
306
+ completedAt: data.completedAt
307
+ })
308
+ ];
309
+ case "execution_error":
310
+ return [
311
+ compact({
312
+ type: "flow_error",
313
+ executionId,
314
+ seq,
315
+ error: data.error,
316
+ code: data.code,
317
+ upgradeUrl: data.upgradeUrl
318
+ })
319
+ ];
320
+ case "await":
321
+ return [
322
+ compact({
323
+ type: "flow_await",
324
+ executionId,
325
+ seq,
326
+ toolId: data.toolId ?? data.toolCallId,
327
+ toolName: data.toolName,
328
+ parameters: data.parameters,
329
+ awaitedAt: data.awaitedAt,
330
+ origin: data.origin,
331
+ pageOrigin: data.pageOrigin
332
+ })
333
+ ];
334
+ // Channels/markers/tool-family/approval/skip/source/custom/ping the flow
335
+ // consumer never read → no legacy event. (A non-terminal `error` is only
336
+ // produced on agent streams; dropping it here avoids a false flow_error.)
337
+ default:
338
+ return [];
339
+ }
340
+ };
341
+ }
342
+ function createAgentEventTranslator() {
343
+ let agentId;
344
+ let iteration;
345
+ let turnId;
346
+ let reasoningScope;
347
+ let media = null;
348
+ return (raw) => {
349
+ if (!raw || typeof raw !== "object") return [];
350
+ const data = raw;
351
+ const type = str(data.type);
352
+ if (!type) return [];
353
+ const executionId = str(data.executionId);
354
+ const seq = num(data.seq);
355
+ const iter = num(data.iteration) ?? iteration;
356
+ if (type.startsWith("agent_")) return [data];
357
+ switch (type) {
358
+ case "execution_start":
359
+ if (data.kind !== "agent") return [];
360
+ agentId = str(data.agentId);
361
+ return [
362
+ compact({
363
+ type: "agent_start",
364
+ executionId,
365
+ seq,
366
+ agentId: data.agentId,
367
+ agentName: data.agentName,
368
+ maxTurns: data.maxTurns,
369
+ startedAt: data.startedAt,
370
+ config: data.config
371
+ })
372
+ ];
373
+ case "turn_start":
374
+ turnId = str(data.id);
375
+ iteration = num(data.iteration) ?? iteration;
376
+ return [
377
+ compact({
378
+ type: "agent_turn_start",
379
+ executionId,
380
+ seq,
381
+ iteration: data.iteration ?? iteration,
382
+ turnId: data.id,
383
+ turnIndex: data.turnIndex,
384
+ role: data.role
385
+ })
386
+ ];
387
+ case "text_delta":
388
+ return [
389
+ compact({
390
+ type: "agent_turn_delta",
391
+ executionId,
392
+ seq,
393
+ iteration: iter,
394
+ turnId,
395
+ delta: str(data.delta) ?? "",
396
+ contentType: "text"
397
+ })
398
+ ];
399
+ case "reasoning_start":
400
+ reasoningScope = data.scope === "loop" ? "loop" : "turn";
401
+ return [];
402
+ case "reasoning_delta":
403
+ return [
404
+ compact({
405
+ type: "agent_turn_delta",
406
+ executionId,
407
+ seq,
408
+ iteration: iter,
409
+ turnId,
410
+ delta: str(data.delta) ?? "",
411
+ contentType: "thinking"
412
+ })
413
+ ];
414
+ case "reasoning_complete": {
415
+ const scope = data.scope === "loop" ? "loop" : reasoningScope;
416
+ reasoningScope = void 0;
417
+ if (scope === "loop") {
418
+ return [
419
+ compact({
420
+ type: "agent_reflection",
421
+ executionId,
422
+ seq,
423
+ iteration: iter,
424
+ reflection: data.text
425
+ })
426
+ ];
427
+ }
428
+ return [];
429
+ }
430
+ case "turn_complete":
431
+ return [
432
+ compact({
433
+ type: "agent_turn_complete",
434
+ executionId,
435
+ seq,
436
+ iteration: data.iteration ?? iter,
437
+ turnId: data.id,
438
+ role: data.role,
439
+ completedAt: data.completedAt,
440
+ content: data.content,
441
+ tokens: data.tokens,
442
+ cost: data.cost,
443
+ stopReason: data.stopReason
444
+ })
445
+ ];
446
+ case "tool_start":
447
+ return [
448
+ compact({
449
+ type: "agent_tool_start",
450
+ executionId,
451
+ seq,
452
+ iteration: iter,
453
+ toolCallId: data.toolCallId,
454
+ toolName: data.toolName,
455
+ toolType: data.toolType,
456
+ parameters: data.parameters,
457
+ origin: data.origin,
458
+ pageOrigin: data.pageOrigin
459
+ })
460
+ ];
461
+ case "tool_output_delta":
462
+ return [
463
+ compact({
464
+ type: "agent_tool_delta",
465
+ executionId,
466
+ seq,
467
+ iteration: iter,
468
+ toolCallId: data.toolCallId,
469
+ delta: str(data.delta) ?? ""
470
+ })
471
+ ];
472
+ case "tool_input_delta":
473
+ return [
474
+ compact({
475
+ type: "agent_tool_input_delta",
476
+ executionId,
477
+ seq,
478
+ iteration: iter,
479
+ toolCallId: data.toolCallId,
480
+ delta: str(data.delta) ?? ""
481
+ })
482
+ ];
483
+ case "tool_input_complete":
484
+ return [
485
+ compact({
486
+ type: "agent_tool_input_complete",
487
+ executionId,
488
+ seq,
489
+ iteration: iter,
490
+ toolCallId: data.toolCallId,
491
+ toolName: data.toolName,
492
+ parameters: data.parameters ?? {},
493
+ hiddenParameterNames: data.hiddenParameterNames
494
+ })
495
+ ];
496
+ case "tool_complete":
497
+ return [
498
+ compact({
499
+ type: "agent_tool_complete",
500
+ executionId,
501
+ seq,
502
+ iteration: num(data.iteration) ?? iter,
503
+ toolCallId: data.toolCallId,
504
+ toolName: data.toolName,
505
+ success: data.success,
506
+ result: data.result,
507
+ executionTime: data.executionTime
508
+ })
509
+ ];
510
+ case "media_start":
511
+ media = {
512
+ mediaType: str(data.mediaType),
513
+ role: str(data.role),
514
+ toolCallId: str(data.toolCallId),
515
+ chunks: []
516
+ };
517
+ return [];
518
+ case "media_delta": {
519
+ const delta = str(data.delta);
520
+ if (media && delta) media.chunks.push(delta);
521
+ return [];
522
+ }
523
+ case "media_complete": {
524
+ const acc = media;
525
+ media = null;
526
+ const mediaType = str(data.mediaType) ?? acc?.mediaType;
527
+ const toolCallId = str(data.toolCallId) ?? acc?.toolCallId;
528
+ const url = str(data.url);
529
+ const inlineData = str(data.data) ?? (acc && acc.chunks.length ? acc.chunks.join("") : void 0);
530
+ let item;
531
+ if (url) {
532
+ const kind = mediaType && mediaType.startsWith("image/") ? "image-url" : "file-url";
533
+ item = compact({ type: kind, url, mediaType });
534
+ } else {
535
+ item = compact({ type: "media", data: inlineData ?? "", mediaType });
536
+ }
537
+ return [
538
+ compact({
539
+ type: "agent_media",
540
+ executionId,
541
+ seq,
542
+ iteration: iter,
543
+ toolCallId,
544
+ media: [item]
545
+ })
546
+ ];
547
+ }
548
+ case "approval_start":
549
+ return [
550
+ compact({
551
+ type: "agent_approval_start",
552
+ executionId,
553
+ seq,
554
+ iteration: iter,
555
+ approvalId: data.approvalId,
556
+ toolCallId: data.toolCallId,
557
+ toolName: data.toolName,
558
+ toolType: data.toolType,
559
+ description: data.description,
560
+ reason: data.reason,
561
+ parameters: data.parameters,
562
+ timeout: data.timeout,
563
+ startedAt: data.startedAt
564
+ })
565
+ ];
566
+ case "approval_complete":
567
+ return [
568
+ compact({
569
+ type: "agent_approval_complete",
570
+ executionId,
571
+ seq,
572
+ approvalId: data.approvalId,
573
+ decision: data.decision,
574
+ completedAt: data.completedAt,
575
+ resolvedBy: data.resolvedBy
576
+ })
577
+ ];
578
+ case "await":
579
+ return [
580
+ compact({
581
+ type: "agent_await",
582
+ executionId,
583
+ seq,
584
+ toolId: data.toolId ?? data.toolCallId,
585
+ toolName: data.toolName,
586
+ parameters: data.parameters,
587
+ awaitedAt: data.awaitedAt,
588
+ origin: data.origin,
589
+ pageOrigin: data.pageOrigin
590
+ })
591
+ ];
592
+ case "execution_complete":
593
+ if (data.kind !== "agent") return [];
594
+ return [
595
+ compact({
596
+ type: "agent_complete",
597
+ executionId,
598
+ seq,
599
+ agentId: data.agentId ?? agentId,
600
+ success: data.success,
601
+ iterations: data.iterations,
602
+ stopReason: data.stopReason,
603
+ completedAt: data.completedAt,
604
+ totalCost: data.totalCost,
605
+ totalTokens: data.totalTokens,
606
+ finalOutput: data.finalOutput,
607
+ duration: data.durationMs
608
+ })
609
+ ];
610
+ case "execution_error":
611
+ return [
612
+ compact({
613
+ type: "agent_complete",
614
+ executionId,
615
+ seq,
616
+ agentId,
617
+ success: false,
618
+ stopReason: "error",
619
+ error: errorMessage(data.error),
620
+ completedAt: data.completedAt
621
+ })
622
+ ];
623
+ case "error":
624
+ return [
625
+ compact({
626
+ type: "agent_error",
627
+ executionId,
628
+ seq,
629
+ iteration: iter,
630
+ error: errorObject(data.error),
631
+ recoverable: true
632
+ })
633
+ ];
634
+ case "ping":
635
+ return [compact({ type: "agent_ping", executionId, seq, timestamp: data.timestamp })];
636
+ // turn/text/reasoning open+close markers, step_*, artifact_*, source,
637
+ // custom (fallback beat / routing), and the skill-fold result envelope
638
+ // the SDK never consumed → no legacy event.
639
+ default:
640
+ return [];
641
+ }
642
+ };
643
+ }
644
+ function errorMessage(error) {
645
+ if (typeof error === "string") return error;
646
+ if (error && typeof error === "object" && "message" in error) {
647
+ const message = error.message;
648
+ if (typeof message === "string") return message;
649
+ }
650
+ return error === void 0 ? "Agent execution failed" : JSON.stringify(error);
651
+ }
652
+ function errorObject(error) {
653
+ if (typeof error === "string") return { code: "error", message: error };
654
+ if (error && typeof error === "object") {
655
+ const e = error;
656
+ const obj = { code: e.code ?? "error", message: e.message ?? "" };
657
+ if (e.details !== void 0) obj.details = e.details;
658
+ return obj;
659
+ }
660
+ return { code: "error", message: String(error) };
661
+ }
662
+
157
663
  // src/stream-utils.ts
158
664
  function parseSSEChunk(chunk, buffer) {
159
665
  buffer += chunk;
@@ -191,7 +697,7 @@ function parseFinalBuffer(buffer) {
191
697
  }
192
698
  return null;
193
699
  }
194
- async function processStream(response, callbacks = {}) {
700
+ async function processStream(response, callbacks = {}, options = {}) {
195
701
  if (!response.ok) {
196
702
  const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
197
703
  callbacks.onError?.(error);
@@ -215,6 +721,20 @@ async function processStream(response, callbacks = {}) {
215
721
  executionTime: 0,
216
722
  success: true
217
723
  };
724
+ let translate = options.unified === true ? createFlowEventTranslator() : null;
725
+ const autoDetect = options.unified === void 0;
726
+ const dispatch = (parsed) => {
727
+ if (autoDetect && !translate && isUnifiedEventType(parsed?.type)) {
728
+ translate = createFlowEventTranslator();
729
+ }
730
+ if (translate) {
731
+ for (const ev of translate(parsed)) {
732
+ handleEvent(ev, callbacks, results, flowSummary);
733
+ }
734
+ } else {
735
+ handleEvent(parsed, callbacks, results, flowSummary);
736
+ }
737
+ };
218
738
  const contentType = response.headers.get("content-type");
219
739
  if (contentType?.includes("application/json")) {
220
740
  try {
@@ -271,8 +791,7 @@ async function processStream(response, callbacks = {}) {
271
791
  buffer = remainingBuffer;
272
792
  for (const eventStr of events) {
273
793
  try {
274
- const event = JSON.parse(eventStr);
275
- handleEvent(event, callbacks, results, flowSummary);
794
+ dispatch(JSON.parse(eventStr));
276
795
  } catch {
277
796
  console.warn("Failed to parse SSE event:", eventStr);
278
797
  }
@@ -281,8 +800,7 @@ async function processStream(response, callbacks = {}) {
281
800
  const finalEvent = parseFinalBuffer(buffer);
282
801
  if (finalEvent) {
283
802
  try {
284
- const event = JSON.parse(finalEvent);
285
- handleEvent(event, callbacks, results, flowSummary);
803
+ dispatch(JSON.parse(finalEvent));
286
804
  } catch {
287
805
  }
288
806
  }
@@ -352,10 +870,17 @@ function handleEvent(event, callbacks, results, summary) {
352
870
  break;
353
871
  }
354
872
  }
355
- async function* streamEvents(response) {
873
+ async function* streamEvents(response, options = {}) {
356
874
  if (!response.ok) {
357
875
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
358
876
  }
877
+ let translate = options.unified === true ? createFlowEventTranslator() : null;
878
+ const autoDetect = options.unified === void 0;
879
+ const maybeDetect = (parsed) => {
880
+ if (autoDetect && !translate && isUnifiedEventType(parsed?.type)) {
881
+ translate = createFlowEventTranslator();
882
+ }
883
+ };
359
884
  const contentType = response.headers.get("content-type");
360
885
  if (contentType?.includes("application/json")) {
361
886
  try {
@@ -385,19 +910,35 @@ async function* streamEvents(response) {
385
910
  const { events, remainingBuffer } = parseSSEChunk(chunk, buffer);
386
911
  buffer = remainingBuffer;
387
912
  for (const eventStr of events) {
913
+ let parsed;
388
914
  try {
389
- const event = JSON.parse(eventStr);
390
- yield event;
915
+ parsed = JSON.parse(eventStr);
391
916
  } catch {
917
+ continue;
918
+ }
919
+ maybeDetect(parsed);
920
+ if (translate) {
921
+ for (const ev of translate(parsed)) yield ev;
922
+ } else {
923
+ yield parsed;
392
924
  }
393
925
  }
394
926
  }
395
927
  const finalEvent = parseFinalBuffer(buffer);
396
928
  if (finalEvent) {
929
+ let parsed;
397
930
  try {
398
- const event = JSON.parse(finalEvent);
399
- yield event;
931
+ parsed = JSON.parse(finalEvent);
400
932
  } catch {
933
+ parsed = void 0;
934
+ }
935
+ if (parsed !== void 0) {
936
+ maybeDetect(parsed);
937
+ if (translate) {
938
+ for (const ev of translate(parsed)) yield ev;
939
+ } else {
940
+ yield parsed;
941
+ }
401
942
  }
402
943
  }
403
944
  } finally {
@@ -407,10 +948,16 @@ async function* streamEvents(response) {
407
948
 
408
949
  // src/flow-result.ts
409
950
  var FlowResult = class {
410
- constructor(response, summary) {
951
+ /**
952
+ * @param options.unified - The response is a unified-vocabulary SSE stream
953
+ * (`/dispatch` since the unified-SSE cutover). Set by dispatch call sites;
954
+ * left unset by still-legacy producers (`/prompts/{id}/run`, eval stream).
955
+ */
956
+ constructor(response, summary, options = {}) {
411
957
  this.consumed = false;
412
958
  this.cachedSummary = null;
413
959
  this.response = response;
960
+ this.streamOptions = options;
414
961
  if (summary) {
415
962
  this.cachedSummary = summary;
416
963
  this.consumed = true;
@@ -463,7 +1010,7 @@ var FlowResult = class {
463
1010
  }
464
1011
  this.ensureNotConsumed();
465
1012
  this.consumed = true;
466
- this.cachedSummary = await processStream(this.response, callbacks);
1013
+ this.cachedSummary = await processStream(this.response, callbacks, this.streamOptions);
467
1014
  return this.cachedSummary;
468
1015
  }
469
1016
  /**
@@ -1309,9 +1856,9 @@ var FlowBuilder = class {
1309
1856
  }
1310
1857
  const response = await client.dispatch(config);
1311
1858
  if (callbacks) {
1312
- return processStream(response, callbacks);
1859
+ return processStream(response, callbacks, { unified: true });
1313
1860
  }
1314
- return new FlowResult(response);
1861
+ return new FlowResult(response, void 0, { unified: true });
1315
1862
  }
1316
1863
  /**
1317
1864
  * Set a run condition (when predicate) on the last added step.
@@ -1443,9 +1990,9 @@ var ClientFlowBuilder = class extends FlowBuilder {
1443
1990
  }
1444
1991
  const response = await dispatchClient.dispatch(config);
1445
1992
  if (runCallbacks) {
1446
- return processStream(response, runCallbacks);
1993
+ return processStream(response, runCallbacks, { unified: true });
1447
1994
  }
1448
- return new FlowResult(response);
1995
+ return new FlowResult(response, void 0, { unified: true });
1449
1996
  }
1450
1997
  };
1451
1998
  function isStreamCallbacks(obj) {
@@ -2463,7 +3010,7 @@ var RuntypeFlowBuilder = class {
2463
3010
  config.options = { ...config.options, streamResponse: true };
2464
3011
  const client = this.getClient();
2465
3012
  const response = await this.dispatchWithPersistedFlow(client, config);
2466
- const result = new FlowResult(response);
3013
+ const result = new FlowResult(response, void 0, { unified: true });
2467
3014
  if (callbacks) {
2468
3015
  await result.stream(callbacks);
2469
3016
  }
@@ -2492,7 +3039,7 @@ var RuntypeFlowBuilder = class {
2492
3039
  config.options = { ...config.options, streamResponse: true };
2493
3040
  const client = this.getClient();
2494
3041
  const response = await this.dispatchWithPersistedFlow(client, config);
2495
- const result = new FlowResult(response);
3042
+ const result = new FlowResult(response, void 0, { unified: true });
2496
3043
  await result.getSummary();
2497
3044
  return result;
2498
3045
  }
@@ -2527,7 +3074,7 @@ var RuntypeFlowBuilder = class {
2527
3074
  onError: (error) => callbacks?.onError?.(error)
2528
3075
  };
2529
3076
  try {
2530
- for await (const event of streamEvents(response)) {
3077
+ for await (const event of streamEvents(response, { unified: true })) {
2531
3078
  collectLocalToolAwait(pausedTools, event);
2532
3079
  switch (event.type) {
2533
3080
  case "flow_start":
@@ -2635,7 +3182,7 @@ var RuntypeFlowBuilder = class {
2635
3182
  streamResponse: isStreaming
2636
3183
  };
2637
3184
  if (isStreaming) {
2638
- currentResponse = await client.requestStream("/dispatch/resume", {
3185
+ currentResponse = await client.requestStream(withUnifiedEvents("/dispatch/resume"), {
2639
3186
  method: "POST",
2640
3187
  body: JSON.stringify(resumeData)
2641
3188
  });
@@ -4426,13 +4973,17 @@ function defineFpo(fpo) {
4426
4973
  return fpo;
4427
4974
  }
4428
4975
  async function ensureFpo(client, fpo, options = {}) {
4429
- const { dryRun, onConflict } = options;
4976
+ const { dryRun, onConflict, prune } = options;
4430
4977
  return client.post("/products/ensure-fpo", {
4431
4978
  fpo,
4432
4979
  ...dryRun ? { dryRun: true } : {},
4433
- ...onConflict ? { onConflict } : {}
4980
+ ...onConflict ? { onConflict } : {},
4981
+ ...prune ? { prune: true } : {}
4434
4982
  });
4435
4983
  }
4984
+ async function pullFpo(client, name) {
4985
+ return client.get("/products/pull-fpo", { name });
4986
+ }
4436
4987
 
4437
4988
  // src/products-namespace.ts
4438
4989
  var ProductsNamespace = class {
@@ -4490,6 +5041,24 @@ var ProductsNamespace = class {
4490
5041
  async ensureFpo(fpo, options = {}) {
4491
5042
  return ensureFpo(this.getClient(), fpo, options);
4492
5043
  }
5044
+ /**
5045
+ * Reconstruct a self-contained Full Product Object from the live product graph
5046
+ * (resolved by name) — the absorb-drift direction of `ensureFpo`. Feeding the
5047
+ * returned `fpo` back into `ensureFpo` converges to `unchanged`.
5048
+ *
5049
+ * records/schedules/secrets are not reconstructed and `tools` is emitted empty
5050
+ * (tool refs are portable `tool:<name>`); inspect `result.warnings` for
5051
+ * per-pull caveats.
5052
+ *
5053
+ * @example
5054
+ * ```typescript
5055
+ * const { fpo } = await Runtype.products.pullFpo('Support Copilot')
5056
+ * await Runtype.products.ensureFpo(fpo, { dryRun: true }) // → result: 'unchanged'
5057
+ * ```
5058
+ */
5059
+ async pullFpo(name) {
5060
+ return pullFpo(this.getClient(), name);
5061
+ }
4493
5062
  };
4494
5063
 
4495
5064
  // src/surfaces-ensure.ts
@@ -4857,7 +5426,7 @@ var RuntypeClient = class {
4857
5426
  * Dispatch flow execution (streaming)
4858
5427
  */
4859
5428
  async dispatch(config) {
4860
- return this.requestStream("/dispatch", {
5429
+ return this.requestStream(withUnifiedEvents("/dispatch"), {
4861
5430
  method: "POST",
4862
5431
  body: JSON.stringify(transformRequest(config))
4863
5432
  });
@@ -5228,7 +5797,7 @@ var Runtype = class {
5228
5797
 
5229
5798
  // src/version.ts
5230
5799
  var FALLBACK_VERSION = "0.0.0";
5231
- var SDK_VERSION = "4.19.2".length > 0 ? "4.19.2" : FALLBACK_VERSION;
5800
+ var SDK_VERSION = "4.21.0".length > 0 ? "4.21.0" : FALLBACK_VERSION;
5232
5801
  var RUNTYPE_CLIENT_KIND = "sdk";
5233
5802
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
5234
5803
 
@@ -7722,7 +8291,7 @@ var DispatchEndpoint = class {
7722
8291
  * Dispatch with streaming response
7723
8292
  */
7724
8293
  async executeStream(data) {
7725
- return this.client.requestStream("/dispatch", {
8294
+ return this.client.requestStream(withUnifiedEvents("/dispatch"), {
7726
8295
  method: "POST",
7727
8296
  body: JSON.stringify(data)
7728
8297
  });
@@ -7738,7 +8307,7 @@ var DispatchEndpoint = class {
7738
8307
  */
7739
8308
  async resume(data) {
7740
8309
  if (data.streamResponse) {
7741
- return this.client.requestStream("/dispatch/resume", {
8310
+ return this.client.requestStream(withUnifiedEvents("/dispatch/resume"), {
7742
8311
  method: "POST",
7743
8312
  body: JSON.stringify(data)
7744
8313
  });
@@ -8253,6 +8822,19 @@ async function processAgentStream(body, callbacks) {
8253
8822
  const reader = body.getReader();
8254
8823
  const decoder = new TextDecoder();
8255
8824
  let buffer = "";
8825
+ let translate = null;
8826
+ const dispatch = (event) => {
8827
+ if (!translate && isUnifiedEventType(event.data?.type ?? event.eventType)) {
8828
+ translate = createAgentEventTranslator();
8829
+ }
8830
+ if (translate) {
8831
+ for (const legacy of translate(event.data)) {
8832
+ dispatchAgentEvent({ eventType: legacy.type, data: legacy }, callbacks);
8833
+ }
8834
+ } else {
8835
+ dispatchAgentEvent(event, callbacks);
8836
+ }
8837
+ };
8256
8838
  try {
8257
8839
  while (true) {
8258
8840
  const { done, value } = await reader.read();
@@ -8260,7 +8842,7 @@ async function processAgentStream(body, callbacks) {
8260
8842
  if (buffer.trim()) {
8261
8843
  const { events: events2 } = parseSSEChunkWithEventType(buffer + "\n\n", "");
8262
8844
  for (const event of events2) {
8263
- dispatchAgentEvent(event, callbacks);
8845
+ dispatch(event);
8264
8846
  }
8265
8847
  }
8266
8848
  break;
@@ -8269,7 +8851,7 @@ async function processAgentStream(body, callbacks) {
8269
8851
  const { events, remainingBuffer } = parseSSEChunkWithEventType(chunk, buffer);
8270
8852
  buffer = remainingBuffer;
8271
8853
  for (const event of events) {
8272
- dispatchAgentEvent(event, callbacks);
8854
+ dispatch(event);
8273
8855
  }
8274
8856
  }
8275
8857
  } finally {
@@ -8457,7 +9039,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
8457
9039
  * ```
8458
9040
  */
8459
9041
  async executeStream(id, data, init) {
8460
- return this.client.requestStream(`/agents/${id}/execute`, {
9042
+ return this.client.requestStream(withUnifiedEvents(`/agents/${id}/execute`), {
8461
9043
  method: "POST",
8462
9044
  body: JSON.stringify({
8463
9045
  ...data,
@@ -8809,16 +9391,19 @@ var _AgentsEndpoint = class _AgentsEndpoint {
8809
9391
  }
8810
9392
  let resumeResponse;
8811
9393
  try {
8812
- resumeResponse = await this.client.requestStream(`/agents/${id}/resume`, {
8813
- method: "POST",
8814
- body: JSON.stringify({
8815
- executionId,
8816
- toolOutputs: { [toolName]: toolResult },
8817
- streamResponse: true,
8818
- debugMode: data.debugMode
8819
- }),
8820
- ...abortSignal ? { signal: abortSignal } : {}
8821
- });
9394
+ resumeResponse = await this.client.requestStream(
9395
+ withUnifiedEvents(`/agents/${id}/resume`),
9396
+ {
9397
+ method: "POST",
9398
+ body: JSON.stringify({
9399
+ executionId,
9400
+ toolOutputs: { [toolName]: toolResult },
9401
+ streamResponse: true,
9402
+ debugMode: data.debugMode
9403
+ }),
9404
+ ...abortSignal ? { signal: abortSignal } : {}
9405
+ }
9406
+ );
8822
9407
  } catch (error) {
8823
9408
  if (abortSignal?.aborted) return finishAborted(executionId);
8824
9409
  throw error;
@@ -10283,9 +10868,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
10283
10868
  }
10284
10869
  /** Returns true if a server-side session error message indicates a transient
10285
10870
  * network failure that is safe to retry. */
10286
- static isRetryableSessionError(errorMessage) {
10287
- if (!errorMessage) return false;
10288
- const lower = errorMessage.toLowerCase();
10871
+ static isRetryableSessionError(errorMessage2) {
10872
+ if (!errorMessage2) return false;
10873
+ const lower = errorMessage2.toLowerCase();
10289
10874
  return _AgentsEndpoint.RETRYABLE_SESSION_ERROR_PATTERNS.some(
10290
10875
  (pattern) => lower.includes(pattern)
10291
10876
  );
@@ -11737,7 +12322,7 @@ var RuntypeClient2 = class {
11737
12322
  success: true
11738
12323
  };
11739
12324
  try {
11740
- for await (const event of streamEvents(response)) {
12325
+ for await (const event of streamEvents(response, { unified: true })) {
11741
12326
  collectLocalToolAwait(pausedTools, event);
11742
12327
  switch (event.type) {
11743
12328
  case "flow_start":
@@ -12921,6 +13506,7 @@ var STEP_TYPE_TO_METHOD = {
12921
13506
  ToolEnsureConflictError,
12922
13507
  ToolsEndpoint,
12923
13508
  ToolsNamespace,
13509
+ UNIFIED_EVENTS_QUERY,
12924
13510
  UsersEndpoint,
12925
13511
  applyGeneratedRuntimeToolProposalToDispatchRequest,
12926
13512
  attachRuntimeToolsToDispatchRequest,
@@ -12937,8 +13523,10 @@ var STEP_TYPE_TO_METHOD = {
12937
13523
  computeSkillContentHash,
12938
13524
  computeSurfaceContentHash,
12939
13525
  computeToolContentHash,
13526
+ createAgentEventTranslator,
12940
13527
  createClient,
12941
13528
  createExternalTool,
13529
+ createFlowEventTranslator,
12942
13530
  defaultWorkflow,
12943
13531
  defaultWorkflowConfig,
12944
13532
  defineAgent,
@@ -12961,6 +13549,7 @@ var STEP_TYPE_TO_METHOD = {
12961
13549
  isDiscoveryToolName,
12962
13550
  isMarathonArtifactPath,
12963
13551
  isPreservationSensitiveTask,
13552
+ isUnifiedEventType,
12964
13553
  isWorkflowHookRef,
12965
13554
  listWorkflowHooks,
12966
13555
  normalizeAgentDefinition,
@@ -12975,6 +13564,7 @@ var STEP_TYPE_TO_METHOD = {
12975
13564
  parseOffloadedOutputId,
12976
13565
  parseSSEChunk,
12977
13566
  processStream,
13567
+ pullFpo,
12978
13568
  registerWorkflowHook,
12979
13569
  resolveStallStopAfter,
12980
13570
  resolveWorkflowHook,
@@ -12982,5 +13572,6 @@ var STEP_TYPE_TO_METHOD = {
12982
13572
  shouldInjectEmptySessionNudge,
12983
13573
  shouldRequestModelEscalation,
12984
13574
  streamEvents,
12985
- unregisterWorkflowHook
13575
+ unregisterWorkflowHook,
13576
+ withUnifiedEvents
12986
13577
  });