@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.
Files changed (64) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/lib/cjs/agents/agent.d.ts +0 -2
  3. package/lib/cjs/agents/agent.js +4 -9
  4. package/lib/cjs/agents/ai-agent.d.ts +74 -0
  5. package/lib/cjs/agents/ai-agent.js +44 -4
  6. package/lib/cjs/agents/user-agent.js +1 -1
  7. package/lib/cjs/aigne/context.d.ts +4 -0
  8. package/lib/cjs/aigne/context.js +0 -10
  9. package/lib/cjs/aigne/index.d.ts +1 -1
  10. package/lib/cjs/aigne/index.js +1 -1
  11. package/lib/cjs/aigne/message-queue.js +6 -6
  12. package/lib/cjs/loader/index.js +3 -0
  13. package/lib/cjs/prompt/prompt-builder.d.ts +6 -2
  14. package/lib/cjs/prompt/prompt-builder.js +48 -19
  15. package/lib/cjs/prompt/prompts/memory-message-template.d.ts +1 -1
  16. package/lib/cjs/prompt/prompts/memory-message-template.js +2 -4
  17. package/lib/cjs/prompt/prompts/structured-stream-instructions.d.ts +7 -0
  18. package/lib/cjs/prompt/prompts/structured-stream-instructions.js +27 -0
  19. package/lib/cjs/prompt/template.d.ts +21 -7
  20. package/lib/cjs/prompt/template.js +57 -19
  21. package/lib/cjs/utils/mcp-utils.d.ts +1 -1
  22. package/lib/cjs/utils/stream-utils.js +3 -0
  23. package/lib/cjs/utils/structured-stream-extractor.d.ts +14 -0
  24. package/lib/cjs/utils/structured-stream-extractor.js +60 -0
  25. package/lib/cjs/utils/type-utils.d.ts +1 -1
  26. package/lib/cjs/utils/type-utils.js +3 -3
  27. package/lib/dts/agents/agent.d.ts +0 -2
  28. package/lib/dts/agents/ai-agent.d.ts +74 -0
  29. package/lib/dts/aigne/context.d.ts +4 -0
  30. package/lib/dts/aigne/index.d.ts +1 -1
  31. package/lib/dts/prompt/prompt-builder.d.ts +6 -2
  32. package/lib/dts/prompt/prompts/memory-message-template.d.ts +1 -1
  33. package/lib/dts/prompt/prompts/structured-stream-instructions.d.ts +7 -0
  34. package/lib/dts/prompt/template.d.ts +21 -7
  35. package/lib/dts/utils/mcp-utils.d.ts +1 -1
  36. package/lib/dts/utils/structured-stream-extractor.d.ts +14 -0
  37. package/lib/dts/utils/type-utils.d.ts +1 -1
  38. package/lib/esm/agents/agent.d.ts +0 -2
  39. package/lib/esm/agents/agent.js +5 -10
  40. package/lib/esm/agents/ai-agent.d.ts +74 -0
  41. package/lib/esm/agents/ai-agent.js +44 -4
  42. package/lib/esm/agents/user-agent.js +2 -2
  43. package/lib/esm/aigne/context.d.ts +4 -0
  44. package/lib/esm/aigne/context.js +1 -11
  45. package/lib/esm/aigne/index.d.ts +1 -1
  46. package/lib/esm/aigne/index.js +1 -1
  47. package/lib/esm/aigne/message-queue.js +7 -7
  48. package/lib/esm/loader/agent-js.js +1 -1
  49. package/lib/esm/loader/index.js +3 -0
  50. package/lib/esm/prompt/prompt-builder.d.ts +6 -2
  51. package/lib/esm/prompt/prompt-builder.js +49 -20
  52. package/lib/esm/prompt/prompts/memory-message-template.d.ts +1 -1
  53. package/lib/esm/prompt/prompts/memory-message-template.js +2 -4
  54. package/lib/esm/prompt/prompts/structured-stream-instructions.d.ts +7 -0
  55. package/lib/esm/prompt/prompts/structured-stream-instructions.js +24 -0
  56. package/lib/esm/prompt/template.d.ts +21 -7
  57. package/lib/esm/prompt/template.js +54 -17
  58. package/lib/esm/utils/mcp-utils.d.ts +1 -1
  59. package/lib/esm/utils/stream-utils.js +4 -1
  60. package/lib/esm/utils/structured-stream-extractor.d.ts +14 -0
  61. package/lib/esm/utils/structured-stream-extractor.js +56 -0
  62. package/lib/esm/utils/type-utils.d.ts +1 -1
  63. package/lib/esm/utils/type-utils.js +2 -2
  64. package/package.json +16 -14
