@flink-app/flink 1.0.0 → 2.0.0-alpha.48

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/cli/build.ts +8 -1
  3. package/cli/run.ts +8 -1
  4. package/dist/cli/build.js +8 -1
  5. package/dist/cli/run.js +8 -1
  6. package/dist/src/FlinkApp.d.ts +33 -0
  7. package/dist/src/FlinkApp.js +247 -27
  8. package/dist/src/FlinkContext.d.ts +21 -0
  9. package/dist/src/FlinkHttpHandler.d.ts +90 -1
  10. package/dist/src/TypeScriptCompiler.d.ts +42 -0
  11. package/dist/src/TypeScriptCompiler.js +346 -4
  12. package/dist/src/TypeScriptUtils.js +4 -0
  13. package/dist/src/ai/AgentRunner.d.ts +39 -0
  14. package/dist/src/ai/AgentRunner.js +625 -0
  15. package/dist/src/ai/FlinkAgent.d.ts +446 -0
  16. package/dist/src/ai/FlinkAgent.js +633 -0
  17. package/dist/src/ai/FlinkTool.d.ts +37 -0
  18. package/dist/src/ai/FlinkTool.js +2 -0
  19. package/dist/src/ai/LLMAdapter.d.ts +119 -0
  20. package/dist/src/ai/LLMAdapter.js +2 -0
  21. package/dist/src/ai/SubAgentExecutor.d.ts +36 -0
  22. package/dist/src/ai/SubAgentExecutor.js +220 -0
  23. package/dist/src/ai/ToolExecutor.d.ts +35 -0
  24. package/dist/src/ai/ToolExecutor.js +237 -0
  25. package/dist/src/ai/index.d.ts +5 -0
  26. package/dist/src/ai/index.js +21 -0
  27. package/dist/src/handlers/StreamWriterFactory.d.ts +20 -0
  28. package/dist/src/handlers/StreamWriterFactory.js +83 -0
  29. package/dist/src/index.d.ts +4 -0
  30. package/dist/src/index.js +4 -0
  31. package/dist/src/utils.d.ts +30 -0
  32. package/dist/src/utils.js +52 -0
  33. package/package.json +14 -2
  34. package/readme.md +425 -0
  35. package/spec/AgentDuplicateDetection.spec.ts +112 -0
  36. package/spec/AgentRunner.spec.ts +527 -0
  37. package/spec/ConversationHooks.spec.ts +290 -0
  38. package/spec/FlinkAgent.spec.ts +310 -0
  39. package/spec/FlinkApp.onError.spec.ts +1 -2
  40. package/spec/StreamingIntegration.spec.ts +138 -0
  41. package/spec/SubAgentSupport.spec.ts +941 -0
  42. package/spec/ToolExecutor.spec.ts +360 -0
  43. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar.js +57 -0
  44. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar2.js +59 -0
  45. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema.js +53 -0
  46. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema2.js +53 -0
  47. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema3.js +53 -0
  48. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema.js +55 -0
  49. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema2.js +55 -0
  50. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile.js +58 -0
  51. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile2.js +58 -0
  52. package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler.js +53 -0
  53. package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler2.js +55 -0
  54. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchCar.js +58 -0
  55. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOnboardingSession.js +76 -0
  56. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOrderWithComplexTypes.js +58 -0
  57. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchProductWithIntersection.js +59 -0
  58. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchUserWithUnion.js +59 -0
  59. package/spec/mock-project/dist/spec/mock-project/src/handlers/PostCar.js +55 -0
  60. package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogin.js +56 -0
  61. package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogout.js +55 -0
  62. package/spec/mock-project/dist/spec/mock-project/src/handlers/PutCar.js +55 -0
  63. package/spec/mock-project/dist/spec/mock-project/src/index.js +83 -0
  64. package/spec/mock-project/dist/spec/mock-project/src/repos/CarRepo.js +26 -0
  65. package/spec/mock-project/dist/spec/mock-project/src/schemas/Car.js +2 -0
  66. package/spec/mock-project/dist/spec/mock-project/src/schemas/DefaultExportSchema.js +2 -0
  67. package/spec/mock-project/dist/spec/mock-project/src/schemas/FileWithTwoSchemas.js +2 -0
  68. package/spec/mock-project/dist/src/FlinkApp.js +1012 -0
  69. package/spec/mock-project/dist/src/FlinkContext.js +2 -0
  70. package/spec/mock-project/dist/src/FlinkErrors.js +143 -0
  71. package/spec/mock-project/dist/src/FlinkHttpHandler.js +47 -0
  72. package/spec/mock-project/dist/src/FlinkJob.js +2 -0
  73. package/spec/mock-project/dist/src/FlinkLog.js +26 -0
  74. package/spec/mock-project/dist/src/FlinkPlugin.js +2 -0
  75. package/spec/mock-project/dist/src/FlinkRepo.js +224 -0
  76. package/spec/mock-project/dist/src/FlinkResponse.js +2 -0
  77. package/spec/mock-project/dist/src/ai/AgentExecutor.js +279 -0
  78. package/spec/mock-project/dist/src/ai/AgentRunner.js +625 -0
  79. package/spec/mock-project/dist/src/ai/FlinkAgent.js +633 -0
  80. package/spec/mock-project/dist/src/ai/FlinkTool.js +2 -0
  81. package/spec/mock-project/dist/src/ai/LLMAdapter.js +2 -0
  82. package/spec/mock-project/dist/src/ai/SubAgentExecutor.js +220 -0
  83. package/spec/mock-project/dist/src/ai/ToolExecutor.js +237 -0
  84. package/spec/mock-project/dist/src/auth/FlinkAuthPlugin.js +2 -0
  85. package/spec/mock-project/dist/src/auth/FlinkAuthUser.js +2 -0
  86. package/spec/mock-project/dist/src/handlers/StreamWriterFactory.js +83 -0
  87. package/spec/mock-project/dist/src/index.js +17 -69
  88. package/spec/mock-project/dist/src/mock-data-generator.js +9 -0
  89. package/spec/mock-project/dist/src/utils.js +290 -0
  90. package/spec/mock-project/tsconfig.json +6 -1
  91. package/spec/testHelpers.ts +49 -0
  92. package/spec/utils.caseConversion.spec.ts +80 -0
  93. package/spec/utils.spec.ts +13 -13
  94. package/src/FlinkApp.ts +251 -7
  95. package/src/FlinkContext.ts +22 -0
  96. package/src/FlinkHttpHandler.ts +100 -2
  97. package/src/TypeScriptCompiler.ts +398 -7
  98. package/src/TypeScriptUtils.ts +5 -0
  99. package/src/ai/AgentRunner.ts +549 -0
  100. package/src/ai/FlinkAgent.ts +770 -0
  101. package/src/ai/FlinkTool.ts +40 -0
  102. package/src/ai/LLMAdapter.ts +96 -0
  103. package/src/ai/SubAgentExecutor.ts +199 -0
  104. package/src/ai/ToolExecutor.ts +193 -0
  105. package/src/ai/index.ts +5 -0
  106. package/src/handlers/StreamWriterFactory.ts +84 -0
  107. package/src/index.ts +4 -0
  108. package/src/utils.ts +52 -0
  109. package/tsconfig.json +6 -1
