@aigne/core 1.72.0-beta.6 → 1.72.0-beta.8

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 (68) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/lib/cjs/agents/agent.d.ts +23 -27
  3. package/lib/cjs/agents/agent.js +16 -8
  4. package/lib/cjs/agents/ai-agent.d.ts +20 -4
  5. package/lib/cjs/agents/ai-agent.js +47 -55
  6. package/lib/cjs/agents/chat-model.d.ts +1 -0
  7. package/lib/cjs/agents/image-model.d.ts +4 -4
  8. package/lib/cjs/agents/mcp-agent.d.ts +2 -2
  9. package/lib/cjs/agents/video-model.d.ts +4 -4
  10. package/lib/cjs/index.d.ts +1 -0
  11. package/lib/cjs/index.js +1 -0
  12. package/lib/cjs/loader/index.d.ts +2 -2
  13. package/lib/cjs/memory/recorder.d.ts +4 -4
  14. package/lib/cjs/memory/retriever.d.ts +4 -4
  15. package/lib/cjs/prompt/agent-session.d.ts +53 -0
  16. package/lib/cjs/prompt/agent-session.js +341 -0
  17. package/lib/cjs/prompt/compact/compactor.d.ts +7 -0
  18. package/lib/cjs/prompt/compact/compactor.js +48 -0
  19. package/lib/cjs/prompt/compact/types.d.ts +79 -0
  20. package/lib/cjs/prompt/compact/types.js +19 -0
  21. package/lib/cjs/prompt/context/afs/history.d.ts +5 -1
  22. package/lib/cjs/prompt/context/afs/history.js +3 -2
  23. package/lib/cjs/prompt/context/afs/index.js +8 -1
  24. package/lib/cjs/prompt/prompt-builder.d.ts +11 -9
  25. package/lib/cjs/prompt/prompt-builder.js +77 -117
  26. package/lib/cjs/prompt/template.d.ts +16 -16
  27. package/lib/dts/agents/agent.d.ts +23 -27
  28. package/lib/dts/agents/ai-agent.d.ts +20 -4
  29. package/lib/dts/agents/chat-model.d.ts +1 -0
  30. package/lib/dts/agents/image-model.d.ts +4 -4
  31. package/lib/dts/agents/mcp-agent.d.ts +2 -2
  32. package/lib/dts/agents/video-model.d.ts +4 -4
  33. package/lib/dts/index.d.ts +1 -0
  34. package/lib/dts/loader/index.d.ts +2 -2
  35. package/lib/dts/memory/recorder.d.ts +4 -4
  36. package/lib/dts/memory/retriever.d.ts +4 -4
  37. package/lib/dts/prompt/agent-session.d.ts +53 -0
  38. package/lib/dts/prompt/compact/compactor.d.ts +7 -0
  39. package/lib/dts/prompt/compact/types.d.ts +79 -0
  40. package/lib/dts/prompt/context/afs/history.d.ts +5 -1
  41. package/lib/dts/prompt/prompt-builder.d.ts +11 -9
  42. package/lib/dts/prompt/template.d.ts +16 -16
  43. package/lib/esm/agents/agent.d.ts +23 -27
  44. package/lib/esm/agents/agent.js +16 -8
  45. package/lib/esm/agents/ai-agent.d.ts +20 -4
  46. package/lib/esm/agents/ai-agent.js +47 -55
  47. package/lib/esm/agents/chat-model.d.ts +1 -0
  48. package/lib/esm/agents/image-model.d.ts +4 -4
  49. package/lib/esm/agents/mcp-agent.d.ts +2 -2
  50. package/lib/esm/agents/video-model.d.ts +4 -4
  51. package/lib/esm/index.d.ts +1 -0
  52. package/lib/esm/index.js +1 -0
  53. package/lib/esm/loader/index.d.ts +2 -2
  54. package/lib/esm/memory/recorder.d.ts +4 -4
  55. package/lib/esm/memory/retriever.d.ts +4 -4
  56. package/lib/esm/prompt/agent-session.d.ts +53 -0
  57. package/lib/esm/prompt/agent-session.js +304 -0
  58. package/lib/esm/prompt/compact/compactor.d.ts +7 -0
  59. package/lib/esm/prompt/compact/compactor.js +44 -0
  60. package/lib/esm/prompt/compact/types.d.ts +79 -0
  61. package/lib/esm/prompt/compact/types.js +16 -0
  62. package/lib/esm/prompt/context/afs/history.d.ts +5 -1
  63. package/lib/esm/prompt/context/afs/history.js +3 -2
  64. package/lib/esm/prompt/context/afs/index.js +8 -1
  65. package/lib/esm/prompt/prompt-builder.d.ts +11 -9
  66. package/lib/esm/prompt/prompt-builder.js +78 -118
  67. package/lib/esm/prompt/template.d.ts +16 -16
  68. package/package.json +4 -4
