@aigne/core 1.29.0 → 1.31.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 +41 -0
- package/lib/cjs/agents/agent.d.ts +0 -2
- package/lib/cjs/agents/agent.js +1 -9
- package/lib/cjs/agents/ai-agent.d.ts +74 -0
- package/lib/cjs/agents/ai-agent.js +43 -3
- package/lib/cjs/agents/user-agent.js +1 -1
- package/lib/cjs/aigne/context.d.ts +4 -0
- 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/prompt/prompt-builder.d.ts +1 -1
- package/lib/cjs/prompt/prompt-builder.js +37 -10
- 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/utils/mcp-utils.d.ts +1 -1
- 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 +1 -1
- 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/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 +2 -10
- package/lib/esm/agents/ai-agent.d.ts +74 -0
- package/lib/esm/agents/ai-agent.js +43 -3
- 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 -1
- 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/prompt/prompt-builder.d.ts +1 -1
- package/lib/esm/prompt/prompt-builder.js +38 -11
- 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/utils/mcp-utils.d.ts +1 -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 +14 -14
|
@@ -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
|
*
|
|
@@ -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/dts/aigne/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { ChatMessagesTemplate } from "./template.js";
|
|
|
6
6
|
export interface PromptBuilderOptions {
|
|
7
7
|
instructions?: string | ChatMessagesTemplate;
|
|
8
8
|
}
|
|
9
|
-
export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"
|
|
9
|
+
export interface PromptBuildOptions extends Partial<Pick<AgentInvokeOptions, "context">> {
|
|
10
10
|
agent?: AIAgent;
|
|
11
11
|
input?: Message;
|
|
12
12
|
model?: ChatModel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MEMORY_MESSAGE_TEMPLATE = "
|
|
1
|
+
export declare const MEMORY_MESSAGE_TEMPLATE = "<related-memories>\n{{memories}}\n</related-memories>\n";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ListPromptsResult, type
|
|
1
|
+
import { type ListPromptsResult, type ListResourcesResult, type ListResourceTemplatesResult, type ListToolsResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import { type MCPBaseOptions, MCPPrompt, MCPResource, MCPTool } from "../agents/mcp-agent.js";
|
|
3
3
|
export declare function toolFromMCPTool(tool: ListToolsResult["tools"][number], options: MCPBaseOptions): MCPTool;
|
|
4
4
|
export declare function promptFromMCPPrompt(prompt: ListPromptsResult["prompts"][number], options: MCPBaseOptions): MCPPrompt;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type AgentResponseChunk } from "../agents/agent.js";
|
|
2
|
+
import type { ChatModelOutput } from "../agents/chat-model.js";
|
|
3
|
+
export declare class ExtractMetadataTransform extends TransformStream<AgentResponseChunk<ChatModelOutput>, AgentResponseChunk<ChatModelOutput & {
|
|
4
|
+
metadata?: string;
|
|
5
|
+
}>> {
|
|
6
|
+
private buffer;
|
|
7
|
+
private cursor;
|
|
8
|
+
private state;
|
|
9
|
+
constructor({ start, end, parse, }: {
|
|
10
|
+
start: string;
|
|
11
|
+
end: string;
|
|
12
|
+
parse: (raw: string) => object;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -19,7 +19,7 @@ export declare function pick<T extends object, K extends keyof T>(obj: T, ...key
|
|
|
19
19
|
export declare function omit<T extends object, K extends keyof T>(obj: T, ...keys: (K | K[])[]): Omit<T, K>;
|
|
20
20
|
export declare function omitDeep<T, K>(obj: T, ...keys: (K | K[])[]): unknown;
|
|
21
21
|
export declare function omitBy<T extends Record<string, unknown>, K extends keyof T>(obj: T, predicate: (value: T[K], key: K) => boolean): Partial<T>;
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function flat<T>(value?: T | T[]): T[];
|
|
23
23
|
export declare function createAccessorArray<T>(array: T[], accessor: (array: T[], name: string) => T | undefined): T[] & {
|
|
24
24
|
[key: string]: T;
|
|
25
25
|
};
|
|
@@ -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/esm/agents/agent.js
CHANGED
|
@@ -2,7 +2,7 @@ import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
|
2
2
|
import { ZodObject, z } from "zod";
|
|
3
3
|
import { logger } from "../utils/logger.js";
|
|
4
4
|
import { agentResponseStreamToObject, asyncGeneratorToReadableStream, isAsyncGenerator, objectToAgentResponseStream, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
|
|
5
|
-
import { checkArguments, createAccessorArray,
|
|
5
|
+
import { checkArguments, createAccessorArray, flat, isEmpty, } from "../utils/type-utils.js";
|
|
6
6
|
import { replaceTransferAgentToName, transferToAgentOutput, } from "./types.js";
|
|
7
7
|
export * from "./types.js";
|
|
8
8
|
export const agentOptionsSchema = z.object({
|
|
@@ -222,7 +222,7 @@ export class Agent {
|
|
|
222
222
|
this.subscribeToTopics(context);
|
|
223
223
|
}
|
|
224
224
|
subscribeToTopics(context) {
|
|
225
|
-
for (const topic of
|
|
225
|
+
for (const topic of flat(this.subscribeTopic).concat(this.topic)) {
|
|
226
226
|
this.subscriptions.push(context.subscribe(topic, (payload) => this.onMessage(payload)));
|
|
227
227
|
}
|
|
228
228
|
}
|
|
@@ -291,14 +291,6 @@ export class Agent {
|
|
|
291
291
|
...options,
|
|
292
292
|
context: options.context ?? (await this.newDefaultContext()),
|
|
293
293
|
};
|
|
294
|
-
if (options.userContext) {
|
|
295
|
-
Object.assign(opts.context.userContext, options.userContext);
|
|
296
|
-
options.userContext = undefined;
|
|
297
|
-
}
|
|
298
|
-
if (options.memories?.length) {
|
|
299
|
-
opts.context.memories.push(...options.memories);
|
|
300
|
-
options.memories = undefined;
|
|
301
|
-
}
|
|
302
294
|
logger.debug("Invoke agent %s started with input: %O", this.name, input);
|
|
303
295
|
if (!this.disableEvents)
|
|
304
296
|
opts.context.emit("agentStarted", { agent: this, input });
|
|
@@ -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
|
*
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { PromptBuilder } from "../prompt/prompt-builder.js";
|
|
3
|
+
import { STRUCTURED_STREAM_INSTRUCTIONS } from "../prompt/prompts/structured-stream-instructions.js";
|
|
3
4
|
import { AgentMessageTemplate, ToolMessageTemplate } from "../prompt/template.js";
|
|
5
|
+
import { ExtractMetadataTransform } from "../utils/structured-stream-extractor.js";
|
|
4
6
|
import { checkArguments, isEmpty } from "../utils/type-utils.js";
|
|
5
7
|
import { Agent, agentOptionsSchema, isAgentResponseDelta, } from "./agent.js";
|
|
6
8
|
import { isTransferAgentOutput } from "./types.js";
|
|
@@ -112,6 +114,13 @@ export class AIAgent extends Agent {
|
|
|
112
114
|
this.memoryPromptTemplate = options.memoryPromptTemplate;
|
|
113
115
|
if (typeof options.catchToolsError === "boolean")
|
|
114
116
|
this.catchToolsError = options.catchToolsError;
|
|
117
|
+
this.structuredStreamMode = options.structuredStreamMode;
|
|
118
|
+
this.customStructuredStreamInstructions = options.customStructuredStreamInstructions && {
|
|
119
|
+
...options.customStructuredStreamInstructions,
|
|
120
|
+
instructions: typeof options.customStructuredStreamInstructions.instructions === "string"
|
|
121
|
+
? PromptBuilder.from(options.customStructuredStreamInstructions.instructions)
|
|
122
|
+
: options.customStructuredStreamInstructions.instructions,
|
|
123
|
+
};
|
|
115
124
|
if (!this.inputKey && !this.instructions) {
|
|
116
125
|
throw new Error("AIAgent requires either inputKey or instructions to be set");
|
|
117
126
|
}
|
|
@@ -181,6 +190,33 @@ export class AIAgent extends Agent {
|
|
|
181
190
|
* @default true
|
|
182
191
|
*/
|
|
183
192
|
catchToolsError = true;
|
|
193
|
+
/**
|
|
194
|
+
* Whether to enable structured stream mode
|
|
195
|
+
*
|
|
196
|
+
* When enabled, the AI model's streaming response will be processed to extract
|
|
197
|
+
* structured metadata. The model needs to include specific format metadata tags
|
|
198
|
+
* (like <metadata></metadata>) in its response, which will be parsed as JSON
|
|
199
|
+
* objects and passed through the stream.
|
|
200
|
+
*
|
|
201
|
+
* This is useful for scenarios that need to extract structured information
|
|
202
|
+
* (like classifications, scores, tags, etc.) from AI responses.
|
|
203
|
+
*
|
|
204
|
+
* @default false
|
|
205
|
+
*/
|
|
206
|
+
structuredStreamMode;
|
|
207
|
+
/**
|
|
208
|
+
* Custom structured stream instructions configuration
|
|
209
|
+
*
|
|
210
|
+
* Allows customization of structured stream mode behavior, including:
|
|
211
|
+
* - instructions: Prompt instructions to guide the AI model on how to output structured data
|
|
212
|
+
* - metadataStart: Metadata start marker (e.g., "<metadata>")
|
|
213
|
+
* - metadataEnd: Metadata end marker (e.g., "</metadata>")
|
|
214
|
+
* - parse: Function to parse metadata content, converting raw string to object
|
|
215
|
+
*
|
|
216
|
+
* If not provided, the default STRUCTURED_STREAM_INSTRUCTIONS configuration will be used,
|
|
217
|
+
* which outputs structured data in YAML format within <metadata> tags.
|
|
218
|
+
*/
|
|
219
|
+
customStructuredStreamInstructions;
|
|
184
220
|
/**
|
|
185
221
|
* Process an input message and generate a response
|
|
186
222
|
*
|
|
@@ -204,7 +240,11 @@ export class AIAgent extends Agent {
|
|
|
204
240
|
const outputKey = this.outputKey;
|
|
205
241
|
for (;;) {
|
|
206
242
|
const modelOutput = {};
|
|
207
|
-
|
|
243
|
+
let stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
|
|
244
|
+
if (this.structuredStreamMode) {
|
|
245
|
+
const { metadataStart, metadataEnd, parse } = this.customStructuredStreamInstructions || STRUCTURED_STREAM_INSTRUCTIONS;
|
|
246
|
+
stream = stream.pipeThrough(new ExtractMetadataTransform({ start: metadataStart, end: metadataEnd, parse }));
|
|
247
|
+
}
|
|
208
248
|
for await (const value of stream) {
|
|
209
249
|
if (isAgentResponseDelta(value)) {
|
|
210
250
|
if (value.delta.text?.text) {
|
|
@@ -251,7 +291,7 @@ export class AIAgent extends Agent {
|
|
|
251
291
|
if (json) {
|
|
252
292
|
Object.assign(result, json);
|
|
253
293
|
}
|
|
254
|
-
|
|
294
|
+
if (text) {
|
|
255
295
|
Object.assign(result, { [outputKey]: text });
|
|
256
296
|
}
|
|
257
297
|
if (!isEmpty(result)) {
|
|
@@ -275,7 +315,7 @@ export class AIAgent extends Agent {
|
|
|
275
315
|
* @protected
|
|
276
316
|
*/
|
|
277
317
|
async *_processRouter(input, model, modelInput, options, toolsMap) {
|
|
278
|
-
const { toolCalls: [call] = []
|
|
318
|
+
const { toolCalls: [call] = [] } = await options.context.invoke(model, modelInput);
|
|
279
319
|
if (!call) {
|
|
280
320
|
throw new Error("Router toolChoice requires exactly one tool to be executed");
|
|
281
321
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toMessagePayload } from "../aigne/message-queue.js";
|
|
2
|
-
import {
|
|
2
|
+
import { flat } from "../utils/type-utils.js";
|
|
3
3
|
import { Agent, } from "./agent.js";
|
|
4
4
|
export class UserAgent extends Agent {
|
|
5
5
|
tag = "UserAgent";
|
|
@@ -67,7 +67,7 @@ export class UserAgent extends Agent {
|
|
|
67
67
|
let subscriptions = [];
|
|
68
68
|
return new ReadableStream({
|
|
69
69
|
start: (controller) => {
|
|
70
|
-
const subscribeTopic =
|
|
70
|
+
const subscribeTopic = flat(this.subscribeTopic);
|
|
71
71
|
subscriptions = subscribeTopic.map((topic) => this.subscribe(topic, (message) => {
|
|
72
72
|
controller.enqueue({ ...message, topic });
|
|
73
73
|
}));
|
|
@@ -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/esm/aigne/context.js
CHANGED
package/lib/esm/aigne/index.d.ts
CHANGED
package/lib/esm/aigne/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Emitter } from "strict-event-emitter";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { checkArguments,
|
|
3
|
+
import { checkArguments, flat, isNil } from "../utils/type-utils.js";
|
|
4
4
|
/**
|
|
5
5
|
* @hidden
|
|
6
6
|
*/
|
|
@@ -41,7 +41,7 @@ export class MessageQueue {
|
|
|
41
41
|
topic,
|
|
42
42
|
payload,
|
|
43
43
|
});
|
|
44
|
-
for (const t of
|
|
44
|
+
for (const t of flat(topic)) {
|
|
45
45
|
this.events.emit(t, payload);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -72,18 +72,18 @@ export class MessageQueue {
|
|
|
72
72
|
topic,
|
|
73
73
|
listener,
|
|
74
74
|
});
|
|
75
|
-
for (const t of
|
|
75
|
+
for (const t of flat(topic)) {
|
|
76
76
|
this.events.off(t, listener);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
function on(events, event, listener) {
|
|
81
|
-
|
|
82
|
-
return () =>
|
|
81
|
+
flat(event).forEach((e) => events.on(e, listener));
|
|
82
|
+
return () => flat(event).forEach((e) => events.off(e, listener));
|
|
83
83
|
}
|
|
84
84
|
function once(events, event, listener) {
|
|
85
|
-
|
|
86
|
-
return () =>
|
|
85
|
+
flat(event).forEach((e) => events.once(e, listener));
|
|
86
|
+
return () => flat(event).forEach((e) => events.off(e, listener));
|
|
87
87
|
}
|
|
88
88
|
const subscribeArgsSchema = z.object({
|
|
89
89
|
topic: z.union([z.string(), z.array(z.string())]),
|
|
@@ -12,7 +12,7 @@ const agentJsFileSchema = z.object({
|
|
|
12
12
|
process: z.custom(),
|
|
13
13
|
});
|
|
14
14
|
export async function loadAgentFromJsFile(path) {
|
|
15
|
-
const { default: agent } = await tryOrThrow(() => import(path), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
|
|
15
|
+
const { default: agent } = await tryOrThrow(() => import(/* @vite-ignore */ path), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
|
|
16
16
|
if (agent instanceof Agent)
|
|
17
17
|
return agent;
|
|
18
18
|
if (typeof agent !== "function") {
|
|
@@ -6,7 +6,7 @@ import { ChatMessagesTemplate } from "./template.js";
|
|
|
6
6
|
export interface PromptBuilderOptions {
|
|
7
7
|
instructions?: string | ChatMessagesTemplate;
|
|
8
8
|
}
|
|
9
|
-
export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"
|
|
9
|
+
export interface PromptBuildOptions extends Partial<Pick<AgentInvokeOptions, "context">> {
|
|
10
10
|
agent?: AIAgent;
|
|
11
11
|
input?: Message;
|
|
12
12
|
model?: ChatModel;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
2
2
|
import { stringify } from "yaml";
|
|
3
3
|
import { ZodObject } from "zod";
|
|
4
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
4
5
|
import { Agent } from "../agents/agent.js";
|
|
5
6
|
import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
|
|
6
|
-
import { unique } from "../utils/type-utils.js";
|
|
7
|
+
import { isRecord, unique } from "../utils/type-utils.js";
|
|
7
8
|
import { MEMORY_MESSAGE_TEMPLATE } from "./prompts/memory-message-template.js";
|
|
9
|
+
import { STRUCTURED_STREAM_INSTRUCTIONS } from "./prompts/structured-stream-instructions.js";
|
|
8
10
|
import { AgentMessageTemplate, ChatMessagesTemplate, PromptTemplate, SystemMessageTemplate, UserMessageTemplate, } from "./template.js";
|
|
9
11
|
export class PromptBuilder {
|
|
10
12
|
static from(instructions) {
|
|
@@ -55,7 +57,9 @@ export class PromptBuilder {
|
|
|
55
57
|
async build(options) {
|
|
56
58
|
return {
|
|
57
59
|
messages: await this.buildMessages(options),
|
|
58
|
-
responseFormat:
|
|
60
|
+
responseFormat: options.agent?.structuredStreamMode
|
|
61
|
+
? undefined
|
|
62
|
+
: this.buildResponseFormat(options),
|
|
59
63
|
...this.buildTools(options),
|
|
60
64
|
};
|
|
61
65
|
}
|
|
@@ -67,14 +71,26 @@ export class PromptBuilder {
|
|
|
67
71
|
? ChatMessagesTemplate.from([SystemMessageTemplate.from(this.instructions)])
|
|
68
72
|
: this.instructions)?.format(options.input) ?? [];
|
|
69
73
|
const memories = [];
|
|
70
|
-
if (options.agent
|
|
71
|
-
memories.push(...(await options.agent.retrieveMemories({ search: message }, options)));
|
|
74
|
+
if (options.agent && options.context) {
|
|
75
|
+
memories.push(...(await options.agent.retrieveMemories({ search: message }, { context: options.context })));
|
|
72
76
|
}
|
|
73
|
-
if (options.context
|
|
77
|
+
if (options.context?.memories?.length) {
|
|
74
78
|
memories.push(...options.context.memories);
|
|
75
79
|
}
|
|
76
80
|
if (memories.length)
|
|
77
81
|
messages.push(...this.convertMemoriesToMessages(memories, options));
|
|
82
|
+
// if the agent is using structured stream mode, add the instructions
|
|
83
|
+
const { structuredStreamMode, outputSchema } = options.agent || {};
|
|
84
|
+
if (structuredStreamMode && outputSchema) {
|
|
85
|
+
const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
|
|
86
|
+
PromptBuilder.from(STRUCTURED_STREAM_INSTRUCTIONS.instructions);
|
|
87
|
+
messages.push(...(await instructions.buildMessages({
|
|
88
|
+
input: {
|
|
89
|
+
...input,
|
|
90
|
+
outputJsonSchema: zodToJsonSchema(outputSchema),
|
|
91
|
+
},
|
|
92
|
+
})));
|
|
93
|
+
}
|
|
78
94
|
if (message) {
|
|
79
95
|
messages.push({
|
|
80
96
|
role: "user",
|
|
@@ -84,13 +100,24 @@ export class PromptBuilder {
|
|
|
84
100
|
return messages;
|
|
85
101
|
}
|
|
86
102
|
convertMemoriesToMessages(memories, options) {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
const messages = [];
|
|
104
|
+
const other = [];
|
|
105
|
+
const stringOrStringify = (value) => typeof value === "string" ? value : stringify(value);
|
|
106
|
+
for (const { content } of memories) {
|
|
107
|
+
if (isRecord(content) && "input" in content && "output" in content) {
|
|
108
|
+
messages.push({ role: "user", content: stringOrStringify(content.input) }, { role: "agent", content: stringOrStringify(content.output) });
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
other.push(content);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (other.length) {
|
|
115
|
+
messages.unshift({
|
|
90
116
|
role: "system",
|
|
91
|
-
content: PromptTemplate.from(options.agent?.memoryPromptTemplate || MEMORY_MESSAGE_TEMPLATE).format({ memories:
|
|
92
|
-
}
|
|
93
|
-
|
|
117
|
+
content: PromptTemplate.from(options.agent?.memoryPromptTemplate || MEMORY_MESSAGE_TEMPLATE).format({ memories: stringify(other) }),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return messages;
|
|
94
121
|
}
|
|
95
122
|
buildResponseFormat(options) {
|
|
96
123
|
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";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { parse } from "yaml";
|
|
2
|
+
export const STRUCTURED_STREAM_INSTRUCTIONS = {
|
|
3
|
+
instructions: `\
|
|
4
|
+
<output-rules>
|
|
5
|
+
- First, output the regular response content.
|
|
6
|
+
- 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>.
|
|
7
|
+
</output-rules>
|
|
8
|
+
|
|
9
|
+
<metadata-schema>
|
|
10
|
+
{{outputJsonSchema}}
|
|
11
|
+
</metadata-schema>
|
|
12
|
+
|
|
13
|
+
<output-example>
|
|
14
|
+
Here is the regular response content
|
|
15
|
+
<metadata>
|
|
16
|
+
foo: bar
|
|
17
|
+
baz: 123
|
|
18
|
+
</metadata>
|
|
19
|
+
</output-example>
|
|
20
|
+
`,
|
|
21
|
+
metadataStart: "<metadata>",
|
|
22
|
+
metadataEnd: "</metadata>",
|
|
23
|
+
parse,
|
|
24
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ListPromptsResult, type
|
|
1
|
+
import { type ListPromptsResult, type ListResourcesResult, type ListResourceTemplatesResult, type ListToolsResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import { type MCPBaseOptions, MCPPrompt, MCPResource, MCPTool } from "../agents/mcp-agent.js";
|
|
3
3
|
export declare function toolFromMCPTool(tool: ListToolsResult["tools"][number], options: MCPBaseOptions): MCPTool;
|
|
4
4
|
export declare function promptFromMCPPrompt(prompt: ListPromptsResult["prompts"][number], options: MCPBaseOptions): MCPPrompt;
|