@@ -0,0 +1,446 @@
1
+ import { FlinkContext } from "../FlinkContext";
2
+ import { LLMMessage } from "./LLMAdapter";
3
+ import { FlinkToolFile } from "./FlinkTool";
4
+ import { ToolExecutor } from "./ToolExecutor";
5
+ export interface FlinkAgentProps {
6
+ id?: string;
7
+ description: string;
8
+ /**
9
+ * Instructions that define the agent's behavior and personality.
10
+ * Converted to a system message and prepended to the conversation.
11
+ * Follows Vercel AI SDK pattern.
12
+ *
13
+ * @example "You are a helpful customer support agent for Acme Corp."
14
+ */
15
+ instructions: string;
16
+ tools: Array<string | FlinkToolFile>;
17
+ agents?: Array<string | (new () => FlinkAgent<any>)>;
18
+ model?: {
19
+ /**
20
+ * ID of the LLM adapter to use (must be registered in FlinkOptions.ai.llmAdapters)
21
+ * Examples: "anthropic", "openai", "anthropic-eu", "gpt4", etc.
22
+ * Defaults to "default" if not specified
23
+ */
24
+ adapterId?: string;
25
+ maxTokens?: number;
26
+ temperature?: number;
27
+ };
28
+ limits?: {
29
+ maxSteps?: number;
30
+ timeoutMs?: number;
31
+ maxSubAgentDepth?: number;
32
+ };
33
+ permissions?: string | string[] | ((user?: any) => boolean);
34
+ /**
35
+ * How this agent handles conversations when called as a sub-agent
36
+ * - "inherit": Use parent's conversationId (default) - saves to parent's conversation
37
+ * - "independent": Create own nested conversation for detailed tracking
38
+ * - "none": Don't track conversations
39
+ */
40
+ conversationStrategy?: "inherit" | "independent" | "none";
41
+ /**
42
+ * Enable verbose debug logging for this agent
43
+ * When true, logs detailed information about:
44
+ * - Full LLM requests (messages, tools, parameters)
45
+ * - Full LLM responses (text, tool calls)
46
+ * - Tool execution details (input, output, errors)
47
+ * - Conversation state changes
48
+ *
49
+ * Useful for debugging tool calling issues and understanding agent behavior
50
+ */
51
+ debug?: boolean;
52
+ beforeRun?: (input: AgentExecuteInput, context: AgentExecuteContext) => void | Promise<void>;
53
+ onStep?: (context: AgentStepContext) => void | Promise<void>;
54
+ afterRun?: (result: AgentExecuteResult, context: AgentFinishContext) => void | Promise<void>;
55
+ transformSubAgentInput?: (subAgentId: string, input: any, context: AgentExecuteContext) => any | Promise<any>;
56
+ onSubAgentCall?: (subAgentId: string, input: any, context: AgentExecuteContext) => void | Promise<void>;
57
+ onSubAgentComplete?: (subAgentId: string, result: AgentExecuteResult, context: AgentExecuteContext) => void | Promise<void>;
58
+ }
59
+ export type FlinkAgentFile = {
60
+ Agent?: FlinkAgentProps;
61
+ default?: new () => FlinkAgent<any>;
62
+ __file?: string;
63
+ };
64
+ /**
65
+ * Base class for Flink agents (similar to FlinkRepo pattern)
66
+ *
67
+ * Agents extend this class and define their configuration as properties.
68
+ * Auto-registered by scanning src/agents/ directory.
69
+ *
70
+ * Tool references are validated at startup to ensure all referenced tools exist.
71
+ *
72
+ * Agents define their own domain-specific entry points that call `this.execute()`.
73
+ * This provides better type safety and developer experience than a generic `run()` method.
74
+ *
75
+ * ## Lifecycle Hooks
76
+ *
77
+ * Agents support lifecycle hooks for advanced orchestration:
78
+ * - `beforeRun`: Load conversation history, prepare context
79
+ * - `onStep`: Save state after each LLM turn
80
+ * - `afterRun`: Persist final conversation state
81
+ * - `transformSubAgentInput`: Compact/brief context before delegating to sub-agents
82
+ * - `onSubAgentCall`: Log/track delegations
83
+ * - `onSubAgentComplete`: Process sub-agent results
84
+ *
85
+ * Example:
86
+ * ```typescript
87
+ * export default class CarAgent extends FlinkAgent<AppCtx> {
88
+ * id = "car-agent"; // Optional: defaults to kebab-case class name "car-agent"
89
+ * description = "Expert in car models";
90
+ * instructions = "You are a car expert...";
91
+ * tools = ["get-cars-tool"]; // Validated at startup
92
+ * agents = [UserAgent, "external-agent"]; // Can use class references or strings
93
+ *
94
+ * // Domain-specific entry points with proper types
95
+ * async searchByBrand(brand: string) {
96
+ * const response = this.execute({
97
+ * message: `Find all ${brand} cars`
98
+ * });
99
+ * return await response.result;
100
+ * }
101
+ *
102
+ * async compareModels(model1: string, model2: string) {
103
+ * const response = this.execute({
104
+ * message: `Compare ${model1} and ${model2}`
105
+ * });
106
+ * return await response.result;
107
+ * }
108
+ *
109
+ * // Hook: Compact context when delegating to sub-agents
110
+ * protected async transformSubAgentInput(subAgentId, input, context) {
111
+ * const summary = await this.summarizeContext(context.conversationId);
112
+ * return { ...input, query: `Context: ${summary}\n\n${input.query}` };
113
+ * }
114
+ * }
115
+ * ```
116
+ */
117
+ export declare abstract class FlinkAgent<Ctx extends FlinkContext> {
118
+ ctx: Ctx;
119
+ private runner?;
120
+ private _boundUser?;
121
+ private _boundUserPermissions?;
122
+ private _llmAdapters?;
123
+ private _tools?;
124
+ abstract description: string;
125
+ abstract instructions: string;
126
+ abstract tools: Array<string | FlinkToolFile>;
127
+ id?: string;
128
+ agents?: Array<string | (new () => FlinkAgent<any>)>;
129
+ model?: {
130
+ adapterId?: string;
131
+ maxTokens?: number;
132
+ temperature?: number;
133
+ };
134
+ limits?: {
135
+ maxSteps?: number;
136
+ timeoutMs?: number;
137
+ maxSubAgentDepth?: number;
138
+ };
139
+ permissions?: string | string[] | ((user?: any) => boolean);
140
+ conversationStrategy?: "inherit" | "independent" | "none";
141
+ debug?: boolean;
142
+ /**
143
+ * Internal initialization called by FlinkApp
144
+ * @internal
145
+ */
146
+ __init(llmAdapters: Map<string, any>, tools: {
147
+ [x: string]: ToolExecutor<Ctx>;
148
+ }): void;
149
+ /**
150
+ * Bind a user to this agent for permission checks
151
+ *
152
+ * This creates a new agent instance with the user bound, allowing clean API:
153
+ * ```typescript
154
+ * const result = await ctx.agents.carAgent
155
+ * .withUser(req.user)
156
+ * .searchByBrand("Volvo");
157
+ * ```
158
+ *
159
+ * The bound user is used for:
160
+ * - Agent-level permission checks
161
+ * - Tool filtering (only allowed tools shown to LLM)
162
+ * - Tool-level permission checks
163
+ */
164
+ withUser(user: any): this;
165
+ /**
166
+ * Bind resolved permissions to this agent for permission checks
167
+ *
168
+ * This creates a new agent instance with permissions bound, allowing clean API:
169
+ * ```typescript
170
+ * const result = await ctx.agents.carAgent
171
+ * .withUser(req.user)
172
+ * .withPermissions(req.userPermissions) // Resolved permissions from auth plugin
173
+ * .searchByBrand("Volvo");
174
+ * ```
175
+ *
176
+ * The bound permissions are used for:
177
+ * - Tool filtering (only allowed tools shown to LLM)
178
+ * - Tool-level permission checks
179
+ *
180
+ * Permissions are typically populated by auth plugins during authentication
181
+ * based on roles, dynamic roles, or custom permission resolution.
182
+ */
183
+ withPermissions(userPermissions?: string[]): this;
184
+ /**
185
+ * Override the LLM adapter for this agent
186
+ *
187
+ * This creates a new agent instance with a different LLM adapter, allowing runtime selection:
188
+ * ```typescript
189
+ * const result = await ctx.agents.carAgent
190
+ * .withUser(req.user)
191
+ * .withLlm("fast") // Use fast LLM instead of default
192
+ * .searchByBrand("Volvo");
193
+ * ```
194
+ *
195
+ * The LLM adapter ID must be registered in FlinkApp's ai.llms configuration.
196
+ *
197
+ * @param adapterId - The ID of the LLM adapter to use (e.g., "default", "fake", "fast", "anthropic")
198
+ * @returns A new agent instance with the specified LLM adapter
199
+ */
200
+ withLlm(adapterId: string): this;
201
+ /**
202
+ * Public execution method for external callers (handlers, sub-agents, etc.)
203
+ *
204
+ * Use this when calling an agent from outside the agent class.
205
+ * For internal use within agent subclasses, use `execute()` instead.
206
+ */
207
+ run(input: AgentExecuteInput): AgentResponse;
208
+ /**
209
+ * Internal execution method - supports both awaiting and streaming
210
+ *
211
+ * Uses lazy generator pattern (similar to Vercel AI SDK) to allow
212
+ * multiple consumption without re-execution.
213
+ *
214
+ * Agents call this method from their run() implementation to execute the AI logic.
215
+ *
216
+ * Examples:
217
+ * const response = this.execute({ message: "Hello" });
218
+ * const result = await response.result; // Await final result
219
+ * for await (const text of response.textStream) { ... } // Stream text
220
+ * for await (const chunk of response.fullStream) { ... } // Stream all events
221
+ */
222
+ protected execute(input: AgentExecuteInput): AgentResponse;
223
+ /**
224
+ * Called before agent execution starts
225
+ * Use this to load conversation history, prepare context, etc.
226
+ *
227
+ * @example
228
+ * protected async beforeRun(input: AgentExecuteInput, context: AgentExecuteContext) {
229
+ * if (input.conversationId) {
230
+ * const conv = await this.ctx.repos.conversationRepo.getById(input.conversationId);
231
+ * input.history = conv?.messages;
232
+ * }
233
+ * }
234
+ */
235
+ protected beforeRun?(input: AgentExecuteInput, context: AgentExecuteContext): void | Promise<void>;
236
+ /**
237
+ * Called after each step (LLM call + tool executions)
238
+ * Use this to save intermediate state, emit progress events, etc.
239
+ *
240
+ * @example
241
+ * protected async onStep(context: AgentStepContext) {
242
+ * if (context.conversationId) {
243
+ * await this.saveConversationState(context.conversationId, context.messages);
244
+ * }
245
+ * }
246
+ */
247
+ protected onStep?(context: AgentStepContext): void | Promise<void>;
248
+ /**
249
+ * Called when agent execution completes
250
+ * This is where you typically save the final conversation state
251
+ *
252
+ * @example
253
+ * protected async afterRun(result: AgentExecuteResult, context: AgentFinishContext) {
254
+ * if (context.conversationId && !context.isSubAgent) {
255
+ * await this.ctx.repos.conversationRepo.save({
256
+ * id: context.conversationId,
257
+ * messages: context.messages,
258
+ * result
259
+ * });
260
+ * }
261
+ * }
262
+ */
263
+ protected afterRun?(result: AgentExecuteResult, context: AgentFinishContext): void | Promise<void>;
264
+ /**
265
+ * Transform/compact input before sending to sub-agent
266
+ * Parent agent can summarize context, add briefings, or modify the query
267
+ *
268
+ * Return value becomes the new input sent to the sub-agent
269
+ *
270
+ * @example
271
+ * protected async transformSubAgentInput(subAgentId: string, input: any, context: AgentExecuteContext) {
272
+ * // Load parent conversation
273
+ * const messages = await this.loadConversation(context.conversationId);
274
+ *
275
+ * // Summarize relevant context
276
+ * const summary = this.compactContext(messages, subAgentId);
277
+ *
278
+ * // Add briefing to query
279
+ * return {
280
+ * ...input,
281
+ * query: `Context: ${summary}\n\nQuery: ${input.query}`
282
+ * };
283
+ * }
284
+ */
285
+ protected transformSubAgentInput?(subAgentId: string, input: any, context: AgentExecuteContext): any | Promise<any>;
286
+ /**
287
+ * Called when a sub-agent is about to be invoked (after transformSubAgentInput)
288
+ * Parent agent can log, or track the delegation
289
+ * Cannot modify input - use transformSubAgentInput for that
290
+ */
291
+ protected onSubAgentCall?(subAgentId: string, input: any, context: AgentExecuteContext): void | Promise<void>;
292
+ /**
293
+ * Called after sub-agent completes
294
+ * Parent agent can process the result, track metrics, etc.
295
+ */
296
+ protected onSubAgentComplete?(subAgentId: string, result: AgentExecuteResult, context: AgentExecuteContext): void | Promise<void>;
297
+ /**
298
+ * Consume stream as final result (for await pattern)
299
+ */
300
+ private consumeAsResult;
301
+ /**
302
+ * Consume stream as text-only stream (for simple streaming UX)
303
+ */
304
+ private consumeAsTextStream;
305
+ private getRunner;
306
+ /**
307
+ * Get agent id - uses explicit id property or falls back to kebab-case class name
308
+ *
309
+ * Examples:
310
+ * - CarAgent → car-agent
311
+ * - APIAgent → api-agent
312
+ * - HTMLParserAgent → html-parser-agent
313
+ */
314
+ private getAgentId;
315
+ private toAgentProps;
316
+ private resolveTools;
317
+ private checkPermissionsSync;
318
+ }
319
+ /**
320
+ * Execution context shared across agent lifecycle hooks
321
+ */
322
+ export interface AgentExecuteContext {
323
+ agentId: string;
324
+ conversationId?: string;
325
+ user?: any;
326
+ isSubAgent: boolean;
327
+ parentAgentId?: string;
328
+ subAgentDepth: number;
329
+ metadata?: Record<string, any>;
330
+ }
331
+ /**
332
+ * Context for onStep hook - includes current conversation state
333
+ */
334
+ export interface AgentStepContext extends AgentExecuteContext {
335
+ step: number;
336
+ maxSteps: number;
337
+ messages: LLMMessage[];
338
+ }
339
+ /**
340
+ * Context for afterRun hook - includes final conversation and result
341
+ */
342
+ export interface AgentFinishContext extends AgentExecuteContext {
343
+ messages: LLMMessage[];
344
+ result: AgentExecuteResult;
345
+ }
346
+ /**
347
+ * Message structure for agent conversations
348
+ * Supports both simple strings and structured message arrays
349
+ */
350
+ export type Message = {
351
+ role: "user";
352
+ content: string;
353
+ } | {
354
+ role: "assistant";
355
+ content: string;
356
+ toolCalls?: ToolCall[];
357
+ } | {
358
+ role: "tool";
359
+ toolCallId: string;
360
+ toolName: string;
361
+ result: string;
362
+ };
363
+ export interface ToolCall {
364
+ id: string;
365
+ name: string;
366
+ input: any;
367
+ }
368
+ export interface AgentExecuteInput {
369
+ message: string | Message[];
370
+ user?: any;
371
+ userPermissions?: string[];
372
+ conversationId?: string;
373
+ /**
374
+ * Previous conversation messages for context
375
+ * Agent can load this in beforeRun hook based on conversationId
376
+ */
377
+ history?: Message[];
378
+ /**
379
+ * Arbitrary metadata that flows through the execution
380
+ * Available in all callbacks
381
+ */
382
+ metadata?: Record<string, any>;
383
+ options?: {
384
+ maxSteps?: number;
385
+ timeoutMs?: number;
386
+ };
387
+ }
388
+ export interface AgentExecuteResult {
389
+ message: string;
390
+ toolCalls: Array<{
391
+ name: string;
392
+ input: any;
393
+ output: any;
394
+ error?: string;
395
+ isAgentCall?: boolean;
396
+ agentId?: string;
397
+ }>;
398
+ stepsUsed: number;
399
+ usage?: {
400
+ inputTokens: number;
401
+ outputTokens: number;
402
+ };
403
+ stoppedEarly: boolean;
404
+ subAgentCalls?: Array<{
405
+ agentId: string;
406
+ input: any;
407
+ result: AgentExecuteResult;
408
+ }>;
409
+ }
410
+ /**
411
+ * Stream chunk types for different streaming events
412
+ *
413
+ * Phase 1: Only "complete" event is emitted
414
+ * Phase 2: Will emit real-time "text_delta", "tool_call_start", and "tool_call_result" events
415
+ */
416
+ export type StreamChunk = {
417
+ type: "text_delta";
418
+ delta: string;
419
+ } | {
420
+ type: "tool_call_start";
421
+ toolCall: ToolCall;
422
+ } | {
423
+ type: "tool_call_result";
424
+ toolCall: ToolCall;
425
+ output: any;
426
+ error?: string;
427
+ } | {
428
+ type: "agent_call_start";
429
+ agentId: string;
430
+ input: any;
431
+ } | {
432
+ type: "agent_call_result";
433
+ agentId: string;
434
+ result: AgentExecuteResult;
435
+ } | {
436
+ type: "complete";
437
+ result: AgentExecuteResult;
438
+ };
439
+ /**
440
+ * Unified response that supports both awaiting and streaming
441
+ */
442
+ export interface AgentResponse {
443
+ result: Promise<AgentExecuteResult>;
444
+ textStream: AsyncGenerator<string>;
445
+ fullStream: AsyncGenerator<StreamChunk>;
446
+ }