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

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 (67) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/lib/cjs/agents/agent.d.ts +2 -21
  3. package/lib/cjs/agents/agent.js +10 -15
  4. package/lib/cjs/agents/ai-agent.d.ts +20 -4
  5. package/lib/cjs/agents/ai-agent.js +37 -35
  6. package/lib/cjs/agents/image-model.d.ts +4 -4
  7. package/lib/cjs/agents/mcp-agent.d.ts +2 -2
  8. package/lib/cjs/agents/video-model.d.ts +4 -4
  9. package/lib/cjs/index.d.ts +1 -0
  10. package/lib/cjs/index.js +1 -0
  11. package/lib/cjs/loader/agent-yaml.d.ts +1 -2
  12. package/lib/cjs/loader/agent-yaml.js +0 -8
  13. package/lib/cjs/loader/index.d.ts +2 -2
  14. package/lib/cjs/memory/recorder.d.ts +4 -4
  15. package/lib/cjs/memory/retriever.d.ts +4 -4
  16. package/lib/cjs/prompt/agent-session.d.ts +53 -0
  17. package/lib/cjs/prompt/agent-session.js +345 -0
  18. package/lib/cjs/prompt/compact/compactor.d.ts +7 -0
  19. package/lib/cjs/prompt/compact/compactor.js +48 -0
  20. package/lib/cjs/prompt/compact/types.d.ts +79 -0
  21. package/lib/cjs/prompt/compact/types.js +19 -0
  22. package/lib/cjs/prompt/context/afs/history.js +1 -1
  23. package/lib/cjs/prompt/prompt-builder.d.ts +6 -8
  24. package/lib/cjs/prompt/prompt-builder.js +67 -123
  25. package/lib/cjs/prompt/skills/afs/agent-skill/skill-loader.js +1 -0
  26. package/lib/cjs/prompt/template.d.ts +16 -16
  27. package/lib/dts/agents/agent.d.ts +2 -21
  28. package/lib/dts/agents/ai-agent.d.ts +20 -4
  29. package/lib/dts/agents/image-model.d.ts +4 -4
  30. package/lib/dts/agents/mcp-agent.d.ts +2 -2
  31. package/lib/dts/agents/video-model.d.ts +4 -4
  32. package/lib/dts/index.d.ts +1 -0
  33. package/lib/dts/loader/agent-yaml.d.ts +1 -2
  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/prompt-builder.d.ts +6 -8
  41. package/lib/dts/prompt/template.d.ts +16 -16
  42. package/lib/esm/agents/agent.d.ts +2 -21
  43. package/lib/esm/agents/agent.js +10 -15
  44. package/lib/esm/agents/ai-agent.d.ts +20 -4
  45. package/lib/esm/agents/ai-agent.js +37 -35
  46. package/lib/esm/agents/image-model.d.ts +4 -4
  47. package/lib/esm/agents/mcp-agent.d.ts +2 -2
  48. package/lib/esm/agents/video-model.d.ts +4 -4
  49. package/lib/esm/index.d.ts +1 -0
  50. package/lib/esm/index.js +1 -0
  51. package/lib/esm/loader/agent-yaml.d.ts +1 -2
  52. package/lib/esm/loader/agent-yaml.js +0 -8
  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 +308 -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.js +1 -1
  63. package/lib/esm/prompt/prompt-builder.d.ts +6 -8
  64. package/lib/esm/prompt/prompt-builder.js +68 -124
  65. package/lib/esm/prompt/skills/afs/agent-skill/skill-loader.js +1 -0
  66. package/lib/esm/prompt/template.d.ts +16 -16
  67. package/package.json +4 -4
@@ -1,17 +1,16 @@
1
- import { AFSHistory } from "@aigne/afs-history";
2
1
  import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
+ import { v7 } from "@aigne/uuid";
3
3
  import { stringify } from "yaml";
4
4
  import { ZodObject } from "zod";
5
5
  import { zodToJsonSchema } from "zod-to-json-schema";
6
6
  import { Agent } from "../agents/agent.js";
7
7
  import { DEFAULT_OUTPUT_FILE_KEY, DEFAULT_OUTPUT_KEY } from "../agents/ai-agent.js";
8
- import { roleSchema, } from "../agents/chat-model.js";
9
8
  import { fileUnionContentsSchema } from "../agents/model.js";
10
9
  import { optionalize } from "../loader/schema.js";
11
10
  import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
