@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.
Files changed (54) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/lib/cjs/agents/agent.d.ts +0 -2
  3. package/lib/cjs/agents/agent.js +1 -9
  4. package/lib/cjs/agents/ai-agent.d.ts +74 -0
  5. package/lib/cjs/agents/ai-agent.js +43 -3
  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/index.d.ts +1 -1
  9. package/lib/cjs/aigne/index.js +1 -1
  10. package/lib/cjs/aigne/message-queue.js +6 -6
  11. package/lib/cjs/prompt/prompt-builder.d.ts +1 -1
  12. package/lib/cjs/prompt/prompt-builder.js +37 -10
  13. package/lib/cjs/prompt/prompts/memory-message-template.d.ts +1 -1
  14. package/lib/cjs/prompt/prompts/memory-message-template.js +2 -4
  15. package/lib/cjs/prompt/prompts/structured-stream-instructions.d.ts +7 -0
  16. package/lib/cjs/prompt/prompts/structured-stream-instructions.js +27 -0
  17. package/lib/cjs/utils/mcp-utils.d.ts +1 -1
  18. package/lib/cjs/utils/structured-stream-extractor.d.ts +14 -0
  19. package/lib/cjs/utils/structured-stream-extractor.js +60 -0
  20. package/lib/cjs/utils/type-utils.d.ts +1 -1
  21. package/lib/cjs/utils/type-utils.js +3 -3
  22. package/lib/dts/agents/agent.d.ts +0 -2
  23. package/lib/dts/agents/ai-agent.d.ts +74 -0
  24. package/lib/dts/aigne/context.d.ts +4 -0
  25. package/lib/dts/aigne/index.d.ts +1 -1
  26. package/lib/dts/prompt/prompt-builder.d.ts +1 -1
  27. package/lib/dts/prompt/prompts/memory-message-template.d.ts +1 -1
  28. package/lib/dts/prompt/prompts/structured-stream-instructions.d.ts +7 -0
  29. package/lib/dts/utils/mcp-utils.d.ts +1 -1
  30. package/lib/dts/utils/structured-stream-extractor.d.ts +14 -0
  31. package/lib/dts/utils/type-utils.d.ts +1 -1
  32. package/lib/esm/agents/agent.d.ts +0 -2
  33. package/lib/esm/agents/agent.js +2 -10
  34. package/lib/esm/agents/ai-agent.d.ts +74 -0
  35. package/lib/esm/agents/ai-agent.js +43 -3
  36. package/lib/esm/agents/user-agent.js +2 -2
  37. package/lib/esm/aigne/context.d.ts +4 -0
  38. package/lib/esm/aigne/context.js +1 -1
  39. package/lib/esm/aigne/index.d.ts +1 -1
  40. package/lib/esm/aigne/index.js +1 -1
  41. package/lib/esm/aigne/message-queue.js +7 -7
  42. package/lib/esm/loader/agent-js.js +1 -1
  43. package/lib/esm/prompt/prompt-builder.d.ts +1 -1
  44. package/lib/esm/prompt/prompt-builder.js +38 -11
  45. package/lib/esm/prompt/prompts/memory-message-template.d.ts +1 -1
  46. package/lib/esm/prompt/prompts/memory-message-template.js +2 -4
  47. package/lib/esm/prompt/prompts/structured-stream-instructions.d.ts +7 -0
  48. package/lib/esm/prompt/prompts/structured-stream-instructions.js +24 -0
  49. package/lib/esm/utils/mcp-utils.d.ts +1 -1
  50. package/lib/esm/utils/structured-stream-extractor.d.ts +14 -0
  51. package/lib/esm/utils/structured-stream-extractor.js +56 -0
  52. package/lib/esm/utils/type-utils.d.ts +1 -1
  53. package/lib/esm/utils/type-utils.js +2 -2
  54. package/package.json +14 -14
package/CHANGELOG.md CHANGED
@@ -12,6 +12,47 @@
12
12
  * dependencies
13
13
  * @aigne/observability bumped to 0.1.0
14
14
 
15
+ ## [1.31.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.30.0...core-v1.31.0) (2025-07-04)
16
+
17
+
18
+ ### Features
19
+
20
+ * **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))
21
+ * **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))
22
+ * **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))
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @aigne/observability-api bumped to 0.5.0
30
+ * @aigne/platform-helpers bumped to 0.3.0
31
+
32
+ ## [1.30.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.29.1...core-v1.30.0) (2025-07-03)
33
+
34
+
35
+ ### Features
36
+
37
+ * 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))
38
+
39
+
40
+ ### Dependencies
41
+
42
+ * The following workspace dependencies were updated
43
+ * dependencies
44
+ * @aigne/observability-api bumped to 0.4.0
45
+ * @aigne/platform-helpers bumped to 0.2.0
46
+
47
+ ## [1.29.1](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.29.0...core-v1.29.1) (2025-07-02)
48
+
49
+
50
+ ### Dependencies
51
+
52
+ * The following workspace dependencies were updated
53
+ * dependencies
54
+ * @aigne/observability-api bumped to 0.3.3
55
+
15
56
  ## [1.29.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.28.2...core-v1.29.0) (2025-07-02)
