@aigne/core 1.72.0-beta.9 → 1.72.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 (78) hide show
  1. package/CHANGELOG.md +342 -0
  2. package/lib/cjs/agents/agent.d.ts +5 -0
  3. package/lib/cjs/agents/agent.js +5 -0
  4. package/lib/cjs/agents/ai-agent.d.ts +41 -5
  5. package/lib/cjs/agents/ai-agent.js +89 -29
  6. package/lib/cjs/agents/chat-model.d.ts +3 -0
  7. package/lib/cjs/agents/chat-model.js +18 -1
  8. package/lib/cjs/agents/image-model.js +1 -1
  9. package/lib/cjs/agents/model.d.ts +3 -3
  10. package/lib/cjs/agents/model.js +2 -2
  11. package/lib/cjs/agents/video-model.js +1 -1
  12. package/lib/cjs/aigne/context.js +1 -3
  13. package/lib/cjs/prompt/agent-session.d.ts +115 -5
  14. package/lib/cjs/prompt/agent-session.js +746 -83
  15. package/lib/cjs/prompt/compact/compactor.js +4 -0
  16. package/lib/cjs/prompt/compact/session-memory-extractor.d.ts +7 -0
  17. package/lib/cjs/prompt/compact/session-memory-extractor.js +143 -0
  18. package/lib/cjs/prompt/compact/types.d.ts +257 -0
  19. package/lib/cjs/prompt/compact/types.js +35 -1
  20. package/lib/cjs/prompt/compact/user-memory-extractor.d.ts +7 -0
  21. package/lib/cjs/prompt/compact/user-memory-extractor.js +124 -0
  22. package/lib/cjs/prompt/prompt-builder.js +3 -3
  23. package/lib/cjs/prompt/skills/afs/agent-skill/agent-skill.d.ts +2 -0
  24. package/lib/cjs/prompt/skills/afs/agent-skill/agent-skill.js +6 -0
  25. package/lib/cjs/prompt/skills/afs/agent-skill/skill-loader.d.ts +1 -2
  26. package/lib/cjs/prompt/skills/afs/agent-skill/skill-loader.js +14 -26
  27. package/lib/cjs/prompt/skills/afs/list.d.ts +2 -0
  28. package/lib/cjs/prompt/skills/afs/list.js +9 -1
  29. package/lib/cjs/prompt/skills/afs/read.d.ts +3 -1
  30. package/lib/cjs/prompt/skills/afs/read.js +5 -0
  31. package/lib/cjs/utils/mcp-utils.js +1 -1
  32. package/lib/cjs/utils/token-estimator.js +1 -1
  33. package/lib/cjs/utils/type-utils.js +0 -1
  34. package/lib/dts/agents/agent.d.ts +5 -0
  35. package/lib/dts/agents/ai-agent.d.ts +41 -5
  36. package/lib/dts/agents/chat-model.d.ts +3 -0
  37. package/lib/dts/agents/model.d.ts +3 -3
  38. package/lib/dts/prompt/agent-session.d.ts +115 -5
  39. package/lib/dts/prompt/compact/session-memory-extractor.d.ts +7 -0
  40. package/lib/dts/prompt/compact/types.d.ts +257 -0
  41. package/lib/dts/prompt/compact/user-memory-extractor.d.ts +7 -0
  42. package/lib/dts/prompt/skills/afs/agent-skill/agent-skill.d.ts +2 -0
  43. package/lib/dts/prompt/skills/afs/agent-skill/skill-loader.d.ts +1 -2
  44. package/lib/dts/prompt/skills/afs/list.d.ts +2 -0
  45. package/lib/dts/prompt/skills/afs/read.d.ts +3 -1
  46. package/lib/esm/agents/agent.d.ts +5 -0
  47. package/lib/esm/agents/agent.js +5 -0
  48. package/lib/esm/agents/ai-agent.d.ts +41 -5
  49. package/lib/esm/agents/ai-agent.js +89 -29
  50. package/lib/esm/agents/chat-model.d.ts +3 -0
  51. package/lib/esm/agents/chat-model.js +18 -1
  52. package/lib/esm/agents/image-model.js +1 -1
  53. package/lib/esm/agents/model.d.ts +3 -3
  54. package/lib/esm/agents/model.js +2 -2
  55. package/lib/esm/agents/video-model.js +1 -1
  56. package/lib/esm/aigne/context.js +2 -4
  57. package/lib/esm/prompt/agent-session.d.ts +115 -5
  58. package/lib/esm/prompt/agent-session.js +744 -84
  59. package/lib/esm/prompt/compact/compactor.js +4 -0
  60. package/lib/esm/prompt/compact/session-memory-extractor.d.ts +7 -0
  61. package/lib/esm/prompt/compact/session-memory-extractor.js +139 -0
  62. package/lib/esm/prompt/compact/types.d.ts +257 -0
  63. package/lib/esm/prompt/compact/types.js +34 -0
  64. package/lib/esm/prompt/compact/user-memory-extractor.d.ts +7 -0
  65. package/lib/esm/prompt/compact/user-memory-extractor.js +120 -0
  66. package/lib/esm/prompt/prompt-builder.js +3 -3
  67. package/lib/esm/prompt/skills/afs/agent-skill/agent-skill.d.ts +2 -0
  68. package/lib/esm/prompt/skills/afs/agent-skill/agent-skill.js +6 -0
  69. package/lib/esm/prompt/skills/afs/agent-skill/skill-loader.d.ts +1 -2
  70. package/lib/esm/prompt/skills/afs/agent-skill/skill-loader.js +13 -24
  71. package/lib/esm/prompt/skills/afs/list.d.ts +2 -0
  72. package/lib/esm/prompt/skills/afs/list.js +9 -1
  73. package/lib/esm/prompt/skills/afs/read.d.ts +3 -1
  74. package/lib/esm/prompt/skills/afs/read.js +5 -0
  75. package/lib/esm/utils/mcp-utils.js +1 -1
  76. package/lib/esm/utils/token-estimator.js +1 -1
  77. package/lib/esm/utils/type-utils.js +0 -1
  78. package/package.json +6 -6
