@aigne/core 1.34.0 → 1.36.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 +14 -0
- package/lib/cjs/agents/agent.d.ts +71 -10
- package/lib/cjs/agents/agent.js +73 -28
- package/lib/cjs/agents/ai-agent.js +6 -3
- package/lib/cjs/agents/team-agent.js +3 -13
- package/lib/cjs/aigne/context.d.ts +1 -0
- package/lib/cjs/aigne/context.js +25 -10
- package/lib/cjs/loader/agent-js.d.ts +2 -11
- package/lib/cjs/loader/agent-js.js +4 -8
- package/lib/cjs/loader/agent-yaml.d.ts +18 -2
- package/lib/cjs/loader/agent-yaml.js +32 -13
- package/lib/cjs/loader/index.d.ts +2 -2
- package/lib/cjs/loader/index.js +48 -15
- package/lib/cjs/loader/schema.d.ts +10 -0
- package/lib/cjs/loader/schema.js +17 -1
- package/lib/cjs/utils/type-utils.d.ts +1 -1
- package/lib/cjs/utils/type-utils.js +2 -4
- package/lib/dts/agents/agent.d.ts +71 -10
- package/lib/dts/aigne/context.d.ts +1 -0
- package/lib/dts/loader/agent-js.d.ts +2 -11
- package/lib/dts/loader/agent-yaml.d.ts +18 -2
- package/lib/dts/loader/index.d.ts +2 -2
- package/lib/dts/loader/schema.d.ts +10 -0
- package/lib/dts/utils/type-utils.d.ts +1 -1
- package/lib/esm/agents/agent.d.ts +71 -10
- package/lib/esm/agents/agent.js +73 -28
- package/lib/esm/agents/ai-agent.js +6 -3
- package/lib/esm/agents/team-agent.js +3 -13
- package/lib/esm/aigne/context.d.ts +1 -0
- package/lib/esm/aigne/context.js +25 -10
- package/lib/esm/loader/agent-js.d.ts +2 -11
- package/lib/esm/loader/agent-js.js +5 -6
- package/lib/esm/loader/agent-yaml.d.ts +18 -2
- package/lib/esm/loader/agent-yaml.js +33 -11
- package/lib/esm/loader/index.d.ts +2 -2
- package/lib/esm/loader/index.js +49 -16
- package/lib/esm/loader/schema.d.ts +10 -0
- package/lib/esm/loader/schema.js +12 -0
- package/lib/esm/utils/type-utils.d.ts +1 -1
- package/lib/esm/utils/type-utils.js +2 -4
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,20 @@
|
|
|
12
12
|
* dependencies
|
|
13
13
|
* @aigne/observability bumped to 0.1.0
|
|
14
14
|
|
|
15
|
+
## [1.36.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.35.0...core-v1.36.0) (2025-07-17)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **core:** support define hooks for agent in yaml ([#260](https://github.com/AIGNE-io/aigne-framework/issues/260)) ([c388e82](https://github.com/AIGNE-io/aigne-framework/commit/c388e8216134271af4d9c7def70862ea3c354c7f))
|
|
21
|
+
|
|
22
|
+
## [1.35.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.34.0...core-v1.35.0) (2025-07-17)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* **core:** support custom default input value for agent ([#258](https://github.com/AIGNE-io/aigne-framework/issues/258)) ([352ac70](https://github.com/AIGNE-io/aigne-framework/commit/352ac70400fb7e28cc36c4f6dc9c591b0d64e546))
|
|
28
|
+
|
|
15
29
|
## [1.34.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.33.2...core-v1.34.0) (2025-07-15)
|
|
16
30
|
|
|
17
31
|
|
|
@@ -10,6 +10,7 @@ import { type Nullish, type PromiseOrValue, type XOr } from "../utils/type-utils
|
|
|
10
10
|
import type { GuideRailAgent, GuideRailAgentOutput } from "./guide-rail-agent.js";
|
|
11
11
|
import { type TransferAgentOutput } from "./types.js";
|
|
12
12
|
export * from "./types.js";
|
|
13
|
+
export declare const DEFAULT_INPUT_ACTION_GET = "$get";
|
|
13
14
|
/**
|
|
14
15
|
* Basic message type that can contain any key-value pairs
|
|
15
16
|
*/
|
|
@@ -72,6 +73,11 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
72
73
|
* Used to validate that input messages conform to the expected format
|
|
73
74
|
*/
|
|
74
75
|
inputSchema?: AgentInputOutputSchema<I>;
|
|
76
|
+
/**
|
|
77
|
+
* Default input message for the agent, it can be used to provide partial input
|
|
78
|
+
* or default values for the agent's input schema.
|
|
79
|
+
*/
|
|
80
|
+
defaultInput?: Agent<I, O>["defaultInput"];
|
|
75
81
|
/**
|
|
76
82
|
* Zod schema defining the output message structure
|
|
77
83
|
*
|
|
@@ -106,7 +112,7 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
106
112
|
* Maximum number of memory items to retrieve
|
|
107
113
|
*/
|
|
108
114
|
maxRetrieveMemoryCount?: number;
|
|
109
|
-
hooks?: AgentHooks<I, O
|
|
115
|
+
hooks?: AgentHooks<I, O> | AgentHooks<I, O>[];
|
|
110
116
|
}
|
|
111
117
|
export declare const agentOptionsSchema: ZodObject<{
|
|
112
118
|
[key in keyof AgentOptions]: ZodType<AgentOptions[key]>;
|
|
@@ -137,6 +143,10 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
|
|
|
137
143
|
* and returns the final JSON result
|
|
138
144
|
*/
|
|
139
145
|
streaming?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Optional hooks for agent invocation
|
|
148
|
+
*/
|
|
149
|
+
hooks?: AgentHooks<any, any>;
|
|
140
150
|
}
|
|
141
151
|
/**
|
|
142
152
|
* Agent is the base class for all agents.
|
|
@@ -190,7 +200,7 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
190
200
|
* Here's an example of using hooks:
|
|
191
201
|
* {@includeCode ../../test/agents/agent.test.ts#example-agent-hooks}
|
|
192
202
|
*/
|
|
193
|
-
readonly hooks: AgentHooks<I, O
|
|
203
|
+
readonly hooks: AgentHooks<I, O>[];
|
|
194
204
|
/**
|
|
195
205
|
* List of GuideRail agents applied to this agent
|
|
196
206
|
*
|
|
@@ -232,6 +242,11 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
232
242
|
*/
|
|
233
243
|
readonly description?: string;
|
|
234
244
|
private readonly _inputSchema?;
|
|
245
|
+
defaultInput?: Partial<{
|
|
246
|
+
[key in keyof I]: {
|
|
247
|
+
[DEFAULT_INPUT_ACTION_GET]: string;
|
|
248
|
+
} | I[key];
|
|
249
|
+
}>;
|
|
235
250
|
private readonly _outputSchema?;
|
|
236
251
|
/**
|
|
237
252
|
* Get the input data schema for this agent
|
|
@@ -372,6 +387,8 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
372
387
|
* @returns Agent response (streaming or regular)
|
|
373
388
|
*/
|
|
374
389
|
invoke(input: I & Message, options?: Partial<AgentInvokeOptions>): Promise<AgentResponse<O>>;
|
|
390
|
+
private callHooks;
|
|
391
|
+
private mergeDefaultInput;
|
|
375
392
|
protected invokeSkill<I extends Message, O extends Message>(skill: Agent<I, O>, input: I & Message, options: AgentInvokeOptions): Promise<O>;
|
|
376
393
|
/**
|
|
377
394
|
* Process agent output
|
|
@@ -517,11 +534,15 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
|
|
|
517
534
|
*
|
|
518
535
|
* @param event Object containing the input message
|
|
519
536
|
*/
|
|
520
|
-
onStart?: (event: {
|
|
537
|
+
onStart?: ((event: {
|
|
521
538
|
context: Context;
|
|
522
539
|
input: I;
|
|
523
540
|
}) => PromiseOrValue<void | {
|
|
524
541
|
input?: I;
|
|
542
|
+
}>) | Agent<{
|
|
543
|
+
input: I;
|
|
544
|
+
}, {
|
|
545
|
+
input?: I;
|
|
525
546
|
}>;
|
|
526
547
|
/**
|
|
527
548
|
* Called when agent processing completes or fails
|
|
@@ -532,13 +553,39 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
|
|
|
532
553
|
*
|
|
533
554
|
* @param event Object containing the input message and either output or error
|
|
534
555
|
*/
|
|
535
|
-
onEnd?: (event: XOr<{
|
|
556
|
+
onEnd?: ((event: XOr<{
|
|
536
557
|
context: Context;
|
|
537
558
|
input: I;
|
|
538
559
|
output: O;
|
|
539
560
|
error: Error;
|
|
540
561
|
}, "output", "error">) => PromiseOrValue<void | {
|
|
541
562
|
output?: O;
|
|
563
|
+
}>) | Agent<XOr<{
|
|
564
|
+
input: I;
|
|
565
|
+
output: O;
|
|
566
|
+
error: Error;
|
|
567
|
+
}, "output", "error">, {
|
|
568
|
+
output?: O;
|
|
569
|
+
}>;
|
|
570
|
+
onSuccess?: ((event: {
|
|
571
|
+
context: Context;
|
|
572
|
+
input: I;
|
|
573
|
+
output: O;
|
|
574
|
+
}) => PromiseOrValue<void | {
|
|
575
|
+
output?: O;
|
|
576
|
+
}>) | Agent<{
|
|
577
|
+
input: I;
|
|
578
|
+
output: O;
|
|
579
|
+
}, {
|
|
580
|
+
output?: O;
|
|
581
|
+
}>;
|
|
582
|
+
onError?: ((event: {
|
|
583
|
+
context: Context;
|
|
584
|
+
input: I;
|
|
585
|
+
error: Error;
|
|
586
|
+
}) => void) | Agent<{
|
|
587
|
+
input: I;
|
|
588
|
+
error: Error;
|
|
542
589
|
}>;
|
|
543
590
|
/**
|
|
544
591
|
* Called before a skill (sub-agent) is invoked
|
|
@@ -548,11 +595,14 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
|
|
|
548
595
|
*
|
|
549
596
|
* @param event Object containing the skill being used and input message
|
|
550
597
|
*/
|
|
551
|
-
onSkillStart?: (event: {
|
|
598
|
+
onSkillStart?: ((event: {
|
|
552
599
|
context: Context;
|
|
553
600
|
skill: Agent;
|
|
554
601
|
input: Message;
|
|
555
|
-
}) => PromiseOrValue<void
|
|
602
|
+
}) => PromiseOrValue<void>) | Agent<{
|
|
603
|
+
skill: Agent;
|
|
604
|
+
input: Message;
|
|
605
|
+
}>;
|
|
556
606
|
/**
|
|
557
607
|
* Called after a skill (sub-agent) completes or fails
|
|
558
608
|
*
|
|
@@ -562,13 +612,18 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
|
|
|
562
612
|
*
|
|
563
613
|
* @param event Object containing the skill used, input message, and either output or error
|
|
564
614
|
*/
|
|
565
|
-
onSkillEnd?: (event: XOr<{
|
|
615
|
+
onSkillEnd?: ((event: XOr<{
|
|
566
616
|
context: Context;
|
|
567
617
|
skill: Agent;
|
|
568
618
|
input: Message;
|
|
569
619
|
output: Message;
|
|
570
620
|
error: Error;
|
|
571
|
-
}, "output", "error">) => PromiseOrValue<void
|
|
621
|
+
}, "output", "error">) => PromiseOrValue<void>) | Agent<XOr<{
|
|
622
|
+
skill: Agent;
|
|
623
|
+
input: Message;
|
|
624
|
+
output: Message;
|
|
625
|
+
error: Error;
|
|
626
|
+
}, "output", "error">>;
|
|
572
627
|
/**
|
|
573
628
|
* Called when an agent hands off processing to another agent
|
|
574
629
|
*
|
|
@@ -578,13 +633,19 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
|
|
|
578
633
|
*
|
|
579
634
|
* @param event Object containing the source agent, target agent, and input message
|
|
580
635
|
*/
|
|
581
|
-
onHandoff?: (event: {
|
|
636
|
+
onHandoff?: ((event: {
|
|
582
637
|
context: Context;
|
|
583
638
|
source: Agent;
|
|
584
639
|
target: Agent;
|
|
585
640
|
input: I;
|
|
586
|
-
}) => PromiseOrValue<void
|
|
641
|
+
}) => PromiseOrValue<void>) | Agent<{
|
|
642
|
+
source: Agent;
|
|
643
|
+
target: Agent;
|
|
644
|
+
input: I;
|
|
645
|
+
}>;
|
|
587
646
|
}
|
|
647
|
+
export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context"> : never;
|
|
648
|
+
export type AgentHookOutput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (...args: any[]) => any ? Exclude<Awaited<ReturnType<Hook>>, void> | undefined : never;
|
|
588
649
|
/**
|
|
589
650
|
* Response type for an agent, can be:
|
|
590
651
|
* - Direct response object
|
package/lib/cjs/agents/agent.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.FunctionAgent = exports.Agent = exports.agentOptionsSchema = void 0;
|
|
39
|
+
exports.FunctionAgent = exports.Agent = exports.agentOptionsSchema = exports.DEFAULT_INPUT_ACTION_GET = void 0;
|
|
40
40
|
exports.isEmptyChunk = isEmptyChunk;
|
|
41
41
|
exports.isAgentResponseDelta = isAgentResponseDelta;
|
|
42
42
|
exports.isAgentResponseProgress = isAgentResponseProgress;
|
|
@@ -50,6 +50,14 @@ const stream_utils_js_1 = require("../utils/stream-utils.js");
|
|
|
50
50
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
51
51
|
const types_js_1 = require("./types.js");
|
|
52
52
|
__exportStar(require("./types.js"), exports);
|
|
53
|
+
exports.DEFAULT_INPUT_ACTION_GET = "$get";
|
|
54
|
+
const hooksSchema = zod_1.z.object({
|
|
55
|
+
onStart: zod_1.z.custom().optional(),
|
|
56
|
+
onEnd: zod_1.z.custom().optional(),
|
|
57
|
+
onSkillStart: zod_1.z.custom().optional(),
|
|
58
|
+
onSkillEnd: zod_1.z.custom().optional(),
|
|
59
|
+
onHandoff: zod_1.z.custom().optional(),
|
|
60
|
+
});
|
|
53
61
|
exports.agentOptionsSchema = zod_1.z.object({
|
|
54
62
|
subscribeTopic: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]).optional(),
|
|
55
63
|
publishTopic: zod_1.z
|
|
@@ -58,21 +66,14 @@ exports.agentOptionsSchema = zod_1.z.object({
|
|
|
58
66
|
name: zod_1.z.string().optional(),
|
|
59
67
|
description: zod_1.z.string().optional(),
|
|
60
68
|
inputSchema: zod_1.z.custom().optional(),
|
|
69
|
+
defaultInput: zod_1.z.record(zod_1.z.any()).optional(),
|
|
61
70
|
outputSchema: zod_1.z.custom().optional(),
|
|
62
71
|
includeInputInOutput: zod_1.z.boolean().optional(),
|
|
63
72
|
skills: zod_1.z.array(zod_1.z.union([zod_1.z.custom(), zod_1.z.custom()])).optional(),
|
|
64
73
|
disableEvents: zod_1.z.boolean().optional(),
|
|
65
74
|
memory: zod_1.z.union([zod_1.z.custom(), zod_1.z.array(zod_1.z.custom())]).optional(),
|
|
66
75
|
maxRetrieveMemoryCount: zod_1.z.number().optional(),
|
|
67
|
-
hooks: zod_1.z
|
|
68
|
-
.object({
|
|
69
|
-
onStart: zod_1.z.custom().optional(),
|
|
70
|
-
onEnd: zod_1.z.custom().optional(),
|
|
71
|
-
onSkillStart: zod_1.z.custom().optional(),
|
|
72
|
-
onSkillEnd: zod_1.z.custom().optional(),
|
|
73
|
-
onHandoff: zod_1.z.custom().optional(),
|
|
74
|
-
})
|
|
75
|
-
.optional(),
|
|
76
|
+
hooks: zod_1.z.union([zod_1.z.array(hooksSchema), hooksSchema]).optional(),
|
|
76
77
|
guideRails: zod_1.z.array(zod_1.z.custom()).optional(),
|
|
77
78
|
});
|
|
78
79
|
/**
|
|
@@ -107,6 +108,7 @@ class Agent {
|
|
|
107
108
|
if (outputSchema)
|
|
108
109
|
checkAgentInputOutputSchema(outputSchema);
|
|
109
110
|
this._inputSchema = inputSchema;
|
|
111
|
+
this.defaultInput = options.defaultInput;
|
|
110
112
|
this._outputSchema = outputSchema;
|
|
111
113
|
this.includeInputInOutput = options.includeInputInOutput;
|
|
112
114
|
this.subscribeTopic = options.subscribeTopic;
|
|
@@ -121,7 +123,7 @@ class Agent {
|
|
|
121
123
|
this.memories.push(options.memory);
|
|
122
124
|
}
|
|
123
125
|
this.maxRetrieveMemoryCount = options.maxRetrieveMemoryCount;
|
|
124
|
-
this.hooks = options.hooks
|
|
126
|
+
this.hooks = (0, type_utils_js_1.flat)(options.hooks);
|
|
125
127
|
this.guideRails = options.guideRails;
|
|
126
128
|
}
|
|
127
129
|
/**
|
|
@@ -187,6 +189,7 @@ class Agent {
|
|
|
187
189
|
*/
|
|
188
190
|
description;
|
|
189
191
|
_inputSchema;
|
|
192
|
+
defaultInput;
|
|
190
193
|
_outputSchema;
|
|
191
194
|
/**
|
|
192
195
|
* Get the input data schema for this agent
|
|
@@ -336,17 +339,23 @@ class Agent {
|
|
|
336
339
|
...options,
|
|
337
340
|
context: options.context ?? (await this.newDefaultContext()),
|
|
338
341
|
};
|
|
342
|
+
input = this.mergeDefaultInput(input);
|
|
339
343
|
logger_js_1.logger.debug("Invoke agent %s started with input: %O", this.name, input);
|
|
340
344
|
if (!this.disableEvents)
|
|
341
345
|
opts.context.emit("agentStarted", { agent: this, input });
|
|
342
346
|
try {
|
|
343
|
-
let
|
|
344
|
-
|
|
345
|
-
|
|
347
|
+
let response;
|
|
348
|
+
const s = await this.callHooks("onStart", { input }, opts);
|
|
349
|
+
if (s?.input)
|
|
350
|
+
input = s.input;
|
|
351
|
+
input = (0, type_utils_js_1.checkArguments)(`Agent ${this.name} input`, this.inputSchema, input);
|
|
352
|
+
await this.preprocess(input, opts);
|
|
346
353
|
this.checkContextStatus(opts);
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
response
|
|
354
|
+
if (!response) {
|
|
355
|
+
response = await this.process(input, opts);
|
|
356
|
+
if (response instanceof Agent) {
|
|
357
|
+
response = (0, types_js_1.transferToAgentOutput)(response);
|
|
358
|
+
}
|
|
350
359
|
}
|
|
351
360
|
if (opts.streaming) {
|
|
352
361
|
const stream = response instanceof ReadableStream
|
|
@@ -356,29 +365,62 @@ class Agent {
|
|
|
356
365
|
: (0, stream_utils_js_1.objectToAgentResponseStream)(response);
|
|
357
366
|
return this.checkResponseByGuideRails(input, (0, stream_utils_js_1.onAgentResponseStreamEnd)(stream, {
|
|
358
367
|
onResult: async (result) => {
|
|
359
|
-
return await this.processAgentOutput(
|
|
368
|
+
return await this.processAgentOutput(input, result, opts);
|
|
360
369
|
},
|
|
361
370
|
onError: async (error) => {
|
|
362
371
|
return await this.processAgentError(input, error, opts);
|
|
363
372
|
},
|
|
364
373
|
}), opts);
|
|
365
374
|
}
|
|
366
|
-
return await this.checkResponseByGuideRails(input, this.processAgentOutput(
|
|
375
|
+
return await this.checkResponseByGuideRails(input, this.processAgentOutput(input, await agentProcessResultToObject(response), opts), opts);
|
|
367
376
|
}
|
|
368
377
|
catch (error) {
|
|
369
378
|
throw await this.processAgentError(input, error, opts);
|
|
370
379
|
}
|
|
371
380
|
}
|
|
381
|
+
async callHooks(hook, input, options) {
|
|
382
|
+
const { context } = options;
|
|
383
|
+
const result = {};
|
|
384
|
+
for (const hooks of (0, type_utils_js_1.flat)(options.hooks, this.hooks)) {
|
|
385
|
+
const h = hooks[hook];
|
|
386
|
+
if (!h)
|
|
387
|
+
continue;
|
|
388
|
+
if (typeof h === "function") {
|
|
389
|
+
Object.assign(result, await h({ ...input, context }));
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
Object.assign(result, await context.invoke(h, input));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
mergeDefaultInput(input) {
|
|
398
|
+
const defaultInput = Object.fromEntries(Object.entries(this.defaultInput ?? {}).filter(([, v]) => !(typeof v === "object" && exports.DEFAULT_INPUT_ACTION_GET in v)));
|
|
399
|
+
input = { ...defaultInput, ...input };
|
|
400
|
+
for (const key of Object.keys(this.defaultInput ?? {})) {
|
|
401
|
+
const v = this.defaultInput?.[key];
|
|
402
|
+
if (v &&
|
|
403
|
+
typeof v === "object" &&
|
|
404
|
+
exports.DEFAULT_INPUT_ACTION_GET in v &&
|
|
405
|
+
typeof v[exports.DEFAULT_INPUT_ACTION_GET] === "string" &&
|
|
406
|
+
(0, type_utils_js_1.isNil)(input[key])) {
|
|
407
|
+
const value = input[v[exports.DEFAULT_INPUT_ACTION_GET]];
|
|
408
|
+
if (!(0, type_utils_js_1.isNil)(value))
|
|
409
|
+
Object.assign(input, { [key]: value });
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return input;
|
|
413
|
+
}
|
|
372
414
|
async invokeSkill(skill, input, options) {
|
|
373
415
|
const { context } = options;
|
|
374
|
-
await this.
|
|
416
|
+
await this.callHooks("onSkillStart", { skill, input }, options);
|
|
375
417
|
try {
|
|
376
418
|
const output = await context.invoke(skill, input);
|
|
377
|
-
await this.
|
|
419
|
+
await this.callHooks("onSkillEnd", { skill, input, output }, options);
|
|
378
420
|
return output;
|
|
379
421
|
}
|
|
380
422
|
catch (error) {
|
|
381
|
-
await this.
|
|
423
|
+
await this.callHooks("onSkillEnd", { skill, input, error }, options);
|
|
382
424
|
throw error;
|
|
383
425
|
}
|
|
384
426
|
}
|
|
@@ -398,14 +440,17 @@ class Agent {
|
|
|
398
440
|
throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof output}): ${output}`);
|
|
399
441
|
}
|
|
400
442
|
const parsedOutput = (0, type_utils_js_1.checkArguments)(`Agent ${this.name} output`, this.outputSchema, output);
|
|
401
|
-
|
|
443
|
+
let finalOutput = this.includeInputInOutput ? { ...input, ...parsedOutput } : parsedOutput;
|
|
402
444
|
await this.postprocess(input, finalOutput, options);
|
|
403
445
|
logger_js_1.logger.debug("Invoke agent %s succeed with output: %O", this.name, finalOutput);
|
|
404
446
|
if (!this.disableEvents)
|
|
405
447
|
context.emit("agentSucceed", { agent: this, output: finalOutput });
|
|
406
|
-
|
|
407
|
-
if (o)
|
|
408
|
-
|
|
448
|
+
let o = await this.callHooks("onSuccess", { input, output: finalOutput }, options);
|
|
449
|
+
if (o?.output)
|
|
450
|
+
finalOutput = o.output;
|
|
451
|
+
o = await this.callHooks("onEnd", { input, output: finalOutput }, options);
|
|
452
|
+
if (o?.output)
|
|
453
|
+
finalOutput = o.output;
|
|
409
454
|
return finalOutput;
|
|
410
455
|
}
|
|
411
456
|
/**
|
|
@@ -420,8 +465,8 @@ class Agent {
|
|
|
420
465
|
logger_js_1.logger.error("Invoke agent %s failed with error: %O", this.name, error);
|
|
421
466
|
if (!this.disableEvents)
|
|
422
467
|
options.context.emit("agentFailed", { agent: this, error });
|
|
423
|
-
|
|
424
|
-
await this.
|
|
468
|
+
await this.callHooks("onError", { input, error }, options);
|
|
469
|
+
await this.callHooks("onEnd", { input, error }, options);
|
|
425
470
|
return error;
|
|
426
471
|
}
|
|
427
472
|
/**
|
|
@@ -243,7 +243,7 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
243
243
|
const outputKey = this.outputKey;
|
|
244
244
|
for (;;) {
|
|
245
245
|
const modelOutput = {};
|
|
246
|
-
let stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
|
|
246
|
+
let stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { ...options, streaming: true });
|
|
247
247
|
if (this.structuredStreamMode) {
|
|
248
248
|
const { metadataStart, metadataEnd, parse } = this.customStructuredStreamInstructions || structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS;
|
|
249
249
|
stream = stream.pipeThrough(new structured_stream_extractor_js_1.ExtractMetadataTransform({ start: metadataStart, end: metadataEnd, parse }));
|
|
@@ -318,14 +318,17 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
318
318
|
* @protected
|
|
319
319
|
*/
|
|
320
320
|
async *_processRouter(input, model, modelInput, options, toolsMap) {
|
|
321
|
-
const { toolCalls: [call] = [] } = await options.context.invoke(model, modelInput
|
|
321
|
+
const { toolCalls: [call] = [] } = await options.context.invoke(model, modelInput, {
|
|
322
|
+
...options,
|
|
323
|
+
streaming: false,
|
|
324
|
+
});
|
|
322
325
|
if (!call) {
|
|
323
326
|
throw new Error("Router toolChoice requires exactly one tool to be executed");
|
|
324
327
|
}
|
|
325
328
|
const tool = toolsMap.get(call.function.name);
|
|
326
329
|
if (!tool)
|
|
327
330
|
throw new Error(`Tool not found: ${call.function.name}`);
|
|
328
|
-
const stream = await options.context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true, sourceAgent: this });
|
|
331
|
+
const stream = await options.context.invoke(tool, { ...call.function.arguments, ...input }, { ...options, streaming: true, sourceAgent: this });
|
|
329
332
|
return yield* stream;
|
|
330
333
|
}
|
|
331
334
|
}
|
|
@@ -171,19 +171,13 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
171
171
|
*/
|
|
172
172
|
async *_processSequential(input, options) {
|
|
173
173
|
const output = {};
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const newAgents = [];
|
|
177
|
-
for (const agent of agents) {
|
|
178
|
-
const [o, transferToAgent] = await options.context.invoke(agent, { ...input, ...output }, { returnActiveAgent: true, streaming: true });
|
|
174
|
+
for (const agent of this.skills) {
|
|
175
|
+
const o = await options.context.invoke(agent, { ...input, ...output }, { ...options, streaming: true });
|
|
179
176
|
for await (const chunk of o) {
|
|
180
177
|
yield chunk;
|
|
181
178
|
(0, stream_utils_js_1.mergeAgentResponseChunk)(output, chunk);
|
|
182
179
|
}
|
|
183
|
-
newAgents.push(await transferToAgent);
|
|
184
180
|
}
|
|
185
|
-
this.skills.splice(0);
|
|
186
|
-
this.skills.push(...newAgents);
|
|
187
181
|
}
|
|
188
182
|
/**
|
|
189
183
|
* Process input in parallel through all agents in the team.
|
|
@@ -200,8 +194,7 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
200
194
|
* @private
|
|
201
195
|
*/
|
|
202
196
|
async *_processParallel(input, options) {
|
|
203
|
-
const
|
|
204
|
-
const streams = result.map((i) => i[0]);
|
|
197
|
+
const streams = await Promise.all(this.skills.map((agent) => options.context.invoke(agent, input, { ...options, streaming: true })));
|
|
205
198
|
const read = async (index, reader) => {
|
|
206
199
|
const promise = reader.read();
|
|
207
200
|
return promise.then((result) => ({ ...result, reader, index }));
|
|
@@ -236,9 +229,6 @@ class TeamAgent extends agent_js_1.Agent {
|
|
|
236
229
|
yield { delta: { ...delta, text } };
|
|
237
230
|
}
|
|
238
231
|
}
|
|
239
|
-
const agents = await Promise.all(result.map((i) => i[1]));
|
|
240
|
-
this.skills.splice(0);
|
|
241
|
-
this.skills.push(...agents);
|
|
242
232
|
}
|
|
243
233
|
}
|
|
244
234
|
exports.TeamAgent = TeamAgent;
|
|
@@ -180,6 +180,7 @@ declare class AIGNEContextShared {
|
|
|
180
180
|
span?: Span;
|
|
181
181
|
constructor(parent?: (Pick<Context, "model" | "skills" | "limits" | "observer"> & {
|
|
182
182
|
messageQueue?: MessageQueue;
|
|
183
|
+
events?: Emitter<any>;
|
|
183
184
|
}) | undefined);
|
|
184
185
|
readonly messageQueue: MessageQueue;
|
|
185
186
|
readonly events: Emitter<any>;
|
package/lib/cjs/aigne/context.js
CHANGED
|
@@ -40,7 +40,7 @@ class AIGNEContext {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
this.internal = new AIGNEContextShared(parent);
|
|
43
|
+
this.internal = new AIGNEContextShared(parent instanceof AIGNEContext ? parent.internal : parent);
|
|
44
44
|
this.span = tracer?.startSpan("AIGNEContext");
|
|
45
45
|
// 修改了 rootId 是否会之前的有影响?,之前为 this.id
|
|
46
46
|
this.rootId = this.span?.spanContext?.().traceId ?? (0, uuid_1.v7)();
|
|
@@ -272,9 +272,10 @@ class AIGNEContextShared {
|
|
|
272
272
|
constructor(parent) {
|
|
273
273
|
this.parent = parent;
|
|
274
274
|
this.messageQueue = this.parent?.messageQueue ?? new message_queue_js_1.MessageQueue();
|
|
275
|
+
this.events = this.parent?.events ?? new strict_event_emitter_1.Emitter();
|
|
275
276
|
}
|
|
276
277
|
messageQueue;
|
|
277
|
-
events
|
|
278
|
+
events;
|
|
278
279
|
get model() {
|
|
279
280
|
return this.parent?.model;
|
|
280
281
|
}
|
|
@@ -309,21 +310,35 @@ class AIGNEContextShared {
|
|
|
309
310
|
this.initTimeout();
|
|
310
311
|
return withAbortSignal(this.abortController.signal, new Error("AIGNEContext is timeout"), () => this.invokeAgent(agent, input, context, options));
|
|
311
312
|
}
|
|
312
|
-
async *invokeAgent(agent, input, context, options) {
|
|
313
|
+
async *invokeAgent(agent, input, context, options = {}) {
|
|
313
314
|
const startedAt = Date.now();
|
|
314
315
|
try {
|
|
315
316
|
let activeAgent = agent;
|
|
316
317
|
for (;;) {
|
|
317
318
|
const result = {};
|
|
318
319
|
if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
|
|
319
|
-
options.sourceAgent.hooks
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
320
|
+
for (const { onHandoff } of [options.hooks ?? {}, ...options.sourceAgent.hooks]) {
|
|
321
|
+
if (!onHandoff)
|
|
322
|
+
continue;
|
|
323
|
+
await (typeof onHandoff === "function"
|
|
324
|
+
? onHandoff({
|
|
325
|
+
context,
|
|
326
|
+
source: options.sourceAgent,
|
|
327
|
+
target: activeAgent,
|
|
328
|
+
input,
|
|
329
|
+
})
|
|
330
|
+
: context.invoke(onHandoff, {
|
|
331
|
+
source: options.sourceAgent,
|
|
332
|
+
target: activeAgent,
|
|
333
|
+
input,
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
325
336
|
}
|
|
326
|
-
const stream = await activeAgent.invoke(input, {
|
|
337
|
+
const stream = await activeAgent.invoke(input, {
|
|
338
|
+
hooks: options.hooks,
|
|
339
|
+
context,
|
|
340
|
+
streaming: true,
|
|
341
|
+
});
|
|
327
342
|
for await (const value of stream) {
|
|
328
343
|
if ((0, agent_js_1.isAgentResponseDelta)(value)) {
|
|
329
344
|
if (value.delta.json) {
|
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
import { type ZodObject, type ZodType, z } from "zod";
|
|
2
1
|
import { Agent, type FunctionAgentFn } from "../agents/agent.js";
|
|
3
2
|
export declare function loadAgentFromJsFile(path: string): Promise<Agent<any, any> | {
|
|
4
3
|
process: FunctionAgentFn;
|
|
5
4
|
name: string;
|
|
6
5
|
description?: string | undefined;
|
|
7
|
-
inputSchema?:
|
|
8
|
-
|
|
9
|
-
}, {
|
|
10
|
-
[x: string]: any;
|
|
11
|
-
}> | undefined;
|
|
12
|
-
outputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
|
|
13
|
-
[x: string]: any;
|
|
14
|
-
}, {
|
|
15
|
-
[x: string]: any;
|
|
16
|
-
}> | undefined;
|
|
6
|
+
inputSchema?: any;
|
|
7
|
+
outputSchema?: any;
|
|
17
8
|
}>;
|
|
@@ -32,34 +32,30 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.loadAgentFromJsFile = loadAgentFromJsFile;
|
|
40
37
|
const json_schema_to_zod_1 = require("@aigne/json-schema-to-zod");
|
|
41
|
-
const camelize_ts_1 = __importDefault(require("camelize-ts"));
|
|
42
38
|
const zod_1 = require("zod");
|
|
43
39
|
const agent_js_1 = require("../agents/agent.js");
|
|
44
40
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
45
41
|
const schema_js_1 = require("./schema.js");
|
|
46
42
|
async function loadAgentFromJsFile(path) {
|
|
47
|
-
const agentJsFileSchema = zod_1.z.object({
|
|
43
|
+
const agentJsFileSchema = (0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
48
44
|
name: zod_1.z.string(),
|
|
49
45
|
description: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
50
46
|
inputSchema: (0, schema_js_1.optionalize)((0, schema_js_1.inputOutputSchema)({ path })).transform((v) => v ? (0, json_schema_to_zod_1.jsonSchemaToZod)(v) : undefined),
|
|
51
47
|
outputSchema: (0, schema_js_1.optionalize)((0, schema_js_1.inputOutputSchema)({ path })).transform((v) => v ? (0, json_schema_to_zod_1.jsonSchemaToZod)(v) : undefined),
|
|
52
48
|
process: zod_1.z.custom(),
|
|
53
|
-
});
|
|
49
|
+
}));
|
|
54
50
|
const { default: agent } = await (0, type_utils_js_1.tryOrThrow)(() => Promise.resolve(`${path}`).then(s => __importStar(require(s))), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
|
|
55
51
|
if (agent instanceof agent_js_1.Agent)
|
|
56
52
|
return agent;
|
|
57
53
|
if (typeof agent !== "function") {
|
|
58
54
|
throw new Error(`Agent file ${path} must export a default function, but got ${typeof agent}`);
|
|
59
55
|
}
|
|
60
|
-
return (0, type_utils_js_1.tryOrThrow)(() => agentJsFileSchema.parseAsync(
|
|
56
|
+
return (0, type_utils_js_1.tryOrThrow)(() => agentJsFileSchema.parseAsync({
|
|
61
57
|
...agent,
|
|
62
58
|
name: agent.agent_name || agent.agentName || agent.name,
|
|
63
59
|
process: agent,
|
|
64
|
-
})
|
|
60
|
+
}), (error) => new Error(`Failed to parse agent from ${path}: ${error.message}`));
|
|
65
61
|
}
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { type ZodType } from "zod";
|
|
2
2
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
3
3
|
import { ProcessMode } from "../agents/team-agent.js";
|
|
4
|
+
export interface HooksSchema {
|
|
5
|
+
onStart?: NestAgentSchema;
|
|
6
|
+
onSuccess?: NestAgentSchema;
|
|
7
|
+
onError?: NestAgentSchema;
|
|
8
|
+
onEnd?: NestAgentSchema;
|
|
9
|
+
onSkillStart?: NestAgentSchema;
|
|
10
|
+
onSkillEnd?: NestAgentSchema;
|
|
11
|
+
onHandoff?: NestAgentSchema;
|
|
12
|
+
}
|
|
13
|
+
export type NestAgentSchema = string | {
|
|
14
|
+
url: string;
|
|
15
|
+
defaultInput?: Record<string, any>;
|
|
16
|
+
hooks?: HooksSchema | HooksSchema[];
|
|
17
|
+
} | AgentSchema;
|
|
4
18
|
interface BaseAgentSchema {
|
|
5
19
|
name?: string;
|
|
6
20
|
description?: string;
|
|
7
21
|
inputSchema?: ZodType<Record<string, any>>;
|
|
22
|
+
defaultInput?: Record<string, any>;
|
|
8
23
|
outputSchema?: ZodType<Record<string, any>>;
|
|
9
|
-
skills?:
|
|
24
|
+
skills?: NestAgentSchema[];
|
|
25
|
+
hooks?: HooksSchema | HooksSchema[];
|
|
10
26
|
memory?: boolean | {
|
|
11
27
|
provider: string;
|
|
12
28
|
subscribeTopic?: string[];
|
|
@@ -19,7 +35,7 @@ interface AIAgentSchema extends BaseAgentSchema {
|
|
|
19
35
|
outputKey?: string;
|
|
20
36
|
toolChoice?: AIAgentToolChoice;
|
|
21
37
|
}
|
|
22
|
-
interface MCPAgentSchema {
|
|
38
|
+
interface MCPAgentSchema extends BaseAgentSchema {
|
|
23
39
|
type: "mcp";
|
|
24
40
|
url?: string;
|
|
25
41
|
command?: string;
|