@aigne/core 1.18.6 → 1.20.1

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 (63) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/lib/cjs/agents/agent.d.ts +31 -8
  3. package/lib/cjs/agents/agent.js +31 -22
  4. package/lib/cjs/agents/ai-agent.d.ts +18 -6
  5. package/lib/cjs/agents/ai-agent.js +23 -12
  6. package/lib/cjs/agents/guide-rail-agent.d.ts +1 -1
  7. package/lib/cjs/agents/mcp-agent.d.ts +1 -1
  8. package/lib/cjs/agents/team-agent.js +1 -1
  9. package/lib/cjs/aigne/aigne.d.ts +10 -10
  10. package/lib/cjs/aigne/context.d.ts +11 -6
  11. package/lib/cjs/aigne/context.js +73 -48
  12. package/lib/cjs/aigne/message-queue.d.ts +1 -1
  13. package/lib/cjs/aigne/message-queue.js +2 -3
  14. package/lib/cjs/aigne/usage.d.ts +1 -0
  15. package/lib/cjs/aigne/usage.js +1 -0
  16. package/lib/cjs/loader/agent-yaml.d.ts +2 -1
  17. package/lib/cjs/loader/agent-yaml.js +4 -0
  18. package/lib/cjs/prompt/prompt-builder.d.ts +2 -16
  19. package/lib/cjs/prompt/prompt-builder.js +12 -25
  20. package/lib/cjs/utils/event-stream.d.ts +5 -1
  21. package/lib/cjs/utils/event-stream.js +88 -23
  22. package/lib/cjs/utils/stream-utils.d.ts +9 -7
  23. package/lib/cjs/utils/stream-utils.js +48 -15
  24. package/lib/cjs/utils/type-utils.d.ts +2 -0
  25. package/lib/cjs/utils/type-utils.js +18 -0
  26. package/lib/dts/agents/agent.d.ts +31 -8
  27. package/lib/dts/agents/ai-agent.d.ts +18 -6
  28. package/lib/dts/agents/guide-rail-agent.d.ts +1 -1
  29. package/lib/dts/agents/mcp-agent.d.ts +1 -1
  30. package/lib/dts/aigne/aigne.d.ts +10 -10
  31. package/lib/dts/aigne/context.d.ts +11 -6
  32. package/lib/dts/aigne/message-queue.d.ts +1 -1
  33. package/lib/dts/aigne/usage.d.ts +1 -0
  34. package/lib/dts/loader/agent-yaml.d.ts +2 -1
  35. package/lib/dts/prompt/prompt-builder.d.ts +2 -16
  36. package/lib/dts/utils/event-stream.d.ts +5 -1
  37. package/lib/dts/utils/stream-utils.d.ts +9 -7
  38. package/lib/dts/utils/type-utils.d.ts +2 -0
  39. package/lib/esm/agents/agent.d.ts +31 -8
  40. package/lib/esm/agents/agent.js +29 -22
  41. package/lib/esm/agents/ai-agent.d.ts +18 -6
  42. package/lib/esm/agents/ai-agent.js +25 -14
  43. package/lib/esm/agents/guide-rail-agent.d.ts +1 -1
  44. package/lib/esm/agents/mcp-agent.d.ts +1 -1
  45. package/lib/esm/agents/team-agent.js +2 -2
  46. package/lib/esm/aigne/aigne.d.ts +10 -10
  47. package/lib/esm/aigne/context.d.ts +11 -6
  48. package/lib/esm/aigne/context.js +76 -51
  49. package/lib/esm/aigne/message-queue.d.ts +1 -1
  50. package/lib/esm/aigne/message-queue.js +2 -3
  51. package/lib/esm/aigne/usage.d.ts +1 -0
  52. package/lib/esm/aigne/usage.js +1 -0
  53. package/lib/esm/loader/agent-yaml.d.ts +2 -1
  54. package/lib/esm/loader/agent-yaml.js +4 -0
  55. package/lib/esm/prompt/prompt-builder.d.ts +2 -16
  56. package/lib/esm/prompt/prompt-builder.js +12 -23
  57. package/lib/esm/utils/event-stream.d.ts +5 -1
  58. package/lib/esm/utils/event-stream.js +86 -22
  59. package/lib/esm/utils/stream-utils.d.ts +9 -7
  60. package/lib/esm/utils/stream-utils.js +48 -16
  61. package/lib/esm/utils/type-utils.d.ts +2 -0
  62. package/lib/esm/utils/type-utils.js +16 -0
  63. package/package.json +2 -2
