@aigne/core 1.72.0-beta.8 → 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 +349 -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 +752 -85
  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 +15 -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 +750 -86
  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 +14 -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
@@ -1,5 +1,13 @@
1
1
  import type { Agent, Message } from "../../agents/agent.js";
2
2
  import type { ChatModelInputMessage } from "../../agents/chat-model.js";
3
+ /**
4
+ * Session mode type
5
+ */
6
+ export type SessionMode = "auto" | "disabled";
7
+ /**
8
+ * Default session mode
9
+ */
10
+ export declare const DEFAULT_SESSION_MODE: SessionMode;
3
11
  /**
4
12
  * Default compaction mode
5
13
  */
@@ -29,6 +37,13 @@ export interface EntryContent {
29
37
  */
30
38
  export interface CompactContent extends Message {
31
39
  summary: string;
40
+ /**
41
+ * Last Agent Skill content in the session
42
+ * Preserved across compactions to maintain skill instructions
43
+ */
44
+ lastAgentSkill?: {
45
+ content: string;
46
+ };
32
47
  }
33
48
  /**
34
49
  * Input structure for the compactor agent
@@ -77,3 +92,245 @@ export interface CompactConfig {
77
92
  */
78
93
  compactor?: Compactor;
79
94
  }
95
+ /**
96
+ * Default ratio of maxTokens to allocate for user memory
97
+ */
98
+ export declare const DEFAULT_MEMORY_RATIO = 0.04;
99
+ /**
100
+ * Default query limit for loading memory facts
101
+ */
102
+ export declare const DEFAULT_MEMORY_QUERY_LIMIT = 200;
103
+ /**
104
+ * Content structure for a single memory fact
105
+ *
106
+ * Used by both session memory and user memory to store learned facts.
107
+ * Each fact is stored as an individual AFSEntry with metadata at the AFSEntry level.
108
+ *
109
+ * Storage paths:
110
+ * - Session Memory:
111
+ * - List: /by-session/:sessionId/@metadata/memory
112
+ * - Create: /by-session/:sessionId/@metadata/memory/new
113
+ * - Read: /by-session/:sessionId/@metadata/memory/:memoryId
114
+ * - User Memory:
115
+ * - List: /by-user/:userId/@metadata/memory
116
+ * - Create: /by-user/:userId/@metadata/memory/new
117
+ * - Read: /by-user/:userId/@metadata/memory/:memoryId
118
+ *
119
+ * @example
120
+ * AFSEntry<MemoryFact> {
121
+ * id: "fact-001", // AFSEntry ID (auto-generated)
122
+ * userId: "user-001",
123
+ * agentId: "assistant", // which agent learned this fact
124
+ * sessionId: "session-123", // which session it was learned from (if applicable)
125
+ * createdAt: Date,
126
+ * content: {
127
+ * label: "pref-package-manager", // semantic label for this fact
128
+ * fact: "User prefers using pnpm",
129
+ * confidence: 0.9,
130
+ * tags: ["preference", "tooling"]
131
+ * }
132
+ * }
133
+ */
134
+ export interface MemoryFact {
135
+ /**
136
+ * Semantic label for this fact (short, human-readable)
137
+ * Used for updates and deletions to uniquely identify facts
138
+ * @example "pref-package-manager", "skill-typescript", "proj-main-language"
139
+ */
140
+ label: string;
141
+ /**
142
+ * The fact content (text description)
143
+ */
144
+ fact: string;
145
+ /**
146
+ * Confidence score (0-1)
147
+ * Higher values indicate more certain facts
148
+ * @default 1.0
149
+ */
150
+ confidence?: number;
151
+ /**
152
+ * Classification tags for the fact
153
+ * @example ['preference', 'technical', 'project-specific']
154
+ */
155
+ tags?: string[];
156
+ }
157
+ /**
158
+ * Input structure for the memory extractor agent
159
+ */
160
+ export interface MemoryExtractorInput extends Message {
161
+ /**
162
+ * User memory facts (long-term, cross-session) to avoid duplication
163
+ */
164
+ existingUserFacts?: MemoryFact[];
165
+ /**
166
+ * Existing session memory facts (for context and deduplication)
167
+ */
168
+ existingFacts?: MemoryFact[];
169
+ /**
170
+ * Recent conversation messages to extract facts from
171
+ */
172
+ messages: ChatModelInputMessage[];
173
+ }
174
+ /**
175
+ * Output structure from the memory extractor agent
176
+ */
177
+ export interface MemoryExtractorOutput extends Message {
178
+ /**
179
+ * New or updated facts from the conversation
180
+ * Only include facts that need to be added or updated
181
+ * Do not include unchanged facts that already exist
182
+ */
183
+ newFacts: MemoryFact[];
184
+ /**
185
+ * Fact labels to remove from existing memory
186
+ * Each string should match a label in existingFacts
187
+ * @example ["pref-package-manager", "skill-old-framework"]
188
+ */
189
+ removeFacts?: string[];
190
+ }
191
+ /**
192
+ * Type alias for a memory extractor agent
193
+ */
194
+ export type MemoryExtractor = Agent<MemoryExtractorInput, MemoryExtractorOutput>;
195
+ /**
196
+ * Default session memory mode
197
+ */
198
+ export declare const DEFAULT_SESSION_MEMORY_MODE: "auto";
199
+ /**
200
+ * Default async mode for session memory extraction
201
+ */
202
+ export declare const DEFAULT_SESSION_MEMORY_ASYNC = true;
203
+ /**
204
+ * Metadata for tracking session memory extraction progress
205
+ *
206
+ * This metadata is stored in each memory entry's metadata field.
207
+ * When extracting new facts, the latestEntryId is recorded in the metadata
208
+ * to track which history entries have been processed.
209
+ */
210
+ export interface SessionMemoryMetadata {
211
+ /**
212
+ * ID of the last extracted history entry
213
+ * Used to determine which entries still need processing
214
+ */
215
+ latestEntryId?: string;
216
+ }
217
+ /**
218
+ * Default user memory mode
219
+ */
220
+ export declare const DEFAULT_USER_MEMORY_MODE: "auto";
221
+ /**
222
+ * Default async mode for user memory consolidation
223
+ */
224
+ export declare const DEFAULT_USER_MEMORY_ASYNC = true;
225
+ /**
226
+ * Input structure for the user memory extractor agent
227
+ */
228
+ export interface UserMemoryExtractorInput extends Message {
229
+ /**
230
+ * Session memory facts from multiple sessions to consolidate
231
+ */
232
+ sessionFacts: MemoryFact[];
233
+ /**
234
+ * Existing user memory facts (for context and deduplication)
235
+ */
236
+ existingUserFacts?: MemoryFact[];
237
+ }
238
+ /**
239
+ * Output structure from the user memory extractor agent
240
+ */
241
+ export interface UserMemoryExtractorOutput extends Message {
242
+ /**
243
+ * New or updated facts for user memory
244
+ * Only include facts that need to be added or updated
245
+ * Do not include unchanged facts that already exist
246
+ * Each label should be unique - these will replace old facts with same labels
247
+ */
248
+ newFacts: MemoryFact[];
249
+ /**
250
+ * Fact labels to remove from user memory
251
+ * Each string should match a label in existingUserFacts
252
+ */
253
+ removeFacts?: string[];
254
+ }
255
+ /**
256
+ * Type alias for a user memory extractor agent
257
+ */
258
+ export type UserMemoryExtractor = Agent<UserMemoryExtractorInput, UserMemoryExtractorOutput>;
259
+ /**
260
+ * Configuration for user memory
261
+ * User memory contains long-term facts consolidated from multiple sessions
262
+ */
263
+ export interface UserMemoryConfig {
264
+ /**
265
+ * User memory mode
266
+ * - "auto": Enable memory and auto-consolidate at appropriate times
267
+ * - "disabled": Disable user memory completely
268
+ * @default DEFAULT_USER_MEMORY_MODE ("auto")
269
+ */
270
+ mode?: "auto" | "disabled";
271
+ /**
272
+ * Ratio of maxTokens to allocate for user memory (0-1)
273
+ *
274
+ * Defines what portion of maxTokens budget should be allocated for
275
+ * injecting user memory facts into the prompt.
276
+ *
277
+ * @default DEFAULT_MEMORY_RATIO (0.04 = 4% of maxTokens)
278
+ * @example 0.04 means if maxTokens=80000, allocate 3200 tokens for memory
279
+ */
280
+ memoryRatio?: number;
281
+ /**
282
+ * Maximum number of fact entries to load from storage
283
+ * @default DEFAULT_MEMORY_QUERY_LIMIT (200)
284
+ */
285
+ queryLimit?: number;
286
+ /**
287
+ * Whether to perform memory consolidation asynchronously
288
+ * @default DEFAULT_USER_MEMORY_ASYNC (true)
289
+ */
290
+ async?: boolean;
291
+ /**
292
+ * Agent that extracts user memory facts from session memory
293
+ * Input: { sessionFacts: MemoryFact[], existingUserFacts?: MemoryFact[] }
294
+ * Output: { newFacts: MemoryFact[], removeFacts?: string[] }
295
+ */
296
+ extractor?: UserMemoryExtractor;
297
+ }
298
+ /**
299
+ * Configuration for session memory
300
+ * Session memory contains facts extracted from the current session's conversation
301
+ */
302
+ export interface SessionMemoryConfig {
303
+ /**
304
+ * Session memory mode
305
+ * - "auto": Enable memory and auto-update after each conversation turn
306
+ * - "disabled": Disable memory completely
307
+ * @default DEFAULT_SESSION_MEMORY_MODE ("auto")
308
+ */
309
+ mode?: "auto" | "disabled";
310
+ /**
311
+ * Ratio of maxTokens to allocate for session memory (0-1)
312
+ *
313
+ * Defines what portion of maxTokens budget should be allocated for
314
+ * injecting session memory facts into the prompt.
315
+ *
316
+ * @default DEFAULT_MEMORY_RATIO (0.04 = 4% of maxTokens)
317
+ * @example 0.04 means if maxTokens=80000, allocate 3200 tokens for memory
318
+ */
319
+ memoryRatio?: number;
320
+ /**
321
+ * Maximum number of fact entries to load from storage
322
+ * @default DEFAULT_MEMORY_QUERY_LIMIT (200)
323
+ */
324
+ queryLimit?: number;
325
+ /**
326
+ * Whether to perform memory extraction asynchronously
327
+ * @default DEFAULT_SESSION_MEMORY_ASYNC (true)
328
+ */
329
+ async?: boolean;
330
+ /**
331
+ * Agent that extracts facts from conversation messages
332
+ * Input: { existingUserFacts?: MemoryFact[], existingFacts?: MemoryFact[], messages: ChatModelInputMessage[] }
333
+ * Output: { newFacts: MemoryFact[], removeFacts?: string[] }
334
+ */
335
+ extractor?: MemoryExtractor;
336
+ }
@@ -0,0 +1,7 @@
1
+ import { AIAgent, type AIAgentOptions } from "../../agents/ai-agent.js";
2
+ import type { UserMemoryExtractorInput, UserMemoryExtractorOutput } from "./types.js";
3
+ export interface CreateUserMemoryExtractorOptions extends AIAgentOptions<UserMemoryExtractorInput, UserMemoryExtractorOutput> {
4
+ }
5
+ export declare class AIUserMemoryExtractor extends AIAgent<UserMemoryExtractorInput, UserMemoryExtractorOutput> {
6
+ constructor(options?: CreateUserMemoryExtractorOptions);
7
+ }
@@ -1,4 +1,5 @@
1
1
  import { Agent, type AgentOptions, type Message } from "../../../../agents/agent.js";
