@aigne/core 1.18.6 → 1.19.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/CHANGELOG.md +7 -0
- package/lib/cjs/agents/agent.d.ts +20 -2
- package/lib/cjs/agents/agent.js +24 -13
- package/lib/cjs/agents/ai-agent.js +9 -8
- package/lib/cjs/agents/team-agent.js +1 -1
- package/lib/cjs/aigne/context.d.ts +3 -0
- package/lib/cjs/aigne/context.js +18 -13
- package/lib/cjs/utils/event-stream.d.ts +5 -1
- package/lib/cjs/utils/event-stream.js +88 -23
- package/lib/cjs/utils/stream-utils.d.ts +8 -5
- package/lib/cjs/utils/stream-utils.js +48 -15
- package/lib/cjs/utils/type-utils.d.ts +1 -0
- package/lib/cjs/utils/type-utils.js +5 -0
- package/lib/dts/agents/agent.d.ts +20 -2
- package/lib/dts/aigne/context.d.ts +3 -0
- package/lib/dts/utils/event-stream.d.ts +5 -1
- package/lib/dts/utils/stream-utils.d.ts +8 -5
- package/lib/dts/utils/type-utils.d.ts +1 -0
- package/lib/esm/agents/agent.d.ts +20 -2
- package/lib/esm/agents/agent.js +22 -13
- package/lib/esm/agents/ai-agent.js +10 -9
- package/lib/esm/agents/team-agent.js +2 -2
- package/lib/esm/aigne/context.d.ts +3 -0
- package/lib/esm/aigne/context.js +20 -15
- package/lib/esm/utils/event-stream.d.ts +5 -1
- package/lib/esm/utils/event-stream.js +86 -22
- package/lib/esm/utils/stream-utils.d.ts +8 -5
- package/lib/esm/utils/stream-utils.js +48 -16
- package/lib/esm/utils/type-utils.d.ts +1 -0
- package/lib/esm/utils/type-utils.js +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
* add user context support ([#131](https://github.com/AIGNE-io/aigne-framework/issues/131)) ([4dd9d20](https://github.com/AIGNE-io/aigne-framework/commit/4dd9d20953f6ac33933723db56efd9b44bafeb02))
|
|
7
7
|
|
|
8
|
+
## [1.19.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.18.6...core-v1.19.0) (2025-06-16)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* support respond progressing chunks by enable `returnProgressChunks` option for aigne.invoke ([cf4c313](https://github.com/AIGNE-io/aigne-framework/commit/cf4c313ee69f255be799ac196da675b79f69bf76))
|
|
14
|
+
|
|
8
15
|
## [1.18.6](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.18.5...core-v1.18.6) (2025-06-11)
|
|
9
16
|
|
|
10
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
2
2
|
import { ZodObject, type ZodType } from "zod";
|
|
3
|
-
import type { Context, UserContext } from "../aigne/context.js";
|
|
3
|
+
import type { AgentEvent, Context, UserContext } from "../aigne/context.js";
|
|
4
4
|
import type { MessagePayload } from "../aigne/message-queue.js";
|
|
5
5
|
import type { Memory, MemoryAgent } from "../memory/memory.js";
|
|
6
6
|
import type { MemoryRecorderInput } from "../memory/recorder.js";
|
|
@@ -594,7 +594,7 @@ export type AgentResponseStream<T> = ReadableStream<AgentResponseChunk<T>>;
|
|
|
594
594
|
*
|
|
595
595
|
* @template T Response data type
|
|
596
596
|
*/
|
|
597
|
-
export type AgentResponseChunk<T> = AgentResponseDelta<T
|
|
597
|
+
export type AgentResponseChunk<T> = AgentResponseDelta<T> | AgentResponseProgress;
|
|
598
598
|
/**
|
|
599
599
|
* Check if a response chunk is empty
|
|
600
600
|
*
|
|
@@ -622,6 +622,24 @@ export interface AgentResponseDelta<T> {
|
|
|
622
622
|
json?: Partial<T> | TransferAgentOutput;
|
|
623
623
|
};
|
|
624
624
|
}
|
|
625
|
+
export declare function isAgentResponseDelta<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseDelta<T>;
|
|
626
|
+
export interface AgentResponseProgress {
|
|
627
|
+
progress: ({
|
|
628
|
+
event: "agentStarted";
|
|
629
|
+
input: Message;
|
|
630
|
+
} | {
|
|
631
|
+
event: "agentSucceed";
|
|
632
|
+
output: Message;
|
|
633
|
+
} | {
|
|
634
|
+
event: "agentFailed";
|
|
635
|
+
error: Error;
|
|
636
|
+
}) & Omit<AgentEvent, "agent"> & {
|
|
637
|
+
agent: {
|
|
638
|
+
name: string;
|
|
639
|
+
};
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
export declare function isAgentResponseProgress<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseProgress;
|
|
625
643
|
/**
|
|
626
644
|
* Creates a text delta for streaming responses
|
|
627
645
|
*
|
package/lib/cjs/agents/agent.js
CHANGED
|
@@ -38,6 +38,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.FunctionAgent = exports.Agent = exports.agentOptionsSchema = void 0;
|
|
40
40
|
exports.isEmptyChunk = isEmptyChunk;
|
|
41
|
+
exports.isAgentResponseDelta = isAgentResponseDelta;
|
|
42
|
+
exports.isAgentResponseProgress = isAgentResponseProgress;
|
|
41
43
|
exports.textDelta = textDelta;
|
|
42
44
|
exports.jsonDelta = jsonDelta;
|
|
43
45
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
@@ -361,10 +363,11 @@ class Agent {
|
|
|
361
363
|
: (0, stream_utils_js_1.isAsyncGenerator)(response)
|
|
362
364
|
? (0, stream_utils_js_1.asyncGeneratorToReadableStream)(response)
|
|
363
365
|
: (0, stream_utils_js_1.objectToAgentResponseStream)(response);
|
|
364
|
-
return this.checkResponseByGuideRails(message, (0, stream_utils_js_1.onAgentResponseStreamEnd)(stream,
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
366
|
+
return this.checkResponseByGuideRails(message, (0, stream_utils_js_1.onAgentResponseStreamEnd)(stream, {
|
|
367
|
+
onResult: async (result) => {
|
|
368
|
+
return await this.processAgentOutput(parsedInput, result, opts);
|
|
369
|
+
},
|
|
370
|
+
onError: async (error) => {
|
|
368
371
|
return await this.processAgentError(message, error, opts);
|
|
369
372
|
},
|
|
370
373
|
}), opts);
|
|
@@ -464,14 +467,16 @@ class Agent {
|
|
|
464
467
|
return output;
|
|
465
468
|
const result = await output;
|
|
466
469
|
if (result instanceof ReadableStream) {
|
|
467
|
-
return (0, stream_utils_js_1.onAgentResponseStreamEnd)(result,
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
470
|
+
return (0, stream_utils_js_1.onAgentResponseStreamEnd)(result, {
|
|
471
|
+
onResult: async (result) => {
|
|
472
|
+
const error = await this.runGuideRails(input, result, options);
|
|
473
|
+
if (error) {
|
|
474
|
+
return {
|
|
475
|
+
...(await this.onGuideRailError(error)),
|
|
476
|
+
$status: "GuideRailError",
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
},
|
|
475
480
|
});
|
|
476
481
|
}
|
|
477
482
|
const error = await this.runGuideRails(input, result, options);
|
|
@@ -585,7 +590,13 @@ exports.Agent = Agent;
|
|
|
585
590
|
* @returns True if the chunk is empty
|
|
586
591
|
*/
|
|
587
592
|
function isEmptyChunk(chunk) {
|
|
588
|
-
return (0, type_utils_js_1.isEmpty)(chunk.delta.json) && (0, type_utils_js_1.isEmpty)(chunk.delta.text);
|
|
593
|
+
return isAgentResponseDelta(chunk) && (0, type_utils_js_1.isEmpty)(chunk.delta.json) && (0, type_utils_js_1.isEmpty)(chunk.delta.text);
|
|
594
|
+
}
|
|
595
|
+
function isAgentResponseDelta(chunk) {
|
|
596
|
+
return "delta" in chunk;
|
|
597
|
+
}
|
|
598
|
+
function isAgentResponseProgress(chunk) {
|
|
599
|
+
return "progress" in chunk;
|
|
589
600
|
}
|
|
590
601
|
/**
|
|
591
602
|
* Creates a text delta for streaming responses
|
|
@@ -191,8 +191,7 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
191
191
|
});
|
|
192
192
|
const toolsMap = new Map(toolAgents?.map((i) => [i.name, i]));
|
|
193
193
|
if (this.toolChoice === "router") {
|
|
194
|
-
yield* this._processRouter(input, model, modelInput, options, toolsMap);
|
|
195
|
-
return;
|
|
194
|
+
return yield* this._processRouter(input, model, modelInput, options, toolsMap);
|
|
196
195
|
}
|
|
197
196
|
const toolCallMessages = [];
|
|
198
197
|
const outputKey = this.outputKey || prompt_builder_js_1.MESSAGE_KEY;
|
|
@@ -200,11 +199,13 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
200
199
|
const modelOutput = {};
|
|
201
200
|
const stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
|
|
202
201
|
for await (const value of stream) {
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
if ((0, agent_js_1.isAgentResponseDelta)(value)) {
|
|
203
|
+
if (value.delta.text?.text) {
|
|
204
|
+
yield { delta: { text: { [outputKey]: value.delta.text.text } } };
|
|
205
|
+
}
|
|
206
|
+
if (value.delta.json) {
|
|
207
|
+
Object.assign(modelOutput, value.delta.json);
|
|
208
|
+
}
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
const { toolCalls, json, text } = modelOutput;
|
|
@@ -275,7 +276,7 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
275
276
|
if (!tool)
|
|
276
277
|
throw new Error(`Tool not found: ${call.function.name}`);
|
|
277
278
|
const stream = await options.context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true, sourceAgent: this });
|
|
278
|
-
yield* stream;
|
|
279
|
+
return yield* stream;
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
exports.AIAgent = AIAgent;
|
|
@@ -158,7 +158,7 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
158
158
|
if (!done) {
|
|
159
159
|
tasks.set(index, read(index, reader));
|
|
160
160
|
}
|
|
161
|
-
if (value) {
|
|
161
|
+
if (value && (0, agent_js_1.isAgentResponseDelta)(value)) {
|
|
162
162
|
let { delta: { text, ...delta }, } = value;
|
|
163
163
|
if (text) {
|
|
164
164
|
for (const key of Object.keys(text)) {
|
|
@@ -41,6 +41,7 @@ export type ContextEmitEventMap = {
|
|
|
41
41
|
*/
|
|
42
42
|
export interface InvokeOptions<U extends UserContext = UserContext> extends Partial<Omit<AgentInvokeOptions<U>, "context">> {
|
|
43
43
|
returnActiveAgent?: boolean;
|
|
44
|
+
returnProgressChunks?: boolean;
|
|
44
45
|
disableTransfer?: boolean;
|
|
45
46
|
sourceAgent?: Agent;
|
|
46
47
|
}
|
|
@@ -53,6 +54,8 @@ export interface UserContext extends Record<string, unknown> {
|
|
|
53
54
|
* @hidden
|
|
54
55
|
*/
|
|
55
56
|
export interface Context<U extends UserContext = UserContext> extends TypedEventEmitter<ContextEventMap, ContextEmitEventMap> {
|
|
57
|
+
id: string;
|
|
58
|
+
parentId?: string;
|
|
56
59
|
model?: ChatModel;
|
|
57
60
|
skills?: Agent[];
|
|
58
61
|
usage: ContextUsage;
|
package/lib/cjs/aigne/context.js
CHANGED
|
@@ -12,6 +12,7 @@ const agent_js_1 = require("../agents/agent.js");
|
|
|
12
12
|
const types_js_1 = require("../agents/types.js");
|
|
13
13
|
const user_agent_js_1 = require("../agents/user-agent.js");
|
|
14
14
|
const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
|
|
15
|
+
const event_stream_js_1 = require("../utils/event-stream.js");
|
|
15
16
|
const promise_js_1 = require("../utils/promise.js");
|
|
16
17
|
const stream_utils_js_1 = require("../utils/stream-utils.js");
|
|
17
18
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
@@ -96,11 +97,9 @@ class AIGNEContext {
|
|
|
96
97
|
return output;
|
|
97
98
|
}
|
|
98
99
|
const activeAgentPromise = (0, promise_js_1.promiseWithResolvers)();
|
|
99
|
-
const stream = (0, stream_utils_js_1.onAgentResponseStreamEnd)((0, stream_utils_js_1.asyncGeneratorToReadableStream)(response),
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
processChunk(chunk) {
|
|
103
|
-
if (chunk.delta.json) {
|
|
100
|
+
const stream = (0, stream_utils_js_1.onAgentResponseStreamEnd)((0, stream_utils_js_1.asyncGeneratorToReadableStream)(response), {
|
|
101
|
+
onChunk(chunk) {
|
|
102
|
+
if ((0, agent_js_1.isAgentResponseDelta)(chunk) && chunk.delta.json) {
|
|
104
103
|
return {
|
|
105
104
|
...chunk,
|
|
106
105
|
delta: {
|
|
@@ -109,13 +108,18 @@ class AIGNEContext {
|
|
|
109
108
|
},
|
|
110
109
|
};
|
|
111
110
|
}
|
|
112
|
-
|
|
111
|
+
},
|
|
112
|
+
onResult({ __activeAgent__: activeAgent }) {
|
|
113
|
+
activeAgentPromise.resolve(activeAgent);
|
|
113
114
|
},
|
|
114
115
|
});
|
|
116
|
+
const finalStream = !options.returnProgressChunks
|
|
117
|
+
? stream
|
|
118
|
+
: (0, stream_utils_js_1.mergeReadableStreams)(stream, new event_stream_js_1.AgentResponseProgressStream(newContext));
|
|
115
119
|
if (options.returnActiveAgent) {
|
|
116
|
-
return [
|
|
120
|
+
return [finalStream, activeAgentPromise.promise];
|
|
117
121
|
}
|
|
118
|
-
return
|
|
122
|
+
return finalStream;
|
|
119
123
|
});
|
|
120
124
|
});
|
|
121
125
|
publish = ((topic, payload, options) => {
|
|
@@ -171,7 +175,6 @@ class AIGNEContextShared {
|
|
|
171
175
|
this.memories = overrides?.memories ?? [];
|
|
172
176
|
}
|
|
173
177
|
messageQueue;
|
|
174
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
175
178
|
events = new strict_event_emitter_1.Emitter();
|
|
176
179
|
get model() {
|
|
177
180
|
return this.parent?.model;
|
|
@@ -218,11 +221,13 @@ class AIGNEContextShared {
|
|
|
218
221
|
}
|
|
219
222
|
const stream = await activeAgent.invoke(input, { ...options, context, streaming: true });
|
|
220
223
|
for await (const value of stream) {
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
+
if ((0, agent_js_1.isAgentResponseDelta)(value)) {
|
|
225
|
+
if (value.delta.json) {
|
|
226
|
+
value.delta.json = omitExistsProperties(result, value.delta.json);
|
|
227
|
+
Object.assign(result, value.delta.json);
|
|
228
|
+
}
|
|
229
|
+
delete value.delta.json?.[types_js_1.transferAgentOutputKey];
|
|
224
230
|
}
|
|
225
|
-
delete value.delta.json?.[types_js_1.transferAgentOutputKey];
|
|
226
231
|
if ((0, agent_js_1.isEmptyChunk)(value))
|
|
227
232
|
continue;
|
|
228
233
|
yield value;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
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,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AgentResponseStreamSSE = exports.AgentResponseStreamParser = exports.EventStreamParser = void 0;
|
|
3
|
+
exports.AgentResponseProgressStream = exports.AgentResponseStreamSSE = exports.AgentResponseStreamParser = exports.EventStreamParser = void 0;
|
|
4
4
|
const eventsource_parser_1 = require("eventsource-parser");
|
|
5
5
|
const immer_1 = require("immer");
|
|
6
|
+
const agent_js_1 = require("../agents/agent.js");
|
|
6
7
|
const type_utils_js_1 = require("./type-utils.js");
|
|
7
8
|
class EventStreamParser extends TransformStream {
|
|
8
9
|
constructor() {
|
|
@@ -15,11 +16,16 @@ class EventStreamParser extends TransformStream {
|
|
|
15
16
|
controller.enqueue(new Error(`Parse response chunk json error: ${e.message} ${event.data}`));
|
|
16
17
|
});
|
|
17
18
|
if (json) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
switch (event.event) {
|
|
20
|
+
case "error":
|
|
21
|
+
controller.enqueue(new Error(json.message));
|
|
22
|
+
break;
|
|
23
|
+
default: {
|
|
24
|
+
if (!event.event)
|
|
25
|
+
controller.enqueue(json);
|
|
26
|
+
else
|
|
27
|
+
console.warn(`Unknown event type: ${event.event}`, event.data);
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
},
|
|
@@ -42,25 +48,35 @@ class AgentResponseStreamParser extends TransformStream {
|
|
|
42
48
|
controller.terminate();
|
|
43
49
|
return;
|
|
44
50
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
if ((0, agent_js_1.isAgentResponseDelta)(chunk)) {
|
|
52
|
+
this.json = (0, immer_1.produce)(this.json, (draft) => {
|
|
53
|
+
if (chunk.delta.json)
|
|
54
|
+
Object.assign(draft, chunk.delta.json);
|
|
55
|
+
if (chunk.delta.text) {
|
|
56
|
+
for (const [key, text] of Object.entries(chunk.delta.text)) {
|
|
57
|
+
const original = draft[key];
|
|
58
|
+
const t = (original || "") + (text || "");
|
|
59
|
+
if (t)
|
|
60
|
+
Object.assign(draft, { [key]: t });
|
|
61
|
+
}
|
|
54
62
|
}
|
|
63
|
+
});
|
|
64
|
+
controller.enqueue({
|
|
65
|
+
...chunk,
|
|
66
|
+
delta: {
|
|
67
|
+
...chunk.delta,
|
|
68
|
+
json: this.json,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else if ((0, agent_js_1.isAgentResponseProgress)(chunk)) {
|
|
73
|
+
if (chunk.progress.event === "agentFailed") {
|
|
74
|
+
const { name, message } = chunk.progress.error;
|
|
75
|
+
chunk.progress.error = new Error(message);
|
|
76
|
+
chunk.progress.error.name = name;
|
|
55
77
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
...chunk,
|
|
59
|
-
delta: {
|
|
60
|
-
...chunk.delta,
|
|
61
|
-
json: this.json,
|
|
62
|
-
},
|
|
63
|
-
});
|
|
78
|
+
controller.enqueue(chunk);
|
|
79
|
+
}
|
|
64
80
|
},
|
|
65
81
|
});
|
|
66
82
|
}
|
|
@@ -78,6 +94,14 @@ class AgentResponseStreamSSE extends ReadableStream {
|
|
|
78
94
|
controller.close();
|
|
79
95
|
return;
|
|
80
96
|
}
|
|
97
|
+
if ((0, agent_js_1.isAgentResponseProgress)(value)) {
|
|
98
|
+
if (value.progress.event === "agentFailed") {
|
|
99
|
+
value.progress.error = {
|
|
100
|
+
name: value.progress.error.name,
|
|
101
|
+
message: value.progress.error.message,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
81
105
|
controller.enqueue(`data: ${JSON.stringify(value)}\n\n`);
|
|
82
106
|
}
|
|
83
107
|
catch (error) {
|
|
@@ -89,3 +113,44 @@ class AgentResponseStreamSSE extends ReadableStream {
|
|
|
89
113
|
}
|
|
90
114
|
}
|
|
91
115
|
exports.AgentResponseStreamSSE = AgentResponseStreamSSE;
|
|
116
|
+
class AgentResponseProgressStream extends ReadableStream {
|
|
117
|
+
constructor(context) {
|
|
118
|
+
super({
|
|
119
|
+
async start(controller) {
|
|
120
|
+
const writeEvent = (eventName, event) => {
|
|
121
|
+
const progress = {
|
|
122
|
+
...event,
|
|
123
|
+
event: eventName,
|
|
124
|
+
agent: { name: event.agent.name },
|
|
125
|
+
};
|
|
126
|
+
controller.enqueue({ progress });
|
|
127
|
+
};
|
|
128
|
+
const close = () => {
|
|
129
|
+
context.off("agentStarted", onAgentStarted);
|
|
130
|
+
context.off("agentSucceed", onAgentSucceed);
|
|
131
|
+
context.off("agentFailed", onAgentFailed);
|
|
132
|
+
controller.close();
|
|
133
|
+
};
|
|
134
|
+
const onAgentStarted = (event) => {
|
|
135
|
+
writeEvent("agentStarted", event);
|
|
136
|
+
};
|
|
137
|
+
const onAgentSucceed = (event) => {
|
|
138
|
+
writeEvent("agentSucceed", event);
|
|
139
|
+
if (event.contextId === context.id) {
|
|
140
|
+
close();
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const onAgentFailed = (event) => {
|
|
144
|
+
writeEvent("agentFailed", event);
|
|
145
|
+
if (event.contextId === context.id) {
|
|
146
|
+
close();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
context.on("agentStarted", onAgentStarted);
|
|
150
|
+
context.on("agentSucceed", onAgentSucceed);
|
|
151
|
+
context.on("agentFailed", onAgentFailed);
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.AgentResponseProgressStream = AgentResponseProgressStream;
|
|
@@ -6,10 +6,11 @@ export declare function objectToAgentResponseStream<T extends Message>(json: T):
|
|
|
6
6
|
export declare function mergeAgentResponseChunk<T extends Message>(output: T, chunk: AgentResponseChunk<T>): T;
|
|
7
7
|
export declare function agentResponseStreamToObject<T extends Message>(stream: AgentResponseStream<T> | AgentProcessAsyncGenerator<T>): Promise<T>;
|
|
8
8
|
export declare function asyncGeneratorToReadableStream<T extends Message>(generator: AgentProcessAsyncGenerator<T>): AgentResponseStream<T>;
|
|
9
|
-
export declare function onAgentResponseStreamEnd<T extends Message>(stream: AgentResponseStream<T>,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
export declare function onAgentResponseStreamEnd<T extends Message>(stream: AgentResponseStream<T>, options?: {
|
|
10
|
+
onChunk?: (chunk: AgentResponseChunk<T>) => PromiseOrValue<AgentResponseChunk<T> | undefined | void>;
|
|
11
|
+
onResult?: (result: T) => PromiseOrValue<Partial<T> | undefined | void>;
|
|
12
|
+
onError?: (error: Error) => PromiseOrValue<Error>;
|
|
13
|
+
}): AgentResponseStream<T>;
|
|
13
14
|
export declare function isAsyncGenerator<T extends AsyncGenerator>(value: AsyncGenerator | unknown): value is T;
|
|
14
15
|
export declare function arrayToAgentProcessAsyncGenerator<T extends Message>(chunks: (AgentResponseChunk<T> | Error)[], result?: Partial<T>): AgentProcessAsyncGenerator<T>;
|
|
15
16
|
export declare function arrayToReadableStream<T>(chunks: (T | Error)[]): ReadableStream<T>;
|
|
@@ -17,8 +18,10 @@ export declare function readableStreamToArray<T>(stream: ReadableStream<T>, opti
|
|
|
17
18
|
catchError: true;
|
|
18
19
|
}): Promise<(T | Error)[]>;
|
|
19
20
|
export declare function readableStreamToArray<T>(stream: ReadableStream<T>, options?: {
|
|
20
|
-
catchError?:
|
|
21
|
+
catchError?: boolean;
|
|
21
22
|
}): Promise<T[]>;
|
|
22
23
|
export declare function stringToAgentResponseStream(str: string, key?: "text" | typeof MESSAGE_KEY | string): AgentResponseStream<Message>;
|
|
23
24
|
export declare function toReadableStream(stream: NodeJS.ReadStream): ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
24
25
|
export declare function readAllString(stream: NodeJS.ReadStream | ReadableStream): Promise<string>;
|
|
26
|
+
export declare function mergeReadableStreams<T1, T2>(s1: ReadableStream<T1>, s2: ReadableStream<T2>): ReadableStream<T1 | T2>;
|
|
27
|
+
export declare function mergeReadableStreams(...streams: ReadableStream<any>[]): ReadableStream<any>;
|
|
@@ -15,6 +15,7 @@ exports.readableStreamToArray = readableStreamToArray;
|
|
|
15
15
|
exports.stringToAgentResponseStream = stringToAgentResponseStream;
|
|
16
16
|
exports.toReadableStream = toReadableStream;
|
|
17
17
|
exports.readAllString = readAllString;
|
|
18
|
+
exports.mergeReadableStreams = mergeReadableStreams;
|
|
18
19
|
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
|
19
20
|
const agent_js_1 = require("../agents/agent.js");
|
|
20
21
|
const type_utils_js_1 = require("./type-utils.js");
|
|
@@ -28,16 +29,18 @@ function objectToAgentResponseStream(json) {
|
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
function mergeAgentResponseChunk(output, chunk) {
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if ((0, agent_js_1.isAgentResponseDelta)(chunk)) {
|
|
33
|
+
if (chunk.delta.text) {
|
|
34
|
+
for (const [key, text] of Object.entries(chunk.delta.text)) {
|
|
35
|
+
const original = output[key];
|
|
36
|
+
const t = (original || "") + (text || "");
|
|
37
|
+
if (t)
|
|
38
|
+
Object.assign(output, { [key]: t });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (chunk.delta.json) {
|
|
42
|
+
Object.assign(output, (0, type_utils_js_1.omitBy)(chunk.delta.json, (v) => v === undefined));
|
|
37
43
|
}
|
|
38
|
-
}
|
|
39
|
-
if (chunk.delta.json) {
|
|
40
|
-
Object.assign(output, (0, type_utils_js_1.omitBy)(chunk.delta.json, (v) => v === undefined));
|
|
41
44
|
}
|
|
42
45
|
return output;
|
|
43
46
|
}
|
|
@@ -88,7 +91,7 @@ function asyncGeneratorToReadableStream(generator) {
|
|
|
88
91
|
},
|
|
89
92
|
});
|
|
90
93
|
}
|
|
91
|
-
function onAgentResponseStreamEnd(stream,
|
|
94
|
+
function onAgentResponseStreamEnd(stream, options) {
|
|
92
95
|
const json = {};
|
|
93
96
|
const reader = stream.getReader();
|
|
94
97
|
return new ReadableStream({
|
|
@@ -97,18 +100,17 @@ function onAgentResponseStreamEnd(stream, callback, options) {
|
|
|
97
100
|
while (true) {
|
|
98
101
|
const { value, done } = await reader.read();
|
|
99
102
|
if (done) {
|
|
100
|
-
const result = await
|
|
103
|
+
const result = (await options?.onResult?.(json)) ?? json;
|
|
101
104
|
if (result && !(0, fast_deep_equal_1.default)(result, json)) {
|
|
102
105
|
let chunk = { delta: { json: result } };
|
|
103
|
-
|
|
104
|
-
chunk = options.processChunk(chunk);
|
|
106
|
+
chunk = (await options?.onChunk?.(chunk)) ?? chunk;
|
|
105
107
|
controller.enqueue(chunk);
|
|
106
108
|
}
|
|
107
109
|
controller.close();
|
|
108
110
|
return;
|
|
109
111
|
}
|
|
110
112
|
mergeAgentResponseChunk(json, value);
|
|
111
|
-
const chunk = options?.
|
|
113
|
+
const chunk = (await options?.onChunk?.(value)) ?? value;
|
|
112
114
|
if (!(0, agent_js_1.isEmptyChunk)(chunk)) {
|
|
113
115
|
controller.enqueue(chunk);
|
|
114
116
|
break;
|
|
@@ -116,7 +118,7 @@ function onAgentResponseStreamEnd(stream, callback, options) {
|
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
catch (error) {
|
|
119
|
-
controller.error((await options?.
|
|
121
|
+
controller.error((await options?.onError?.(error)) ?? error);
|
|
120
122
|
}
|
|
121
123
|
},
|
|
122
124
|
});
|
|
@@ -197,3 +199,34 @@ function toReadableStream(stream) {
|
|
|
197
199
|
async function readAllString(stream) {
|
|
198
200
|
return (await readableStreamToArray((stream instanceof ReadableStream ? stream : toReadableStream(stream)).pipeThrough(new TextDecoderStream()))).join("");
|
|
199
201
|
}
|
|
202
|
+
function mergeReadableStreams(...streams) {
|
|
203
|
+
let readers;
|
|
204
|
+
return new ReadableStream({
|
|
205
|
+
async pull(controller) {
|
|
206
|
+
try {
|
|
207
|
+
readers ??= streams.map((s) => ({ reader: s.getReader(), data: [] }));
|
|
208
|
+
while (readers.length) {
|
|
209
|
+
const chunk = await Promise.race(readers.map((i) => {
|
|
210
|
+
i.reading ??= i.reader.read().then((result) => ({ result, item: i }));
|
|
211
|
+
return i.reading;
|
|
212
|
+
}));
|
|
213
|
+
if (chunk.result.value) {
|
|
214
|
+
controller.enqueue(chunk.result.value);
|
|
215
|
+
chunk.item.reading = undefined;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (chunk.result.done) {
|
|
219
|
+
readers = readers.filter((i) => i !== chunk.item);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
controller.close();
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
controller.error(error);
|
|
226
|
+
if (readers)
|
|
227
|
+
for (const item of readers)
|
|
228
|
+
item.reader.releaseLock();
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
}
|
|
@@ -15,6 +15,7 @@ export declare function isNotEmpty<T>(arr: T[]): arr is [T, ...T[]];
|
|
|
15
15
|
export declare function duplicates<T>(arr: T[], key?: (item: T) => unknown): T[];
|
|
16
16
|
export declare function remove<T>(arr: T[], remove: T[] | ((item: T) => boolean)): T[];
|
|
17
17
|
export declare function unique<T>(arr: T[], key?: (item: T) => unknown): T[];
|
|
18
|
+
export declare function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, ...keys: (K | K[])[]): Omit<T, K>;
|
|
18
19
|
export declare function omitBy<T extends Record<string, unknown>, K extends keyof T>(obj: T, predicate: (value: T[K], key: K) => boolean): Partial<T>;
|
|
19
20
|
export declare function orArrayToArray<T>(value?: T | T[]): T[];
|
|
20
21
|
export declare function createAccessorArray<T>(array: T[], accessor: (array: T[], name: string) => T | undefined): T[] & {
|
|
@@ -8,6 +8,7 @@ exports.isNotEmpty = isNotEmpty;
|
|
|
8
8
|
exports.duplicates = duplicates;
|
|
9
9
|
exports.remove = remove;
|
|
10
10
|
exports.unique = unique;
|
|
11
|
+
exports.omit = omit;
|
|
11
12
|
exports.omitBy = omitBy;
|
|
12
13
|
exports.orArrayToArray = orArrayToArray;
|
|
13
14
|
exports.createAccessorArray = createAccessorArray;
|
|
@@ -73,6 +74,10 @@ function unique(arr, key = (item) => item) {
|
|
|
73
74
|
return true;
|
|
74
75
|
});
|
|
75
76
|
}
|
|
77
|
+
function omit(obj, ...keys) {
|
|
78
|
+
const flattenedKeys = new Set(keys.flat());
|
|
79
|
+
return Object.fromEntries(Object.entries(obj).filter(([key]) => !flattenedKeys.has(key)));
|
|
80
|
+
}
|
|
76
81
|
function omitBy(obj, predicate) {
|
|
77
82
|
return Object.fromEntries(Object.entries(obj).filter(([key, value]) => {
|
|
78
83
|
const k = key;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
2
2
|
import { ZodObject, type ZodType } from "zod";
|
|
3
|
-
import type { Context, UserContext } from "../aigne/context.js";
|
|
3
|
+
import type { AgentEvent, Context, UserContext } from "../aigne/context.js";
|
|
4
4
|
import type { MessagePayload } from "../aigne/message-queue.js";
|
|
5
5
|
import type { Memory, MemoryAgent } from "../memory/memory.js";
|
|
6
6
|
import type { MemoryRecorderInput } from "../memory/recorder.js";
|
|
@@ -594,7 +594,7 @@ export type AgentResponseStream<T> = ReadableStream<AgentResponseChunk<T>>;
|
|
|
594
594
|
*
|
|
595
595
|
* @template T Response data type
|
|
596
596
|
*/
|
|
597
|
-
export type AgentResponseChunk<T> = AgentResponseDelta<T
|
|
597
|
+
export type AgentResponseChunk<T> = AgentResponseDelta<T> | AgentResponseProgress;
|
|
598
598
|
/**
|
|
599
599
|
* Check if a response chunk is empty
|
|
600
600
|
*
|
|
@@ -622,6 +622,24 @@ export interface AgentResponseDelta<T> {
|
|
|
622
622
|
json?: Partial<T> | TransferAgentOutput;
|
|
623
623
|
};
|
|
624
624
|
}
|
|
625
|
+
export declare function isAgentResponseDelta<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseDelta<T>;
|
|
626
|
+
export interface AgentResponseProgress {
|
|
627
|
+
progress: ({
|
|
628
|
+
event: "agentStarted";
|
|
629
|
+
input: Message;
|
|
630
|
+
} | {
|
|
631
|
+
event: "agentSucceed";
|
|
632
|
+
output: Message;
|
|
633
|
+
} | {
|
|
634
|
+
event: "agentFailed";
|
|
635
|
+
error: Error;
|
|
636
|
+
}) & Omit<AgentEvent, "agent"> & {
|
|
637
|
+
agent: {
|
|
638
|
+
name: string;
|
|
639
|
+
};
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
export declare function isAgentResponseProgress<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseProgress;
|
|
625
643
|
/**
|
|
626
644
|
* Creates a text delta for streaming responses
|
|
627
645
|
*
|
|
@@ -41,6 +41,7 @@ export type ContextEmitEventMap = {
|
|
|
41
41
|
*/
|
|
42
42
|
export interface InvokeOptions<U extends UserContext = UserContext> extends Partial<Omit<AgentInvokeOptions<U>, "context">> {
|
|
43
43
|
returnActiveAgent?: boolean;
|
|
44
|
+
returnProgressChunks?: boolean;
|
|
44
45
|
disableTransfer?: boolean;
|
|
45
46
|
sourceAgent?: Agent;
|
|
46
47
|
}
|
|
@@ -53,6 +54,8 @@ export interface UserContext extends Record<string, unknown> {
|
|
|
53
54
|
* @hidden
|
|
54
55
|
*/
|
|
55
56
|
export interface Context<U extends UserContext = UserContext> extends TypedEventEmitter<ContextEventMap, ContextEmitEventMap> {
|
|
57
|
+
id: string;
|
|
58
|
+
parentId?: string;
|
|
56
59
|
model?: ChatModel;
|
|
57
60
|
skills?: Agent[];
|
|
58
61
|
usage: ContextUsage;
|