@@ -57,7 +57,9 @@ export declare abstract class ChatModel extends Model<ChatModelInput, ChatModelO
57
57
  getModelCapabilities(): {
58
58
  supportsParallelToolCalls: boolean;
59
59
  };
60
+ getModelOptions(input: Message, options: AgentInvokeOptions): Promise<ChatModelInputOptions>;
60
61
  private validateToolNames;
62
+ countTokens(input: ChatModelInput): Promise<number>;
61
63
  /**
62
64
  * Normalizes tool names to ensure compatibility with language models
63
65
  *
@@ -226,6 +228,7 @@ export type TextContent = {
226
228
  type: "text";
227
229
  text: string;
228
230
  isThinking?: boolean;
231
+ isAgentSkill?: boolean;
229
232
  /**
230
233
  * Cache control marker (only supported by Claude)
231
234
  *
@@ -4,6 +4,7 @@ import { convertJsonSchemaToZod } from "zod-from-json-schema";
4
4
  import { optionalize } from "../loader/schema.js";
5
5
  import { wrapAutoParseJsonSchema } from "../utils/json-schema.js";
6
6
  import { logger } from "../utils/logger.js";
7
+ import { estimateTokens } from "../utils/token-estimator.js";
7
8
  import { checkArguments, isNil, omitByDeep } from "../utils/type-utils.js";
8
9
  import { agentOptionsSchema, getterSchema, } from "./agent.js";
9
10
  import { fileContentSchema, fileUnionContentSchema, localContentSchema, Model, urlContentSchema, } from "./model.js";
@@ -80,6 +81,19 @@ export class ChatModel extends Model {
80
81
  supportsParallelToolCalls: this.supportsParallelToolCalls,
81
82
  };
82
83
  }
84
+ async getModelOptions(input, options) {
85
+ const modelOptions = (await super.getModelOptions(input, options));
86
+ return {
87
+ ...modelOptions,
88
+ cacheConfig: {
89
+ ...modelOptions.cacheConfig,
90
+ autoBreakpoints: {
91
+ ...modelOptions.cacheConfig?.autoBreakpoints,
92
+ lastMessage: modelOptions.cacheConfig?.autoBreakpoints?.lastMessage ?? true,
93
+ },
94
+ },
95
+ };
96
+ }
83
97
  validateToolNames(tools) {
84
98
  for (const tool of tools ?? []) {
85
99
  if (!/^[a-zA-Z0-9_]+$/.test(tool.function.name)) {
@@ -87,6 +101,9 @@ export class ChatModel extends Model {
87
101
  }
88
102
  }
89
103
  }
104
+ async countTokens(input) {
105
+ return estimateTokens(JSON.stringify(input));
106
+ }
90
107
  /**
91
108
  * Normalizes tool names to ensure compatibility with language models
92
109
  *
@@ -201,7 +218,7 @@ export class ChatModel extends Model {
201
218
  const files = z.array(fileUnionContentSchema).parse(output.files);
202
219
  output = {
203
220
  ...output,
204
- files: await Promise.all(files.map((file) => this.transformFileType(input.outputFileType, file, options))),
221
+ files: await Promise.all(files.map((file) => this.transformFileType(input.outputFileType, file))),
205
222
  };
206
223
  }
207
224
  // Remove fields with `null` value for validation
@@ -67,7 +67,7 @@ export class ImageModel extends Model {
67
67
  const images = z.array(fileUnionContentSchema).parse(output.images);
68
68
  output = {
69
69
  ...output,
70
- images: await Promise.all(images.map((image) => this.transformFileType(input.outputFileType, image, options))),
70
+ images: await Promise.all(images.map((image) => this.transformFileType(input.outputFileType, image))),
71
71
  };
72
72
  }
73
73
  return super.processAgentOutput(input, output, options);
@@ -17,9 +17,9 @@ export declare abstract class Model<I extends Message = any, O extends Message =
17
17
  */