2
+ import type { PromiseOrValue } from "../../../../utils/type-utils.js";
2
3
  import type { Skill } from "./skill-loader.js";
3
4
  export interface SkillToolInput extends Message {
4
5
  skill: string;
@@ -11,6 +12,7 @@ export interface SkillToolOptions extends AgentOptions<SkillToolInput, SkillTool
11
12
  agentSkills: Skill[];
12
13
  }
13
14
  export declare class AgentSkill extends Agent<SkillToolInput, SkillToolOutput> {
15
+ formatOutput(output: SkillToolOutput | Message): PromiseOrValue<string>;
14
16
  constructor(options: SkillToolOptions);
15
17
  private agentSkills;
16
18
  process(input: SkillToolInput): Promise<SkillToolOutput>;
@@ -6,8 +6,7 @@ export interface Skill {
6
6
  description: string;
7
7
  content: string;
8
8
  }
9
- export declare function loadSkill(path: string): Promise<Skill>;
10
- export declare function loadSkills(paths: string[]): Promise<Skill[]>;
9
+ export declare function discoverSkillsFromAFS(afs: AFS): Promise<Skill[]>;
11
10
  export declare function loadAgentSkillFromAFS({ afs, }: {
12
11
  afs: AFS;
13
12
  }): Promise<AgentSkill | undefined>;
@@ -1,5 +1,6 @@
1
1
  import type { AFSListOptions } from "@aigne/afs";
2
2
  import type { AgentInvokeOptions, AgentOptions, Message } from "../../../agents/agent.js";
3
+ import type { PromiseOrValue } from "../../../utils/type-utils.js";
3
4
  import { AFSSkillBase } from "./base.js";
4
5
  export interface AFSListInput extends Message {
5
6
  path: string;
@@ -18,5 +19,6 @@ export interface AFSListAgentOptions extends AgentOptions<AFSListInput, AFSListO
18
19
  }
19
20
  export declare class AFSListAgent extends AFSSkillBase<AFSListInput, AFSListOutput> {
20
21
  constructor(options: AFSListAgentOptions);
22
+ formatOutput(output: AFSListOutput): PromiseOrValue<string>;
21
23
  process(input: AFSListInput, _options: AgentInvokeOptions): Promise<AFSListOutput>;
22
24
  }
@@ -1,5 +1,6 @@
1
1
  import type { AFSEntry } from "@aigne/afs";
2
2
  import type { AgentInvokeOptions, AgentOptions, Message } from "../../../agents/agent.js";
3
+ import type { PromiseOrValue } from "../../../utils/type-utils.js";
3
4
  import { AFSSkillBase } from "./base.js";
4
5
  export interface AFSReadInput extends Message {
5
6
  path: string;
@@ -10,7 +11,7 @@ export interface AFSReadOutput extends Message {
10
11
  status: string;
11
12
  tool: string;
12
13
  path: string;
13
- data?: AFSEntry;
14
+ data?: AFSEntry | null;
14
15
  message?: string;
15
16
  totalLines?: number;
16
17
  returnedLines?: number;
@@ -22,5 +23,6 @@ export interface AFSReadAgentOptions extends AgentOptions<AFSReadInput, AFSReadO
22
23
  }
23
24
  export declare class AFSReadAgent extends AFSSkillBase<AFSReadInput, AFSReadOutput> {
24
25
  constructor(options: AFSReadAgentOptions);
26
+ formatOutput(output: AFSReadOutput): PromiseOrValue<string>;
25
27
  process(input: AFSReadInput, _options: AgentInvokeOptions): Promise<AFSReadOutput>;
26
28
  }
@@ -172,6 +172,10 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
172
172
  * This property only exists in the CLI context by command `aigne run`
173
173
  */
174
174
  prompts?: typeof prompts;
175
+ /**
176
+ * The caller agent that invoked this agent
177
+ */
178
+ caller?: Agent;
175
179
  }
176
180
  /**
177
181
  * Agent is the base class for all agents.
@@ -513,6 +517,7 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
513
517
  */
514
518
  protected postprocess(input: I, output: O, options: AgentInvokeOptions): Promise<void>;
515
519
  protected publishToTopics(output: Message, options: AgentInvokeOptions): Promise<void>;
520
+ formatOutput(output: O): PromiseOrValue<string>;
516
521
  /**
517
522
  * Core processing method of the agent, must be implemented in subclasses
518
523
  *
@@ -3,6 +3,7 @@ import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
3
3
  import equal from "fast-deep-equal";
4
4
  import nunjucks from "nunjucks";
5
5
  import { joinURL } from "ufo";
6
+ import { stringify } from "yaml";
6
7
  import { z } from "zod";
7
8
  import { zodToJsonSchema } from "zod-to-json-schema";
8
9
  import { codeToFunctionAgentFn } from "../loader/function-agent.js";
@@ -506,6 +507,7 @@ export class Agent {
506
507
  ...options,
507
508
  model: this.model || options.model,
508
509
  imageModel: this.imageModel || options.imageModel,
510
+ caller: this,
509
511
  });
510
512
  });
511
513
  /**
@@ -667,6 +669,9 @@ export class Agent {
667
669
  });
668
670
  }
669
671
  }
672
+ formatOutput(output) {
673
+ return stringify(output);
674
+ }
670
675
  /**
671
676
  * Shut down the agent and clean up resources
672
677
  *
@@ -2,7 +2,7 @@ import { type ZodObject, type ZodType, z } from "zod";
2
2
  import { type NestAgentSchema } from "../loader/agent-yaml.js";
3
3
  import type { AgentLoadOptions } from "../loader/index.js";
4
4
  import { type Instructions } from "../loader/schema.js";
5
- import type { CompactConfig } from "../prompt/agent-session.js";
5
+ import type { CompactConfig, SessionMemoryConfig, UserMemoryConfig } from "../prompt/agent-session.js";
6
6
  import { PromptBuilder } from "../prompt/prompt-builder.js";
7
7
  import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessAsyncGenerator, type AgentProcessResult, type Message } from "./agent.js";
8
8
  import type { ChatModel, ChatModelInput } from "./chat-model.js";
@@ -126,7 +126,31 @@ export interface AIAgentOptions<I extends Message = Message, O extends Message =
126
126
  */
127
127
  memoryPromptTemplate?: string;
128
128
  useMemoriesFromContext?: boolean;
129
- compact?: CompactConfig;
129
+ /**
130
+ * Agent session configuration
131
+ *
132
+ * Controls history recording, memory extraction, and conversation compaction.
133
+ * By default, mode is "auto" (enabled). Set `{ mode: "disabled" }` to disable
134
+ * for internal utility agents (extractors, compactors, etc.).
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * // Default behavior - session features enabled
139
+ * new AIAgent({
140
+ * session: {
141
+ * compact: { mode: "auto" },
142
+ * sessionMemory: { mode: "auto" },
143
+ * userMemory: { mode: "auto" }
144
+ * }
145
+ * })
146
+ *
147
+ * // Disable for internal utility agents
148
+ * new AIAgent({
149
+ * session: { mode: "disabled" }
150
+ * })
151
+ * ```
152
+ */
153
+ session?: Partial<Omit<import("../prompt/agent-session.js").AgentSessionOptions, "sessionId" | "userId" | "agentId" | "afs">>;
130
154
  }