12
- import { checkArguments, flat, isNonNullable, isRecord, partition, unique, } from "../utils/type-utils.js";
11
+ import { checkArguments, flat, isRecord, partition, unique } from "../utils/type-utils.js";
12
+ import { AgentSession } from "./agent-session.js";
13
13
  import { createPromptBuilderContext } from "./context/index.js";
14
- import { AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE } from "./prompts/afs-builtin-prompt.js";
15
14
  import { MEMORY_MESSAGE_TEMPLATE } from "./prompts/memory-message-template.js";
16
15
  import { STRUCTURED_STREAM_INSTRUCTIONS } from "./prompts/structured-stream-instructions.js";
17
16
  import { getAFSSkills } from "./skills/afs/index.js";
@@ -71,13 +70,28 @@ export class PromptBuilder {
71
70
  });
72
71
  }
73
72
  async build(options) {
73
+ let { userId, sessionId } = options.context?.userContext || {};
74
+ const agentId = options.agent?.name;
75
+ const afs = options.agent?.afs;
76
+ sessionId ||= v7();
77
+ const session = new AgentSession({
78
+ agentId,
79
+ userId,
80
+ sessionId,
81
+ afs,
82
+ compact: options.agent?.compact,
83
+ });
84
+ const { systemMessage, userMessage } = await this.buildMessages(options);
85
+ if (systemMessage)
86
+ await session.setSystemMessages(systemMessage);
74
87
  return {
75
- messages: await this.buildMessages(options),
88
+ userMessage,
76
89
  responseFormat: options.agent?.structuredStreamMode
77
90
  ? undefined
78
91
  : this.buildResponseFormat(options),
79
92
  outputFileType: options.agent?.outputFileType,
80
93
  ...(await this.buildTools(options)),
94
+ session,
81
95
  };
82
96
  }
