@aigne/core 1.18.3 → 1.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@
5
5
 
6
6
  * add user context support ([#131](https://github.com/AIGNE-io/aigne-framework/issues/131)) ([4dd9d20](https://github.com/AIGNE-io/aigne-framework/commit/4dd9d20953f6ac33933723db56efd9b44bafeb02))
7
7
 
8
+ ## [1.18.5](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.18.4...core-v1.18.5) (2025-06-06)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **core:** should pass memories from invocation options to nested agents ([#153](https://github.com/AIGNE-io/aigne-framework/issues/153)) ([57629a5](https://github.com/AIGNE-io/aigne-framework/commit/57629a5da6cf2a295356dfe32ecbb15154e098fe))
14
+
15
+ ## [1.18.4](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.18.3...core-v1.18.4) (2025-06-05)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **core:** prioritize returning json chunks ([#151](https://github.com/AIGNE-io/aigne-framework/issues/151)) ([8bf49a1](https://github.com/AIGNE-io/aigne-framework/commit/8bf49a18c083b33d2e0b35e8d0f22f68d9d6effa))
21
+
8
22
  ## [1.18.3](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.18.2...core-v1.18.3) (2025-06-05)
9
23
 
10
24
 
@@ -336,6 +336,11 @@ class Agent {
336
336
  };
337
337
  if (options.userContext) {
338
338
  Object.assign(opts.context.userContext, options.userContext);
339
+ options.userContext = undefined;
340
+ }
341
+ if (options.memories?.length) {
342
+ opts.context.memories.push(...options.memories);
343
+ options.memories = undefined;
339
344
  }
340
345
  const message = typeof input === "string" ? (0, prompt_builder_js_1.createMessage)(input) : input;
341
346
  logger_js_1.logger.debug("Invoke agent %s started with input: %O", this.name, input);
@@ -2,6 +2,7 @@ import { Emitter } from "strict-event-emitter";
2
2
  import { Agent, type AgentInvokeOptions, type AgentProcessAsyncGenerator, type AgentResponse, type AgentResponseStream, type Message } from "../agents/agent.js";
3
3
  import type { ChatModel } from "../agents/chat-model.js";
4
4
  import { UserAgent } from "../agents/user-agent.js";
5
+ import type { Memory } from "../memory/memory.js";
5
6
  import { type OmitPropertiesFromArrayFirstElement } from "../utils/type-utils.js";
6
7
  import type { Args, Listener, TypedEventEmitter } from "../utils/typed-event-emtter.js";
7
8
  import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
@@ -58,6 +59,7 @@ export interface Context<U extends UserContext = UserContext> extends TypedEvent
58
59
  limits?: ContextLimits;
59
60
  status?: "normal" | "timeout";
60
61
  userContext: U;
62
+ memories: Pick<Memory, "content">[];
61
63
  /**
62
64
  * Create a user agent to consistently invoke an agent
63
65
  * @param agent Agent to invoke
@@ -131,6 +133,8 @@ export declare class AIGNEContext implements Context {
131
133
  get usage(): ContextUsage;
132
134
  get userContext(): Context["userContext"];
133
135
  set userContext(userContext: Context["userContext"]);
136
+ get memories(): Context["memories"];
137
+ set memories(memories: Context["memories"]);
134
138
  newContext({ reset }?: {
135
139
  reset?: boolean;
136
140
  }): AIGNEContext;
@@ -155,6 +159,7 @@ declare class AIGNEContextShared {
155
159
  get limits(): ContextLimits | undefined;
156
160
  usage: ContextUsage;
157
161
  userContext: Context["userContext"];
162
+ memories: Context["memories"];
158
163
  private abortController;
159
164
  private timer?;
160
165
  private initTimeout;
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.AIGNEContext = void 0;
7
+ const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
4
8
  const strict_event_emitter_1 = require("strict-event-emitter");
5
9
  const uuid_1 = require("uuid");
6
10
  const zod_1 = require("zod");
@@ -50,6 +54,12 @@ class AIGNEContext {
50
54
  set userContext(userContext) {
51
55
  this.internal.userContext = userContext;
52
56
  }
57
+ get memories() {
58
+ return this.internal.memories;
59
+ }
60
+ set memories(memories) {
61
+ this.internal.memories = memories;
62
+ }
53
63
  newContext({ reset } = {}) {
54
64
  if (reset)
55
65
  return new AIGNEContext(this, { userContext: {} });
@@ -61,8 +71,14 @@ class AIGNEContext {
61
71
  message,
62
72
  options,
63
73
  });
64
- if (options?.userContext)
74
+ if (options?.userContext) {
65
75
  Object.assign(this.userContext, options.userContext);
76
+ options.userContext = undefined;
77
+ }
78
+ if (options?.memories?.length) {
79
+ this.memories.push(...options.memories);
80
+ options.memories = undefined;
81
+ }
66
82
  if ((0, type_utils_js_1.isNil)(message)) {
67
83
  return user_agent_js_1.UserAgent.from({
68
84
  context: this,
@@ -103,8 +119,14 @@ class AIGNEContext {
103
119
  });
104
120
  });
105
121
  publish = ((topic, payload, options) => {
106
- if (options?.userContext)
122
+ if (options?.userContext) {
107
123
  Object.assign(this.userContext, options.userContext);
124
+ options.userContext = undefined;
125
+ }
126
+ if (options?.memories?.length) {
127
+ this.memories.push(...options.memories);
128
+ options.memories = undefined;
129
+ }
108
130
  return this.internal.messageQueue.publish(topic, {
109
131
  ...(0, message_queue_js_1.toMessagePayload)(payload),
110
132
  context: this,
@@ -146,6 +168,7 @@ class AIGNEContextShared {
146
168
  this.parent = parent;
147
169
  this.messageQueue = this.parent?.messageQueue ?? new message_queue_js_1.MessageQueue();
148
170
  this.userContext = overrides?.userContext ?? {};
171
+ this.memories = overrides?.memories ?? [];
149
172
  }
150
173
  messageQueue;
151
174
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
@@ -161,6 +184,7 @@ class AIGNEContextShared {
161
184
  }
162
185
  usage = (0, usage_js_1.newEmptyContextUsage)();
163
186
  userContext;
187
+ memories;
164
188
  abortController = new AbortController();
165
189
  timer;
166
190
  initTimeout() {
@@ -182,7 +206,6 @@ class AIGNEContextShared {
182
206
  }
183
207
  async *invokeAgent(agent, input, context, options) {
184
208
  let activeAgent = agent;
185
- let output;
186
209
  for (;;) {
187
210
  const result = {};
188
211
  if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
@@ -195,12 +218,14 @@ class AIGNEContextShared {
195
218
  }
196
219
  const stream = await activeAgent.invoke(input, { ...options, context, streaming: true });
197
220
  for await (const value of stream) {
198
- if (value.delta.text) {
199
- yield { delta: { text: value.delta.text } };
200
- }
201
221
  if (value.delta.json) {
222
+ value.delta.json = omitExistsProperties(result, value.delta.json);
202
223
  Object.assign(result, value.delta.json);
203
224
  }
225
+ delete value.delta.json?.[types_js_1.transferAgentOutputKey];
226
+ if ((0, agent_js_1.isEmptyChunk)(value))
227
+ continue;
228
+ yield value;
204
229
  }
205
230
  if (!options?.disableTransfer) {
206
231
  const transferToAgent = (0, types_js_1.isTransferAgentOutput)(result)
@@ -211,21 +236,22 @@ class AIGNEContextShared {
211
236
  continue;
212
237
  }
213
238
  }
214
- output = result;
215
239
  break;
216
240
  }
217
- if (!output)
218
- throw new Error("Unexpected empty output");
219
241
  yield {
220
242
  delta: {
221
- json: {
222
- ...output,
223
- __activeAgent__: activeAgent,
224
- },
243
+ json: { __activeAgent__: activeAgent },
225
244
  },
226
245
  };
227
246
  }
228
247
  }
248
+ function omitExistsProperties(result, { ...delta }) {
249
+ for (const [key, val] of Object.entries(delta)) {
250
+ if ((0, fast_deep_equal_1.default)(result[key], val))
251
+ delete delta[key];
252
+ }
253
+ return (0, type_utils_js_1.isEmpty)(delta) ? undefined : delta;
254
+ }
229
255
  async function* withAbortSignal(signal, error, fn) {
230
256
  const iterator = fn();
231
257
  const timeoutPromise = (0, promise_js_1.promiseWithResolvers)();
@@ -15,7 +15,7 @@ export declare function getMessage(input: Message): string | undefined;
15
15
  export interface PromptBuilderOptions {
16
16
  instructions?: string | ChatMessagesTemplate;
17
17
  }
18
- export interface PromptBuildOptions extends AgentInvokeOptions {
18
+ export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"> {
19
19
  agent?: AIAgent;
20
20
  input?: Message;
21
21
  model?: ChatModel;
@@ -87,8 +87,8 @@ class PromptBuilder {
87
87
  if (options.agent) {
88
88
  memories.push(...(await options.agent.retrieveMemories({ search: options.input }, options)));
89
89
  }
90
- if (options.memories?.length) {
91
- memories.push(...options.memories);
90
+ if (options.context.memories?.length) {
91
+ memories.push(...options.context.memories);
92
92
  }
93
93
  if (memories.length)
94
94
  messages.push(...this.convertMemoriesToMessages(memories, options));
@@ -2,6 +2,7 @@ import { Emitter } from "strict-event-emitter";
2
2
  import { Agent, type AgentInvokeOptions, type AgentProcessAsyncGenerator, type AgentResponse, type AgentResponseStream, type Message } from "../agents/agent.js";
3
3
  import type { ChatModel } from "../agents/chat-model.js";
4
4
  import { UserAgent } from "../agents/user-agent.js";
5
+ import type { Memory } from "../memory/memory.js";
5
6
  import { type OmitPropertiesFromArrayFirstElement } from "../utils/type-utils.js";
6
7
  import type { Args, Listener, TypedEventEmitter } from "../utils/typed-event-emtter.js";
7
8
  import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
@@ -58,6 +59,7 @@ export interface Context<U extends UserContext = UserContext> extends TypedEvent
58
59
  limits?: ContextLimits;
59
60
  status?: "normal" | "timeout";
60
61
  userContext: U;
62
+ memories: Pick<Memory, "content">[];
61
63
  /**
62
64
  * Create a user agent to consistently invoke an agent
63
65
  * @param agent Agent to invoke
@@ -131,6 +133,8 @@ export declare class AIGNEContext implements Context {
131
133
  get usage(): ContextUsage;
132
134
  get userContext(): Context["userContext"];
133
135
  set userContext(userContext: Context["userContext"]);
136
+ get memories(): Context["memories"];
137
+ set memories(memories: Context["memories"]);
134
138
  newContext({ reset }?: {
135
139
  reset?: boolean;
136
140
  }): AIGNEContext;
@@ -155,6 +159,7 @@ declare class AIGNEContextShared {
155
159
  get limits(): ContextLimits | undefined;
156
160
  usage: ContextUsage;
157
161
  userContext: Context["userContext"];
162
+ memories: Context["memories"];
158
163
  private abortController;
159
164
  private timer?;
160
165
  private initTimeout;
@@ -15,7 +15,7 @@ export declare function getMessage(input: Message): string | undefined;
15
15
  export interface PromptBuilderOptions {
16
16
  instructions?: string | ChatMessagesTemplate;
17
17
  }
18
- export interface PromptBuildOptions extends AgentInvokeOptions {
18
+ export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"> {
19
19
  agent?: AIAgent;
20
20
  input?: Message;
21
21
  model?: ChatModel;
@@ -294,6 +294,11 @@ export class Agent {
294
294
  };
295
295
  if (options.userContext) {
296
296
  Object.assign(opts.context.userContext, options.userContext);
297
+ options.userContext = undefined;
298
+ }
299
+ if (options.memories?.length) {
300
+ opts.context.memories.push(...options.memories);
301
+ options.memories = undefined;
297
302
  }
298
303
  const message = typeof input === "string" ? createMessage(input) : input;
299
304
  logger.debug("Invoke agent %s started with input: %O", this.name, input);
@@ -2,6 +2,7 @@ import { Emitter } from "strict-event-emitter";
2
2
  import { Agent, type AgentInvokeOptions, type AgentProcessAsyncGenerator, type AgentResponse, type AgentResponseStream, type Message } from "../agents/agent.js";
3
3
  import type { ChatModel } from "../agents/chat-model.js";
4
4
  import { UserAgent } from "../agents/user-agent.js";
5
+ import type { Memory } from "../memory/memory.js";
5
6
  import { type OmitPropertiesFromArrayFirstElement } from "../utils/type-utils.js";
6
7
  import type { Args, Listener, TypedEventEmitter } from "../utils/typed-event-emtter.js";
7
8
  import { type MessagePayload, MessageQueue, type MessageQueueListener, type Unsubscribe } from "./message-queue.js";
@@ -58,6 +59,7 @@ export interface Context<U extends UserContext = UserContext> extends TypedEvent
58
59
  limits?: ContextLimits;
59
60
  status?: "normal" | "timeout";
60
61
  userContext: U;
62
+ memories: Pick<Memory, "content">[];
61
63
  /**
62
64
  * Create a user agent to consistently invoke an agent
63
65
  * @param agent Agent to invoke
@@ -131,6 +133,8 @@ export declare class AIGNEContext implements Context {
131
133
  get usage(): ContextUsage;
132
134
  get userContext(): Context["userContext"];
133
135
  set userContext(userContext: Context["userContext"]);
136
+ get memories(): Context["memories"];
137
+ set memories(memories: Context["memories"]);
134
138
  newContext({ reset }?: {
135
139
  reset?: boolean;
136
140
  }): AIGNEContext;
@@ -155,6 +159,7 @@ declare class AIGNEContextShared {
155
159
  get limits(): ContextLimits | undefined;
156
160
  usage: ContextUsage;
157
161
  userContext: Context["userContext"];
162
+ memories: Context["memories"];
158
163
  private abortController;
159
164
  private timer?;
160
165
  private initTimeout;
@@ -1,13 +1,14 @@
1
+ import equal from "fast-deep-equal";
1
2
  import { Emitter } from "strict-event-emitter";
2
3
  import { v7 } from "uuid";
3
4
  import { z } from "zod";
4
- import { Agent, } from "../agents/agent.js";
5
+ import { Agent, isEmptyChunk, } from "../agents/agent.js";
5
6
  import { isTransferAgentOutput, transferAgentOutputKey, } from "../agents/types.js";
6
7
  import { UserAgent } from "../agents/user-agent.js";
7
8
  import { createMessage } from "../prompt/prompt-builder.js";
8
9
  import { promiseWithResolvers } from "../utils/promise.js";
9
10
  import { agentResponseStreamToObject, asyncGeneratorToReadableStream, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
10
- import { checkArguments, isNil, omitBy, } from "../utils/type-utils.js";
11
+ import { checkArguments, isEmpty, isNil, omitBy, } from "../utils/type-utils.js";
11
12
  import { MessageQueue, toMessagePayload, } from "./message-queue.js";
12
13
  import { newEmptyContextUsage } from "./usage.js";
13
14
  /**
@@ -47,6 +48,12 @@ export class AIGNEContext {
47
48
  set userContext(userContext) {
48
49
  this.internal.userContext = userContext;
49
50
  }
51
+ get memories() {
52
+ return this.internal.memories;
53
+ }
54
+ set memories(memories) {
55
+ this.internal.memories = memories;
56
+ }
50
57
  newContext({ reset } = {}) {
51
58
  if (reset)
52
59
  return new AIGNEContext(this, { userContext: {} });
@@ -58,8 +65,14 @@ export class AIGNEContext {
58
65
  message,
59
66
  options,
60
67
  });
61
- if (options?.userContext)
68
+ if (options?.userContext) {
62
69
  Object.assign(this.userContext, options.userContext);
70
+ options.userContext = undefined;
71
+ }
72
+ if (options?.memories?.length) {
73
+ this.memories.push(...options.memories);
74
+ options.memories = undefined;
75
+ }
63
76
  if (isNil(message)) {
64
77
  return UserAgent.from({
65
78
  context: this,
@@ -100,8 +113,14 @@ export class AIGNEContext {
100
113
  });
101
114
  });
102
115
  publish = ((topic, payload, options) => {
103
- if (options?.userContext)
116
+ if (options?.userContext) {
104
117
  Object.assign(this.userContext, options.userContext);
118
+ options.userContext = undefined;
119
+ }
120
+ if (options?.memories?.length) {
121
+ this.memories.push(...options.memories);
122
+ options.memories = undefined;
123
+ }
105
124
  return this.internal.messageQueue.publish(topic, {
106
125
  ...toMessagePayload(payload),
107
126
  context: this,
@@ -142,6 +161,7 @@ class AIGNEContextShared {
142
161
  this.parent = parent;
143
162
  this.messageQueue = this.parent?.messageQueue ?? new MessageQueue();
144
163
  this.userContext = overrides?.userContext ?? {};
164
+ this.memories = overrides?.memories ?? [];
145
165
  }
146
166
  messageQueue;
147
167
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
@@ -157,6 +177,7 @@ class AIGNEContextShared {
157
177
  }
158
178
  usage = newEmptyContextUsage();
159
179
  userContext;
180
+ memories;
160
181
  abortController = new AbortController();
161
182
  timer;
162
183
  initTimeout() {
@@ -178,7 +199,6 @@ class AIGNEContextShared {
178
199
  }
179
200
  async *invokeAgent(agent, input, context, options) {
180
201
  let activeAgent = agent;
181
- let output;
182
202
  for (;;) {
183
203
  const result = {};
184
204
  if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
@@ -191,12 +211,14 @@ class AIGNEContextShared {
191
211
  }
192
212
  const stream = await activeAgent.invoke(input, { ...options, context, streaming: true });
193
213
  for await (const value of stream) {
194
- if (value.delta.text) {
195
- yield { delta: { text: value.delta.text } };
196
- }
197
214
  if (value.delta.json) {
215
+ value.delta.json = omitExistsProperties(result, value.delta.json);
198
216
  Object.assign(result, value.delta.json);
199
217
  }
218
+ delete value.delta.json?.[transferAgentOutputKey];
219
+ if (isEmptyChunk(value))
220
+ continue;
221
+ yield value;
200
222
  }
201
223
  if (!options?.disableTransfer) {
202
224
  const transferToAgent = isTransferAgentOutput(result)
@@ -207,21 +229,22 @@ class AIGNEContextShared {
207
229
  continue;
208
230
  }
209
231
  }
210
- output = result;
211
232
  break;
212
233
  }
213
- if (!output)
214
- throw new Error("Unexpected empty output");
215
234
  yield {
216
235
  delta: {
217
- json: {
218
- ...output,
219
- __activeAgent__: activeAgent,
220
- },
236
+ json: { __activeAgent__: activeAgent },
221
237
  },
222
238
  };
223
239
  }
224
240
  }
241
+ function omitExistsProperties(result, { ...delta }) {
242
+ for (const [key, val] of Object.entries(delta)) {
243
+ if (equal(result[key], val))
244
+ delete delta[key];
245
+ }
246
+ return isEmpty(delta) ? undefined : delta;
247
+ }
225
248
  async function* withAbortSignal(signal, error, fn) {
226
249
  const iterator = fn();
227
250
  const timeoutPromise = promiseWithResolvers();
@@ -15,7 +15,7 @@ export declare function getMessage(input: Message): string | undefined;
15
15
  export interface PromptBuilderOptions {
16
16
  instructions?: string | ChatMessagesTemplate;
17
17
  }
18
- export interface PromptBuildOptions extends AgentInvokeOptions {
18
+ export interface PromptBuildOptions extends Pick<AgentInvokeOptions, "context"> {
19
19
  agent?: AIAgent;
20
20
  input?: Message;
21
21
  model?: ChatModel;
@@ -82,8 +82,8 @@ export class PromptBuilder {
82
82
  if (options.agent) {
83
83
  memories.push(...(await options.agent.retrieveMemories({ search: options.input }, options)));
84
84
  }
85
- if (options.memories?.length) {
86
- memories.push(...options.memories);
85
+ if (options.context.memories?.length) {
86
+ memories.push(...options.context.memories);
87
87
  }
88
88
  if (memories.length)
89
89
  messages.push(...this.convertMemoriesToMessages(memories, options));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.18.3",
3
+ "version": "1.18.5",
4
4
  "description": "AIGNE core library for building AI-powered applications",
5
5
  "publishConfig": {
6
6
  "access": "public"