@@ -1,16 +1,30 @@
1
+ import nunjucks, { type Callback, type LoaderSource } from "nunjucks";
1
2
  import type { ChatModelInputMessage, ChatModelInputMessageContent, ChatModelOutputToolCall } from "../agents/chat-model.js";
3
+ export interface FormatOptions {
4
+ workingDir?: string;
5
+ }
2
6
  export declare class PromptTemplate {
3
7
  template: string;
4
8
  static from(template: string): PromptTemplate;
5
9
  constructor(template: string);
6
- format(variables?: Record<string, unknown>): string;
10
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<string>;
11
+ }
12
+ export declare class CustomLoader extends nunjucks.Loader {
13
+ options: {
14
+ workingDir: string;
15
+ };
16
+ constructor(options: {
17
+ workingDir: string;
18
+ });
19
+ async: boolean;
20
+ getSource(name: string, callback: Callback<Error, LoaderSource>): LoaderSource;
7
21
  }
8
22
  export declare class ChatMessageTemplate {
9
23
  role: "system" | "user" | "agent" | "tool";
10
24
  content?: ChatModelInputMessage["content"];
11
25
  name?: string | undefined;
12
26
  constructor(role: "system" | "user" | "agent" | "tool", content?: ChatModelInputMessage["content"], name?: string | undefined);
13
- format(variables?: Record<string, unknown>): ChatModelInputMessage;
27
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<ChatModelInputMessage>;
14
28
  }
15
29
  export declare class SystemMessageTemplate extends ChatMessageTemplate {
16
30
  static from(content: string, name?: string): SystemMessageTemplate;
@@ -22,19 +36,19 @@ export declare class AgentMessageTemplate extends ChatMessageTemplate {
22
36
  toolCalls?: ChatModelOutputToolCall[] | undefined;
23
37
  static from(template?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[], name?: string): AgentMessageTemplate;
24
38
  constructor(content?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[] | undefined, name?: string);
25
- format(variables?: Record<string, unknown>): {
39
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<{
26
40
  toolCalls: ChatModelOutputToolCall[] | undefined;
27
41
  role: import("../agents/chat-model.js").Role;
28
42
  content?: ChatModelInputMessageContent;
29
43
  toolCallId?: string;
30
44
  name?: string;
31
- };
45
+ }>;
32
46
  }
33
47
  export declare class ToolMessageTemplate extends ChatMessageTemplate {
34
48
  toolCallId: string;
35
49
  static from(content: object | string, toolCallId: string, name?: string): ToolMessageTemplate;
36
50
  constructor(content: object | string, toolCallId: string, name?: string);
37
- format(variables?: Record<string, unknown>): {
51
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<{
38
52
  toolCallId: string;
39
53
  role: import("../agents/chat-model.js").Role;
40
54
  content?: ChatModelInputMessageContent;
@@ -47,12 +61,12 @@ export declare class ToolMessageTemplate extends ChatMessageTemplate {
47
61
  };
48
62
  }[];
49
63
  name?: string;
50
- };
64
+ }>;
51
65
  }
52
66
  export declare class ChatMessagesTemplate {
53
67
  messages: ChatMessageTemplate[];
54
68
  static from(messages: ChatMessageTemplate[] | string): ChatMessagesTemplate;
55
69
  constructor(messages: ChatMessageTemplate[]);
56
- format(variables?: Record<string, unknown>): ChatModelInputMessage[];
70
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<ChatModelInputMessage[]>;
57
71
  }
