@aigne/core 1.29.1 → 1.32.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 +52 -0
- package/lib/cjs/agents/agent.d.ts +0 -2
- package/lib/cjs/agents/agent.js +4 -9
- package/lib/cjs/agents/ai-agent.d.ts +74 -0
- package/lib/cjs/agents/ai-agent.js +44 -4
- package/lib/cjs/agents/user-agent.js +1 -1
- package/lib/cjs/aigne/context.d.ts +4 -0
- package/lib/cjs/aigne/context.js +0 -10
- package/lib/cjs/aigne/index.d.ts +1 -1
- package/lib/cjs/aigne/index.js +1 -1
- package/lib/cjs/aigne/message-queue.js +6 -6
- package/lib/cjs/loader/index.js +3 -0
- package/lib/cjs/prompt/prompt-builder.d.ts +6 -2
- package/lib/cjs/prompt/prompt-builder.js +48 -19
- package/lib/cjs/prompt/prompts/memory-message-template.d.ts +1 -1
- package/lib/cjs/prompt/prompts/memory-message-template.js +2 -4
- package/lib/cjs/prompt/prompts/structured-stream-instructions.d.ts +7 -0
- package/lib/cjs/prompt/prompts/structured-stream-instructions.js +27 -0
- package/lib/cjs/prompt/template.d.ts +21 -7
- package/lib/cjs/prompt/template.js +57 -19
- package/lib/cjs/utils/mcp-utils.d.ts +1 -1
- package/lib/cjs/utils/stream-utils.js +3 -0
- package/lib/cjs/utils/structured-stream-extractor.d.ts +14 -0
- package/lib/cjs/utils/structured-stream-extractor.js +60 -0
- package/lib/cjs/utils/type-utils.d.ts +1 -1
- package/lib/cjs/utils/type-utils.js +3 -3
- package/lib/dts/agents/agent.d.ts +0 -2
- package/lib/dts/agents/ai-agent.d.ts +74 -0
- package/lib/dts/aigne/context.d.ts +4 -0
- package/lib/dts/aigne/index.d.ts +1 -1
- package/lib/dts/prompt/prompt-builder.d.ts +6 -2
- package/lib/dts/prompt/prompts/memory-message-template.d.ts +1 -1
- package/lib/dts/prompt/prompts/structured-stream-instructions.d.ts +7 -0
- package/lib/dts/prompt/template.d.ts +21 -7
- package/lib/dts/utils/mcp-utils.d.ts +1 -1
- package/lib/dts/utils/structured-stream-extractor.d.ts +14 -0
- package/lib/dts/utils/type-utils.d.ts +1 -1
- package/lib/esm/agents/agent.d.ts +0 -2
- package/lib/esm/agents/agent.js +5 -10
- package/lib/esm/agents/ai-agent.d.ts +74 -0
- package/lib/esm/agents/ai-agent.js +44 -4
- package/lib/esm/agents/user-agent.js +2 -2
- package/lib/esm/aigne/context.d.ts +4 -0
- package/lib/esm/aigne/context.js +1 -11
- package/lib/esm/aigne/index.d.ts +1 -1
- package/lib/esm/aigne/index.js +1 -1
- package/lib/esm/aigne/message-queue.js +7 -7
- package/lib/esm/loader/agent-js.js +1 -1
- package/lib/esm/loader/index.js +3 -0
- package/lib/esm/prompt/prompt-builder.d.ts +6 -2
- package/lib/esm/prompt/prompt-builder.js +49 -20
- package/lib/esm/prompt/prompts/memory-message-template.d.ts +1 -1
- package/lib/esm/prompt/prompts/memory-message-template.js +2 -4
- package/lib/esm/prompt/prompts/structured-stream-instructions.d.ts +7 -0
- package/lib/esm/prompt/prompts/structured-stream-instructions.js +24 -0
- package/lib/esm/prompt/template.d.ts +21 -7
- package/lib/esm/prompt/template.js +54 -17
- package/lib/esm/utils/mcp-utils.d.ts +1 -1
- package/lib/esm/utils/stream-utils.js +4 -1
- package/lib/esm/utils/structured-stream-extractor.d.ts +14 -0
- package/lib/esm/utils/structured-stream-extractor.js +56 -0
- package/lib/esm/utils/type-utils.d.ts +1 -1
- package/lib/esm/utils/type-utils.js +2 -2
- package/package.json +16 -14
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,58 @@
|
|
|
12
12
|
* dependencies
|
|
13
13
|
* @aigne/observability bumped to 0.1.0
|
|
14
14
|
|
|
15
|
+
## [1.32.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.31.0...core-v1.32.0) (2025-07-08)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **core:** add jinja syntax support for prompt builder ([#230](https://github.com/AIGNE-io/aigne-framework/issues/230)) ([74436a7](https://github.com/AIGNE-io/aigne-framework/commit/74436a7faac0c59a32b0153481386162649f4357))
|
|
21
|
+
* support setting component id to different component data ([#226](https://github.com/AIGNE-io/aigne-framework/issues/226)) ([c7b3224](https://github.com/AIGNE-io/aigne-framework/commit/c7b32240e6660f34974615bcb9b91978a1191e3e))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* **core:** ensure output is a record type ([#228](https://github.com/AIGNE-io/aigne-framework/issues/228)) ([dfd9104](https://github.com/AIGNE-io/aigne-framework/commit/dfd910451e5f1f9edd94a719857e36d34fadbe45))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Dependencies
|
|
30
|
+
|
|
31
|
+
* The following workspace dependencies were updated
|
|
32
|
+
* dependencies
|
|
33
|
+
* @aigne/observability-api bumped to 0.6.0
|
|
34
|
+
|
|
35
|
+
## [1.31.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.30.0...core-v1.31.0) (2025-07-04)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Features
|
|
39
|
+
|
|
40
|
+
* **core:** add standard userId/sessionId in userContext ([#219](https://github.com/AIGNE-io/aigne-framework/issues/219)) ([58e5804](https://github.com/AIGNE-io/aigne-framework/commit/58e5804cf08b1d2fa6e232646fadd70b5db2e007))
|
|
41
|
+
* **core:** add strucutredStreamMode option for AIAgent to support text and json output in one-shot ([#222](https://github.com/AIGNE-io/aigne-framework/issues/222)) ([c0af92b](https://github.com/AIGNE-io/aigne-framework/commit/c0af92b6a020453b047e5bb3782239795839baa8))
|
|
42
|
+
* **memory:** add support for AgenticMemory & some improvements for DefaultMemory ([#224](https://github.com/AIGNE-io/aigne-framework/issues/224)) ([f4a08af](https://github.com/AIGNE-io/aigne-framework/commit/f4a08aff935205c62615c060763c835a9579607d))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
### Dependencies
|
|
46
|
+
|
|
47
|
+
* The following workspace dependencies were updated
|
|
48
|
+
* dependencies
|
|
49
|
+
* @aigne/observability-api bumped to 0.5.0
|
|
50
|
+
* @aigne/platform-helpers bumped to 0.3.0
|
|
51
|
+
|
|
52
|
+
## [1.30.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.29.1...core-v1.30.0) (2025-07-03)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
### Features
|
|
56
|
+
|
|
57
|
+
* upgrade dependencies and adapt code to breaking changes ([#216](https://github.com/AIGNE-io/aigne-framework/issues/216)) ([f215ced](https://github.com/AIGNE-io/aigne-framework/commit/f215cedc1a57e321164064c33316e496eae8d25f))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Dependencies
|
|
61
|
+
|
|
62
|
+
* The following workspace dependencies were updated
|
|
63
|
+
* dependencies
|
|
64
|
+
* @aigne/observability-api bumped to 0.4.0
|
|
65
|
+
* @aigne/platform-helpers bumped to 0.2.0
|
|
66
|
+
|
|
15
67
|
## [1.29.1](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.29.0...core-v1.29.1) (2025-07-02)
|
|
16
68
|
|
|
17
69
|
|
|
@@ -137,8 +137,6 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
|
|
|
137
137
|
* and returns the final JSON result
|
|
138
138
|
*/
|
|
139
139
|
streaming?: boolean;
|
|
140
|
-
userContext?: U;
|
|
141
|
-
memories?: Pick<Memory, "content">[];
|
|
142
140
|
}
|
|
143
141
|
/**
|
|
144
142
|
* Agent is the base class for all agents.
|
package/lib/cjs/agents/agent.js
CHANGED
|
@@ -267,7 +267,7 @@ class Agent {
|
|
|
267
267
|
this.subscribeToTopics(context);
|
|
268
268
|
}
|
|
269
269
|
subscribeToTopics(context) {
|
|
270
|
-
for (const topic of (0, type_utils_js_1.
|
|
270
|
+
for (const topic of (0, type_utils_js_1.flat)(this.subscribeTopic).concat(this.topic)) {
|
|
271
271
|
this.subscriptions.push(context.subscribe(topic, (payload) => this.onMessage(payload)));
|
|
272
272
|
}
|
|
273
273
|
}
|
|
@@ -336,14 +336,6 @@ class Agent {
|
|
|
336
336
|
...options,
|
|
337
337
|
context: options.context ?? (await this.newDefaultContext()),
|
|
338
338
|
};
|
|
339
|
-
if (options.userContext) {
|
|
340
|
-
Object.assign(opts.context.userContext, options.userContext);
|
|
341
|
-
options.userContext = undefined;
|
|
342
|
-
}
|
|
343
|
-
if (options.memories?.length) {
|
|
344
|
-
opts.context.memories.push(...options.memories);
|
|
345
|
-
options.memories = undefined;
|
|
346
|
-
}
|
|
347
339
|
logger_js_1.logger.debug("Invoke agent %s started with input: %O", this.name, input);
|
|
348
340
|
if (!this.disableEvents)
|
|
349
341
|
opts.context.emit("agentStarted", { agent: this, input });
|
|
@@ -402,6 +394,9 @@ class Agent {
|
|
|
402
394
|
*/
|
|
403
395
|
async processAgentOutput(input, output, options) {
|
|
404
396
|
const { context } = options;
|
|
397
|
+
if (!(0, type_utils_js_1.isRecord)(output)) {
|
|
398
|
+
throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof output}): ${output}`);
|
|
399
|
+
}
|
|
405
400
|
const parsedOutput = (0, type_utils_js_1.checkArguments)(`Agent ${this.name} output`, this.outputSchema, output);
|
|
406
401
|
const finalOutput = this.includeInputInOutput ? { ...input, ...parsedOutput } : parsedOutput;
|
|
407
402
|
await this.postprocess(input, finalOutput, options);
|
|
@@ -50,6 +50,48 @@ export interface AIAgentOptions<I extends Message = Message, O extends Message =
|
|
|
50
50
|
* @default true
|
|
51
51
|
*/
|
|
52
52
|
catchToolsError?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether to enable structured stream mode
|
|
55
|
+
*
|
|
56
|
+
* When enabled, the AI model's streaming response will be processed to extract
|
|
57
|
+
* structured metadata. The model needs to include specific format metadata tags
|
|
58
|
+
* (like <metadata></metadata>) in its response, which will be parsed as JSON
|
|
59
|
+
* objects and passed through the stream.
|
|
60
|
+
*
|
|
61
|
+
* This is useful for scenarios that need to extract structured information
|
|
62
|
+
* (like classifications, scores, tags, etc.) from AI responses.
|
|
63
|
+
*
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
structuredStreamMode?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Custom structured stream instructions configuration
|
|
69
|
+
*
|
|
70
|
+
* Allows customization of structured stream mode behavior, including:
|
|
71
|
+
* - instructions: Prompt instructions to guide the AI model on how to output structured data
|
|
72
|
+
* - metadataStart: Metadata start marker (e.g., "<metadata>")
|
|
73
|
+
* - metadataEnd: Metadata end marker (e.g., "</metadata>")
|
|
74
|
+
* - parse: Function to parse metadata content, converting raw string to object
|
|
75
|
+
*
|
|
76
|
+
* If not provided, the default STRUCTURED_STREAM_INSTRUCTIONS configuration will be used,
|
|
77
|
+
* which outputs structured data in YAML format within <metadata> tags.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* {
|
|
82
|
+
* instructions: "Output metadata in JSON format at the end of response in markdown code block with json language",
|
|
83
|
+
* metadataStart: "```json",
|
|
84
|
+
* metadataEnd: "```",
|
|
85
|
+
* parse: JSON.parse
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
customStructuredStreamInstructions?: {
|
|
90
|
+
instructions: string | PromptBuilder;
|
|
91
|
+
metadataStart: string;
|
|
92
|
+
metadataEnd: string;
|
|
93
|
+
parse: (raw: string) => object;
|
|
94
|
+
};
|
|
53
95
|
/**
|
|
54
96
|
* Whether to include memory agents as tools for the AI model
|
|
55
97
|
*
|
|
@@ -217,6 +259,38 @@ export declare class AIAgent<I extends Message = any, O extends Message = any> e
|
|
|
217
259
|
* @default true
|
|
218
260
|
*/
|
|
219
261
|
catchToolsError: boolean;
|
|
262
|
+
/**
|
|
263
|
+
* Whether to enable structured stream mode
|
|
264
|
+
*
|
|
265
|
+
* When enabled, the AI model's streaming response will be processed to extract
|
|
266
|
+
* structured metadata. The model needs to include specific format metadata tags
|
|
267
|
+
* (like <metadata></metadata>) in its response, which will be parsed as JSON
|
|
268
|
+
* objects and passed through the stream.
|
|
269
|
+
*
|
|
270
|
+
* This is useful for scenarios that need to extract structured information
|
|
271
|
+
* (like classifications, scores, tags, etc.) from AI responses.
|
|
272
|
+
*
|
|
273
|
+
* @default false
|
|
274
|
+
*/
|
|
275
|
+
structuredStreamMode?: boolean;
|
|
276
|
+
/**
|
|
277
|
+
* Custom structured stream instructions configuration
|
|
278
|
+
*
|
|
279
|
+
* Allows customization of structured stream mode behavior, including:
|
|
280
|
+
* - instructions: Prompt instructions to guide the AI model on how to output structured data
|
|
281
|
+
* - metadataStart: Metadata start marker (e.g., "<metadata>")
|
|
282
|
+
* - metadataEnd: Metadata end marker (e.g., "</metadata>")
|
|
283
|
+
* - parse: Function to parse metadata content, converting raw string to object
|
|
284
|
+
*
|
|
285
|
+
* If not provided, the default STRUCTURED_STREAM_INSTRUCTIONS configuration will be used,
|
|
286
|
+
* which outputs structured data in YAML format within <metadata> tags.
|
|
287
|
+
*/
|
|
288
|
+
customStructuredStreamInstructions?: {
|
|
289
|
+
instructions: PromptBuilder;
|
|
290
|
+
metadataStart: string;
|
|
291
|
+
metadataEnd: string;
|
|
292
|
+
parse: (raw: string) => object;
|
|
293
|
+
};
|
|
220
294
|
/**
|
|
221
295
|
* Process an input message and generate a response
|
|
222
296
|
*
|
|
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AIAgent = exports.aiAgentOptionsSchema = exports.aiAgentToolChoiceSchema = exports.AIAgentToolChoice = exports.DEFAULT_OUTPUT_KEY = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
|
|
6
|
+
const structured_stream_instructions_js_1 = require("../prompt/prompts/structured-stream-instructions.js");
|
|
6
7
|
const template_js_1 = require("../prompt/template.js");
|
|
8
|
+
const structured_stream_extractor_js_1 = require("../utils/structured-stream-extractor.js");
|
|
7
9
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
8
10
|
const agent_js_1 = require("./agent.js");
|
|
9
11
|
const types_js_1 = require("./types.js");
|
|
@@ -115,6 +117,13 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
115
117
|
this.memoryPromptTemplate = options.memoryPromptTemplate;
|
|
116
118
|
if (typeof options.catchToolsError === "boolean")
|
|
117
119
|
this.catchToolsError = options.catchToolsError;
|
|
120
|
+
this.structuredStreamMode = options.structuredStreamMode;
|
|
121
|
+
this.customStructuredStreamInstructions = options.customStructuredStreamInstructions && {
|
|
122
|
+
...options.customStructuredStreamInstructions,
|
|
123
|
+
instructions: typeof options.customStructuredStreamInstructions.instructions === "string"
|
|
124
|
+
? prompt_builder_js_1.PromptBuilder.from(options.customStructuredStreamInstructions.instructions)
|
|
125
|
+
: options.customStructuredStreamInstructions.instructions,
|
|
126
|
+
};
|
|
118
127
|
if (!this.inputKey && !this.instructions) {
|
|
119
128
|
throw new Error("AIAgent requires either inputKey or instructions to be set");
|
|
120
129
|
}
|
|
@@ -184,6 +193,33 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
184
193
|
* @default true
|
|
185
194
|
*/
|
|
186
195
|
catchToolsError = true;
|
|
196
|
+
/**
|
|
197
|
+
* Whether to enable structured stream mode
|
|
198
|
+
*
|
|
199
|
+
* When enabled, the AI model's streaming response will be processed to extract
|
|
200
|
+
* structured metadata. The model needs to include specific format metadata tags
|
|
201
|
+
* (like <metadata></metadata>) in its response, which will be parsed as JSON
|
|
202
|
+
* objects and passed through the stream.
|
|
203
|
+
*
|
|
204
|
+
* This is useful for scenarios that need to extract structured information
|
|
205
|
+
* (like classifications, scores, tags, etc.) from AI responses.
|
|
206
|
+
*
|
|
207
|
+
* @default false
|
|
208
|
+
*/
|
|
209
|
+
structuredStreamMode;
|
|
210
|
+
/**
|
|
211
|
+
* Custom structured stream instructions configuration
|
|
212
|
+
*
|
|
213
|
+
* Allows customization of structured stream mode behavior, including:
|
|
214
|
+
* - instructions: Prompt instructions to guide the AI model on how to output structured data
|
|
215
|
+
* - metadataStart: Metadata start marker (e.g., "<metadata>")
|
|
216
|
+
* - metadataEnd: Metadata end marker (e.g., "</metadata>")
|
|
217
|
+
* - parse: Function to parse metadata content, converting raw string to object
|
|
218
|
+
*
|
|
219
|
+
* If not provided, the default STRUCTURED_STREAM_INSTRUCTIONS configuration will be used,
|
|
220
|
+
* which outputs structured data in YAML format within <metadata> tags.
|
|
221
|
+
*/
|
|
222
|
+
customStructuredStreamInstructions;
|
|
187
223
|
/**
|
|
188
224
|
* Process an input message and generate a response
|
|
189
225
|
*
|
|
@@ -207,7 +243,11 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
207
243
|
const outputKey = this.outputKey;
|
|
208
244
|
for (;;) {
|
|
209
245
|
const modelOutput = {};
|
|
210
|
-
|
|
246
|
+
let stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
|
|
247
|
+
if (this.structuredStreamMode) {
|
|
248
|
+
const { metadataStart, metadataEnd, parse } = this.customStructuredStreamInstructions || structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS;
|
|
249
|
+
stream = stream.pipeThrough(new structured_stream_extractor_js_1.ExtractMetadataTransform({ start: metadataStart, end: metadataEnd, parse }));
|
|
250
|
+
}
|
|
211
251
|
for await (const value of stream) {
|
|
212
252
|
if ((0, agent_js_1.isAgentResponseDelta)(value)) {
|
|
213
253
|
if (value.delta.text?.text) {
|
|
@@ -246,7 +286,7 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
246
286
|
}
|
|
247
287
|
// Continue LLM function calling loop if any tools were executed
|
|
248
288
|
if (executedToolCalls.length) {
|
|
249
|
-
toolCallMessages.push(template_js_1.AgentMessageTemplate.from(undefined, executedToolCalls.map(({ call }) => call)).format(), ...executedToolCalls.map(({ call, output }) => template_js_1.ToolMessageTemplate.from(output, call.id).format()));
|
|
289
|
+
toolCallMessages.push(await template_js_1.AgentMessageTemplate.from(undefined, executedToolCalls.map(({ call }) => call)).format(), ...(await Promise.all(executedToolCalls.map(({ call, output }) => template_js_1.ToolMessageTemplate.from(output, call.id).format()))));
|
|
250
290
|
continue;
|
|
251
291
|
}
|
|
252
292
|
}
|
|
@@ -254,7 +294,7 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
254
294
|
if (json) {
|
|
255
295
|
Object.assign(result, json);
|
|
256
296
|
}
|
|
257
|
-
|
|
297
|
+
if (text) {
|
|
258
298
|
Object.assign(result, { [outputKey]: text });
|
|
259
299
|
}
|
|
260
300
|
if (!(0, type_utils_js_1.isEmpty)(result)) {
|
|
@@ -278,7 +318,7 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
278
318
|
* @protected
|
|
279
319
|
*/
|
|
280
320
|
async *_processRouter(input, model, modelInput, options, toolsMap) {
|
|
281
|
-
const { toolCalls: [call] = []
|
|
321
|
+
const { toolCalls: [call] = [] } = await options.context.invoke(model, modelInput);
|
|
282
322
|
if (!call) {
|
|
283
323
|
throw new Error("Router toolChoice requires exactly one tool to be executed");
|
|
284
324
|
}
|
|
@@ -70,7 +70,7 @@ class UserAgent extends agent_js_1.Agent {
|
|
|
70
70
|
let subscriptions = [];
|
|
71
71
|
return new ReadableStream({
|
|
72
72
|
start: (controller) => {
|
|
73
|
-
const subscribeTopic = (0, type_utils_js_1.
|
|
73
|
+
const subscribeTopic = (0, type_utils_js_1.flat)(this.subscribeTopic);
|
|
74
74
|
subscriptions = subscribeTopic.map((topic) => this.subscribe(topic, (message) => {
|
|
75
75
|
controller.enqueue({ ...message, topic });
|
|
76
76
|
}));
|
|
@@ -54,11 +54,15 @@ export interface InvokeOptions<U extends UserContext = UserContext> extends Part
|
|
|
54
54
|
* @default true
|
|
55
55
|
*/
|
|
56
56
|
newContext?: boolean;
|
|
57
|
+
userContext?: U;
|
|
58
|
+
memories?: Pick<Memory, "content">[];
|
|
57
59
|
}
|
|
58
60
|
/**
|
|
59
61
|
* @hidden
|
|
60
62
|
*/
|
|
61
63
|
export interface UserContext extends Record<string, unknown> {
|
|
64
|
+
userId?: string;
|
|
65
|
+
sessionId?: string;
|
|
62
66
|
}
|
|
63
67
|
/**
|
|
64
68
|
* @hidden
|
package/lib/cjs/aigne/context.js
CHANGED
|
@@ -237,22 +237,12 @@ class AIGNEContext {
|
|
|
237
237
|
span.setAttribute("output", JSON.stringify({}));
|
|
238
238
|
}
|
|
239
239
|
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
240
|
-
await this.observer?.traceExporter
|
|
241
|
-
?.upsertInitialSpan?.(span)
|
|
242
|
-
.catch((err) => {
|
|
243
|
-
logger_js_1.logger.error("upsertInitialSpan error", err?.message || err);
|
|
244
|
-
});
|
|
245
240
|
span.end();
|
|
246
241
|
break;
|
|
247
242
|
}
|
|
248
243
|
case "agentFailed": {
|
|
249
244
|
const { error } = args[0];
|
|
250
245
|
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
251
|
-
await this.observer?.traceExporter
|
|
252
|
-
?.upsertInitialSpan?.(span)
|
|
253
|
-
.catch((err) => {
|
|
254
|
-
logger_js_1.logger.error("upsertInitialSpan error", err?.message || err);
|
|
255
|
-
});
|
|
256
246
|
span.end();
|
|
257
247
|
break;
|
|
258
248
|
}
|
package/lib/cjs/aigne/index.d.ts
CHANGED
package/lib/cjs/aigne/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./context.js"), exports);
|
|
18
17
|
__exportStar(require("./aigne.js"), exports);
|
|
18
|
+
__exportStar(require("./context.js"), exports);
|
|
19
19
|
__exportStar(require("./message-queue.js"), exports);
|
|
20
20
|
__exportStar(require("./usage.js"), exports);
|
|
@@ -45,7 +45,7 @@ class MessageQueue {
|
|
|
45
45
|
topic,
|
|
46
46
|
payload,
|
|
47
47
|
});
|
|
48
|
-
for (const t of (0, type_utils_js_1.
|
|
48
|
+
for (const t of (0, type_utils_js_1.flat)(topic)) {
|
|
49
49
|
this.events.emit(t, payload);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -76,19 +76,19 @@ class MessageQueue {
|
|
|
76
76
|
topic,
|
|
77
77
|
listener,
|
|
78
78
|
});
|
|
79
|
-
for (const t of (0, type_utils_js_1.
|
|
79
|
+
for (const t of (0, type_utils_js_1.flat)(topic)) {
|
|
80
80
|
this.events.off(t, listener);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
exports.MessageQueue = MessageQueue;
|
|
85
85
|
function on(events, event, listener) {
|
|
86
|
-
(0, type_utils_js_1.
|
|
87
|
-
return () => (0, type_utils_js_1.
|
|
86
|
+
(0, type_utils_js_1.flat)(event).forEach((e) => events.on(e, listener));
|
|
87
|
+
return () => (0, type_utils_js_1.flat)(event).forEach((e) => events.off(e, listener));
|
|
88
88
|
}
|
|
89
89
|
function once(events, event, listener) {
|
|
90
|
-
(0, type_utils_js_1.
|
|
91
|
-
return () => (0, type_utils_js_1.
|
|
90
|
+
(0, type_utils_js_1.flat)(event).forEach((e) => events.once(e, listener));
|
|
91
|
+
return () => (0, type_utils_js_1.flat)(event).forEach((e) => events.off(e, listener));
|
|
92
92
|
}
|
|
93
93
|
const subscribeArgsSchema = zod_1.z.object({
|
|
94
94
|
topic: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]),
|
package/lib/cjs/loader/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const ai_agent_js_1 = require("../agents/ai-agent.js");
|
|
|
12
12
|
const mcp_agent_js_1 = require("../agents/mcp-agent.js");
|
|
13
13
|
const team_agent_js_1 = require("../agents/team-agent.js");
|
|
14
14
|
const transform_agent_js_1 = require("../agents/transform-agent.js");
|
|
15
|
+
const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
|
|
15
16
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
16
17
|
const agent_js_js_1 = require("./agent-js.js");
|
|
17
18
|
const agent_yaml_js_1 = require("./agent-yaml.js");
|
|
@@ -61,6 +62,8 @@ async function parseAgent(path, agent, options) {
|
|
|
61
62
|
case "ai": {
|
|
62
63
|
return ai_agent_js_1.AIAgent.from({
|
|
63
64
|
...agent,
|
|
65
|
+
instructions: agent.instructions &&
|
|
66
|
+
prompt_builder_js_1.PromptBuilder.from(agent.instructions, { workingDir: index_js_1.nodejs.path.dirname(path) }),
|
|
64
67
|
memory,
|
|
65
68
|
skills,
|
|
66
69
|
});
|
|
@@ -5,8 +5,9 @@ import type { ChatModel, ChatModelInput } from "../agents/chat-model.js";
|
|
|
5
5
|
import { ChatMessagesTemplate } from "./template.js";
|
|
6
6
|
export interface PromptBuilderOptions {
|
|
7
7
|
instructions?: string | ChatMessagesTemplate;
|
|
8
|
+
workingDir?: string;
|
|
8
9
|
}
|
|
9
|
-
export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"
|
|
10
|
+
export interface PromptBuildOptions extends Partial<Pick<AgentInvokeOptions, "context">> {
|
|
10
11
|
agent?: AIAgent;
|
|
11
12
|
input?: Message;
|
|
12
13
|
model?: ChatModel;
|
|
@@ -15,11 +16,14 @@ export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context">
|
|
|
15
16
|
export declare class PromptBuilder {
|
|
16
17
|
static from(instructions: string | {
|
|
17
18
|
path: string;
|
|
18
|
-
} | GetPromptResult
|
|
19
|
+
} | GetPromptResult, { workingDir }?: {
|
|
20
|
+
workingDir?: string;
|
|
21
|
+
}): PromptBuilder;
|
|
19
22
|
private static fromFile;
|
|
20
23
|
private static fromMCPPromptResult;
|
|
21
24
|
constructor(options?: PromptBuilderOptions);
|
|
22
25
|
instructions?: string | ChatMessagesTemplate;
|
|
26
|
+
workingDir?: string;
|
|
23
27
|
build(options: PromptBuildOptions): Promise<ChatModelInput & {
|
|
24
28
|
toolAgents?: Agent[];
|
|
25
29
|
}>;
|
|
@@ -4,24 +4,26 @@ exports.PromptBuilder = void 0;
|
|
|
4
4
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
5
5
|
const yaml_1 = require("yaml");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
|
+
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
7
8
|
const agent_js_1 = require("../agents/agent.js");
|
|
8
9
|
const json_schema_js_1 = require("../utils/json-schema.js");
|
|
9
10
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
10
11
|
const memory_message_template_js_1 = require("./prompts/memory-message-template.js");
|
|
12
|
+
const structured_stream_instructions_js_1 = require("./prompts/structured-stream-instructions.js");
|
|
11
13
|
const template_js_1 = require("./template.js");
|
|
12
14
|
class PromptBuilder {
|
|
13
|
-
static from(instructions) {
|
|
15
|
+
static from(instructions, { workingDir } = {}) {
|
|
14
16
|
if (typeof instructions === "string")
|
|
15
|
-
return new PromptBuilder({ instructions });
|
|
17
|
+
return new PromptBuilder({ instructions, workingDir: workingDir });
|
|
16
18
|
if (isFromPromptResult(instructions))
|
|
17
19
|
return PromptBuilder.fromMCPPromptResult(instructions);
|
|
18
20
|
if (isFromPath(instructions))
|
|
19
|
-
return PromptBuilder.fromFile(instructions.path);
|
|
21
|
+
return PromptBuilder.fromFile(instructions.path, { workingDir });
|
|
20
22
|
throw new Error(`Invalid instructions ${instructions}`);
|
|
21
23
|
}
|
|
22
|
-
static fromFile(path) {
|
|
24
|
+
static fromFile(path, { workingDir }) {
|
|
23
25
|
const text = index_js_1.nodejs.fsSync.readFileSync(path, "utf-8");
|
|
24
|
-
return PromptBuilder.from(text);
|
|
26
|
+
return PromptBuilder.from(text, { workingDir: workingDir || index_js_1.nodejs.path.dirname(path) });
|
|
25
27
|
}
|
|
26
28
|
static fromMCPPromptResult(result) {
|
|
27
29
|
return new PromptBuilder({
|
|
@@ -53,12 +55,16 @@ class PromptBuilder {
|
|
|
53
55
|
}
|
|
54
56
|
constructor(options) {
|
|
55
57
|
this.instructions = options?.instructions;
|
|
58
|
+
this.workingDir = options?.workingDir;
|
|
56
59
|
}
|
|
57
60
|
instructions;
|
|
61
|
+
workingDir;
|
|
58
62
|
async build(options) {
|
|
59
63
|
return {
|
|
60
64
|
messages: await this.buildMessages(options),
|
|
61
|
-
responseFormat:
|
|
65
|
+
responseFormat: options.agent?.structuredStreamMode
|
|
66
|
+
? undefined
|
|
67
|
+
: this.buildResponseFormat(options),
|
|
62
68
|
...this.buildTools(options),
|
|
63
69
|
};
|
|
64
70
|
}
|
|
@@ -66,18 +72,30 @@ class PromptBuilder {
|
|
|
66
72
|
const { input } = options;
|
|
67
73
|
const inputKey = options.agent?.inputKey;
|
|
68
74
|
const message = inputKey && typeof input?.[inputKey] === "string" ? input[inputKey] : undefined;
|
|
69
|
-
const messages = (typeof this.instructions === "string"
|
|
75
|
+
const messages = (await (typeof this.instructions === "string"
|
|
70
76
|
? template_js_1.ChatMessagesTemplate.from([template_js_1.SystemMessageTemplate.from(this.instructions)])
|
|
71
|
-
: this.instructions)?.format(options.input) ?? [];
|
|
77
|
+
: this.instructions)?.format(options.input, { workingDir: this.workingDir })) ?? [];
|
|
72
78
|
const memories = [];
|
|
73
|
-
if (options.agent
|
|
74
|
-
memories.push(...(await options.agent.retrieveMemories({ search: message }, options)));
|
|
79
|
+
if (options.agent && options.context) {
|
|
80
|
+
memories.push(...(await options.agent.retrieveMemories({ search: message }, { context: options.context })));
|
|
75
81
|
}
|
|
76
|
-
if (options.context
|
|
82
|
+
if (options.context?.memories?.length) {
|
|
77
83
|
memories.push(...options.context.memories);
|
|
78
84
|
}
|
|
79
85
|
if (memories.length)
|
|
80
|
-
messages.push(...this.convertMemoriesToMessages(memories, options));
|
|
86
|
+
messages.push(...(await this.convertMemoriesToMessages(memories, options)));
|
|
87
|
+
// if the agent is using structured stream mode, add the instructions
|
|
88
|
+
const { structuredStreamMode, outputSchema } = options.agent || {};
|
|
89
|
+
if (structuredStreamMode && outputSchema) {
|
|
90
|
+
const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
|
|
91
|
+
PromptBuilder.from(structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS.instructions);
|
|
92
|
+
messages.push(...(await instructions.buildMessages({
|
|
93
|
+
input: {
|
|
94
|
+
...input,
|
|
95
|
+
outputJsonSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(outputSchema),
|
|
96
|
+
},
|
|
97
|
+
})));
|
|
98
|
+
}
|
|
81
99
|
if (message) {
|
|
82
100
|
messages.push({
|
|
83
101
|
role: "user",
|
|
@@ -86,14 +104,25 @@ class PromptBuilder {
|
|
|
86
104
|
}
|
|
87
105
|
return messages;
|
|
88
106
|
}
|
|
89
|
-
convertMemoriesToMessages(memories, options) {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
107
|
+
async convertMemoriesToMessages(memories, options) {
|
|
108
|
+
const messages = [];
|
|
109
|
+
const other = [];
|
|
110
|
+
const stringOrStringify = (value) => typeof value === "string" ? value : (0, yaml_1.stringify)(value);
|
|
111
|
+
for (const { content } of memories) {
|
|
112
|
+
if ((0, type_utils_js_1.isRecord)(content) && "input" in content && "output" in content) {
|
|
113
|
+
messages.push({ role: "user", content: stringOrStringify(content.input) }, { role: "agent", content: stringOrStringify(content.output) });
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
other.push(content);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (other.length) {
|
|
120
|
+
messages.unshift({
|
|
93
121
|
role: "system",
|
|
94
|
-
content: template_js_1.PromptTemplate.from(options.agent?.memoryPromptTemplate || memory_message_template_js_1.MEMORY_MESSAGE_TEMPLATE).format({ memories:
|
|
95
|
-
}
|
|
96
|
-
|
|
122
|
+
content: await template_js_1.PromptTemplate.from(options.agent?.memoryPromptTemplate || memory_message_template_js_1.MEMORY_MESSAGE_TEMPLATE).format({ memories: (0, yaml_1.stringify)(other) }),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return messages;
|
|
97
126
|
}
|
|
98
127
|
buildResponseFormat(options) {
|
|
99
128
|
const outputSchema = options.outputSchema || options.agent?.outputSchema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MEMORY_MESSAGE_TEMPLATE = "
|
|
1
|
+
export declare const MEMORY_MESSAGE_TEMPLATE = "<related-memories>\n{{memories}}\n</related-memories>\n";
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MEMORY_MESSAGE_TEMPLATE = void 0;
|
|
4
4
|
exports.MEMORY_MESSAGE_TEMPLATE = `\
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<memories>
|
|
5
|
+
<related-memories>
|
|
8
6
|
{{memories}}
|
|
9
|
-
</memories>
|
|
7
|
+
</related-memories>
|
|
10
8
|
`;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.STRUCTURED_STREAM_INSTRUCTIONS = void 0;
|
|
4
|
+
const yaml_1 = require("yaml");
|
|
5
|
+
exports.STRUCTURED_STREAM_INSTRUCTIONS = {
|
|
6
|
+
instructions: `\
|
|
7
|
+
<output-rules>
|
|
8
|
+
- First, output the regular response content.
|
|
9
|
+
- At the end of the response, use <metadata></metadata> tags to output metadata. The metadata should be output in YAML format as structured data, and must conform to the format defined in <metadata-schema></metadata-schema>.
|
|
10
|
+
</output-rules>
|
|
11
|
+
|
|
12
|
+
<metadata-schema>
|
|
13
|
+
{{outputJsonSchema}}
|
|
14
|
+
</metadata-schema>
|
|
15
|
+
|
|
16
|
+
<output-example>
|
|
17
|
+
Here is the regular response content
|
|
18
|
+
<metadata>
|
|
19
|
+
foo: bar
|
|
20
|
+
baz: 123
|
|
21
|
+
</metadata>
|
|
22
|
+
</output-example>
|
|
23
|
+
`,
|
|
24
|
+
metadataStart: "<metadata>",
|
|
25
|
+
metadataEnd: "</metadata>",
|
|
26
|
+
parse: yaml_1.parse,
|
|
27
|
+
};
|