@aigne/core 1.72.0-beta.5 → 1.72.0-beta.7

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 CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.72.0-beta.7](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.6...core-v1.72.0-beta.7) (2025-12-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * **core:** add session history support ([#858](https://github.com/AIGNE-io/aigne-framework/issues/858)) ([28a070e](https://github.com/AIGNE-io/aigne-framework/commit/28a070ed33b821d1fd344b899706d817ca992b9f))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @aigne/afs bumped to 1.4.0-beta.4
16
+ * @aigne/afs-history bumped to 1.2.0-beta.4
17
+
18
+ ## [1.72.0-beta.6](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.5...core-v1.72.0-beta.6) (2025-12-25)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **core:** passthrough model options in chat model ([#856](https://github.com/AIGNE-io/aigne-framework/issues/856)) ([41387bd](https://github.com/AIGNE-io/aigne-framework/commit/41387bde0a615080ea5d665e998afb0b9c32c5fd))
24
+
3
25
  ## [1.72.0-beta.5](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.4...core-v1.72.0-beta.5) (2025-12-25)
4
26
 
5
27
 
@@ -9,7 +9,7 @@ import type { Memory, MemoryAgent } from "../memory/memory.js";
9
9
  import type { MemoryRecorderInput } from "../memory/recorder.js";
10
10
  import type { MemoryRetrieverInput } from "../memory/retriever.js";
11
11
  import { type Nullish, type PromiseOrValue, type XOr } from "../utils/type-utils.js";
12
- import type { ChatModel } from "./chat-model.js";
12
+ import type { ChatModel, ChatModelInputMessage } from "./chat-model.js";
13
13
  import type { GuideRailAgent, GuideRailAgentOutput } from "./guide-rail-agent.js";
14
14
  import type { ImageModel } from "./image-model.js";
15
15
  import { type GetterSchema, type TransferAgentOutput } from "./types.js";
@@ -350,7 +350,20 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
350
350
  */
351
351
  private disableEvents?;
352
352
  historyConfig?: {
353
- disabled?: boolean;
353
+ /**
354
+ * Whether to enable history recording and injection
355
+ * @default false
356
+ */
357
+ enabled?: boolean;
358
+ /**
359
+ * Whether to record history entries, default to enabled when history is enabled
360
+ */
361
+ record?: boolean;
362
+ /**
363
+ * Whether to inject history entries into the context, default to enabled when history is enabled
364
+ */
365
+ inject?: boolean;
366
+ useOldMemory?: boolean;
354
367
  maxTokens?: number;
355
368
  maxItems?: number;
356
369
  };
@@ -455,7 +468,9 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
455
468
  * @param options Invocation options
456
469
  * @returns Final processed output
457
470
  */
458
- protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, options: AgentInvokeOptions): Promise<O>;
471
+ protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, { messages, ...options }: AgentInvokeOptions & {
472
+ messages?: ChatModelInputMessage[];
473
+ }): Promise<O>;
459
474
  /**
460
475
  * Process errors that occur during agent execution
461
476
  *
@@ -785,29 +800,29 @@ export interface AgentResponseProgress {
785
800
  error: Error;
786
801
  } | {
787
802
  event: "message";
788
- role: "user" | "agent";
789
- message: ({
790
- type: "text";
791
- content: string;
792
- } | {
793
- type: "thinking";
794
- thoughts: string;
795
- } | {
796
- type: "tool_use";
797
- toolUseId: string;
798
- name: string;
799
- input: unknown;
800
- } | {
801
- type: "tool_result";
802
- toolUseId: string;
803
- content: unknown;
804
- })[];
803
+ message: ChatModelInputMessage;
805
804
  }) & Omit<AgentEvent, "agent"> & {
806
805
  agent: {
807
806
  name: string;
808
807
  };
809
808
  };
810
809
  }
810
+ export type AgentResponseProgressMessageItem = {
811
+ type: "text";
812
+ content: string;
813
+ } | {
814
+ type: "thinking";
815
+ thoughts: string;
816
+ } | {
817
+ type: "tool_use";
818
+ toolUseId: string;
819
+ name: string;
820
+ input: unknown;
821
+ } | {
822
+ type: "tool_result";
823
+ toolUseId: string;
824
+ content: unknown;
825
+ };
811
826
  export declare function isAgentResponseProgress<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseProgress;
812
827
  /**
813
828
  * Creates a text delta for streaming responses
@@ -463,11 +463,15 @@ class Agent {
463
463
  : (0, stream_utils_js_1.isAsyncGenerator)(response)
464
464
  ? (0, stream_utils_js_1.asyncGeneratorToReadableStream)(response)
465
465
  : (0, stream_utils_js_1.objectToAgentResponseStream)(response);
466
+ const messages = [];
466
467
  for await (const chunk of stream) {
467
468
  (0, stream_utils_js_1.mergeAgentResponseChunk)(output, chunk);
468
469
  yield chunk;
470
+ if (isAgentResponseProgress(chunk) && chunk.progress.event === "message") {
471
+ messages.push(chunk.progress.message);
472
+ }
469
473
  }
470
- let result = await this.processAgentOutput(input, output, options);
474
+ let result = await this.processAgentOutput(input, output, { ...options, messages });
471
475
  if (attempt > 0) {
472
476
  result = { ...result, $meta: { ...result.$meta, retries: attempt } };
473
477
  }
@@ -564,7 +568,7 @@ class Agent {
564
568
  * @param options Invocation options
565
569
  * @returns Final processed output
566
570
  */
567
- async processAgentOutput(input, output, options) {
571
+ async processAgentOutput(input, output, { messages, ...options }) {
568
572
  const { context } = options;
569
573
  if (!(0, type_utils_js_1.isRecord)(output)) {
570
574
  throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof output}): ${output}`);
@@ -576,8 +580,17 @@ class Agent {
576
580
  const o = await this.callHooks(["onSuccess", "onEnd"], { input, output: finalOutput }, options);
577
581
  if (o?.output)
578
582
  finalOutput = o.output;
579
- if (this.historyConfig?.disabled !== true)
580
- this.afs?.emit("agentSucceed", { input, output: finalOutput });
583
+ if (this.historyConfig?.record === true ||
584
+ (this.historyConfig?.record !== false && this.historyConfig?.enabled)) {
585
+ this.afs?.emit("agentSucceed", {
586
+ agentId: this.name,
587
+ userId: context.userContext.userId,
588
+ sessionId: context.userContext.sessionId,
589
+ input,
590
+ output: finalOutput,
591
+ messages,
592
+ });
593
+ }
581
594
  if (!this.disableEvents)
582
595
  context.emit("agentSucceed", { agent: this, output: finalOutput });
583
596
  return finalOutput;
@@ -349,8 +349,10 @@ class AIAgent extends agent_js_1.Agent {
349
349
  yield {
350
350
  progress: {
351
351
  event: "message",
352
- role: "user",
353
- message: [{ type: "text", content: inputMessage }],
352
+ message: {
353
+ role: "user",
354
+ content: [{ type: "text", text: inputMessage }],
355
+ },
354
356
  },
355
357
  };
356
358
  }
@@ -379,15 +381,22 @@ class AIAgent extends agent_js_1.Agent {
379
381
  }
380
382
  }
381
383
  const { toolCalls, json, text, thoughts, files } = modelOutput;
382
- if (text) {
383
- yield {
384
- progress: { event: "message", role: "agent", message: [{ type: "text", content: text }] },
385
- };
386
- }
387
- if (thoughts) {
388
- yield {
389
- progress: { event: "message", role: "agent", message: [{ type: "thinking", thoughts }] },
390
- };
384
+ if (text || thoughts) {
385
+ const content = [];
386
+ if (thoughts) {
387
+ content.push({ type: "text", text: thoughts, isThinking: true });
388
+ }
389
+ if (text) {
390
+ content.push({ type: "text", text });
391
+ }
392
+ if (content.length) {
393
+ yield {
394
+ progress: {
395
+ event: "message",
396
+ message: { role: "agent", content },
397
+ },
398
+ };
399
+ }
391
400
  }
392
401
  if (toolCalls?.length) {
393
402
  if (this.keepTextInToolUses !== true) {
@@ -419,25 +428,14 @@ class AIAgent extends agent_js_1.Agent {
419
428
  queue.killAndDrain();
420
429
  }
421
430
  }, this.toolCallsConcurrency || 1);
431
+ yield {
432
+ progress: { event: "message", message: { role: "agent", toolCalls } },
433
+ };
422
434
  // Execute tools
423
435
  for (const call of toolCalls) {
424
436
  const tool = toolsMap.get(call.function.name);
425
437
  if (!tool)
426
438
  throw new Error(`Tool not found: ${call.function.name}`);
427
- yield {
428
- progress: {
429
- event: "message",
430
- role: "agent",
431
- message: [
432
- {
433
- type: "tool_use",
434
- name: call.function.name,
435
- input: call.function.arguments,
436
- toolUseId: call.id,
437
- },
438
- ],
439
- },
440
- };
441
439
  queue.push({ tool, call });
442
440
  }
443
441
  await queue.drained();
@@ -449,14 +447,11 @@ class AIAgent extends agent_js_1.Agent {
449
447
  yield {
450
448
  progress: {
451
449
  event: "message",
452
- role: "agent",
453
- message: [
454
- {
455
- type: "tool_result",
456
- toolUseId: call.id,
457
- content: output,
458
- },
459
- ],
450
+ message: {
451
+ role: "tool",
452
+ toolCallId: call.id,
453
+ content: JSON.stringify(output),
454
+ },
460
455
  },
461
456
  };
462
457
  }
@@ -480,11 +475,6 @@ class AIAgent extends agent_js_1.Agent {
480
475
  if (!(0, type_utils_js_1.isEmpty)(result)) {
481
476
  yield { delta: { json: result } };
482
477
  }
483
- if (text) {
484
- yield {
485
- progress: { event: "message", role: "agent", message: [{ type: "text", content: text }] },
486
- };
487
- }
488
478
  return;
489
479
  }
490
480
  }
@@ -225,6 +225,7 @@ export type ChatModelInputMessageContent = string | UnionContent[];
225
225
  export type TextContent = {
226
226
  type: "text";
227
227
  text: string;
228
+ isThinking?: boolean;
228
229
  /**
229
230
  * Cache control marker (only supported by Claude)
230
231
  *
@@ -378,15 +378,29 @@ const modelOptionsSchemaProperties = {
378
378
  zod_1.z.literal("medium"),
379
379
  zod_1.z.literal("high"),
380
380
  ]),
381
+ cacheConfig: zod_1.z.object({
382
+ enabled: (0, schema_js_1.optionalize)(zod_1.z.boolean().default(true)),
383
+ ttl: (0, schema_js_1.optionalize)(zod_1.z.union([zod_1.z.literal("5m"), zod_1.z.literal("1h"), zod_1.z.number()]).default("5m")),
384
+ strategy: (0, schema_js_1.optionalize)(zod_1.z.union([zod_1.z.literal("auto"), zod_1.z.literal("manual")]).default("auto")),
385
+ autoBreakpoints: (0, schema_js_1.optionalize)(zod_1.z.object({
386
+ tools: (0, schema_js_1.optionalize)(zod_1.z.boolean().default(true)),
387
+ system: (0, schema_js_1.optionalize)(zod_1.z.boolean().default(true)),
388
+ lastMessage: (0, schema_js_1.optionalize)(zod_1.z.boolean().default(false)),
389
+ })),
390
+ }),
381
391
  };
382
- const modelOptionsSchema = zod_1.z.object(Object.fromEntries(Object.entries(modelOptionsSchemaProperties).map(([key, schema]) => [
392
+ const modelOptionsSchema = zod_1.z
393
+ .object(Object.fromEntries(Object.entries(modelOptionsSchemaProperties).map(([key, schema]) => [
383
394
  key,
384
395
  (0, schema_js_1.optionalize)(schema),
385
- ])));
386
- const modelOptionsWithGetterSchema = zod_1.z.object(Object.fromEntries(Object.entries(modelOptionsSchemaProperties).map(([key, schema]) => [
396
+ ])))
397
+ .passthrough();
398
+ const modelOptionsWithGetterSchema = zod_1.z
399
+ .object(Object.fromEntries(Object.entries(modelOptionsSchemaProperties).map(([key, schema]) => [
387
400
  key,
388
401
  (0, schema_js_1.optionalize)((0, agent_js_1.getterSchema)(schema)),
389
- ])));
402
+ ])))
403
+ .passthrough();
390
404
  const chatModelOptionsSchema = agent_js_1.agentOptionsSchema.extend({
391
405
  model: (0, schema_js_1.optionalize)(zod_1.z.string()),
392
406
  modelOptions: (0, schema_js_1.optionalize)(modelOptionsWithGetterSchema),
@@ -1,6 +1,6 @@
1
1
  import type { AFSOptions } from "@aigne/afs";
2
2
  import { type ZodType, z } from "zod";
3
- import type { AgentHooks, TaskRenderMode } from "../agents/agent.js";
3
+ import type { Agent, AgentHooks, TaskRenderMode } from "../agents/agent.js";
4
4
  import type { LoadOptions } from "./index.js";
5
5
  import { chatModelSchema, imageModelSchema } from "./schema.js";
6
6
  export interface HooksSchema {
@@ -65,6 +65,7 @@ export interface AgentSchema {
65
65
  context?: AFSContextSchema;
66
66
  });
67
67
  shareAFS?: boolean;
68
+ historyConfig?: Agent["historyConfig"];
68
69
  [key: string]: unknown;
69
70
  }
70
71
  export declare function parseAgentFile(path: string, data: any, options: LoadOptions): Promise<AgentSchema>;
@@ -100,6 +100,14 @@ const getAgentSchema = ({ filepath }) => {
100
100
  })),
101
101
  ])),
102
102
  shareAFS: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
103
+ historyConfig: (0, schema_js_1.camelizeSchema)((0, schema_js_1.optionalize)(zod_1.z.object({
104
+ enabled: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
105
+ record: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
106
+ inject: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
107
+ use_old_memory: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
108
+ maxTokens: (0, schema_js_1.optionalize)(zod_1.z.number().int().positive()),
109
+ maxItems: (0, schema_js_1.optionalize)(zod_1.z.number().int().positive()),
110
+ }))),
103
111
  });
104
112
  return (0, schema_js_1.camelizeSchema)(baseAgentSchema.passthrough());
105
113
  });
@@ -1,5 +1,9 @@
1
+ import type { AFSListOptions } from "@aigne/afs";
1
2
  import type { Agent } from "../../../agents/agent.js";
2
- export declare function getHistories(agent: Agent): Promise<{
3
+ export declare function getHistories({ filter, agent, }: {
4
+ filter: AFSListOptions["filter"];
5
+ agent: Agent;
6
+ }): Promise<{
3
7
  role: "user" | "agent";
4
8
  content: unknown;
5
9
  }[]>;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getHistories = getHistories;
4
4
  const afs_history_1 = require("@aigne/afs-history");
5
5
  const type_utils_js_1 = require("../../../utils/type-utils.js");
6
- async function getHistories(agent) {
6
+ async function getHistories({ filter, agent, }) {
7
7
  const afs = agent?.afs;
8
8
  if (!afs)
9
9
  return [];
@@ -11,6 +11,7 @@ async function getHistories(agent) {
11
11
  if (!historyModule)
12
12
  return [];
13
13
  const history = (await afs.list(historyModule.path, {
14
+ filter,
14
15
  limit: agent.historyConfig?.maxItems || 10,
15
16
  orderBy: [["createdAt", "desc"]],
16
17
  })).data;
@@ -20,7 +20,14 @@ function createAFSContext(agent, context) {
20
20
  get histories() {
21
21
  if (!agent)
22
22
  return Promise.resolve([]);
23
- return (0, history_js_1.getHistories)(agent);
23
+ return (0, history_js_1.getHistories)({
24
+ agent,
25
+ filter: {
26
+ agentId: agent.name,
27
+ userId: context?.userContext.userId,
28
+ sessionId: context?.userContext.sessionId,
29
+ },
30
+ });
24
31
  },
25
32
  get skills() {
26
33
  const afs = agent?.afs;
@@ -1,14 +1,16 @@
1
1
  import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
2
- import { Agent, type AgentInvokeOptions, type Message } from "../agents/agent.js";
2
+ import { Agent, type Message } from "../agents/agent.js";
3
3
  import { type AIAgent } from "../agents/ai-agent.js";
4
- import type { ChatModel, ChatModelInput } from "../agents/chat-model.js";
4
+ import { type ChatModel, type ChatModelInput, type ChatModelInputMessage } from "../agents/chat-model.js";
5
5
  import { type FileUnionContent } from "../agents/model.js";
6
+ import type { Context } from "../aigne/context.js";
6
7
  import { ChatMessagesTemplate } from "./template.js";
7
8
  export interface PromptBuilderOptions {
8
9
  instructions?: string | ChatMessagesTemplate;
9
10
  workingDir?: string;
10
11
  }
11
- export interface PromptBuildOptions extends Partial<Pick<AgentInvokeOptions, "context">> {
12
+ export interface PromptBuildOptions {
13
+ context?: Context;
12
14
  agent?: AIAgent;
13
15
  input?: Message;
14
16
  model?: ChatModel;
@@ -37,10 +39,12 @@ export declare class PromptBuilder {
37
39
  }>;
38
40
  private getTemplateVariables;
39
41
  private buildMessages;
40
- getHistories(options: PromptBuildOptions): Promise<{
41
- role: "user" | "agent";
42
- content: unknown;
43
- }[]>;
42
+ protected deprecatedMemories(message: string | undefined, options: PromptBuildOptions): Promise<ChatModelInputMessage[]>;
43
+ getHistories({ agentId, userId, sessionId, ...options }: PromptBuildOptions & {
44
+ agentId?: string;
45
+ userId?: string;
46
+ sessionId?: string;
47
+ }): Promise<ChatModelInputMessage[]>;
44
48
  private refineMessages;
45
49
  private convertMemoriesToMessages;
46
50
  private buildResponseFormat;
@@ -8,6 +8,7 @@ const zod_1 = require("zod");
8
8
  const zod_to_json_schema_1 = require("zod-to-json-schema");
9
9
  const agent_js_1 = require("../agents/agent.js");
10
10
  const ai_agent_js_1 = require("../agents/ai-agent.js");
11
+ const chat_model_js_1 = require("../agents/chat-model.js");
11
12
  const model_js_1 = require("../agents/model.js");
12
13
  const schema_js_1 = require("../loader/schema.js");
13
14
  const json_schema_js_1 = require("../utils/json-schema.js");
@@ -100,6 +101,9 @@ class PromptBuilder {
100
101
  }
101
102
  async buildMessages(options) {
102
103
  const { input } = options;
104
+ const agentId = options.agent?.name;
105
+ const userId = options.context?.userContext.userId;
106
+ const sessionId = options.context?.userContext.sessionId;
103
107
  const inputKey = options.agent?.inputKey;
104
108
  const message = inputKey && typeof input?.[inputKey] === "string" ? input[inputKey] : undefined;
105
109
  const [messages, otherCustomMessages] = (0, type_utils_js_1.partition)((await (typeof this.instructions === "string"
@@ -109,6 +113,50 @@ class PromptBuilder {
109
113
  const files = (0, type_utils_js_1.flat)(inputFileKey
110
114
  ? (0, type_utils_js_1.checkArguments)("Check input files", (0, schema_js_1.optionalize)(model_js_1.fileUnionContentsSchema), input?.[inputFileKey])
111
115
  : null);
116
+ const historyConfig = options.agent?.historyConfig;
117
+ const injectHistory = historyConfig?.inject === true || (historyConfig?.inject !== false && historyConfig?.enabled);
118
+ if (injectHistory) {
119
+ if (historyConfig.useOldMemory) {
120
+ messages.push(...(await this.deprecatedMemories(message, options)));
121
+ }
122
+ else {
123
+ const history = await this.getHistories({ ...options, agentId, userId, sessionId });
124
+ messages.push(...history);
125
+ }
126
+ }
127
+ // if the agent is using structured stream mode, add the instructions
128
+ const { structuredStreamMode, outputSchema } = options.agent || {};
129
+ if (structuredStreamMode && outputSchema) {
130
+ const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
131
+ PromptBuilder.from(structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS.instructions);
132
+ messages.push(...(await instructions.buildMessages({
133
+ input: {
134
+ ...input,
135
+ outputJsonSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(outputSchema),
136
+ },
137
+ })));
138
+ }
139
+ messages.push(...otherCustomMessages);
140
+ if (message || files.length) {
141
+ const content = [];
142
+ if (message &&
143
+ // avoid duplicate user messages: developer may have already included the message in the messages
144
+ !otherCustomMessages.some((i) => i.role === "user" &&
145
+ (typeof i.content === "string"
146
+ ? i.content.includes(message)
147
+ : i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
148
+ content.push({ type: "text", text: message });
149
+ }
150
+ if (files.length)
151
+ content.push(...files);
152
+ if (content.length) {
153
+ messages.push({ role: "user", content });
154
+ }
155
+ }
156
+ return this.refineMessages(options, messages);
157
+ }
158
+ async deprecatedMemories(message, options) {
159
+ const messages = [];
112
160
  const memories = [];
113
161
  if (options.agent && options.context) {
114
162
  memories.push(...(await options.agent.retrieveMemories({ search: message }, { context: options.context })));
@@ -117,7 +165,7 @@ class PromptBuilder {
117
165
  memories.push(...options.context.memories);
118
166
  }
119
167
  const afs = options.agent?.afs;
120
- if (afs && options.agent?.historyConfig?.disabled !== true) {
168
+ if (afs && options.agent?.historyConfig?.enabled) {
121
169
  const historyModule = (await afs.listModules()).find((m) => m.module instanceof afs_history_1.AFSHistory);
122
170
  if (historyModule) {
123
171
  const history = await afs.list(historyModule.path, {
@@ -163,38 +211,9 @@ class PromptBuilder {
163
211
  }
164
212
  if (memories.length)
165
213
  messages.push(...(await this.convertMemoriesToMessages(memories, options)));
166
- // if the agent is using structured stream mode, add the instructions
167
- const { structuredStreamMode, outputSchema } = options.agent || {};
168
- if (structuredStreamMode && outputSchema) {
169
- const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
170
- PromptBuilder.from(structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS.instructions);
171
- messages.push(...(await instructions.buildMessages({
172
- input: {
173
- ...input,
174
- outputJsonSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(outputSchema),
175
- },
176
- })));
177
- }
178
- if (message || files.length) {
179
- const content = [];
180
- if (message &&
181
- // avoid duplicate user messages: developer may have already included the message in the custom user messages
182
- !otherCustomMessages.some((i) => i.role === "user" &&
183
- (typeof i.content === "string"
184
- ? i.content.includes(message)
185
- : i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
186
- content.push({ type: "text", text: message });
187
- }
188
- if (files.length)
189
- content.push(...files);
190
- if (content.length) {
191
- messages.push({ role: "user", content });
192
- }
193
- }
194
- messages.push(...otherCustomMessages);
195
- return this.refineMessages(options, messages);
214
+ return messages;
196
215
  }
197
- async getHistories(options) {
216
+ async getHistories({ agentId, userId, sessionId, ...options }) {
198
217
  const { agent } = options;
199
218
  const afs = agent?.afs;
200
219
  if (!afs)
@@ -203,24 +222,21 @@ class PromptBuilder {
203
222
  if (!historyModule)
204
223
  return [];
205
224
  const history = (await afs.list(historyModule.path, {
225
+ filter: { agentId, userId, sessionId },
206
226
  limit: agent.historyConfig?.maxItems || 10,
207
227
  orderBy: [["createdAt", "desc"]],
208
- })).data;
209
- return history
210
- .reverse()
211
- .map((i) => {
212
- if (!i.content)
213
- return;
214
- const { input, output } = i.content;
215
- if (!input || !output)
216
- return;
217
- return [
218
- { role: "user", content: input },
219
- { role: "agent", content: output },
220
- ];
221
- })
222
- .filter(type_utils_js_1.isNonNullable)
223
- .flat();
228
+ })).data.reverse();
229
+ return (await Promise.all(history.map(async (i) => {
230
+ if (Array.isArray(i.content?.messages) &&
231
+ i.content.messages.every((m) => chat_model_js_1.roleSchema.parse(m?.role))) {
232
+ return i.content.messages;
233
+ }
234
+ const { input, output } = i.content || {};
235
+ if (input && output) {
236
+ return await this.convertMemoriesToMessages([{ content: { input, output } }], options);
237
+ }
238
+ return [];
239
+ }))).flat();
224
240
  }
225
241
  refineMessages(options, messages) {
226
242
  const { autoReorderSystemMessages, autoMergeSystemMessages } = options.agent ?? {};