58
72
  export declare function parseChatMessages(messages: unknown): ChatMessageTemplate[] | undefined;
@@ -3,10 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ChatMessagesTemplate = exports.ToolMessageTemplate = exports.AgentMessageTemplate = exports.UserMessageTemplate = exports.SystemMessageTemplate = exports.ChatMessageTemplate = exports.PromptTemplate = void 0;
6
+ exports.ChatMessagesTemplate = exports.ToolMessageTemplate = exports.AgentMessageTemplate = exports.UserMessageTemplate = exports.SystemMessageTemplate = exports.ChatMessageTemplate = exports.CustomLoader = exports.PromptTemplate = void 0;
7
7
  exports.parseChatMessages = parseChatMessages;
8
- const mustache_1 = __importDefault(require("mustache"));
8
+ const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
9
+ const nunjucks_1 = __importDefault(require("nunjucks"));
9
10
  const zod_1 = require("zod");
11
+ const type_utils_js_1 = require("../utils/type-utils.js");
12
+ nunjucks_1.default.runtime.suppressValue = (v) => {
13
+ if ((0, type_utils_js_1.isNil)(v))
14
+ return "";
15
+ return typeof v === "object" ? JSON.stringify(v) : v;
16
+ };
10
17
  class PromptTemplate {
11
18
  template;
12
19
  static from(template) {
@@ -15,15 +22,46 @@ class PromptTemplate {
15
22
  constructor(template) {
16
23
  this.template = template;
17
24
  }
18
- format(variables) {
19
- return mustache_1.default.render(this.template, variables, undefined, {
20
- escape: (v) => {
21
- return typeof v === "object" ? JSON.stringify(v) : v;
22
- },
23
- });
25
+ async format(variables = {}, options) {
26
+ let env = new nunjucks_1.default.Environment();
27
+ if (options?.workingDir) {
28
+ env = new nunjucks_1.default.Environment(new CustomLoader({ workingDir: options.workingDir }));
29
+ }
30
+ return new Promise((resolve, reject) => env.renderString(this.template, variables, (err, res) => {
31
+ if (err || !res) {
32
+ reject(err || new Error(`Failed to render template: ${this.template}`));
33
+ }
34
+ else {
35
+ resolve(res);
36
+ }
37
+ }));
24
38
  }
25
39
  }
26
40
  exports.PromptTemplate = PromptTemplate;
41
+ class CustomLoader extends nunjucks_1.default.Loader {
42
+ options;
43
+ constructor(options) {
44
+ super();
45
+ this.options = options;
46
+ }
47
+ async = true;
48
+ getSource(name, callback) {
49
+ let result = null;
50
+ index_js_1.nodejs.fs.readFile(index_js_1.nodejs.path.join(this.options.workingDir, name), "utf-8").then((content) => {
51
+ result = {
52
+ src: content,
53
+ path: name,
54
+ noCache: true,
55
+ };
56
+ callback(null, result);
57
+ }, (error) => {
58
+ callback(error, null);
59
+ });
60
+ // nunjucks expects return LoaderSource synchronously, but we handle it asynchronously.
61
+ return result;
62
+ }
63
+ }
64
+ exports.CustomLoader = CustomLoader;
27
65
  class ChatMessageTemplate {
28
66
  role;
29
67
  content;
@@ -33,17 +71,17 @@ class ChatMessageTemplate {
33
71
  this.content = content;
34
72
  this.name = name;
35
73
  }
36
- format(variables) {
74
+ async format(variables, options) {
37
75
  let { content } = this;
38
76
  if (Array.isArray(content)) {
39
- content = content.map((i) => {
77
+ content = await Promise.all(content.map(async (i) => {
40
78
  if (i.type === "text")
41
- return { ...i, text: PromptTemplate.from(i.text).format(variables) };
79
+ return { ...i, text: await PromptTemplate.from(i.text).format(variables, options) };
42
80
  return i;
43
- });
81
+ }));
44
82
  }
45
83
  else if (typeof content === "string") {
46
- content = PromptTemplate.from(content).format(variables);
84
+ content = await PromptTemplate.from(content).format(variables, options);
47
85
  }
48
86
  return {
49
87
  role: this.role,
@@ -74,9 +112,9 @@ class AgentMessageTemplate extends ChatMessageTemplate {
74
112
  super("agent", content, name);
75
113
  this.toolCalls = toolCalls;
76
114
  }
77
- format(variables) {
115
+ async format(variables, options) {
78
116
  return {
79
- ...super.format(variables),
117
+ ...(await super.format(variables, options)),
80
118
  toolCalls: this.toolCalls,
81
119
  };
82
120
  }
@@ -93,9 +131,9 @@ class ToolMessageTemplate extends ChatMessageTemplate {
93
131
  : JSON.stringify(content, (_, value) => typeof value === "bigint" ? value.toString() : value), name);
94
132
  this.toolCallId = toolCallId;
95
133
  }
96
- format(variables) {
134
+ async format(variables, options) {
97
135
  return {
98
- ...super.format(variables),
136
+ ...(await super.format(variables, options)),
99
137
  toolCallId: this.toolCallId,
100
138
  };
101
139
  }
@@ -109,8 +147,8 @@ class ChatMessagesTemplate {
109
147
  constructor(messages) {
110
148
  this.messages = messages;
111
149
  }
112
- format(variables) {
113
- return this.messages.map((message) => message.format(variables));
150
+ async format(variables, options) {
151
+ return Promise.all(this.messages.map((message) => message.format(variables, options)));
114
152
  }
115
153
  }
116
154
  exports.ChatMessagesTemplate = ChatMessagesTemplate;
@@ -1,4 +1,4 @@
1
- import { type ListPromptsResult, type ListResourceTemplatesResult, type ListResourcesResult, type ListToolsResult } from "@modelcontextprotocol/sdk/types.js";
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;
@@ -21,6 +21,9 @@ const agent_js_1 = require("../agents/agent.js");
21
21
  const type_utils_js_1 = require("./type-utils.js");
22
22
  require("./stream-polyfill.js");
23
23
  function objectToAgentResponseStream(json) {
24
+ if (!(0, type_utils_js_1.isRecord)(json)) {
25
+ throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof json}): ${json}`);
26
+ }
24
27
  return new ReadableStream({
25
28
  pull(controller) {
26
29
  controller.enqueue({ delta: { json } });
@@ -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
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExtractMetadataTransform = void 0;
4
+ const agent_js_1 = require("../agents/agent.js");
5
+ class ExtractMetadataTransform extends TransformStream {
6
+ buffer = "";
7
+ cursor = 0;
8
+ state = "none";
9
+ constructor({ start, end, parse, }) {
10
+ super({
11
+ transform: async (chunk, controller) => {
12
+ if ((0, agent_js_1.isAgentResponseDelta)(chunk) && chunk.delta.text?.text) {
13
+ const text = chunk.delta.text.text;
14
+ this.buffer += text;
15
+ for (;;) {
16
+ if (this.state === "none") {
17
+ const found = findMatchIndex(this.buffer, this.cursor, start);
18
+ if (found.start > this.cursor) {
19
+ const text = this.buffer.slice(this.cursor, found.start);
20
+ this.cursor = found.start;
21
+ controller.enqueue({ delta: { text: { text } } });
22
+ }
23
+ if (found.end) {
24
+ this.state = "start";
25
+ this.cursor = found.end;
26
+ }
27
+ }
28
+ if (this.state === "start") {
29
+ const found = findMatchIndex(this.buffer, this.cursor, end);
30
+ if (found.end) {
31
+ const metadata = this.buffer.slice(this.cursor, found.start);
32
+ const json = parse(metadata);
33
+ controller.enqueue({ delta: { json: { json } } });
34
+ this.state = "none";
35
+ this.cursor = found.end;
36
+ continue;
37
+ }
38
+ }
39
+ break;
40
+ }
41
+ return;
42
+ }
43
+ controller.enqueue(chunk);
44
+ },
45
+ });
46
+ }
47
+ }
48
+ exports.ExtractMetadataTransform = ExtractMetadataTransform;
49
+ function findMatchIndex(str, position, match) {
50
+ const i = str.indexOf(match, position);
51
+ if (i >= 0)
52
+ return { start: i, end: i + match.length };
53
+ for (let i = match.length - 1; i > 0; i--) {
54
+ const m = match.slice(0, i);
55
+ if (str.endsWith(m)) {
56
+ return { start: str.length - m.length };
57
+ }
58
+ }
59
+ return { start: str.length };
60
+ }
@@ -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 orArrayToArray<T>(value?: T | T[]): T[];
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
  };
@@ -12,7 +12,7 @@ exports.pick = pick;
12
12
  exports.omit = omit;
13
13
  exports.omitDeep = omitDeep;
14
14
  exports.omitBy = omitBy;
15
- exports.orArrayToArray = orArrayToArray;
15
+ exports.flat = flat;
16
16
  exports.createAccessorArray = createAccessorArray;
17
17
  exports.checkArguments = checkArguments;
18
18
  exports.tryOrThrow = tryOrThrow;
@@ -55,7 +55,7 @@ function duplicates(arr, key = (item) => item) {
55
55
  function remove(arr, remove) {
56
56
  const removed = [];
57
57
  for (let i = 0; i < arr.length; i++) {
58
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
58
+ // biome-ignore lint/style/noNonNullAssertion: false positive
59
59
  const item = arr[i];
60
60
  if ((Array.isArray(remove) && remove.includes(item)) ||
61
61
  (typeof remove === "function" && remove(item))) {
@@ -102,7 +102,7 @@ function omitBy(obj, predicate) {
102
102
  return !predicate(value, k);
103
103
  }));
104
104
  }
105
- function orArrayToArray(value) {
105
+ function flat(value) {
106
106
  if (isNil(value))
107
107
  return [];
108
108
  return Array.isArray(value) ? value : [value];
@@ -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.
@@ -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
@@ -1,4 +1,4 @@
1
- export * from "./context.js";
2
1
  export * from "./aigne.js";
2
+ export * from "./context.js";
3
3
  export * from "./message-queue.js";
4
4
  export * from "./usage.js";
@@ -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): PromptBuilder;
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
  }>;
@@ -1 +1 @@
1
- export declare const MEMORY_MESSAGE_TEMPLATE = "Here are some useful memories to consider:\n\n<memories>\n{{memories}}\n</memories>\n";
1
+ export declare const MEMORY_MESSAGE_TEMPLATE = "<related-memories>\n{{memories}}\n</related-memories>\n";
@@ -0,0 +1,7 @@
1
+ import { parse } from "yaml";
2
+ export declare const STRUCTURED_STREAM_INSTRUCTIONS: {
3
+ instructions: string;
4
+ metadataStart: string;
5
+ metadataEnd: string;
6
+ parse: typeof parse;
7
+ };
@@ -1,16 +1,30 @@
1
+ import nunjucks, { type Callback, type LoaderSource } from "nunjucks";
1
2
  import type { ChatModelInputMessage, ChatModelInputMessageContent, ChatModelOutputToolCall } from "../agents/chat-model.js";
3
+ export interface FormatOptions {
4
+ workingDir?: string;
5
+ }
2
6
  export declare class PromptTemplate {
3
7
  template: string;
4
8
  static from(template: string): PromptTemplate;
5
9
  constructor(template: string);
6
- format(variables?: Record<string, unknown>): string;
10
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<string>;
11
+ }
12
+ export declare class CustomLoader extends nunjucks.Loader {
13
+ options: {
14
+ workingDir: string;
15
+ };
16
+ constructor(options: {
17
+ workingDir: string;
18
+ });
19
+ async: boolean;
20
+ getSource(name: string, callback: Callback<Error, LoaderSource>): LoaderSource;
7
21
  }
8
22
  export declare class ChatMessageTemplate {
9
23
  role: "system" | "user" | "agent" | "tool";
10
24
  content?: ChatModelInputMessage["content"];
11
25
  name?: string | undefined;
12
26
  constructor(role: "system" | "user" | "agent" | "tool", content?: ChatModelInputMessage["content"], name?: string | undefined);
13
- format(variables?: Record<string, unknown>): ChatModelInputMessage;
27
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<ChatModelInputMessage>;
14
28
  }
15
29
  export declare class SystemMessageTemplate extends ChatMessageTemplate {
16
30
  static from(content: string, name?: string): SystemMessageTemplate;
@@ -22,19 +36,19 @@ export declare class AgentMessageTemplate extends ChatMessageTemplate {
22
36
  toolCalls?: ChatModelOutputToolCall[] | undefined;
23
37
  static from(template?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[], name?: string): AgentMessageTemplate;
24
38
  constructor(content?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[] | undefined, name?: string);
25
- format(variables?: Record<string, unknown>): {
39
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<{
26
40
  toolCalls: ChatModelOutputToolCall[] | undefined;
27
41
  role: import("../agents/chat-model.js").Role;
28
42
  content?: ChatModelInputMessageContent;
29
43
  toolCallId?: string;
30
44
  name?: string;
31
- };
45
+ }>;
32
46
  }
33
47
  export declare class ToolMessageTemplate extends ChatMessageTemplate {
34
48
  toolCallId: string;
35
49
  static from(content: object | string, toolCallId: string, name?: string): ToolMessageTemplate;
36
50
  constructor(content: object | string, toolCallId: string, name?: string);
37
- format(variables?: Record<string, unknown>): {
51
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<{
38
52
  toolCallId: string;
39
53
  role: import("../agents/chat-model.js").Role;
40
54
  content?: ChatModelInputMessageContent;
@@ -47,12 +61,12 @@ export declare class ToolMessageTemplate extends ChatMessageTemplate {
47
61
  };
48
62
  }[];
49
63
  name?: string;
50
- };
64
+ }>;
51
65
  }
52
66
  export declare class ChatMessagesTemplate {
53
67
  messages: ChatMessageTemplate[];
54
68
  static from(messages: ChatMessageTemplate[] | string): ChatMessagesTemplate;
55
69
  constructor(messages: ChatMessageTemplate[]);
56
- format(variables?: Record<string, unknown>): ChatModelInputMessage[];
70
+ format(variables?: Record<string, unknown>, options?: FormatOptions): Promise<ChatModelInputMessage[]>;
57
71
  }
58
72
  export declare function parseChatMessages(messages: unknown): ChatMessageTemplate[] | undefined;
@@ -1,4 +1,4 @@
1
- import { type ListPromptsResult, type ListResourceTemplatesResult, type ListResourcesResult, type ListToolsResult } from "@modelcontextprotocol/sdk/types.js";
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 orArrayToArray<T>(value?: T | T[]): T[];
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.
@@ -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, isEmpty, orArrayToArray, } from "../utils/type-utils.js";
5
+ import { checkArguments, createAccessorArray, flat, isEmpty, isRecord, } 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 orArrayToArray(this.subscribeTopic).concat(this.topic)) {
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 });
@@ -357,6 +349,9 @@ export class Agent {
357
349
  */
358
350
  async processAgentOutput(input, output, options) {
359
351
  const { context } = options;
352
+ if (!isRecord(output)) {
353
+ throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof output}): ${output}`);
354
+ }
360
355
  const parsedOutput = checkArguments(`Agent ${this.name} output`, this.outputSchema, output);
361
356
  const finalOutput = this.includeInputInOutput ? { ...input, ...parsedOutput } : parsedOutput;
362
357
  await this.postprocess(input, finalOutput, options);