@@ -0,0 +1,304 @@
1
+ import { AFSHistory } from "@aigne/afs-history";
2
+ import { v7 } from "@aigne/uuid";
3
+ import { joinURL } from "ufo";
4
+ import { estimateTokens } from "../utils/token-estimator.js";
5
+ import { isNonNullable } from "../utils/type-utils.js";
6
+ import { DEFAULT_COMPACT_ASYNC, DEFAULT_COMPACT_MODE, DEFAULT_KEEP_RECENT_RATIO, DEFAULT_MAX_TOKENS, } from "./compact/types.js";
7
+ export class AgentSession {
8
+ sessionId;
9
+ userId;
10
+ agentId;
11
+ afs;
12
+ historyModulePath;
13
+ compactConfig;
14
+ runtimeState;
15
+ initialized;
16
+ compactionPromise;
17
+ constructor(options) {
18
+ this.sessionId = options.sessionId;
19
+ this.userId = options.userId;
20
+ this.agentId = options.agentId;
21
+ this.afs = options.afs;
22
+ this.compactConfig = options.compact ?? {};
23
+ this.runtimeState = {
24
+ historyEntries: [],
25
+ currentEntry: null,
26
+ };
27
+ }
28
+ async setSystemMessages(...messages) {
29
+ await this.ensureInitialized();
30
+ this.runtimeState.systemMessages = messages;
31
+ }
32
+ async getMessages() {
33
+ await this.ensureInitialized();
34
+ const { systemMessages, compactSummary, historyEntries, currentEntry } = this.runtimeState;
35
+ const messages = [
36
+ ...(systemMessages ?? []),
37
+ ...(compactSummary
38
+ ? [
39
+ {
40
+ role: "system",
41
+ content: `Previous conversation summary:\n${compactSummary}`,
42
+ },
43
+ ]
44
+ : []),
45
+ ...historyEntries.flatMap((entry) => entry.content?.messages ?? []),
46
+ ...(currentEntry?.messages ?? []),
47
+ ];
48
+ // Filter out thinking messages from content
49
+ return messages.map((msg) => {
50
+ if (!msg.content || typeof msg.content === "string") {
51
+ return msg;
52
+ }
53
+ // Filter out thinking from UnionContent[]
54
+ const filteredContent = msg.content.filter((c) => !(c.type === "text" && c.isThinking));
55
+ return { ...msg, content: filteredContent.length > 0 ? filteredContent : undefined };
56
+ });
57
+ }
58
+ async startMessage(input, message, options) {
59
+ await this.ensureInitialized();
60
+ await this.maybeAutoCompact(options);
61
+ // Always wait for compaction to complete before starting a new message
62
+ // This ensures data consistency even in async compact mode
63
+ if (this.compactionPromise)
64
+ await this.compactionPromise;
65
+ this.runtimeState.currentEntry = { input, messages: [message] };
66
+ }
67
+ async endMessage(output, options) {
68
+ await this.ensureInitialized();
69
+ if (!this.runtimeState.currentEntry?.input ||
70
+ !this.runtimeState.currentEntry.messages?.length) {
71
+ throw new Error("No current entry to end. Call startMessage() first.");
72
+ }
73
+ this.runtimeState.currentEntry.output = output;
74
+ let newEntry;
75
+ if (this.afs && this.historyModulePath) {
76
+ newEntry = (await this.afs.write(joinURL(this.historyModulePath, "new"), {
77
+ userId: this.userId,
78
+ sessionId: this.sessionId,
79
+ agentId: this.agentId,
80
+ content: this.runtimeState.currentEntry,
81
+ })).data;
82
+ }
83
+ else {
84
+ const id = v7();
85
+ newEntry = {
86
+ id,
87
+ path: `/history/${id}`,
88
+ userId: this.userId,
89
+ sessionId: this.sessionId,
90
+ agentId: this.agentId,
91
+ content: this.runtimeState.currentEntry,
92
+ };
93
+ }
94
+ this.runtimeState.historyEntries.push(newEntry);
95
+ this.runtimeState.currentEntry = null;
96
+ // Check if auto-compact should be triggered
97
+ await this.maybeAutoCompact(options);
98
+ }
99
+ /**
100
+ * Manually trigger compaction
101
+ */
102
+ async compact(options) {
103
+ await this.ensureInitialized();
104
+ // If compaction is already in progress, wait for it to complete
105
+ if (this.compactionPromise) {
106
+ return this.compactionPromise;
107
+ }
108
+ // Start new compaction task
109
+ this.compactionPromise = this.doCompact(options).finally(() => {
110
+ this.compactionPromise = undefined;
111
+ });
112
+ return this.compactionPromise;
113
+ }
114
+ /**
115
+ * Internal method that performs the actual compaction
116
+ */
117
+ async doCompact(options) {
118
+ const { compactor, keepRecentRatio } = this.compactConfig ?? {};
119
+ if (!compactor) {
120
+ throw new Error("Cannot compact without a compactor agent configured.");
121
+ }
122
+ const historyEntries = this.runtimeState.historyEntries;
123
+ if (historyEntries.length === 0)
124
+ return;
125
+ // Calculate token budget for keeping recent messages
126
+ const ratio = keepRecentRatio ?? DEFAULT_KEEP_RECENT_RATIO;
127
+ const maxTokens = this.compactConfig?.maxTokens ?? DEFAULT_MAX_TOKENS;
128
+ let keepTokenBudget = Math.floor(maxTokens * ratio);
129
+ // Calculate tokens for system messages
130
+ const systemTokens = (this.runtimeState.systemMessages ?? []).reduce((sum, msg) => {
131
+ const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content ?? "");
132
+ return sum + estimateTokens(content);
133
+ }, 0);
134
+ // Calculate tokens for current entry messages
135
+ const currentTokens = (this.runtimeState.currentEntry?.messages ?? []).reduce((sum, msg) => {
136
+ const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content ?? "");
137
+ return sum + estimateTokens(content);
138
+ }, 0);
139
+ // Subtract system and current tokens from budget
140
+ // This ensures total tokens (system + current + kept history) stays within ratio budget
141
+ keepTokenBudget = Math.max(0, keepTokenBudget - systemTokens - currentTokens);
142
+ // Find split point by iterating backwards from most recent entry
143
+ // The split point divides history into: [compact] | [keep]
144
+ let splitIndex = historyEntries.length; // Default: keep all (no compaction)
145
+ let accumulatedTokens = 0;
146
+ for (let i = historyEntries.length - 1; i >= 0; i--) {
147
+ const entry = historyEntries[i];
148
+ if (!entry)
149
+ continue;
150
+ const entryTokens = this.estimateMessagesTokens(entry.content?.messages ?? []);
151
+ // Check if adding this entry would exceed token budget
152
+ if (accumulatedTokens + entryTokens > keepTokenBudget) {
153
+ // Would exceed budget, split here (this entry and earlier ones will be compacted)
154
+ splitIndex = i + 1;
155
+ break;
156
+ }
157
+ // Can keep this entry, accumulate and continue
158
+ accumulatedTokens += entryTokens;
159
+ splitIndex = i;
160
+ }
161
+ // Split history at the found point
162
+ const entriesToCompact = historyEntries.slice(0, splitIndex);
163
+ const entriesToKeep = historyEntries.slice(splitIndex);
164
+ // If nothing to compact, return
165
+ if (entriesToCompact.length === 0) {
166
+ return;
167
+ }
168
+ const latestCompactedEntry = entriesToCompact.at(-1);
169
+ if (!latestCompactedEntry)
170
+ return;
171
+ // Split into batches to avoid context overflow
172
+ const batches = this.splitIntoBatches(entriesToCompact, maxTokens);
173
+ // Process batches incrementally, each summary becomes input for the next
174
+ let currentSummary = this.runtimeState.compactSummary;
175
+ for (const batch of batches) {
176
+ const result = await options.context.invoke(compactor, {
177
+ previousSummary: [currentSummary].filter(isNonNullable),
178
+ messages: batch.flatMap((e) => e.content?.messages ?? []).filter(isNonNullable),
179
+ });
180
+ currentSummary = result.summary;
181
+ }
182
+ // Write compact entry to AFS
183
+ if (this.afs && this.historyModulePath) {
184
+ await this.afs.write(joinURL(this.historyModulePath, "by-session", this.sessionId, "@metadata/compact/new"), {
185
+ userId: this.userId,
186
+ agentId: this.agentId,
187
+ content: { summary: currentSummary },
188
+ metadata: {
189
+ latestEntryId: latestCompactedEntry.id,
190
+ },
191
+ });
192
+ }
193
+ // Update runtime state: keep the summary and recent entries
194
+ this.runtimeState.compactSummary = currentSummary;
195
+ this.runtimeState.historyEntries = entriesToKeep;
196
+ }
197
+ async maybeAutoCompact(options) {
198
+ if (this.compactionPromise)
199
+ await this.compactionPromise;
200
+ if (!this.compactConfig)
201
+ return;
202
+ // Check if compaction is disabled
203
+ const mode = this.compactConfig.mode ?? DEFAULT_COMPACT_MODE;
204
+ if (mode === "disabled")
205
+ return;
206
+ const { compactor } = this.compactConfig;
207
+ const maxTokens = this.compactConfig.maxTokens ?? DEFAULT_MAX_TOKENS;
208
+ if (!compactor)
209
+ return;
210
+ const currentTokens = this.estimateMessagesTokens(await this.getMessages());
211
+ if (currentTokens >= maxTokens) {
212
+ this.compact(options);
213
+ const isAsync = this.compactConfig.async ?? DEFAULT_COMPACT_ASYNC;
214
+ if (!isAsync)
215
+ await this.compactionPromise;
216
+ }
217
+ }
218
+ /**
219
+ * Estimate token count for an array of messages
220
+ */
221
+ estimateMessagesTokens(messages) {
222
+ return messages.reduce((sum, msg) => {
223
+ const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content ?? "");
224
+ return sum + estimateTokens(content);
225
+ }, 0);
226
+ }
227
+ /**
228
+ * Split entries into batches based on token limit
229
+ * Each batch will not exceed the specified maxTokens
230
+ */
231
+ splitIntoBatches(entries, maxTokens) {
232
+ const batches = [];
233
+ let currentBatch = [];
234
+ let currentTokens = 0;
235
+ for (const entry of entries) {
236
+ const entryTokens = this.estimateMessagesTokens(entry.content?.messages ?? []);
237
+ // If adding this entry exceeds limit and we have entries in current batch, start new batch
238
+ if (currentTokens + entryTokens > maxTokens && currentBatch.length > 0) {
239
+ batches.push(currentBatch);
240
+ currentBatch = [entry];
241
+ currentTokens = entryTokens;
242
+ }
243
+ else {
244
+ currentBatch.push(entry);
245
+ currentTokens += entryTokens;
246
+ }
247
+ }
248
+ // Add remaining entries
249
+ if (currentBatch.length > 0) {
250
+ batches.push(currentBatch);
251
+ }
252
+ return batches;
253
+ }
254
+ async appendCurrentMessages(...messages) {
255
+ await this.ensureInitialized();
256
+ if (!this.runtimeState.currentEntry || !this.runtimeState.currentEntry.messages?.length) {
257
+ throw new Error("No current entry to append messages. Call startMessage() first.");
258
+ }
259
+ this.runtimeState.currentEntry.messages.push(...messages);
260
+ }
261
+ async ensureInitialized() {
262
+ this.initialized ??= this.initialize();
263
+ await this.initialized;
264
+ }
265
+ async initialize() {
266
+ if (this.initialized)
267
+ return;
268
+ await this.initializeDefaultCompactor();
269
+ const historyModule = (await this.afs?.listModules())?.find((m) => m.module instanceof AFSHistory);
270
+ this.historyModulePath = historyModule?.path;
271
+ if (this.afs && this.historyModulePath) {
272
+ // Load latest compact entry if exists
273
+ const compactPath = joinURL(this.historyModulePath, "by-session", this.sessionId, "@metadata/compact");
274
+ const compactResult = await this.afs.list(compactPath, {
275
+ filter: { userId: this.userId, agentId: this.agentId },
276
+ orderBy: [["createdAt", "desc"]],
277
+ limit: 1,
278
+ });
279
+ const latestCompact = compactResult.data[0];
280
+ if (latestCompact?.content?.summary) {
281
+ this.runtimeState.compactSummary = latestCompact.content.summary;
282
+ }
283
+ // Load history entries (after compact point if exists)
284
+ const afsEntries = (await this.afs.list(joinURL(this.historyModulePath, "by-session", this.sessionId), {
285
+ filter: {
286
+ userId: this.userId,
287
+ agentId: this.agentId,
288
+ // Only load entries after the latest compact
289
+ after: latestCompact?.createdAt?.toISOString(),
290
+ },
291
+ orderBy: [["createdAt", "desc"]],
292
+ // Set a very large limit to load all history entries
293
+ // The default limit is 10 which would cause history truncation
294
+ limit: 10000,
295
+ })).data;
296
+ this.runtimeState.historyEntries = afsEntries
297
+ .reverse()
298
+ .filter((entry) => isNonNullable(entry.content));
299
+ }
300
+ }
301
+ async initializeDefaultCompactor() {
302
+ this.compactConfig.compactor ??= await import("./compact/compactor.js").then((m) => new m.AISessionCompactor());
303
+ }
304
+ }
@@ -0,0 +1,7 @@
1
+ import { AIAgent, type AIAgentOptions } from "../../agents/ai-agent.js";
2
+ import type { CompactContent, CompactorInput } from "./types.js";
3
+ export interface CreateCompactorOptions extends AIAgentOptions<CompactorInput, CompactContent> {
4
+ }
5
+ export declare class AISessionCompactor extends AIAgent<CompactorInput, CompactContent> {
6
+ constructor(options?: CreateCompactorOptions);
7
+ }
@@ -0,0 +1,44 @@
1
+ import { optional, z } from "zod";
2
+ import { AIAgent } from "../../agents/ai-agent.js";
3
+ import { isNil, omitBy } from "../../utils/type-utils.js";
4
+ const COMPACTOR_INSTRUCTIONS = `\
5
+ You are a conversation summarizer. Your task is to create a concise but comprehensive summary of the conversation history provided.
6
+
7
+ ## Conversation history
8
+
9
+ ${"```"}yaml alt="previous-summary"
10
+ {{ previousSummary | yaml.stringify }}
11
+ ${"```"}
12
+
13
+
14
+ ${"```"}yaml alt="conversation-histories"
15
+ {{ messages | yaml.stringify }}
16
+ ${"```"}
17
+
18
+ ## Guidelines
19
+
20
+ 1. Preserve key information, decisions, and context that would be needed for future conversation continuity
21
+ 2. Include important facts, names, dates, and specific details mentioned
22
+ 3. Summarize the user's goals and preferences expressed in the conversation
23
+ 4. Note any pending tasks or follow-up items
24
+ 5. Keep the summary focused and avoid unnecessary verbosity
25
+ 6. Write in a neutral, factual tone
26
+
27
+ Output a single summary that captures the essence of the conversation.`;
28
+ export class AISessionCompactor extends AIAgent {
29
+ constructor(options) {
30
+ super({
31
+ name: "SessionCompactor",
32
+ description: "Generates conversation summaries for session compaction",
33
+ inputSchema: z.object({
34
+ previousSummary: optional(z.array(z.string()).describe("List of previous conversation summaries")),
35
+ messages: z.array(z.any()),
36
+ }),
37
+ outputSchema: z.object({
38
+ summary: z.string().describe("A comprehensive summary of the conversation history"),
39
+ }),
40
+ instructions: COMPACTOR_INSTRUCTIONS,
41
+ ...omitBy(options ?? {}, (v) => isNil(v)),
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,79 @@
1
+ import type { Agent, Message } from "../../agents/agent.js";
2
+ import type { ChatModelInputMessage } from "../../agents/chat-model.js";
3
+ /**
4
+ * Default compaction mode
5
+ */
6
+ export declare const DEFAULT_COMPACT_MODE: "auto";
7
+ /**
8
+ * Default maximum tokens before triggering compaction
9
+ */
10
+ export declare const DEFAULT_MAX_TOKENS = 80000;
11
+ /**
12
+ * Default ratio of maxTokens to reserve for keeping recent messages
13
+ */
14
+ export declare const DEFAULT_KEEP_RECENT_RATIO = 0.5;
15
+ /**
16
+ * Default async mode for compaction
17
+ */
18
+ export declare const DEFAULT_COMPACT_ASYNC = true;
19
+ /**
20
+ * Content structure for history entries
21
+ */
22
+ export interface EntryContent {
23
+ input?: unknown;
24
+ output?: unknown;
25
+ messages?: ChatModelInputMessage[];
26
+ }
27
+ /**
28
+ * Output structure from the compactor agent
29
+ */
30
+ export interface CompactContent extends Message {
31
+ summary: string;
32
+ }
33
+ /**
34
+ * Input structure for the compactor agent
35
+ */
36
+ export interface CompactorInput extends Message {
37
+ previousSummary?: string[];
38
+ messages: ChatModelInputMessage[];
39
+ }
40
+ /**
41
+ * Type alias for a compactor agent
42
+ */
43
+ export type Compactor = Agent<CompactorInput, CompactContent>;
44
+ /**
45
+ * Configuration for session compaction
46
+ */
47
+ export interface CompactConfig {
48
+ /**
49
+ * Compaction mode
50
+ * @default DEFAULT_COMPACT_MODE ("auto")
51
+ */
52
+ mode?: "auto" | "disabled";
53
+ /**
54
+ * Maximum tokens before triggering compaction
55
+ * @default DEFAULT_MAX_TOKENS (80000)
56
+ */
57
+ maxTokens?: number;
58
+ /**
59
+ * Ratio of maxTokens to reserve for keeping recent messages (0-1)
60
+ *
61
+ * Defines what portion of maxTokens budget should be allocated for
62
+ * preserving recent conversation history without compaction.
63
+ *
64
+ * @default 0.5 (50% of maxTokens)
65
+ * @example 0.5 means if maxTokens=80000, keep up to 40000 tokens of recent messages
66
+ */
67
+ keepRecentRatio?: number;
68
+ /**
69
+ * Whether to perform compaction asynchronously
70
+ * @default DEFAULT_COMPACT_ASYNC (true)
71
+ */
72
+ async?: boolean;
73
+ /**
74
+ * Agent that generates summaries from conversation entries
75
+ * Input: { entries: EntryContent[] }
76
+ * Output: { summary: string }
77
+ */
78
+ compactor?: Compactor;
79
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Default compaction mode
3
+ */
4
+ export const DEFAULT_COMPACT_MODE = "auto";
5
+ /**
6
+ * Default maximum tokens before triggering compaction
7
+ */
8
+ export const DEFAULT_MAX_TOKENS = 80000;
9
+ /**
10
+ * Default ratio of maxTokens to reserve for keeping recent messages
11
+ */
12
+ export const DEFAULT_KEEP_RECENT_RATIO = 0.5;
13
+ /**
14
+ * Default async mode for compaction
15
+ */
16
+ export const DEFAULT_COMPACT_ASYNC = true;
@@ -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
  }[]>;
@@ -1,6 +1,6 @@
1
1
  import { AFSHistory } from "@aigne/afs-history";
2
2
  import { isNonNullable } from "../../../utils/type-utils.js";
3
- export async function getHistories(agent) {
3
+ export async function getHistories({ filter, agent, }) {
4
4
  const afs = agent?.afs;
5
5
  if (!afs)
6
6
  return [];
@@ -8,7 +8,8 @@ export async function getHistories(agent) {
8
8
  if (!historyModule)
9
9
  return [];
10
10
  const history = (await afs.list(historyModule.path, {
11
- limit: agent.historyConfig?.maxItems || 10,
11
+ filter,
12
+ limit: 10,
12
13
  orderBy: [["createdAt", "desc"]],
13
14
  })).data;
14
15
  return history
@@ -17,7 +17,14 @@ export function createAFSContext(agent, context) {
17
17
  get histories() {
18
18
  if (!agent)
19
19
  return Promise.resolve([]);
20
- return getHistories(agent);
20
+ return getHistories({
21
+ agent,
22
+ filter: {
23
+ agentId: agent.name,
24
+ userId: context?.userContext.userId,
25
+ sessionId: context?.userContext.sessionId,
26
+ },
27
+ });
21
28
  },
22
29
  get skills() {
23
30
  const afs = agent?.afs;
@@ -1,14 +1,17 @@
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, ChatModelInput, ChatModelInputMessage } from "../agents/chat-model.js";
5
5
  import { type FileUnionContent } from "../agents/model.js";
6
+ import type { Context } from "../aigne/context.js";
7
+ import { AgentSession } from "./agent-session.js";
6
8
  import { ChatMessagesTemplate } from "./template.js";
7
9
  export interface PromptBuilderOptions {
8
10
  instructions?: string | ChatMessagesTemplate;
9
11
  workingDir?: string;
10
12
  }
11
- export interface PromptBuildOptions extends Partial<Pick<AgentInvokeOptions, "context">> {
13
+ export interface PromptBuildOptions {
14
+ context?: Context;
12
15
  agent?: AIAgent;
13
16
  input?: Message;
14
17
  model?: ChatModel;
@@ -26,7 +29,9 @@ export declare class PromptBuilder {
26
29
  instructions?: string | ChatMessagesTemplate;
27
30
  workingDir?: string;
28
31
  copy(): PromptBuilder;
29
- build(options: PromptBuildOptions): Promise<ChatModelInput & {
32
+ build(options: PromptBuildOptions): Promise<Omit<ChatModelInput, "messages"> & {
33
+ session: AgentSession;
34
+ userMessage: ChatModelInputMessage;
30
35
  toolAgents?: Agent[];
31
36
  }>;
32
37
  buildPrompt(options: Pick<PromptBuildOptions, "input" | "context"> & {
@@ -37,11 +42,8 @@ export declare class PromptBuilder {
37
42
  }>;
38
43
  private getTemplateVariables;
39
44
  private buildMessages;
40
- getHistories(options: PromptBuildOptions): Promise<{
41
- role: "user" | "agent";
42
- content: unknown;
43
- }[]>;
44
- private refineMessages;
45
+ private mergeMessages;
46
+ protected deprecatedMemories(message: string | undefined, options: PromptBuildOptions): Promise<ChatModelInputMessage[]>;
45
47
  private convertMemoriesToMessages;
46
48
  private buildResponseFormat;
47
49
  private buildTools;