@@ -3,8 +3,12 @@ import { usePartySocket } from "partysocket/react";
33import { useCallback , useRef , use , useMemo , useEffect } from "react" ;
44import type { Agent , MCPServersState , RPCRequest , RPCResponse } from "./" ;
55import type { StreamOptions } from "./client" ;
6- import type { Method , RPCMethod } from "./serializable" ;
76import { MessageType } from "./ai-types" ;
7+ import type {
8+ AllSerializableValues ,
9+ SerializableReturnValue ,
10+ SerializableValue
11+ } from "./serializable" ;
812
913/**
1014 * Convert a camelCase string to a kebab-case string
@@ -130,17 +134,68 @@ export type UseAgentOptions<State = unknown> = Omit<
130134 onMcpUpdate ?: ( mcpServers : MCPServersState ) => void ;
131135} ;
132136
137+ // biome-ignore lint: suppressions/parse
138+ type Method = ( ...args : any [ ] ) => any ;
139+
140+ type NonStreamingRPCMethod < T extends Method > =
141+ AllSerializableValues < Parameters < T > > extends true
142+ ? ReturnType < T > extends SerializableReturnValue
143+ ? T
144+ : never
145+ : never ;
146+
147+ interface StreamingResponse <
148+ OnChunkT extends SerializableValue | unknown = unknown ,
149+ OnDoneT extends SerializableValue | unknown = unknown
150+ > {
151+ send ( chunk : OnChunkT ) : void ;
152+ end ( finalChunk ?: OnDoneT ) : void ;
153+ }
154+
155+ type StreamingRPCMethod < T extends Method > = T extends (
156+ arg : infer A ,
157+ ...rest : infer R
158+ ) => void | Promise < void >
159+ ? A extends StreamingResponse < SerializableValue , SerializableValue >
160+ ? AllSerializableValues < R > extends true
161+ ? T
162+ : never
163+ : never
164+ : never ;
165+
166+ type RPCMethod < T extends Method > =
167+ T extends NonStreamingRPCMethod < T >
168+ ? NonStreamingRPCMethod < T >
169+ : T extends StreamingRPCMethod < T >
170+ ? StreamingRPCMethod < T >
171+ : never ;
172+
173+ type RPCMethods < T > = {
174+ [ K in keyof T as T [ K ] extends Method ? K : never ] : T [ K ] extends Method
175+ ? RPCMethod < T [ K ] >
176+ : never ;
177+ } ;
178+
133179type AllOptional < T > = T extends [ infer A , ...infer R ]
134180 ? undefined extends A
135181 ? AllOptional < R >
136182 : false
137183 : true ; // no params means optional by default
138184
139- type RPCMethods < T > = {
140- [ K in keyof T as T [ K ] extends RPCMethod < T [ K ] > ? K : never ] : RPCMethod < T [ K ] > ;
141- } ;
185+ type StreamOptionsFrom < StreamingResponseT > =
186+ StreamingResponseT extends StreamingResponse <
187+ infer T extends SerializableValue ,
188+ infer U extends SerializableValue
189+ >
190+ ? StreamOptions < T , U >
191+ : never ;
192+
193+ type RestParameters < T extends Method > =
194+ Parameters < StreamingRPCMethod < T > > extends [ unknown , ...infer Rest ]
195+ ? Rest
196+ : never ;
142197
143- type OptionalParametersMethod < T extends RPCMethod > =
198+ type OptionalParametersMethod < T extends Method > =
144199 AllOptional < Parameters < T > > extends true ? T : never ;
145200
146201// all methods of the Agent, excluding the ones that are declared in the base Agent class
@@ -160,6 +215,14 @@ type RequiredAgentMethods<T> = Omit<
160215 keyof OptionalAgentMethods < T >
161216> ;
162217
218+ type StreamingAgentMethods < T > = {
219+ [ K in keyof AgentMethods < T > as AgentMethods < T > [ K ] extends StreamingRPCMethod <
220+ AgentMethods < T > [ K ]
221+ >
222+ ? K
223+ : never ] : StreamingRPCMethod < AgentMethods < T > [ K ] > ;
224+ } ;
225+
163226type AgentPromiseReturnType < T , K extends keyof AgentMethods < T > > =
164227 // biome-ignore lint: suppressions/parse
165228 ReturnType < AgentMethods < T > [ K ] > extends Promise < any >
@@ -182,7 +245,18 @@ type RequiredArgsAgentMethodCall<AgentT> = <
182245 streamOptions ?: StreamOptions
183246) => AgentPromiseReturnType < AgentT , K > ;
184247
185- type AgentMethodCall < AgentT > = OptionalArgsAgentMethodCall < AgentT > &
248+ type StreamingAgentMethodCall < AgentT > = <
249+ K extends keyof StreamingAgentMethods < AgentT >
250+ > (
251+ method : K ,
252+ args : RestParameters < StreamingAgentMethods < AgentT > [ K ] > ,
253+ streamOptions : StreamOptionsFrom <
254+ Parameters < StreamingAgentMethods < AgentT > [ K ] > [ 0 ]
255+ >
256+ ) => void ;
257+
258+ type AgentMethodCall < AgentT > = StreamingAgentMethodCall < AgentT > &
259+ OptionalArgsAgentMethodCall < AgentT > &
186260 RequiredArgsAgentMethodCall < AgentT > ;
187261
188262type UntypedAgentMethodCall = < T = unknown > (
@@ -192,9 +266,16 @@ type UntypedAgentMethodCall = <T = unknown>(
192266) => Promise < T > ;
193267
194268type AgentStub < T > = {
195- [ K in keyof AgentMethods < T > ] : (
196- ...args : Parameters < AgentMethods < T > [ K ] >
197- ) => AgentPromiseReturnType < AgentMethods < T > , K > ;
269+ [ K in keyof AgentMethods < T > ] : AgentMethods < T > [ K ] extends StreamingRPCMethod <
270+ AgentMethods < T > [ K ]
271+ >
272+ ? (
273+ options : StreamOptionsFrom < Parameters < AgentMethods < T > [ K ] > [ 0 ] > ,
274+ ...args : RestParameters < AgentMethods < T > [ K ] >
275+ ) => void
276+ : (
277+ ...args : Parameters < AgentMethods < T > [ K ] >
278+ ) => AgentPromiseReturnType < AgentMethods < T > , K > ;
198279} ;
199280
200281// we neet to use Method instead of RPCMethod here for retro-compatibility
@@ -232,7 +313,7 @@ export function useAgent<State>(
232313 agent : string ;
233314 name : string ;
234315 setState : ( state : State ) => void ;
235- call : UntypedAgentMethodCall | AgentMethodCall < unknown > ;
316+ call : UntypedAgentMethodCall ;
236317 stub : UntypedAgentStub ;
237318} {
238319 const agentNamespace = camelCaseToKebabCase ( options . agent ) ;
0 commit comments