18
18
  getModelOptions(input: Message, options: AgentInvokeOptions): Promise<Record<string, unknown>>;
19
19
  protected preprocess(input: I, options: AgentInvokeOptions): Promise<void>;
20
- transformFileType(fileType: "file", data: FileUnionContent, options: AgentInvokeOptions): Promise<FileContent>;
21
- transformFileType(fileType: "local" | undefined, data: FileUnionContent, options: AgentInvokeOptions): Promise<LocalContent>;
22
- transformFileType(fileType: FileType | undefined, data: FileUnionContent, options: AgentInvokeOptions): Promise<FileUnionContent>;
20
+ transformFileType(fileType: "file", data: FileUnionContent): Promise<FileContent>;
21
+ transformFileType(fileType: "local" | undefined, data: FileUnionContent): Promise<LocalContent>;
22
+ transformFileType(fileType: FileType | undefined, data: FileUnionContent): Promise<FileUnionContent>;
23
23
  static getFileExtension(type: string): Promise<string | undefined>;
24
24
  static getMimeType(filename: string): Promise<string | undefined>;
25
25
  downloadFile(url: string): Promise<Response>;
@@ -53,13 +53,13 @@ export class Model extends Agent {
53
53
  Object.assign(input, { modelOptions: await this.getModelOptions(input, options) });
54
54
  return super.preprocess(input, options);
55
55
  }