@@ -2,13 +2,13 @@ import equal from "fast-deep-equal";
2
2
  import { Emitter } from "strict-event-emitter";
3
3
  import { v7 } from "uuid";
4
4
  import { z } from "zod";
5
- import { Agent, isEmptyChunk, } from "../agents/agent.js";
5
+ import { Agent, isAgentResponseDelta, isEmptyChunk, } from "../agents/agent.js";
6
6
  import { isTransferAgentOutput, transferAgentOutputKey, } from "../agents/types.js";
7
7
  import { UserAgent } from "../agents/user-agent.js";
8
- import { createMessage } from "../prompt/prompt-builder.js";
8
+ import { AgentResponseProgressStream } from "../utils/event-stream.js";
9
9
  import { promiseWithResolvers } from "../utils/promise.js";
10
- import { agentResponseStreamToObject, asyncGeneratorToReadableStream, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
11
- import { checkArguments, isEmpty, isNil, omitBy, } from "../utils/type-utils.js";
10
+ import { agentResponseStreamToObject, asyncGeneratorToReadableStream, mergeReadableStreams, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
11
+ import { checkArguments, isEmpty, isNil, omit, } from "../utils/type-utils.js";
12
12
  import { MessageQueue, toMessagePayload, } from "./message-queue.js";
13
13
  import { newEmptyContextUsage } from "./usage.js";
14
14
  /**
@@ -80,38 +80,54 @@ export class AIGNEContext {
80
80
  });
81
81
  }
82
82
  const newContext = this.newContext();
83
- const msg = createMessage(message);
84
- return Promise.resolve(newContext.internal.invoke(agent, msg, newContext, options)).then(async (response) => {
83
+ return Promise.resolve(newContext.internal.invoke(agent, message, newContext, options)).then(async (response) => {
85
84
  if (!options?.streaming) {
86
- const { __activeAgent__: activeAgent, ...output } = await agentResponseStreamToObject(response);
85
+ let { __activeAgent__: activeAgent, ...output } = await agentResponseStreamToObject(response);
86
+ output = await this.onInvocationResult(output, options);
87
87
  if (options?.returnActiveAgent) {
88
88
  return [output, activeAgent];
89
89
  }
90
90
  return output;
91
91
  }
92
92
  const activeAgentPromise = promiseWithResolvers();
93
- const stream = onAgentResponseStreamEnd(asyncGeneratorToReadableStream(response), async ({ __activeAgent__: activeAgent }) => {
94
- activeAgentPromise.resolve(activeAgent);
95
- }, {
96
- processChunk(chunk) {
97
- if (chunk.delta.json) {
93
+ const stream = onAgentResponseStreamEnd(asyncGeneratorToReadableStream(response), {
94
+ onChunk(chunk) {
95
+ if (isAgentResponseDelta(chunk) && chunk.delta.json) {
98
96
  return {
99
97
  ...chunk,
100
98
  delta: {
101
99
  ...chunk.delta,
102
- json: omitBy(chunk.delta.json, (_, k) => k === "__activeAgent__"),
100
+ json: omit(chunk.delta.json, "__activeAgent__"),
103
101
  },
104
102
  };
105
103
  }
106
- return chunk;
104
+ },
105
+ onResult: async (output) => {
106
+ activeAgentPromise.resolve(output.__activeAgent__);
107
+ return await this.onInvocationResult(output, options);
107
108
  },
108
109
  });
110
+ const finalStream = !options.returnProgressChunks
111
+ ? stream
112
+ : mergeReadableStreams(stream, new AgentResponseProgressStream(newContext));
109
113
  if (options.returnActiveAgent) {
110
- return [stream, activeAgentPromise.promise];
114
+ return [finalStream, activeAgentPromise.promise];
111
115
  }
112
- return stream;
116
+ return finalStream;
113
117
  });
114
118
  });
119
+ async onInvocationResult(output, options) {
120
+ if (!options?.returnMetadata) {
121
+ return output;
122
+ }
123
+ return {
124
+ ...output,
125
+ $meta: {
126
+ ...output.$meta,
127
+ usage: this.usage,
128
+ },
129
+ };
130
+ }
115
131
  publish = ((topic, payload, options) => {
116
132
  if (options?.userContext) {
117
133
  Object.assign(this.userContext, options.userContext);
@@ -164,7 +180,6 @@ class AIGNEContextShared {
164
180
  this.memories = overrides?.memories ?? [];
165
181
  }
166
182
  messageQueue;
167
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
168
183
  events = new Emitter();
169
184
  get model() {
170
185
  return this.parent?.model;
@@ -198,44 +213,54 @@ class AIGNEContextShared {
198
213
  return withAbortSignal(this.abortController.signal, new Error("AIGNEContext is timeout"), () => this.invokeAgent(agent, input, context, options));
199
214
  }
200
215
  async *invokeAgent(agent, input, context, options) {
201
- let activeAgent = agent;
202
- for (;;) {
203
- const result = {};
204
- if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
205
- options.sourceAgent.hooks.onHandoff?.({
206
- context,
207
- source: options.sourceAgent,
208
- target: activeAgent,
209
- input,
210
- });
211
- }
212
- const stream = await activeAgent.invoke(input, { ...options, context, streaming: true });
213
- for await (const value of stream) {
214
- if (value.delta.json) {
215
- value.delta.json = omitExistsProperties(result, value.delta.json);
216
- Object.assign(result, value.delta.json);
216
+ const startedAt = Date.now();
217
+ try {
218
+ let activeAgent = agent;
219
+ for (;;) {
220
+ const result = {};
221
+ if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
222
+ options.sourceAgent.hooks.onHandoff?.({
223
+ context,
224
+ source: options.sourceAgent,
225
+ target: activeAgent,
226
+ input,
227
+ });
217
228
  }
218
- delete value.delta.json?.[transferAgentOutputKey];
219
- if (isEmptyChunk(value))
220
- continue;
221
- yield value;
222
- }
223
- if (!options?.disableTransfer) {
224
- const transferToAgent = isTransferAgentOutput(result)
225
- ? result[transferAgentOutputKey].agent
226
- : undefined;
227
- if (transferToAgent) {
228
- activeAgent = transferToAgent;
229
- continue;
229
+ const stream = await activeAgent.invoke(input, { ...options, context, streaming: true });
230
+ for await (const value of stream) {
231
+ if (isAgentResponseDelta(value)) {
232
+ if (value.delta.json) {
233
+ value.delta.json = omitExistsProperties(result, value.delta.json);
234
+ Object.assign(result, value.delta.json);
235
+ }
236
+ delete value.delta.json?.[transferAgentOutputKey];
237
+ }
238
+ if (isEmptyChunk(value))
239
+ continue;
240
+ yield value;
241
+ }
242
+ if (!options?.disableTransfer) {
243
+ const transferToAgent = isTransferAgentOutput(result)
244
+ ? result[transferAgentOutputKey].agent
245
+ : undefined;
246
+ if (transferToAgent) {
247
+ activeAgent = transferToAgent;
248
+ continue;
249
+ }
230
250
  }
251
+ break;
231
252
  }
232
- break;
253
+ yield {
254
+ delta: {
255
+ json: { __activeAgent__: activeAgent },
256
+ },
257
+ };
258
+ }
259
+ finally {
260
+ const endedAt = Date.now();
261
+ const duration = endedAt - startedAt;
262
+ this.usage.duration += duration;
233
263
  }
234
- yield {
235
- delta: {
236
- json: { __activeAgent__: activeAgent },
237
- },
238
- };
239
264
  }
240
265
  }
241
266
  function omitExistsProperties(result, { ...delta }) {
@@ -21,7 +21,7 @@ export interface MessagePayload {
21
21
  /**
22
22
  * @hidden
23
23
  */
24
- export declare function toMessagePayload(payload: Omit<MessagePayload, "context"> | string | Message, options?: Partial<Pick<MessagePayload, "role" | "source">>): Omit<MessagePayload, "context">;
24
+ export declare function toMessagePayload(payload: Omit<MessagePayload, "context"> | Message, options?: Partial<Pick<MessagePayload, "role" | "source">>): Omit<MessagePayload, "context">;
25
25
  /**
26
26
  * @hidden
27
27
  */
@@ -1,6 +1,5 @@
1
1
  import { Emitter } from "strict-event-emitter";
2
2
  import { z } from "zod";
3
- import { createMessage } from "../prompt/prompt-builder.js";
4
3
  import { checkArguments, isNil, orArrayToArray } from "../utils/type-utils.js";
5
4
  /**
6
5
  * @hidden
@@ -24,12 +23,12 @@ function isMessagePayload(payload) {
24
23
  */
25
24
  export function toMessagePayload(payload, options) {
26
25
  if (isMessagePayload(payload)) {
27
- return { ...payload, message: createMessage(payload.message), ...options };
26
+ return { ...payload, ...options };
28
27
  }
29
28
  return {
30
29
  role: options?.role || "user",
31
30
  source: options?.source,
32
- message: createMessage(payload),
31
+ message: payload,
33
32
  };
34
33
  }
35
34
  /**
@@ -5,6 +5,7 @@ export interface ContextUsage {
5
5
  inputTokens: number;
6
6
  outputTokens: number;
7
7
  agentCalls: number;
8
+ duration: number;
8
9
  }
9
10
  /**
10
11
  * @hidden
@@ -6,5 +6,6 @@ export function newEmptyContextUsage() {
6
6
  inputTokens: 0,
7
7
  outputTokens: 0,
8
8
  agentCalls: 0,
9
+ duration: 0,
9
10
  };
10
11
  }
@@ -5,11 +5,11 @@ export declare function loadAgentFromYamlFile(path: string): Promise<{
5
5
  name: string;
6
6
  description?: string | undefined;
7
7
  skills?: string[] | undefined;
8
- instructions?: string | undefined;
9
8
  memory?: true | {
10
9
  provider: string;
11
10
  subscribeTopic?: string[] | undefined;
12
11
  } | undefined;
12
+ instructions?: string | undefined;
13
13
  inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
14
14
  [x: string]: any;
15
15
  }, {
@@ -20,6 +20,7 @@ export declare function loadAgentFromYamlFile(path: string): Promise<{
20
20
  }, {
21
21
  [x: string]: any;
22
22
  }> | undefined;
23
+ inputKey?: string | undefined;
23
24
  outputKey?: string | undefined;
24
25
  toolChoice?: AIAgentToolChoice | undefined;
25
26
  } | {
@@ -18,6 +18,10 @@ const agentFileSchema = z.discriminatedUnion("type", [
18
18
  .string()
19
19
  .nullish()
20
20
  .transform((v) => v ?? undefined),
21
+ input_key: z
22
+ .string()
23
+ .nullish()
24
+ .transform((v) => v ?? undefined),
21
25
  input_schema: inputOutputSchema
22
26
  .nullish()
23
27
  .transform((v) => (v ? jsonSchemaToZod(v) : undefined)),
@@ -3,33 +3,19 @@ import { Agent, type AgentInvokeOptions, type Message } from "../agents/agent.js
3
3
  import type { AIAgent } from "../agents/ai-agent.js";
4
4
  import type { ChatModel, ChatModelInput } from "../agents/chat-model.js";
5
5
  import { ChatMessagesTemplate } from "./template.js";
6
- export declare const MESSAGE_KEY = "$message";
7
- export declare function createMessage<V extends Message>(message: string, variables?: V): {
8
- [MESSAGE_KEY]: string;
9
- } & typeof variables;
10
- export declare function createMessage<I extends Message, V extends Message>(message: I, variables?: V): I & typeof variables;
11
- export declare function createMessage<I extends Message, V extends Message>(message: string | I, variables?: V): ({
12
- [MESSAGE_KEY]: string;
13
- } | I) & typeof variables;
14
- export declare function getMessage(input: Message): string | undefined;
15
6
  export interface PromptBuilderOptions {
16
7
  instructions?: string | ChatMessagesTemplate;
17
8
  }
18
9
  export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"> {
19
- agent?: AIAgent;
10
+ agent?: AIAgent<any, any, any>;
20
11
  input?: Message;
21
12
  model?: ChatModel;
22
13
  outputSchema?: Agent["outputSchema"];
23
14
  }
24
15
  export declare class PromptBuilder {
25
- static from(instructions: string): PromptBuilder;
26
- static from(instructions: GetPromptResult): PromptBuilder;
27
- static from(instructions: {
28
- path: string;
29
- }): Promise<PromptBuilder>;
30
16
  static from(instructions: string | {
31
17
  path: string;
32
- } | GetPromptResult): PromptBuilder | Promise<PromptBuilder>;
18
+ } | GetPromptResult): PromptBuilder;
33
19
  private static fromFile;
34
20
  private static fromMCPPromptResult;
35
21
  constructor(options?: PromptBuilderOptions);
@@ -3,23 +3,9 @@ import { stringify } from "yaml";
3
3
  import { ZodObject } from "zod";
4
4
  import { Agent } from "../agents/agent.js";
5
5
  import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
6
- import { isNil, unique } from "../utils/type-utils.js";
6
+ import { unique } from "../utils/type-utils.js";
7
7
  import { MEMORY_MESSAGE_TEMPLATE } from "./prompts/memory-message-template.js";
8
8
  import { AgentMessageTemplate, ChatMessagesTemplate, PromptTemplate, SystemMessageTemplate, UserMessageTemplate, } from "./template.js";
9
- export const MESSAGE_KEY = "$message";
10
- export function createMessage(message, variables) {
11
- return (typeof message === "string"
12
- ? { [MESSAGE_KEY]: message, ...variables }
13
- : { ...message, ...variables });
14
- }
15
- export function getMessage(input) {
16
- const userInputMessage = input[MESSAGE_KEY];
17
- if (typeof userInputMessage === "string")
18
- return userInputMessage;
19
- if (!isNil(userInputMessage))
20
- return JSON.stringify(userInputMessage);
21
- return undefined;
22
- }
23
9
  export class PromptBuilder {
24
10
  static from(instructions) {
25
11
  if (typeof instructions === "string")
@@ -30,8 +16,8 @@ export class PromptBuilder {
30
16
  return PromptBuilder.fromFile(instructions.path);
31
17
  throw new Error(`Invalid instructions ${instructions}`);
32
18
  }
33
- static async fromFile(path) {
34
- const text = await nodejs.fs.readFile(path, "utf-8");
19
+ static fromFile(path) {
20
+ const text = nodejs.fsSync.readFileSync(path, "utf-8");
35
21
  return PromptBuilder.from(text);
36
22
  }
37
23
  static fromMCPPromptResult(result) {
@@ -75,22 +61,25 @@ export class PromptBuilder {
75
61
  }
76
62
  async buildMessages(options) {
77
63
  const { input } = options;
64
+ const inputKey = options.agent?.inputKey;
65
+ const message = inputKey && typeof input?.[inputKey] === "string" ? input[inputKey] : undefined;
78
66
  const messages = (typeof this.instructions === "string"
79
67
  ? ChatMessagesTemplate.from([SystemMessageTemplate.from(this.instructions)])
80
68
  : this.instructions)?.format(options.input) ?? [];
81
69
  const memories = [];
82
- if (options.agent) {
83
- memories.push(...(await options.agent.retrieveMemories({ search: options.input }, options)));
70
+ if (options.agent?.inputKey) {
71
+ memories.push(...(await options.agent.retrieveMemories({ search: message }, options)));
84
72
  }
85
73
  if (options.context.memories?.length) {
86
74
  memories.push(...options.context.memories);
87
75
  }
88
76
  if (memories.length)
89
77
  messages.push(...this.convertMemoriesToMessages(memories, options));
90
- const content = input && getMessage(input);
91
- // add user input if it's not the same as the last message
92
- if (content && messages.at(-1)?.content !== content) {
93
- messages.push({ role: "user", content });
78
+ if (message) {
79
+ messages.push({
80
+ role: "user",
81
+ content: message,
82
+ });
94
83
  }
95
84
  return messages;
96
85
  }
@@ -1,4 +1,5 @@
1
- import type { AgentResponseChunk, AgentResponseStream, Message } from "../agents/agent.js";
1
+ import { type AgentResponseChunk, type AgentResponseProgress, type AgentResponseStream, type Message } from "../agents/agent.js";
2
+ import type { Context } from "../aigne/context.js";
2
3
  export declare class EventStreamParser<T> extends TransformStream<string, T | Error> {
3
4
  constructor();
4
5
  }
@@ -9,3 +10,6 @@ export declare class AgentResponseStreamParser<O extends Message> extends Transf
9
10
  export declare class AgentResponseStreamSSE<O extends Message> extends ReadableStream<string> {
10
11
  constructor(stream: AgentResponseStream<O>);
11
12
  }
13
+ export declare class AgentResponseProgressStream extends ReadableStream<AgentResponseProgress> {
14
+ constructor(context: Context);
15
+ }
@@ -1,5 +1,6 @@
1
1
  import { createParser } from "eventsource-parser";
2
2
  import { produce } from "immer";
3
+ import { isAgentResponseDelta, isAgentResponseProgress, } from "../agents/agent.js";
3
4
  import { tryOrThrow } from "./type-utils.js";
4
5
  export class EventStreamParser extends TransformStream {
5
6
  constructor() {
@@ -12,11 +13,16 @@ export class EventStreamParser extends TransformStream {
12
13
  controller.enqueue(new Error(`Parse response chunk json error: ${e.message} ${event.data}`));
13
14
  });
14
15
  if (json) {
15
- if (event.event === "error") {
16
- controller.enqueue(new Error(json.message));
17
- }
18
- else {
19
- controller.enqueue(json);
16
+ switch (event.event) {
17
+ case "error":
18
+ controller.enqueue(new Error(json.message));
19
+ break;
20
+ default: {
21
+ if (!event.event)
22
+ controller.enqueue(json);
23
+ else
24
+ console.warn(`Unknown event type: ${event.event}`, event.data);
25
+ }
20
26
  }
21
27
  }
22
28
  },
@@ -38,25 +44,35 @@ export class AgentResponseStreamParser extends TransformStream {
38
44
  controller.terminate();
39
45
  return;
40
46
  }
41
- this.json = produce(this.json, (draft) => {
42
- if (chunk.delta.json)
43
- Object.assign(draft, chunk.delta.json);
44
- if (chunk.delta.text) {
45
- for (const [key, text] of Object.entries(chunk.delta.text)) {
46
- const original = draft[key];
47
- const t = (original || "") + (text || "");
48
- if (t)
49
- Object.assign(draft, { [key]: t });
47
+ if (isAgentResponseDelta(chunk)) {
48
+ this.json = produce(this.json, (draft) => {
49
+ if (chunk.delta.json)
50
+ Object.assign(draft, chunk.delta.json);
51
+ if (chunk.delta.text) {
52
+ for (const [key, text] of Object.entries(chunk.delta.text)) {
53
+ const original = draft[key];
54
+ const t = (original || "") + (text || "");
55
+ if (t)
56
+ Object.assign(draft, { [key]: t });
57
+ }
50
58
  }
59
+ });
60
+ controller.enqueue({
61
+ ...chunk,
62
+ delta: {
63
+ ...chunk.delta,
64
+ json: this.json,
65
+ },
66
+ });
67
+ }
68
+ else if (isAgentResponseProgress(chunk)) {
69
+ if (chunk.progress.event === "agentFailed") {
70
+ const { name, message } = chunk.progress.error;
71
+ chunk.progress.error = new Error(message);
72
+ chunk.progress.error.name = name;
51
73
  }
52
- });
53
- controller.enqueue({
54
- ...chunk,
55
- delta: {
56
- ...chunk.delta,
57
- json: this.json,
58
- },
59
- });
74
+ controller.enqueue(chunk);
75
+ }
60
76
  },
61
77
  });
62
78
  }
@@ -73,6 +89,14 @@ export class AgentResponseStreamSSE extends ReadableStream {
73
89
  controller.close();
74
90
  return;
75
91
  }
92
+ if (isAgentResponseProgress(value)) {
93
+ if (value.progress.event === "agentFailed") {
94
+ value.progress.error = {
95
+ name: value.progress.error.name,
96
+ message: value.progress.error.message,
97
+ };
98
+ }
99
+ }
76
100
  controller.enqueue(`data: ${JSON.stringify(value)}\n\n`);
77
101
  }
78
102
  catch (error) {
@@ -83,3 +107,43 @@ export class AgentResponseStreamSSE extends ReadableStream {
83
107
  });
84
108
  }
85
109
  }
110
+ export class AgentResponseProgressStream extends ReadableStream {
111
+ constructor(context) {
112
+ super({
113
+ async start(controller) {
114
+ const writeEvent = (eventName, event) => {
115
+ const progress = {
116
+ ...event,
117
+ event: eventName,
118
+ agent: { name: event.agent.name },
119
+ };
120
+ controller.enqueue({ progress });
121
+ };
122
+ const close = () => {
123
+ context.off("agentStarted", onAgentStarted);
124
+ context.off("agentSucceed", onAgentSucceed);
125
+ context.off("agentFailed", onAgentFailed);
126
+ controller.close();
127
+ };
128
+ const onAgentStarted = (event) => {
129
+ writeEvent("agentStarted", event);
130
+ };
131
+ const onAgentSucceed = (event) => {
132
+ writeEvent("agentSucceed", event);
133
+ if (event.contextId === context.id) {
134
+ close();
135
+ }
136
+ };
137
+ const onAgentFailed = (event) => {
138
+ writeEvent("agentFailed", event);
139
+ if (event.contextId === context.id) {
140
+ close();
141
+ }
142
+ };
143
+ context.on("agentStarted", onAgentStarted);
144
+ context.on("agentSucceed", onAgentSucceed);
145
+ context.on("agentFailed", onAgentFailed);
146
+ },
147
+ });
148
+ }
149
+ }
@@ -1,15 +1,15 @@
1
1
  import { type AgentProcessAsyncGenerator, type AgentResponseChunk, type AgentResponseStream, type Message } from "../agents/agent.js";
2
- import type { MESSAGE_KEY } from "../prompt/prompt-builder.js";
3
2
  import { type PromiseOrValue } from "./type-utils.js";
4
3
  import "./stream-polyfill.js";
5
4
  export declare function objectToAgentResponseStream<T extends Message>(json: T): AgentResponseStream<T>;
6
5
  export declare function mergeAgentResponseChunk<T extends Message>(output: T, chunk: AgentResponseChunk<T>): T;
7
6
  export declare function agentResponseStreamToObject<T extends Message>(stream: AgentResponseStream<T> | AgentProcessAsyncGenerator<T>): Promise<T>;
8
7
  export declare function asyncGeneratorToReadableStream<T extends Message>(generator: AgentProcessAsyncGenerator<T>): AgentResponseStream<T>;
9
- export declare function onAgentResponseStreamEnd<T extends Message>(stream: AgentResponseStream<T>, callback: (result: T) => PromiseOrValue<Partial<T> | void>, options?: {
10
- errorCallback?: (error: Error) => PromiseOrValue<Error>;
11
- processChunk?: (chunk: AgentResponseChunk<T>) => AgentResponseChunk<T>;
12
- }): ReadableStream<any>;
8
+ export declare function onAgentResponseStreamEnd<T extends Message>(stream: AgentResponseStream<T>, options?: {
9
+ onChunk?: (chunk: AgentResponseChunk<T>) => PromiseOrValue<AgentResponseChunk<T> | undefined | void>;
10
+ onResult?: (result: T) => PromiseOrValue<Partial<T> | undefined | void>;
11
+ onError?: (error: Error) => PromiseOrValue<Error>;
12
+ }): AgentResponseStream<T>;
13
13
  export declare function isAsyncGenerator<T extends AsyncGenerator>(value: AsyncGenerator | unknown): value is T;
14
14
  export declare function arrayToAgentProcessAsyncGenerator<T extends Message>(chunks: (AgentResponseChunk<T> | Error)[], result?: Partial<T>): AgentProcessAsyncGenerator<T>;
15
15
  export declare function arrayToReadableStream<T>(chunks: (T | Error)[]): ReadableStream<T>;
@@ -17,8 +17,10 @@ export declare function readableStreamToArray<T>(stream: ReadableStream<T>, opti
17
17
  catchError: true;
18
18
  }): Promise<(T | Error)[]>;
19
19
  export declare function readableStreamToArray<T>(stream: ReadableStream<T>, options?: {
20
- catchError?: false;
20
+ catchError?: boolean;
21
21
  }): Promise<T[]>;
22
- export declare function stringToAgentResponseStream(str: string, key?: "text" | typeof MESSAGE_KEY | string): AgentResponseStream<Message>;
22
+ export declare function stringToAgentResponseStream(str: string, key?: "text" | string): AgentResponseStream<Message>;
23
23
  export declare function toReadableStream(stream: NodeJS.ReadStream): ReadableStream<Uint8Array<ArrayBufferLike>>;
24
24
  export declare function readAllString(stream: NodeJS.ReadStream | ReadableStream): Promise<string>;
25
+ export declare function mergeReadableStreams<T1, T2>(s1: ReadableStream<T1>, s2: ReadableStream<T2>): ReadableStream<T1 | T2>;
26
+ export declare function mergeReadableStreams(...streams: ReadableStream<any>[]): ReadableStream<any>;