83
97
  async buildPrompt(options) {
@@ -98,47 +112,43 @@ export class PromptBuilder {
98
112
  }
99
113
  async buildMessages(options) {
100
114
  const { input } = options;
101
- const agentId = options.agent?.name;
102
- const userId = options.context?.userContext.userId;
103
- const sessionId = options.context?.userContext.sessionId;
104
115
  const inputKey = options.agent?.inputKey;
105
116
  const message = inputKey && typeof input?.[inputKey] === "string" ? input[inputKey] : undefined;
106
- const [messages, otherCustomMessages] = partition((await (typeof this.instructions === "string"
117
+ const template = typeof this.instructions === "string"
107
118
  ? ChatMessagesTemplate.from([SystemMessageTemplate.from(this.instructions)])
108
- : this.instructions)?.format(this.getTemplateVariables(options), { workingDir: this.workingDir })) ?? [], (i) => i.role === "system");
119
+ : this.instructions;
120
+ const [systemMessages, userMessages] = partition((await template?.format(this.getTemplateVariables(options), {
121
+ workingDir: this.workingDir,
122
+ })) ?? [], (i) => i.role === "system");
109
123
  const inputFileKey = options.agent?.inputFileKey;
110
124
  const files = flat(inputFileKey
111
125
  ? checkArguments("Check input files", optionalize(fileUnionContentsSchema), input?.[inputFileKey])
112
126
  : null);
113
- const historyConfig = options.agent?.historyConfig;
114
- const injectHistory = historyConfig?.inject === true || (historyConfig?.inject !== false && historyConfig?.enabled);
115
- if (injectHistory) {
116
- if (historyConfig.useOldMemory) {
117
- messages.push(...(await this.deprecatedMemories(message, options)));
118
- }
119
- else {
120
- const history = await this.getHistories({ ...options, agentId, userId, sessionId });
121
- messages.push(...history);
122
- }
127
+ if (options.agent?.memories.length || options.context?.memories.length) {
128
+ const deprecatedMemories = await this.deprecatedMemories(message, options);
129
+ if (deprecatedMemories.length)
130
+ systemMessages.push(...deprecatedMemories);
123
131
  }
124
132
  // if the agent is using structured stream mode, add the instructions
125
133
  const { structuredStreamMode, outputSchema } = options.agent || {};
126
134
  if (structuredStreamMode && outputSchema) {
127
135
  const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
128
136
  PromptBuilder.from(STRUCTURED_STREAM_INSTRUCTIONS.instructions);
129
- messages.push(...(await instructions.buildMessages({
130
- input: {
131
- ...input,
132
- outputJsonSchema: zodToJsonSchema(outputSchema),
133
- },
134
- })));
137
+ systemMessages.push({
138
+ role: "system",
139
+ content: (await instructions.buildPrompt({
140
+ input: {
141
+ ...input,
142
+ outputJsonSchema: zodToJsonSchema(outputSchema),
143
+ },
144
+ })).prompt,
145
+ });
135
146
  }
136
- messages.push(...otherCustomMessages);
137
147
  if (message || files.length) {
138
148
  const content = [];
139
149
  if (message &&
140
150
  // avoid duplicate user messages: developer may have already included the message in the messages
141
- !otherCustomMessages.some((i) => i.role === "user" &&
151
+ !userMessages.some((i) => i.role === "user" &&
142
152
  (typeof i.content === "string"
143
153
  ? i.content.includes(message)
144
154
  : i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
@@ -147,10 +157,38 @@ export class PromptBuilder {
147
157
  if (files.length)
148
158
  content.push(...files);
149
159
  if (content.length) {
150
- messages.push({ role: "user", content });
160
+ userMessages.push({ role: "user", content });
151
161
  }
152
162
  }
153
- return this.refineMessages(options, messages);
163
+ let systemMessage = this.mergeMessages(systemMessages, "system");
164
+ if (!systemMessage.content?.length)
165
+ systemMessage = undefined;
166
+ let userMessage = this.mergeMessages(userMessages, "user");
167
+ if (!userMessage.content?.length) {
168
+ userMessage = { role: "user", content: systemMessage?.content };
169
+ systemMessage = undefined;
170
+ }
171
+ if (!userMessage.content?.length)
172
+ throw new Error("User message cannot be empty.");
173
+ return {
174
+ systemMessage,
175
+ userMessage,
176
+ };
177
+ }
178
+ mergeMessages(messages, role) {
179
+ const content = [];
180
+ for (const message of messages) {
181
+ if (typeof message.content === "string") {
182
+ content.push({ type: "text", text: message.content });
183
+ }
184
+ else if (Array.isArray(message.content)) {
185
+ content.push(...message.content);
186
+ }
187
+ else if (message.content) {
188
+ throw new Error(`Unsupported message content type: ${typeof message.content}`);
189
+ }
190
+ }
191
+ return { role, content };
154
192
  }
155
193
  async deprecatedMemories(message, options) {
156
194
  const messages = [];
@@ -161,104 +199,10 @@ export class PromptBuilder {
161
199
  if (options.agent?.useMemoriesFromContext && options.context?.memories?.length) {
162
200
  memories.push(...options.context.memories);
163
201
  }
164
- const afs = options.agent?.afs;
165
- if (afs && options.agent?.historyConfig?.enabled) {
166
- const historyModule = (await afs.listModules()).find((m) => m.module instanceof AFSHistory);
167
- if (historyModule) {
168
- const history = await afs.list(historyModule.path, {
169
- limit: options.agent?.maxRetrieveMemoryCount || 10,
170
- orderBy: [["createdAt", "desc"]],
171
- });
172
- memories.push(...history.data
173
- .reverse()
174
- .filter((i) => isNonNullable(i.content)));
175
- if (message) {
176
- const result = (await afs.search("/", message)).data;
177
- const ms = result
178
- .map((entry) => {
179
- if (entry.metadata?.execute)
180
- return null;
181
- const content = entry.content || entry.summary;
182
- if (!content)
183
- return null;
184
- return {
185
- content,
186
- description: entry.description,
187
- };
188
- })
189
- .filter(isNonNullable);
190
- memories.push(...ms);
191
- const executable = result.filter((i) => !!i.metadata?.execute);
192
- if (executable.length) {
193
- messages.push({
194
- role: "system",
195
- content: await PromptTemplate.from(AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE).format({
196
- tools: executable.map((entry) => ({
197
- path: entry.path,
198
- name: entry.metadata.execute.name,
199
- description: entry.metadata.execute.description,
200
- inputSchema: entry.metadata.execute.inputSchema,
201
- outputSchema: entry.metadata.execute.outputSchema,
202
- })),
203
- }),
204
- });
205
- }
206
- }
207
- }
208
- }
209
202
  if (memories.length)
210
203
  messages.push(...(await this.convertMemoriesToMessages(memories, options)));
211
204
  return messages;
212
205
  }
213
- async getHistories({ agentId, userId, sessionId, ...options }) {
214
- const { agent } = options;
215
- const afs = agent?.afs;
216
- if (!afs)
217
- return [];
218
- const historyModule = (await afs.listModules()).find((m) => m.module instanceof AFSHistory);
219
- if (!historyModule)
220
- return [];
221
- const history = (await afs.list(historyModule.path, {
222
- filter: { agentId, userId, sessionId },
223
- limit: agent.historyConfig?.maxItems || 10,
224
- orderBy: [["createdAt", "desc"]],
225
- })).data.reverse();
226
- return (await Promise.all(history.map(async (i) => {
227
- if (Array.isArray(i.content?.messages) &&
228
- i.content.messages.every((m) => roleSchema.parse(m?.role))) {
229
- return i.content.messages;
230
- }
231
- const { input, output } = i.content || {};
232
- if (input && output) {
233
- return await this.convertMemoriesToMessages([{ content: { input, output } }], options);
234
- }
235
- return [];
236
- }))).flat();
237
- }
238
- refineMessages(options, messages) {
239
- const { autoReorderSystemMessages, autoMergeSystemMessages } = options.agent ?? {};
240
- if (!autoReorderSystemMessages && !autoMergeSystemMessages)
241
- return messages;
242
- const [systemMessages, otherMessages] = partition(messages, (m) => m.role === "system");
243
- if (!autoMergeSystemMessages) {
244
- return systemMessages.concat(otherMessages);
245
- }
246
- const result = [];
247
- if (systemMessages.length) {
248
- result.push({
249
- role: "system",
250
- content: systemMessages
251
- .map((i) => typeof i.content === "string"
252
- ? i.content
253
- : i.content
254
- ?.map((c) => (c.type === "text" ? c.text : null))
255
- .filter(isNonNullable)
256
- .join("\n"))
257
- .join("\n"),
258
- });
259
- }
260
- return result.concat(otherMessages);
261
- }
262
206
  async convertMemoriesToMessages(memories, options) {
263
207
  const messages = [];
264
208
  const other = [];
@@ -36,6 +36,7 @@ export async function loadAgentSkillFromAFS({ afs, }) {
36
36
  for (const module of filtered) {
37
37
  const data = (await afs.list(module.path, {
38
38
  pattern: "**/SKILL.md",
39
+ maxDepth: 10,
39
40
  })).data;
40
41
  for (const entry of data) {
41
42
  const { data: file } = await afs.read(entry.path);
@@ -42,7 +42,7 @@ export declare class AgentMessageTemplate extends ChatMessageTemplate {
42
42
  static from(template?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[], name?: string, options?: FormatOptions, cacheControl?: ChatModelInputMessage["cacheControl"]): AgentMessageTemplate;
43
43
  constructor(content?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[] | undefined, name?: string, options?: FormatOptions, cacheControl?: ChatModelInputMessage["cacheControl"]);
44
44
  format(_variables?: Record<string, unknown>, _options?: FormatOptions): Promise<{
45
- role: "system" | "user" | "agent" | "tool";
45
+ role: "agent" | "user" | "system" | "tool";
46
46
  name: string | undefined;
47
47
  content: ChatModelInputMessageContent | undefined;
48
48
  toolCalls: ChatModelOutputToolCall[] | undefined;
@@ -54,7 +54,7 @@ export declare class ToolMessageTemplate extends ChatMessageTemplate {
54
54
  static from(content: object | string, toolCallId: string, name?: string, options?: FormatOptions, cacheControl?: ChatModelInputMessage["cacheControl"]): ToolMessageTemplate;
55
55
  constructor(content: object | string, toolCallId: string, name?: string, options?: FormatOptions, cacheControl?: ChatModelInputMessage["cacheControl"]);
56
56
  format(_variables?: Record<string, unknown>, _options?: FormatOptions): Promise<{
57
- role: "system" | "user" | "agent" | "tool";
57
+ role: "agent" | "user" | "system" | "tool";
58
58
  name: string | undefined;
59
59
  content: ChatModelInputMessageContent | undefined;
60
60
  toolCallId: string;
@@ -83,21 +83,21 @@ declare const chatMessageSchema: z.ZodUnion<[z.ZodObject<{
83
83
  ttl?: "5m" | "1h" | undefined;
84
84
  }>>;
85
85
  }, "strip", z.ZodTypeAny, {
86
- content: string;
87
86
  role: "system";
87
+ content: string;
88
+ name?: string | undefined;
88
89
  cacheControl?: {
89
90
  type: "ephemeral";
90
91
  ttl?: "5m" | "1h" | undefined;
91
92
  } | undefined;
92
- name?: string | undefined;
93
93
  }, {
94
- content: string;
95
94
  role: "system";
95
+ content: string;
96
+ name?: string | undefined;
96
97
  cacheControl?: {
97
98
  type: "ephemeral";
98
99
  ttl?: "5m" | "1h" | undefined;
99
100
  } | undefined;
100
- name?: string | undefined;
101
101
  }>, z.ZodObject<{
102
102
  role: z.ZodLiteral<"user">;
103
103
  content: z.ZodString;
@@ -113,21 +113,21 @@ declare const chatMessageSchema: z.ZodUnion<[z.ZodObject<{
113
113
  ttl?: "5m" | "1h" | undefined;
114
114
  }>>;
115
115
  }, "strip", z.ZodTypeAny, {
116
- content: string;
117
116
  role: "user";
117
+ content: string;
118
+ name?: string | undefined;
118
119
  cacheControl?: {
119
120
  type: "ephemeral";
120
121
  ttl?: "5m" | "1h" | undefined;
121
122
  } | undefined;
122
- name?: string | undefined;
123
123
  }, {
124
- content: string;
125
124
  role: "user";
125
+ content: string;
126
+ name?: string | undefined;
126
127
  cacheControl?: {
127
128
  type: "ephemeral";
128
129
  ttl?: "5m" | "1h" | undefined;
129
130
  } | undefined;
130
- name?: string | undefined;
131
131
  }>, z.ZodObject<{
132
132
  role: z.ZodLiteral<"agent">;
133
133
  content: z.ZodOptional<z.ZodString>;
@@ -172,6 +172,7 @@ declare const chatMessageSchema: z.ZodUnion<[z.ZodObject<{
172
172
  }>>;
173
173
  }, "strip", z.ZodTypeAny, {
174
174
  role: "agent";
175
+ name?: string | undefined;
175
176
  content?: string | undefined;
176
177
  cacheControl?: {
177
178
  type: "ephemeral";
@@ -185,9 +186,9 @@ declare const chatMessageSchema: z.ZodUnion<[z.ZodObject<{
185
186
  type: "function";
186
187
  id: string;
187
188
  }[] | undefined;
188
- name?: string | undefined;
189
189
  }, {
190
190
  role: "agent";
191
+ name?: string | undefined;
191
192
  content?: string | undefined;
192
193
  cacheControl?: {
193
194
  type: "ephemeral";
@@ -201,7 +202,6 @@ declare const chatMessageSchema: z.ZodUnion<[z.ZodObject<{
201
202
  type: "function";
202
203
  id: string;
203
204
  }[] | undefined;
204
- name?: string | undefined;
205
205
  }>, z.ZodObject<{
206
206
  role: z.ZodLiteral<"tool">;
207
207
  content: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>, string, string | Record<string, unknown>>;
@@ -218,23 +218,23 @@ declare const chatMessageSchema: z.ZodUnion<[z.ZodObject<{
218
218
  ttl?: "5m" | "1h" | undefined;
219
219
  }>>;
220
220
  }, "strip", z.ZodTypeAny, {
221
- content: string;
222
221
  role: "tool";
222
+ content: string;
223
223
  toolCallId: string;
224
+ name?: string | undefined;
224
225
  cacheControl?: {
225
226
  type: "ephemeral";
226
227
  ttl?: "5m" | "1h" | undefined;
227
228
  } | undefined;
228
- name?: string | undefined;
229
229
  }, {
230
- content: string | Record<string, unknown>;
231
230
  role: "tool";
231
+ content: string | Record<string, unknown>;
232
232
  toolCallId: string;
233
+ name?: string | undefined;
233
234
  cacheControl?: {
234
235
  type: "ephemeral";
235
236
  ttl?: "5m" | "1h" | undefined;
236
237
  } | undefined;
237
- name?: string | undefined;
238
238
  }>]>;
239
239
  export declare function safeParseChatMessages(messages: unknown): ChatMessageTemplate[] | undefined;
240
240
  export declare function parseChatMessages(messages: (z.infer<typeof chatMessageSchema> & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.72.0-beta.7",
3
+ "version": "1.72.0-beta.9",
4
4
  "description": "The functional core of agentic AI",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -93,10 +93,10 @@
93
93
  "zod": "^3.25.67",
94
94
  "zod-from-json-schema": "^0.0.5",
95
95
  "zod-to-json-schema": "^3.24.6",
96
- "@aigne/afs": "^1.4.0-beta.4",
97
- "@aigne/afs-history": "^1.2.0-beta.4",
96
+ "@aigne/afs": "^1.4.0-beta.5",
97
+ "@aigne/platform-helpers": "^0.6.7-beta",
98
98
  "@aigne/observability-api": "^0.11.14-beta.1",
99
- "@aigne/platform-helpers": "^0.6.7-beta"
99
+ "@aigne/afs-history": "^1.2.0-beta.5"
100
100
  },
101
101
  "devDependencies": {
102
102
  "@types/bun": "^1.2.22",