56
- async transformFileType(fileType = "local", data, options) {
56
+ async transformFileType(fileType = "local", data) {
57
57
  if (fileType === data.type)
58
58
  return data;
59
59
  const common = pick(data, "filename", "mimeType");
60
60
  switch (fileType) {
61
61
  case "local": {
62
- const dir = nodejs.path.join(nodejs.os.tmpdir(), options.context.id);
62
+ const dir = nodejs.path.join(nodejs.os.tmpdir(), v7());
63
63
  await nodejs.fs.mkdir(dir, { recursive: true });
64
64
  const ext = await Model.getFileExtension(data.mimeType || data.filename || "");
65
65
  const id = v7();
@@ -40,7 +40,7 @@ export class VideoModel extends Model {
40
40
  const videos = z.array(fileUnionContentSchema).parse(output.videos);
41
41
  output = {
42
42
  ...output,
43
- videos: await Promise.all(videos.map((video) => this.transformFileType(input.outputFileType, video, options))),
43
+ videos: await Promise.all(videos.map((video) => this.transformFileType(input.outputFileType, video))),
44
44
  };
45
45
  }
46
46
  return super.processAgentOutput(input, output, options);
@@ -10,7 +10,7 @@ import { AgentResponseProgressStream } from "../utils/event-stream.js";
10
10
  import { logger } from "../utils/logger.js";
11
11
  import { promiseWithResolvers } from "../utils/promise.js";
12
12
  import { agentResponseStreamToObject, asyncGeneratorToReadableStream, mergeReadableStreams, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
13
- import { checkArguments, flat, isEmpty, isNil, omit, } from "../utils/type-utils.js";
13
+ import { checkArguments, flat, isEmpty, isNil, omit, pick, } from "../utils/type-utils.js";
14
14
  import { MessageQueue, toMessagePayload, } from "./message-queue.js";
15
15
  import { newEmptyContextUsage } from "./usage.js";
16
16
  /**
@@ -340,11 +340,9 @@ class AIGNEContextShared {
340
340
  }
341
341
  }
342
342
  const stream = await activeAgent.invoke(input, {
343
- hooks: options.hooks,
343
+ ...pick(options, "hooks", "model", "imageModel", "caller"),
344
344
  context,
345
345
  streaming: true,
346
- model: options.model,
347
- imageModel: options.imageModel,
348
346
  });
349
347
  for await (const value of stream) {
350
348
  if (isAgentResponseDelta(value)) {
@@ -1,17 +1,36 @@
1
1
  import type { AFS } from "@aigne/afs";
2
2
  import type { AgentInvokeOptions } from "../agents/agent.js";
3
3
  import type { ChatModelInputMessage } from "../agents/chat-model.js";
4
- import { type CompactConfig, type CompactContent, type EntryContent } from "./compact/types.js";
5
- export type { CompactConfig, CompactContent, EntryContent };
4
+ import { type CompactConfig, type SessionMemoryConfig, type SessionMode, type UserMemoryConfig } from "./compact/types.js";
5
+ export * from "./compact/types.js";
6
6
  export interface AgentSessionOptions {
7
7
  sessionId: string;
8
8
  userId?: string;
9
9
  agentId?: string;
10
10
  afs?: AFS;
11
+ /**
12
+ * Session mode
13
+ * - "auto": Enable history recording, compaction, and memory extraction
14
+ * - "disabled": Disable all session features (history, compaction, memory)
15
+ *
16
+ * **Should be "disabled" for internal utility agents** (extractors, compactors, etc.)
17
+ * to avoid recursive memory extraction and unnecessary overhead.
18
+ *
19
+ * @default DEFAULT_SESSION_MODE ("auto")
20
+ */
21
+ mode?: SessionMode;
11
22
  /**
12
23
  * Compaction configuration
13
24
  */
14
25
  compact?: CompactConfig;
26
+ /**
27
+ * Session memory configuration
28
+ */
29
+ sessionMemory?: SessionMemoryConfig;
30
+ /**
31
+ * User memory configuration
32
+ */
33
+ userMemory?: UserMemoryConfig;
15
34
  }
16
35
  export declare class AgentSession {
17
36
  readonly sessionId: string;
@@ -19,15 +38,36 @@ export declare class AgentSession {
19
38
  readonly agentId?: string;
20
39
  private afs?;
21
40
  private historyModulePath?;
41
+ private mode;
22
42
  private compactConfig;
43
+ private sessionMemoryConfig;
44
+ private userMemoryConfig;
23
45
  private runtimeState;
24
46
  private initialized?;
25
47
  private compactionPromise?;
48
+ private sessionMemoryUpdatePromise?;
49
+ private userMemoryUpdatePromise?;
26
50
  constructor(options: AgentSessionOptions);
51
+ /**
52
+ * Check if memory extraction is enabled
53
+ * Memory extraction requires mode to be "auto" AND AFS history module to be available
54
+ */
55
+ private get isMemoryEnabled();
27
56
  setSystemMessages(...messages: ChatModelInputMessage[]): Promise<void>;
28
57
  getMessages(): Promise<ChatModelInputMessage[]>;
58
+ /**
59
+ * Format user memory facts into a system message
60
+ * Applies token budget limit to ensure memory injection fits within constraints
61
+ */
62
+ private formatUserMemory;
63
+ /**
64
+ * Format session memory facts into a system message
65
+ * Applies token budget limit to ensure memory injection fits within constraints
66
+ */
67
+ private formatSessionMemory;
68
+ private formatMemoryTemplate;
29
69
  startMessage(input: unknown, message: ChatModelInputMessage, options: AgentInvokeOptions): Promise<void>;
30
- endMessage(output: unknown, options: AgentInvokeOptions): Promise<void>;
70
+ endMessage(output: unknown, message: ChatModelInputMessage | undefined, options: AgentInvokeOptions): Promise<void>;
31
71
  /**
32
72
  * Manually trigger compaction
33
73
  */
@@ -36,9 +76,13 @@ export declare class AgentSession {
36
76
  * Internal method that performs the actual compaction
37
77
  */
38
78
  private doCompact;
79
+ private compactCurrentEntry;
80
+ private maybeCompactCurrentEntry;
39
81
  private maybeAutoCompact;
40
82
  /**
41
- * Estimate token count for an array of messages
83
+ * Estimate token count for messages
84
+ * Applies singleMessageLimit to each text block individually
85
+ * Non-text tokens (images, tool calls) are always counted in full
42
86
  */
43
87
  private estimateMessagesTokens;
44
88
  /**
@@ -46,8 +90,74 @@ export declare class AgentSession {
46
90
  * Each batch will not exceed the specified maxTokens
47
91
  */
48
92
  private splitIntoBatches;
49
- appendCurrentMessages(...messages: ChatModelInputMessage[]): Promise<void>;
93
+ appendCurrentMessages(messages: ChatModelInputMessage | ChatModelInputMessage[], options: AgentInvokeOptions): Promise<void>;
94
+ /**
95
+ * Truncate text content to fit within target token limit
96
+ * @param text The text to truncate
97
+ * @param currentTokens Current token count of the text
98
+ * @param targetTokens Target token count after truncation
99
+ * @returns Truncated text
100
+ */
101
+ private truncateText;
102
+ private truncateLargeMessage;
50
103
  private ensureInitialized;
51
104
  private initialize;
105
+ /**
106
+ * Load session memory facts
107
+ * @returns Array of memory fact entries for the current session
108
+ */
109
+ private loadSessionMemory;
110
+ /**
111
+ * Load user memory facts
112
+ * @returns Array of memory fact entries for the current user
113
+ */
114
+ private loadUserMemory;
115
+ /**
116
+ * Load session history including compact content and history entries
117
+ * @returns Object containing history compact and history entries
118
+ */
119
+ private loadSessionHistory;
120
+ /**
121
+ * Manually trigger session memory update
122
+ */
123
+ updateSessionMemory(options: AgentInvokeOptions): Promise<void>;
124
+ private maybeAutoUpdateSessionMemory;
125
+ private maybeAutoUpdateUserMemory;
126
+ /**
127
+ * Internal method that performs the actual session memory update
128
+ */
129
+ private doUpdateSessionMemory;
130
+ /**
131
+ * Manually trigger user memory update
132
+ */
133
+ updateUserMemory(options: AgentInvokeOptions): Promise<void>;
134
+ /**
135
+ * Internal method that performs the actual user memory extraction
136
+ */
137
+ private doUpdateUserMemory;
138
+ /**
139
+ * Find Agent Skill content from a single message
140
+ * @param msg - Message to search in
141
+ * @returns The skill content text if found, undefined otherwise
142
+ */
143
+ private findSkillContentInMessage;
144
+ /**
145
+ * Find the last Agent Skill from a list of messages
146
+ * @param messages - Messages to search through
147
+ * @returns The last Agent Skill found, or undefined if none found
148
+ */
149
+ private findLastAgentSkillFromMessages;
150
+ /**
151
+ * Find the last Agent Skill from a list of history entries
152
+ * @param entries - History entries to search through
153
+ * @returns The last Agent Skill found, or undefined if none found
154
+ */
155
+ private findLastAgentSkill;
52
156
  private initializeDefaultCompactor;
157
+ private initializeDefaultSessionMemoryExtractor;
158
+ private initializeDefaultUserMemoryExtractor;
159
+ private get maxTokens();
160
+ private get keepRecentRatio();
161
+ private get keepRecentTokens();
162
+ private get singleMessageLimit();
53
163
  }