131
155
  export interface AIAgentLoadSchema {
132
156
  instructions?: Instructions;
@@ -137,8 +161,17 @@ export interface AIAgentLoadSchema {
137
161
  toolChoice?: AIAgentToolChoice;
138
162
  toolCallsConcurrency?: number;
139
163
  keepTextInToolUses?: boolean;
140
- compact?: Omit<CompactConfig, "compactor"> & {
141
- compactor?: NestAgentSchema;
164
+ session?: {
165
+ mode?: "auto" | "disabled";
166
+ compact?: Omit<CompactConfig, "compactor"> & {
167
+ compactor?: NestAgentSchema;
168
+ };
169
+ sessionMemory?: Omit<SessionMemoryConfig, "extractor"> & {
170
+ extractor?: NestAgentSchema;
171
+ };
172
+ userMemory?: Omit<UserMemoryConfig, "extractor"> & {
173
+ extractor?: NestAgentSchema;
174
+ };
142
175
  };
143
176
  }
144
177
  /**
@@ -337,7 +370,10 @@ export declare class AIAgent<I extends Message = any, O extends Message = any> e
337
370
  metadataEnd: string;
338
371
  parse: (raw: string) => object;
339
372
  };
340
- compact?: CompactConfig;
373
+ /**
374
+ * Agent session configuration
375
+ */
376
+ session?: Partial<Omit<import("../prompt/agent-session.js").AgentSessionOptions, "sessionId" | "userId" | "agentId" | "afs">>;
341
377
  get inputSchema(): ZodType<I>;
342
378
  /**
343
379
  * Process an input message and generate a response
@@ -3,6 +3,7 @@ import { getNestAgentSchema } from "../loader/agent-yaml.js";
3
3
  import { camelizeSchema, getInstructionsSchema, instructionsToPromptBuilder, optionalize, } from "../loader/schema.js";
4
4
  import { PromptBuilder } from "../prompt/prompt-builder.js";
5
5
  import { STRUCTURED_STREAM_INSTRUCTIONS } from "../prompt/prompts/structured-stream-instructions.js";
6
+ import { AgentSkill } from "../prompt/skills/afs/agent-skill/agent-skill.js";
6
7
  import * as fastq from "../utils/queue.js";
7
8
  import { mergeAgentResponseChunk } from "../utils/stream-utils.js";
8
9
  import { ExtractMetadataTransform } from "../utils/structured-stream-extractor.js";
@@ -89,7 +90,7 @@ export class AIAgent extends Agent {
89
90
  static schema({ filepath }) {
90
91
  const instructionsSchema = getInstructionsSchema({ filepath });
91
92
  const nestAgentSchema = getNestAgentSchema({ filepath });
92
- return camelizeSchema(z.object({
93
+ const schema = camelizeSchema(z.object({
93
94
  instructions: optionalize(instructionsSchema),
94
95
  inputKey: optionalize(z.string()),
95
96
  outputKey: optionalize(z.string()),
@@ -100,28 +101,75 @@ export class AIAgent extends Agent {
100
101
  keepTextInToolUses: optionalize(z.boolean()),
101
102
  catchToolsError: optionalize(z.boolean()),
102
103
  structuredStreamMode: optionalize(z.boolean()),
103
- compact: camelizeSchema(optionalize(z.object({
104
+ session: optionalize(camelizeSchema(z.object({
104
105
  mode: optionalize(z.enum(["auto", "disabled"])),
105
- maxTokens: z.number().int().min(0).optional(),
106
- keepRecentRatio: optionalize(z.number().min(0).max(1)),
107
- async: optionalize(z.boolean()),
108
- compactor: optionalize(nestAgentSchema),
106
+ sessionMemory: optionalize(camelizeSchema(z.object({
107
+ mode: optionalize(z.enum(["auto", "disabled"])),
108
+ memoryRatio: optionalize(z.number().min(0).max(1)),
109
+ queryLimit: optionalize(z.number().int().min(0)),
110
+ async: optionalize(z.boolean()),
111
+ extractor: optionalize(nestAgentSchema),
112
+ }))),
113
+ userMemory: optionalize(camelizeSchema(z.object({
114
+ mode: optionalize(z.enum(["auto", "disabled"])),
115
+ memoryRatio: optionalize(z.number().min(0).max(1)),
116
+ queryLimit: optionalize(z.number().int().min(0)),
117
+ async: optionalize(z.boolean()),
118
+ extractor: optionalize(nestAgentSchema),
119
+ }))),
120
+ compact: optionalize(camelizeSchema(z.object({
121
+ mode: optionalize(z.enum(["auto", "disabled"])),
122
+ maxTokens: z.number().int().min(0).optional(),
123
+ keepRecentRatio: optionalize(z.number().min(0).max(1)),
124
+ async: optionalize(z.boolean()),
125
+ compactor: optionalize(nestAgentSchema),
126
+ }))),
109
127
  }))),
110
128
  }));
129
+ return schema;
111
130
  }
112
131
  static async load(options) {
113
132
  const schema = AIAgent.schema(options);
114
133
  const valid = await schema.parseAsync(options.parsed);
134
+ // Load nested agents from session config if present
135
+ const sessionCompactor = valid.session?.compact?.compactor
136
+ ? await options.options?.loadNestAgent(options.filepath, valid.session.compact.compactor, options.options)
137
+ : undefined;
138
+ const sessionMemoryExtractor = valid.session?.sessionMemory?.extractor
139
+ ? await options.options?.loadNestAgent(options.filepath, valid.session.sessionMemory.extractor, options.options)
140
+ : undefined;
141
+ const userMemoryExtractor = valid.session?.userMemory?.extractor
142
+ ? await options.options?.loadNestAgent(options.filepath, valid.session.userMemory.extractor, options.options)
143
+ : undefined;
144
+ // Build session configuration with loaded agents
145
+ const sessionConfig = valid.session
146
+ ? {
147
+ ...valid.session,
148
+ compact: valid.session.compact
149
+ ? {
150
+ ...valid.session.compact,
151
+ compactor: sessionCompactor,
152
+ }
153
+ : undefined,
154
+ sessionMemory: valid.session.sessionMemory
155
+ ? {
156
+ ...valid.session.sessionMemory,
157
+ extractor: sessionMemoryExtractor,
158
+ }
159
+ : undefined,
160
+ userMemory: valid.session.userMemory
161
+ ? {
162
+ ...valid.session.userMemory,
163
+ extractor: userMemoryExtractor,
164
+ }
165
+ : undefined,
166
+ }
167
+ : undefined;
115
168
  return new AIAgent({
116
169
  ...options.parsed,
117
170
  ...valid,
118
171
  instructions: valid.instructions && instructionsToPromptBuilder(valid.instructions),
119
- compact: {
120
- ...valid.compact,
121
- compactor: valid.compact?.compactor
122
- ? await options.options?.loadNestAgent(options.filepath, valid.compact.compactor, options.options)
123
- : undefined,
124
- },
172
+ session: sessionConfig,
125
173
  });
126
174
  }
127
175
  /**
@@ -162,7 +210,7 @@ export class AIAgent extends Agent {
162
210
  this.memoryAgentsAsTools = options.memoryAgentsAsTools;
163
211
  this.memoryPromptTemplate = options.memoryPromptTemplate;
164
212
  this.useMemoriesFromContext = options.useMemoriesFromContext;
165
- this.compact = options.compact;
213
+ this.session = options.session;
166
214
  if (typeof options.catchToolsError === "boolean")
167
215
  this.catchToolsError = options.catchToolsError;
168
216
  this.structuredStreamMode = options.structuredStreamMode;
@@ -278,7 +326,10 @@ export class AIAgent extends Agent {
278
326
  * which outputs structured data in YAML format within <metadata> tags.
279
327
  */
280
328
  customStructuredStreamInstructions;
281
- compact;
329
+ /**
330
+ * Agent session configuration
331
+ */
332
+ session;
282
333
  get inputSchema() {
283
334
  let schema = super.inputSchema;
284
335
  if (this.inputKey) {
@@ -364,16 +415,27 @@ export class AIAgent extends Agent {
364
415
  if (content.length) {
365
416
  const message = { role: "agent", content };
366
417
  yield { progress: { event: "message", message } };
367
- await session.appendCurrentMessages(message);
418
+ await session.appendCurrentMessages(message, options);
368
419
  }
369
420
  }
370
- if (toolCalls?.length) {
421
+ const toolCallsWithTools = toolCalls?.map((call) => {
422
+ const tool = toolsMap.get(call.function.name);
423
+ if (!tool)
424
+ throw new Error(`Tool not found: ${call.function.name}`);
425
+ return {
426
+ ...call,
427
+ tool,
428
+ };
429
+ });
430
+ if (toolCallsWithTools?.length) {
371
431
  if (this.keepTextInToolUses !== true) {
372
432
  yield { delta: { json: { [outputKey]: "" } } };
373
433
  }
374
434
  else {
375
435
  yield { delta: { text: { [outputKey]: "\n\n" } } };
376
436
  }
437
+ const toolCallMessage = { role: "agent", toolCalls };
438
+ yield { progress: { event: "message", message: toolCallMessage } };
377
439
  const executedToolCalls = [];
378
440
  let error;
379
441
  const queue = fastq.promise(async ({ tool, call }) => {
@@ -390,40 +452,38 @@ export class AIAgent extends Agent {
390
452
  },
391
453
  };
392
454
  });
393
- executedToolCalls.push({ call, output });
455
+ executedToolCalls.push({ call, tool, output });
394
456
  }
395
457
  catch (e) {
396
458
  error = e;
397
459
  queue.killAndDrain();
398
460
  }
399
461
  }, this.toolCallsConcurrency || 1);
400
- const message = { role: "agent", toolCalls };
401
- yield { progress: { event: "message", message } };
402
- await session.appendCurrentMessages(message);
403
462
  // Execute tools
404
- for (const call of toolCalls) {
405
- const tool = toolsMap.get(call.function.name);
406
- if (!tool)
407
- throw new Error(`Tool not found: ${call.function.name}`);
408
- queue.push({ tool, call });
463
+ for (const call of toolCallsWithTools) {
464
+ queue.push({ tool: call.tool, call });
409
465
  }
410
466
  await queue.drained();
411
467
  if (error)
412
468
  throw error;
469
+ const toolResultMessages = [];
413
470
  // Continue LLM function calling loop if any tools were executed
414
471
  if (executedToolCalls.length) {
415
- for (const { call, output } of executedToolCalls) {
472
+ for (const { call, tool, output } of executedToolCalls) {
473
+ const isAgentSkill = !output.isError && tool instanceof AgentSkill ? true : undefined;
474
+ const text = await tool.formatOutput(output);
416
475
  const message = {
417
476
  role: "tool",
418
477
  toolCallId: call.id,
419
- content: JSON.stringify(output),
478
+ content: [{ type: "text", text, isAgentSkill }],
420
479
  };
421
480
  yield { progress: { event: "message", message: message } };
422
- await session.appendCurrentMessages(message);
481
+ toolResultMessages.push(message);
423
482
  }
424
483
  const transferOutput = executedToolCalls.find((i) => isTransferAgentOutput(i.output))?.output;
425
484
  if (transferOutput)
426
485
  return transferOutput;
486
+ await session.appendCurrentMessages([toolCallMessage, ...toolResultMessages], options);
427
487
  continue;
428
488
  }
429
489
  }
@@ -440,7 +500,7 @@ export class AIAgent extends Agent {
440
500
  if (!isEmpty(result)) {
441
501
  yield { delta: { json: result } };
442
502
  }
443
- await session.endMessage(result, options);
503
+ await session.endMessage(result, undefined, options);
444
504
  return;
445
505
  }
446
506
  }