16
57
 
17
58
 
@@ -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.
@@ -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.orArrayToArray)(this.subscribeTopic).concat(this.topic)) {
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 });
@@ -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
- const stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
246
+ let stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { 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) {
@@ -254,7 +294,7 @@ class AIAgent extends agent_js_1.Agent {
254
294
  if (json) {
255
295
  Object.assign(result, json);
256
296
  }
257
- else if (text) {
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] = [], } = await options.context.invoke(model, modelInput);
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.orArrayToArray)(this.subscribeTopic);
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
@@ -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";
@@ -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.orArrayToArray)(topic)) {
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.orArrayToArray)(topic)) {
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.orArrayToArray)(event).forEach((e) => events.on(e, listener));
87
- return () => (0, type_utils_js_1.orArrayToArray)(event).forEach((e) => events.off(e, listener));
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.orArrayToArray)(event).forEach((e) => events.once(e, listener));
91
- return () => (0, type_utils_js_1.orArrayToArray)(event).forEach((e) => events.off(e, listener));
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())]),
@@ -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;
@@ -4,10 +4,12 @@ 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
15
  static from(instructions) {
@@ -58,7 +60,9 @@ class PromptBuilder {
58
60
  async build(options) {
59
61
  return {
60
62
  messages: await this.buildMessages(options),
61
- responseFormat: this.buildResponseFormat(options),
63
+ responseFormat: options.agent?.structuredStreamMode
64
+ ? undefined
65
+ : this.buildResponseFormat(options),
62
66
  ...this.buildTools(options),
63
67
  };
64
68
  }
@@ -70,14 +74,26 @@ class PromptBuilder {
70
74
  ? template_js_1.ChatMessagesTemplate.from([template_js_1.SystemMessageTemplate.from(this.instructions)])
71
75
  : this.instructions)?.format(options.input) ?? [];
72
76
  const memories = [];
73
- if (options.agent?.inputKey) {
74
- memories.push(...(await options.agent.retrieveMemories({ search: message }, options)));
77
+ if (options.agent && options.context) {
78
+ memories.push(...(await options.agent.retrieveMemories({ search: message }, { context: options.context })));
75
79
  }
76
- if (options.context.memories?.length) {
80
+ if (options.context?.memories?.length) {
77
81
  memories.push(...options.context.memories);
78
82
  }
79
83
  if (memories.length)
80
84
  messages.push(...this.convertMemoriesToMessages(memories, options));
85
+ // if the agent is using structured stream mode, add the instructions
86
+ const { structuredStreamMode, outputSchema } = options.agent || {};
87
+ if (structuredStreamMode && outputSchema) {
88
+ const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
89
+ PromptBuilder.from(structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS.instructions);
90
+ messages.push(...(await instructions.buildMessages({
91
+ input: {
92
+ ...input,
93
+ outputJsonSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(outputSchema),
94
+ },
95
+ })));
96
+ }
81
97
  if (message) {
82
98
  messages.push({
83
99
  role: "user",
@@ -87,13 +103,24 @@ class PromptBuilder {
87
103
  return messages;
88
104
  }
89
105
  convertMemoriesToMessages(memories, options) {
90
- const str = (0, yaml_1.stringify)(memories.map((i) => i.content));
91
- return [
92
- {
106
+ const messages = [];
107
+ const other = [];
108
+ const stringOrStringify = (value) => typeof value === "string" ? value : (0, yaml_1.stringify)(value);
109
+ for (const { content } of memories) {
110
+ if ((0, type_utils_js_1.isRecord)(content) && "input" in content && "output" in content) {
111
+ messages.push({ role: "user", content: stringOrStringify(content.input) }, { role: "agent", content: stringOrStringify(content.output) });
112
+ }
113
+ else {
114
+ other.push(content);
115
+ }
116
+ }
117
+ if (other.length) {
118
+ messages.unshift({
93
119
  role: "system",
94
- content: template_js_1.PromptTemplate.from(options.agent?.memoryPromptTemplate || memory_message_template_js_1.MEMORY_MESSAGE_TEMPLATE).format({ memories: str }),
95
- },
96
- ];
120
+ content: template_js_1.PromptTemplate.from(options.agent?.memoryPromptTemplate || memory_message_template_js_1.MEMORY_MESSAGE_TEMPLATE).format({ memories: (0, yaml_1.stringify)(other) }),
121
+ });
122
+ }
123
+ return messages;
97
124
  }
98
125
  buildResponseFormat(options) {
99
126
  const outputSchema = options.outputSchema || options.agent?.outputSchema;
@@ -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";
@@ -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
- Here are some useful memories to consider:
6
-
7
- <memories>
5
+ <related-memories>
8
6
  {{memories}}
9
- </memories>
7
+ </related-memories>
10
8
  `;
@@ -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
+ };
@@ -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
+ };
@@ -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
+ }
@@ -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.