@@ -10,24 +10,34 @@ const messageStream = streams.input<{ text: string }>({ id: "messages" });
1010/**
1111 * Coordinator task that exercises all input stream patterns end-to-end.
1212 *
13- * 1. .once() — trigger a child, send it data via SSE tail, poll until complete
14- * 2. .on() — trigger a child, send it multiple messages, poll until complete
15- * 3. .wait() — trigger a child, send it data (completes its waitpoint), poll until complete
16- * 4. .wait() race — send data before child calls .wait(), verify race handling
13+ * 1a. .once().unwrap() — trigger a child, send data, verify unwrap returns TData
14+ * 1b. .once() result — trigger a child, send data, verify result object { ok, output }
15+ * 2. .on() — trigger a child, send it multiple messages, poll until complete
16+ * 3. .wait() — trigger a child, send it data (completes its waitpoint), poll until complete
17+ * 4. .wait() race — send data before child calls .wait(), verify race handling
1718 */
1819export const inputStreamCoordinator = task ( {
1920 id : "input-stream-coordinator" ,
2021 run : async ( ) => {
2122 const results : Record < string , unknown > = { } ;
2223
23- // --- Test 1 : .once() - ---
24- logger . info ( "Test 1 : .once()" ) ;
25- const onceHandle = await inputStreamOnce . trigger ( { } ) ;
24+ // --- Test 1a : .once() with .unwrap() ---
25+ logger . info ( "Test 1a : .once().unwrap ()" ) ;
26+ const onceUnwrapHandle = await inputStreamOnceUnwrap . trigger ( { } ) ;
2627 await wait . for ( { seconds : 5 } ) ;
27- await approvalStream . send ( onceHandle . id , { approved : true , reviewer : "coordinator-once" } ) ;
28- const onceRun = await runs . poll ( onceHandle , { pollIntervalMs : 1000 } ) ;
29- results . once = onceRun . output ;
30- logger . info ( "Test 1 passed" , { output : onceRun . output } ) ;
28+ await approvalStream . send ( onceUnwrapHandle . id , { approved : true , reviewer : "coordinator-unwrap" } ) ;
29+ const onceUnwrapRun = await runs . poll ( onceUnwrapHandle , { pollIntervalMs : 1000 } ) ;
30+ results . onceUnwrap = onceUnwrapRun . output ;
31+ logger . info ( "Test 1a passed" , { output : onceUnwrapRun . output } ) ;
32+
33+ // --- Test 1b: .once() with result object ---
34+ logger . info ( "Test 1b: .once() result object" ) ;
35+ const onceResultHandle = await inputStreamOnceResult . trigger ( { } ) ;
36+ await wait . for ( { seconds : 5 } ) ;
37+ await approvalStream . send ( onceResultHandle . id , { approved : true , reviewer : "coordinator-result" } ) ;
38+ const onceResultRun = await runs . poll ( onceResultHandle , { pollIntervalMs : 1000 } ) ;
39+ results . onceResult = onceResultRun . output ;
40+ logger . info ( "Test 1b passed" , { output : onceResultRun . output } ) ;
3141
3242 // --- Test 2: .on() with multiple messages ---
3343 logger . info ( "Test 2: .on()" ) ;
@@ -64,18 +74,40 @@ export const inputStreamCoordinator = task({
6474} ) ;
6575
6676/**
67- * Uses .once() to wait for a single input stream message .
77+ * Uses .once().unwrap() — returns TData directly, throws InputStreamTimeoutError on timeout .
6878 */
69- export const inputStreamOnce = task ( {
70- id : "input-stream-once" ,
79+ export const inputStreamOnceUnwrap = task ( {
80+ id : "input-stream-once-unwrap " ,
7181 run : async ( _payload : Record < string , never > ) => {
72- logger . info ( "Waiting for approval via .once()" ) ;
73- const approval = await approvalStream . once ( ) ;
82+ logger . info ( "Waiting for approval via .once().unwrap()" ) ;
83+
84+ const approval = await approvalStream . once ( { timeoutMs : 30_000 } ) . unwrap ( ) ;
85+
7486 logger . info ( "Received approval" , { approval } ) ;
7587 return { approval } ;
7688 } ,
7789} ) ;
7890
91+ /**
92+ * Uses .once() with result object — check result.ok to handle timeout without try/catch.
93+ */
94+ export const inputStreamOnceResult = task ( {
95+ id : "input-stream-once-result" ,
96+ run : async ( _payload : Record < string , never > ) => {
97+ logger . info ( "Waiting for approval via .once() result object" ) ;
98+
99+ const result = await approvalStream . once ( { timeoutMs : 30_000 } ) ;
100+
101+ if ( ! result . ok ) {
102+ logger . error ( "Timed out waiting for approval" , { error : result . error . message } ) ;
103+ return { approval : null , timedOut : true } ;
104+ }
105+
106+ logger . info ( "Received approval" , { approval : result . output } ) ;
107+ return { approval : result . output } ;
108+ } ,
109+ } ) ;
110+
79111/**
80112 * Uses .on() to subscribe and collect multiple messages.
81113 */
0 commit comments