@aigne/core 1.16.0 → 1.18.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 (100) hide show
  1. package/CHANGELOG.md +37 -16
  2. package/lib/cjs/agents/agent.d.ts +69 -37
  3. package/lib/cjs/agents/agent.js +93 -65
  4. package/lib/cjs/agents/ai-agent.d.ts +4 -7
  5. package/lib/cjs/agents/ai-agent.js +10 -19
  6. package/lib/cjs/agents/chat-model.d.ts +7 -8
  7. package/lib/cjs/agents/chat-model.js +9 -9
  8. package/lib/cjs/agents/mcp-agent.d.ts +4 -5
  9. package/lib/cjs/agents/mcp-agent.js +7 -13
  10. package/lib/cjs/agents/team-agent.d.ts +7 -8
  11. package/lib/cjs/agents/team-agent.js +10 -10
  12. package/lib/cjs/agents/user-agent.d.ts +4 -5
  13. package/lib/cjs/agents/user-agent.js +11 -12
  14. package/lib/cjs/aigne/aigne.d.ts +10 -9
  15. package/lib/cjs/aigne/aigne.js +5 -4
  16. package/lib/cjs/aigne/context.d.ts +18 -9
  17. package/lib/cjs/aigne/context.js +23 -12
  18. package/lib/cjs/aigne/message-queue.d.ts +6 -2
  19. package/lib/cjs/aigne/message-queue.js +2 -2
  20. package/lib/cjs/index.d.ts +3 -1
  21. package/lib/cjs/index.js +3 -1
  22. package/lib/cjs/loader/agent-js.d.ts +1 -1
  23. package/lib/cjs/loader/agent-yaml.d.ts +3 -2
  24. package/lib/cjs/loader/agent-yaml.js +3 -2
  25. package/lib/cjs/loader/index.d.ts +5 -1
  26. package/lib/cjs/loader/index.js +25 -16
  27. package/lib/cjs/memory/memory.d.ts +3 -2
  28. package/lib/cjs/memory/memory.js +1 -1
  29. package/lib/cjs/memory/retriever.d.ts +2 -2
  30. package/lib/cjs/prompt/prompt-builder.d.ts +9 -7
  31. package/lib/cjs/prompt/prompt-builder.js +14 -10
  32. package/lib/cjs/prompt/template.js +1 -3
  33. package/lib/cjs/utils/logger.js +3 -3
  34. package/lib/cjs/utils/nodejs.d.ts +8 -0
  35. package/lib/cjs/utils/nodejs.js +24 -0
  36. package/lib/cjs/utils/type-utils.d.ts +2 -2
  37. package/lib/dts/agents/agent.d.ts +69 -37
  38. package/lib/dts/agents/ai-agent.d.ts +4 -7
  39. package/lib/dts/agents/chat-model.d.ts +7 -8
  40. package/lib/dts/agents/mcp-agent.d.ts +4 -5
  41. package/lib/dts/agents/team-agent.d.ts +7 -8
  42. package/lib/dts/agents/user-agent.d.ts +4 -5
  43. package/lib/dts/aigne/aigne.d.ts +10 -9
  44. package/lib/dts/aigne/context.d.ts +18 -9
  45. package/lib/dts/aigne/message-queue.d.ts +6 -2
  46. package/lib/dts/index.d.ts +3 -1
  47. package/lib/dts/loader/agent-js.d.ts +1 -1
  48. package/lib/dts/loader/agent-yaml.d.ts +3 -2
  49. package/lib/dts/loader/index.d.ts +5 -1
  50. package/lib/dts/memory/memory.d.ts +3 -2
  51. package/lib/dts/memory/retriever.d.ts +2 -2
  52. package/lib/dts/prompt/prompt-builder.d.ts +9 -7
  53. package/lib/dts/utils/nodejs.d.ts +8 -0
  54. package/lib/dts/utils/type-utils.d.ts +2 -2
  55. package/lib/esm/agents/agent.d.ts +69 -37
  56. package/lib/esm/agents/agent.js +94 -66
  57. package/lib/esm/agents/ai-agent.d.ts +4 -7
  58. package/lib/esm/agents/ai-agent.js +10 -19
  59. package/lib/esm/agents/chat-model.d.ts +7 -8
  60. package/lib/esm/agents/chat-model.js +9 -9
  61. package/lib/esm/agents/mcp-agent.d.ts +4 -5
  62. package/lib/esm/agents/mcp-agent.js +7 -13
  63. package/lib/esm/agents/team-agent.d.ts +7 -8
  64. package/lib/esm/agents/team-agent.js +10 -10
  65. package/lib/esm/agents/user-agent.d.ts +4 -5
  66. package/lib/esm/agents/user-agent.js +10 -11
  67. package/lib/esm/aigne/aigne.d.ts +10 -9
  68. package/lib/esm/aigne/aigne.js +5 -4
  69. package/lib/esm/aigne/context.d.ts +18 -9
  70. package/lib/esm/aigne/context.js +24 -10
  71. package/lib/esm/aigne/message-queue.d.ts +6 -2
  72. package/lib/esm/aigne/message-queue.js +2 -2
  73. package/lib/esm/index.d.ts +3 -1
  74. package/lib/esm/index.js +3 -1
  75. package/lib/esm/loader/agent-js.d.ts +1 -1
  76. package/lib/esm/loader/agent-yaml.d.ts +3 -2
  77. package/lib/esm/loader/agent-yaml.js +3 -2
  78. package/lib/esm/loader/index.d.ts +5 -1
  79. package/lib/esm/loader/index.js +25 -16
  80. package/lib/esm/memory/memory.d.ts +3 -2
  81. package/lib/esm/memory/memory.js +2 -2
  82. package/lib/esm/memory/retriever.d.ts +2 -2
  83. package/lib/esm/prompt/prompt-builder.d.ts +9 -7
  84. package/lib/esm/prompt/prompt-builder.js +15 -11
  85. package/lib/esm/prompt/template.js +1 -3
  86. package/lib/esm/utils/logger.js +3 -3
  87. package/lib/esm/utils/nodejs.d.ts +8 -0
  88. package/lib/esm/utils/nodejs.js +21 -0
  89. package/lib/esm/utils/type-utils.d.ts +2 -2
  90. package/package.json +4 -3
  91. package/lib/cjs/memory/default-memory.d.ts +0 -16
  92. package/lib/cjs/memory/default-memory.js +0 -70
  93. package/lib/cjs/utils/fs.d.ts +0 -2
  94. package/lib/cjs/utils/fs.js +0 -25
  95. package/lib/dts/memory/default-memory.d.ts +0 -16
  96. package/lib/dts/utils/fs.d.ts +0 -2
  97. package/lib/esm/memory/default-memory.d.ts +0 -16
  98. package/lib/esm/memory/default-memory.js +0 -63
  99. package/lib/esm/utils/fs.d.ts +0 -2
  100. package/lib/esm/utils/fs.js +0 -21
@@ -1,8 +1,8 @@
1
- import EventEmitter from "node:events";
1
+ import { Emitter } from "strict-event-emitter";
2
2
  import { v7 } from "uuid";
3
3
  import { z } from "zod";
4
4
  import { Agent, } from "../agents/agent.js";
5
- import { isTransferAgentOutput, transferAgentOutputKey } from "../agents/types.js";
5
+ import { isTransferAgentOutput, transferAgentOutputKey, } from "../agents/types.js";
6
6
  import { UserAgent } from "../agents/user-agent.js";
7
7
  import { createMessage } from "../prompt/prompt-builder.js";
8
8
  import { agentResponseStreamToObject, asyncGeneratorToReadableStream, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
@@ -13,13 +13,13 @@ import { newEmptyContextUsage } from "./usage.js";
13
13
  * @hidden
14
14
  */
15
15
  export class AIGNEContext {
16
- constructor(parent) {
16
+ constructor(...[parent, ...args]) {
17
17
  if (parent instanceof AIGNEContext) {
18
18
  this.parentId = parent.id;
19
19
  this.internal = parent.internal;
20
20
  }
21
21
  else {
22
- this.internal = new AIGNEContextInternal(parent);
22
+ this.internal = new AIGNEContextShared(parent, ...args);
23
23
  }
24
24
  }
25
25
  parentId;
@@ -40,9 +40,15 @@ export class AIGNEContext {
40
40
  get usage() {
41
41
  return this.internal.usage;
42
42
  }
43
+ get userContext() {
44
+ return this.internal.userContext;
45
+ }
46
+ set userContext(userContext) {
47
+ this.internal.userContext = userContext;
48
+ }
43
49
  newContext({ reset } = {}) {
44
50
  if (reset)
45
- return new AIGNEContext(this.internal);
51
+ return new AIGNEContext(this, { userContext: {} });
46
52
  return new AIGNEContext(this);
47
53
  }
48
54
  invoke = ((agent, message, options) => {
@@ -51,6 +57,8 @@ export class AIGNEContext {
51
57
  message,
52
58
  options,
53
59
  });
60
+ if (options?.userContext)
61
+ Object.assign(this.userContext, options.userContext);
54
62
  if (isNil(message)) {
55
63
  return UserAgent.from({
56
64
  context: this,
@@ -90,7 +98,9 @@ export class AIGNEContext {
90
98
  return stream;
91
99
  });
92
100
  });
93
- publish = ((topic, payload) => {
101
+ publish = ((topic, payload, options) => {
102
+ if (options?.userContext)
103
+ Object.assign(this.userContext, options.userContext);
94
104
  return this.internal.messageQueue.publish(topic, {
95
105
  ...toMessagePayload(payload),
96
106
  context: this,
@@ -125,14 +135,16 @@ export class AIGNEContext {
125
135
  return this;
126
136
  }
127
137
  }
128
- class AIGNEContextInternal {
138
+ class AIGNEContextShared {
129
139
  parent;
130
- constructor(parent) {
140
+ constructor(parent, overrides) {
131
141
  this.parent = parent;
132
142
  this.messageQueue = this.parent?.messageQueue ?? new MessageQueue();
143
+ this.userContext = overrides?.userContext ?? {};
133
144
  }
134
145
  messageQueue;
135
- events = new EventEmitter();
146
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
147
+ events = new Emitter();
136
148
  get model() {
137
149
  return this.parent?.model;
138
150
  }
@@ -143,6 +155,7 @@ class AIGNEContextInternal {
143
155
  return this.parent?.limits;
144
156
  }
145
157
  usage = newEmptyContextUsage();
158
+ userContext;
146
159
  abortController = new AbortController();
147
160
  timer;
148
161
  initTimeout() {
@@ -169,12 +182,13 @@ class AIGNEContextInternal {
169
182
  const result = {};
170
183
  if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
171
184
  options.sourceAgent.hooks.onHandoff?.({
185
+ context,
172
186
  source: options.sourceAgent,
173
187
  target: activeAgent,
174
188
  input,
175
189
  });
176
190
  }
177
- const stream = await activeAgent.invoke(input, context, { streaming: true });
191
+ const stream = await activeAgent.invoke(input, { ...options, context, streaming: true });
178
192
  for await (const value of stream) {
179
193
  if (value.delta.text) {
180
194
  yield { delta: { text: value.delta.text } };
@@ -1,4 +1,4 @@
1
- import { EventEmitter } from "node:events";
1
+ import { Emitter, type EventMap } from "strict-event-emitter";
2
2
  import type { Message } from "../agents/agent.js";
3
3
  import type { Context } from "./context.js";
4
4
  /**
@@ -30,11 +30,14 @@ export type MessageQueueListener = (message: MessagePayload) => void;
30
30
  * @hidden
31
31
  */
32
32
  export type Unsubscribe = () => void;
33
+ interface MessageQueueEventMap extends EventMap {
34
+ [key: string]: any[];
35
+ }
33
36
  /**
34
37
  * @hidden
35
38
  */
36
39
  export declare class MessageQueue {
37
- events: EventEmitter<[never]>;
40
+ events: Emitter<MessageQueueEventMap>;
38
41
  publish(topic: string | string[], payload: MessagePayload): void;
39
42
  error(error: Error): void;
40
43
  subscribe(topic: string | string[], listener?: undefined): Promise<MessagePayload>;
@@ -42,3 +45,4 @@ export declare class MessageQueue {
42
45
  subscribe(topic: string | string[], listener?: MessageQueueListener): Unsubscribe | Promise<MessagePayload>;
43
46
  unsubscribe(topic: string | string[], listener: MessageQueueListener): void;
44
47
  }
48
+ export {};
@@ -1,4 +1,4 @@
1
- import { EventEmitter } from "node:events";
1
+ import { Emitter } from "strict-event-emitter";
2
2
  import { z } from "zod";
3
3
  import { createMessage } from "../prompt/prompt-builder.js";
4
4
  import { checkArguments, isNil, orArrayToArray } from "../utils/type-utils.js";
@@ -36,7 +36,7 @@ export function toMessagePayload(payload, options) {
36
36
  * @hidden
37
37
  */
38
38
  export class MessageQueue {
39
- events = new EventEmitter();
39
+ events = new Emitter();
40
40
  publish(topic, payload) {
41
41
  checkArguments("MessageQueue.publish", publishArgsSchema, {
42
42
  topic,
@@ -1,10 +1,12 @@
1
1
  export * from "./agents/agent.js";
2
2
  export * from "./agents/ai-agent.js";
3
+ export * from "./agents/chat-model.js";
4
+ export * from "./agents/guide-rail-agent.js";
3
5
  export * from "./agents/mcp-agent.js";
4
6
  export * from "./agents/team-agent.js";
5
7
  export * from "./agents/types.js";
6
8
  export * from "./agents/user-agent.js";
7
9
  export * from "./aigne/index.js";
8
- export * from "./agents/chat-model.js";
10
+ export * from "./memory/index.js";
9
11
  export * from "./prompt/prompt-builder.js";
10
12
  export * from "./prompt/template.js";
package/lib/esm/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  export * from "./agents/agent.js";
2
2
  export * from "./agents/ai-agent.js";
3
+ export * from "./agents/chat-model.js";
4
+ export * from "./agents/guide-rail-agent.js";
3
5
  export * from "./agents/mcp-agent.js";
4
6
  export * from "./agents/team-agent.js";
5
7
  export * from "./agents/types.js";
6
8
  export * from "./agents/user-agent.js";
7
9
  export * from "./aigne/index.js";
8
- export * from "./agents/chat-model.js";
10
+ export * from "./memory/index.js";
9
11
  export * from "./prompt/prompt-builder.js";
10
12
  export * from "./prompt/template.js";
@@ -1,8 +1,8 @@
1
1
  import { type ZodObject, type ZodType, z } from "zod";
2
2
  import type { Message } from "../agents/agent.js";
3
3
  export declare function loadAgentFromJsFile(path: string): Promise<{
4
- name: string;
5
4
  process: (args_0: Message) => Message;
5
+ name: string;
6
6
  description?: string | undefined;
7
7
  inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
8
8
  [x: string]: any;
@@ -5,10 +5,11 @@ export declare function loadAgentFromYamlFile(path: string): Promise<{
5
5
  name: string;
6
6
  description?: string | undefined;
7
7
  skills?: string[] | undefined;
8
+ instructions?: string | undefined;
8
9
  memory?: true | {
10
+ provider: string;
9
11
  subscribeTopic?: string[] | undefined;
10
12
  } | undefined;
11
- instructions?: string | undefined;
12
13
  inputSchema?: ZodObject<Record<string, ZodType<any, z.ZodTypeDef, any>>, z.UnknownKeysParam, z.ZodTypeAny, {
13
14
  [x: string]: any;
14
15
  }, {
@@ -24,6 +25,6 @@ export declare function loadAgentFromYamlFile(path: string): Promise<{
24
25
  } | {
25
26
  type: "mcp";
26
27
  url?: string | undefined;
27
- command?: string | undefined;
28
28
  args?: string[] | undefined;
29
+ command?: string | undefined;
29
30
  }>;
@@ -1,9 +1,9 @@
1
- import { readFile } from "node:fs/promises";
2
1
  import { jsonSchemaToZod } from "@aigne/json-schema-to-zod";
3
2
  import { parse } from "yaml";
4
3
  import { z } from "zod";
5
4
  import { AIAgentToolChoice } from "../agents/ai-agent.js";
6
5
  import { customCamelize } from "../utils/camelize.js";
6
+ import { nodejs } from "../utils/nodejs.js";
7
7
  import { tryOrThrow } from "../utils/type-utils.js";
8
8
  import { inputOutputSchema } from "./schema.js";
9
9
  const agentFileSchema = z.discriminatedUnion("type", [
@@ -40,6 +40,7 @@ const agentFileSchema = z.discriminatedUnion("type", [
40
40
  .union([
41
41
  z.boolean(),
42
42
  z.object({
43
+ provider: z.string(),
43
44
  subscribe_topic: z
44
45
  .array(z.string())
45
46
  .nullish()
@@ -66,7 +67,7 @@ const agentFileSchema = z.discriminatedUnion("type", [
66
67
  }),
67
68
  ]);
68
69
  export async function loadAgentFromYamlFile(path) {
69
- const raw = await tryOrThrow(() => readFile(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
70
+ const raw = await tryOrThrow(() => nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load agent definition from ${path}: ${error.message}`));
70
71
  const json = await tryOrThrow(() => parse(raw), (error) => new Error(`Failed to parse agent definition from ${path}: ${error.message}`));
71
72
  const agent = tryOrThrow(() => customCamelize(agentFileSchema.parse({
72
73
  ...json,
@@ -2,6 +2,7 @@ import type { Camelize } from "camelize-ts";
2
2
  import { z } from "zod";
3
3
  import { type Agent } from "../agents/agent.js";
4
4
  import type { ChatModel, ChatModelOptions } from "../agents/chat-model.js";
5
+ import type { MemoryAgent, MemoryAgentOptions } from "../memory/memory.js";
5
6
  export interface LoadOptions {
6
7
  models: {
7
8
  new (parameters: {
@@ -9,6 +10,9 @@ export interface LoadOptions {
9
10
  modelOptions?: ChatModelOptions;
10
11
  }): ChatModel;
11
12
  }[];
13
+ memories?: {
14
+ new (parameters?: MemoryAgentOptions): MemoryAgent;
15
+ }[];
12
16
  path: string;
13
17
  }
14
18
  export declare function load(options: LoadOptions): Promise<{
@@ -26,7 +30,7 @@ export declare function load(options: LoadOptions): Promise<{
26
30
  presence_penalty?: number | null | undefined;
27
31
  } | null | undefined;
28
32
  }>;
29
- export declare function loadAgent(path: string): Promise<Agent>;
33
+ export declare function loadAgent(path: string, options?: LoadOptions): Promise<Agent>;
30
34
  export declare function loadModel(models: LoadOptions["models"], model?: Camelize<z.infer<typeof aigneFileSchema>["chat_model"]>, modelOptions?: ChatModelOptions): Promise<ChatModel | undefined>;
31
35
  declare const aigneFileSchema: z.ZodObject<{
32
36
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1,21 +1,19 @@
1
- import { readFile, stat } from "node:fs/promises";
2
- import { dirname, extname, join } from "node:path";
3
1
  import { parse } from "yaml";
4
2
  import { z } from "zod";
5
3
  import { FunctionAgent } from "../agents/agent.js";
6
4
  import { AIAgent } from "../agents/ai-agent.js";
7
5
  import { MCPAgent } from "../agents/mcp-agent.js";
6
+ import { nodejs } from "../utils/nodejs.js";
8
7
  import { tryOrThrow } from "../utils/type-utils.js";
9
8
  import { loadAgentFromJsFile } from "./agent-js.js";
10
9
  import { loadAgentFromYamlFile } from "./agent-yaml.js";
11
10
  const AIGNE_FILE_NAME = ["aigne.yaml", "aigne.yml"];
12
11
  export async function load(options) {
13
- const { path } = options;
14
- const aigneFilePath = await getAIGNEFilePath(path);
15
- const rootDir = dirname(aigneFilePath);
12
+ const aigneFilePath = await getAIGNEFilePath(options.path);
13
+ const rootDir = nodejs.path.dirname(aigneFilePath);
16
14
  const aigne = await loadAIGNEFile(aigneFilePath);
17
- const agents = await Promise.all((aigne.agents ?? []).map((filename) => loadAgent(join(rootDir, filename))));
18
- const skills = await Promise.all((aigne.skills ?? []).map((filename) => loadAgent(join(rootDir, filename))));
15
+ const agents = await Promise.all((aigne.agents ?? []).map((filename) => loadAgent(nodejs.path.join(rootDir, filename))));
16
+ const skills = await Promise.all((aigne.skills ?? []).map((filename) => loadAgent(nodejs.path.join(rootDir, filename))));
19
17
  return {
20
18
  ...aigne,
21
19
  model: await loadModel(options.models, aigne.chat_model),
@@ -23,18 +21,21 @@ export async function load(options) {
23
21
  skills,
24
22
  };
25
23
  }
26
- export async function loadAgent(path) {
27
- if (extname(path) === ".js") {
24
+ export async function loadAgent(path, options) {
25
+ if (nodejs.path.extname(path) === ".js") {
28
26
  const agent = await loadAgentFromJsFile(path);
29
27
  return FunctionAgent.from(agent);
30
28
  }
31
- if (extname(path) === ".yaml" || extname(path) === ".yml") {
29
+ if (nodejs.path.extname(path) === ".yaml" || nodejs.path.extname(path) === ".yml") {
32
30
  const agent = await loadAgentFromYamlFile(path);
33
31
  if (agent.type === "ai") {
34
32
  return AIAgent.from({
35
33
  ...agent,
34
+ memory: !options?.memories?.length || !agent.memory
35
+ ? undefined
36
+ : await loadMemory(options.memories, typeof agent.memory === "object" ? agent.memory.provider : undefined, typeof agent.memory === "object" ? agent.memory : {}),
36
37
  skills: agent.skills &&
37
- (await Promise.all(agent.skills.map((filename) => loadAgent(join(dirname(path), filename))))),
38
+ (await Promise.all(agent.skills.map((filename) => loadAgent(nodejs.path.join(nodejs.path.dirname(path), filename))))),
38
39
  });
39
40
  }
40
41
  if (agent.type === "mcp") {
@@ -54,7 +55,15 @@ export async function loadAgent(path) {
54
55
  }
55
56
  throw new Error(`Unsupported agent file type: ${path}`);
56
57
  }
57
- const { MODEL_PROVIDER, MODEL_NAME } = process.env;
58
+ async function loadMemory(memories, provider, options) {
59
+ const M = !provider
60
+ ? memories[0]
61
+ : memories.find((i) => i.name.toLowerCase().includes(provider.toLowerCase()));
62
+ if (!M)
63
+ throw new Error(`Unsupported memory: ${provider}`);
64
+ return new M(options);
65
+ }
66
+ const { MODEL_PROVIDER, MODEL_NAME } = nodejs.env;
58
67
  const DEFAULT_MODEL_PROVIDER = "openai";
59
68
  export async function loadModel(models, model, modelOptions) {
60
69
  const params = {
@@ -92,17 +101,17 @@ const aigneFileSchema = z.object({
92
101
  skills: z.array(z.string()).nullish(),
93
102
  });
94
103
  export async function loadAIGNEFile(path) {
95
- const raw = await tryOrThrow(() => readFile(path, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${path}: ${error.message}`));
104
+ const raw = await tryOrThrow(() => nodejs.fs.readFile(path, "utf8"), (error) => new Error(`Failed to load aigne.yaml from ${path}: ${error.message}`));
96
105
  const json = await tryOrThrow(() => parse(raw), (error) => new Error(`Failed to parse aigne.yaml from ${path}: ${error.message}`));
97
106
  const agent = tryOrThrow(() => aigneFileSchema.parse({ ...json, skills: json.skills ?? json.tools }), (error) => new Error(`Failed to validate aigne.yaml from ${path}: ${error.message}`));
98
107
  return agent;
99
108
  }
100
109
  async function getAIGNEFilePath(path) {
101
- const s = await stat(path);
110
+ const s = await nodejs.fs.stat(path);
102
111
  if (s.isDirectory()) {
103
112
  for (const file of AIGNE_FILE_NAME) {
104
- const filePath = join(path, file);
105
- if ((await stat(filePath)).isFile())
113
+ const filePath = nodejs.path.join(path, file);
114
+ if ((await nodejs.fs.stat(filePath)).isFile())
106
115
  return filePath;
107
116
  }
108
117
  }
@@ -1,10 +1,11 @@
1
- import { Agent, type AgentOptions, type Message } from "../agents/agent.js";
1
+ import { Agent, type AgentInvokeOptions, type AgentOptions, type Message } from "../agents/agent.js";
2
2
  import type { Context } from "../aigne/context.js";
3
3
  import type { MessagePayload } from "../aigne/message-queue.js";
4
4
  import type { MemoryRecorder, MemoryRecorderInput, MemoryRecorderOutput } from "./recorder.js";
5
5
  import type { MemoryRetriever, MemoryRetrieverInput, MemoryRetrieverOutput } from "./retriever.js";
6
6
  export interface Memory {
7
7
  id: string;
8
+ sessionId?: string | null;
8
9
  content: unknown;
9
10
  createdAt: string;
10
11
  }
@@ -62,7 +63,7 @@ export declare class MemoryAgent extends Agent {
62
63
  * MemoryAgent doesn't directly process messages like other agents, so this method
63
64
  * throws an error when called. Use the specialized retrieve() and record() methods instead.
64
65
  */
65
- process(_input: Message, _context: Context): Promise<Message>;
66
+ process(_input: Message, _options: AgentInvokeOptions): Promise<Message>;
66
67
  /**
67
68
  * Retrieves memories based on the provided input criteria.
68
69
  *
@@ -1,6 +1,6 @@
1
1
  import { v7 } from "uuid";
2
2
  import { z } from "zod";
3
- import { Agent } from "../agents/agent.js";
3
+ import { Agent, } from "../agents/agent.js";
4
4
  import { checkArguments, remove } from "../utils/type-utils.js";
5
5
  export const newMemoryId = () => v7();
6
6
  /**
@@ -81,7 +81,7 @@ export class MemoryAgent extends Agent {
81
81
  * MemoryAgent doesn't directly process messages like other agents, so this method
82
82
  * throws an error when called. Use the specialized retrieve() and record() methods instead.
83
83
  */
84
- async process(_input, _context) {
84
+ async process(_input, _options) {
85
85
  throw new Error("Method not implemented.");
86
86
  }
87
87
  /**
@@ -39,11 +39,11 @@ export declare const memoryRetrieverInputSchema: z.ZodObject<{
39
39
  limit: z.ZodOptional<z.ZodNumber>;
40
40
  search: z.ZodOptional<z.ZodString>;
41
41
  }, "strip", z.ZodTypeAny, {
42
- search?: string | undefined;
43
42
  limit?: number | undefined;
44
- }, {
45
43
  search?: string | undefined;
44
+ }, {
46
45
  limit?: number | undefined;
46
+ search?: string | undefined;
47
47
  }>;
48
48
  /**
49
49
  * @hidden
@@ -1,19 +1,21 @@
1
1
  import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
2
- import { Agent, type Message } from "../agents/agent.js";
2
+ import { Agent, type AgentInvokeOptions, type Message } from "../agents/agent.js";
3
3
  import type { AIAgent } from "../agents/ai-agent.js";
4
4
  import type { ChatModel, ChatModelInput } from "../agents/chat-model.js";
5
- import type { Context } from "../aigne/context.js";
6
- import type { MemoryAgent } from "../memory/memory.js";
7
5
  import { ChatMessagesTemplate } from "./template.js";
8
6
  export declare const MESSAGE_KEY = "$message";
9
- export declare function createMessage<I extends Message>(message: string | I): I;
7
+ export declare function createMessage<V extends Message>(message: string, variables?: V): {
8
+ [MESSAGE_KEY]: string;
9
+ } & typeof variables;
10
+ export declare function createMessage<I extends Message, V extends Message>(message: I, variables?: V): I & typeof variables;
11
+ export declare function createMessage<I extends Message, V extends Message>(message: string | I, variables?: V): ({
12
+ [MESSAGE_KEY]: string;
13
+ } | I) & typeof variables;
10
14
  export declare function getMessage(input: Message): string | undefined;
11
15
  export interface PromptBuilderOptions {
12
16
  instructions?: string | ChatMessagesTemplate;
13
17
  }
14
- export interface PromptBuildOptions {
15
- memory?: MemoryAgent | MemoryAgent[];
16
- context: Context;
18
+ export interface PromptBuildOptions extends AgentInvokeOptions {
17
19
  agent?: AIAgent;
18
20
  input?: Message;
19
21
  model?: ChatModel;
@@ -1,16 +1,16 @@
1
- import { readFile } from "node:fs/promises";
2
1
  import { stringify } from "yaml";
3
2
  import { ZodObject } from "zod";
4
3
  import { Agent } from "../agents/agent.js";
5
4
  import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
6
- import { isNil, orArrayToArray, unique } from "../utils/type-utils.js";
5
+ import { nodejs } from "../utils/nodejs.js";
6
+ import { isNil, unique } from "../utils/type-utils.js";
7
7
  import { MEMORY_MESSAGE_TEMPLATE } from "./prompts/memory-message-template.js";
8
8
  import { AgentMessageTemplate, ChatMessagesTemplate, PromptTemplate, SystemMessageTemplate, UserMessageTemplate, } from "./template.js";
9
9
  export const MESSAGE_KEY = "$message";
10
- export function createMessage(message) {
11
- return typeof message === "string"
12
- ? { [MESSAGE_KEY]: message }
13
- : { ...message };
10
+ export function createMessage(message, variables) {
11
+ return (typeof message === "string"
12
+ ? { [MESSAGE_KEY]: message, ...variables }
13
+ : { ...message, ...variables });
14
14
  }
15
15
  export function getMessage(input) {
16
16
  const userInputMessage = input[MESSAGE_KEY];
@@ -31,7 +31,7 @@ export class PromptBuilder {
31
31
  throw new Error(`Invalid instructions ${instructions}`);
32
32
  }
33
33
  static async fromFile(path) {
34
- const text = await readFile(path, "utf-8");
34
+ const text = await nodejs.fs.readFile(path, "utf-8");
35
35
  return PromptBuilder.from(text);
36
36
  }
37
37
  static fromMCPPromptResult(result) {
@@ -78,11 +78,15 @@ export class PromptBuilder {
78
78
  const messages = (typeof this.instructions === "string"
79
79
  ? ChatMessagesTemplate.from([SystemMessageTemplate.from(this.instructions)])
80
80
  : this.instructions)?.format(options.input) ?? [];
81
- for (const memory of orArrayToArray(options.memory ?? options.agent?.memories)) {
82
- const memories = (await memory.retrieve({ search: input && getMessage(input) }, options.context))?.memories;
83
- if (memories?.length)
84
- messages.push(...this.convertMemoriesToMessages(memories, options));
81
+ const memories = [];
82
+ if (options.agent) {
83
+ memories.push(...(await options.agent.retrieveMemories({ search: options.input }, options)));
85
84
  }
85
+ if (options.memories?.length) {
86
+ memories.push(...options.memories);
87
+ }
88
+ if (memories.length)
89
+ messages.push(...this.convertMemoriesToMessages(memories, options));
86
90
  const content = input && getMessage(input);
87
91
  // add user input if it's not the same as the last message
88
92
  if (content && messages.at(-1)?.content !== content) {
@@ -1,7 +1,5 @@
1
- import { inspect } from "node:util";
2
1
  import Mustache from "mustache";
3
2
  import { z } from "zod";
4
- import { tryOrThrow } from "../utils/type-utils.js";
5
3
  export class PromptTemplate {
6
4
  template;
7
5
  static from(template) {
@@ -80,7 +78,7 @@ export class ToolMessageTemplate extends ChatMessageTemplate {
80
78
  constructor(content, toolCallId, name) {
81
79
  super("tool", typeof content === "string"
82
80
  ? content
83
- : tryOrThrow(() => JSON.stringify(content, (_, value) => typeof value === "bigint" ? value.toString() : value), `Failed to stringify tool content. toolCallId: ${toolCallId}, content: ${inspect(content)}`), name);
81
+ : JSON.stringify(content, (_, value) => typeof value === "bigint" ? value.toString() : value), name);
84
82
  this.toolCallId = toolCallId;
85
83
  }
86
84
  format(variables) {
@@ -1,5 +1,5 @@
1
- import { isatty } from "node:tty";
2
1
  import debug from "debug";
2
+ import { nodejs } from "./nodejs.js";
3
3
  export var LogLevel;
4
4
  (function (LogLevel) {
5
5
  LogLevel["ERROR"] = "error";
@@ -17,13 +17,13 @@ export class Logger {
17
17
  this.errorLogger = debug(`${options.ns}:error`);
18
18
  for (const logger of [this.debugLogger, this.infoLogger, this.warnLogger]) {
19
19
  // @ts-ignore
20
- logger.useColors = isatty(process.stdout.fd);
20
+ logger.useColors = nodejs.isStdoutATTY;
21
21
  logger.enabled = true;
22
22
  logger.log = (...args) => this.logMessage(...args);
23
23
  }
24
24
  this.errorLogger.log = (...args) => this.logError(...args);
25
25
  // @ts-ignore
26
- this.errorLogger.useColors = isatty(process.stderr.fd);
26
+ this.errorLogger.useColors = nodejs.isStderrATTY;
27
27
  this.errorLogger.enabled = true;
28
28
  }
29
29
  level;
@@ -0,0 +1,8 @@
1
+ export declare const nodejs: {
2
+ customInspect: any;
3
+ isStdoutATTY: boolean;
4
+ isStderrATTY: boolean;
5
+ env: NodeJS.ProcessEnv;
6
+ readonly fs: typeof import("node:fs/promises");
7
+ readonly path: typeof import("node:path");
8
+ };
@@ -0,0 +1,21 @@
1
+ export const nodejs = {
2
+ customInspect: isNodejsEnvironment() ? require("node:util").inspect.custom : Symbol("inspect"),
3
+ isStdoutATTY: isNodejsEnvironment() && process.stdout?.isTTY,
4
+ isStderrATTY: isNodejsEnvironment() && process.stderr?.isTTY,
5
+ env: isNodejsEnvironment() ? process.env : {},
6
+ get fs() {
7
+ ensureNodejsEnvironment();
8
+ return require("node:fs/promises");
9
+ },
10
+ get path() {
11
+ ensureNodejsEnvironment();
12
+ return require("node:path");
13
+ },
14
+ };
15
+ function isNodejsEnvironment() {
16
+ return typeof process !== "undefined";
17
+ }
18
+ function ensureNodejsEnvironment() {
19
+ if (!isNodejsEnvironment())
20
+ throw new Error("This code must run in a Node.js environment.");
21
+ }
@@ -1,4 +1,4 @@
1
- import { type ZodType } from "zod";
1
+ import { type ZodType, z } from "zod";
2
2
  export type PromiseOrValue<T> = T | Promise<T>;
3
3
  export type Nullish<T> = T | null | undefined | void;
4
4
  export type OmitPropertiesFromArrayFirstElement<T extends unknown[], K extends string | number | symbol> = T extends [infer U, ...infer Rest] ? [Omit<U, K>, ...Rest] : never;
@@ -20,6 +20,6 @@ export declare function orArrayToArray<T>(value?: T | T[]): T[];
20
20
  export declare function createAccessorArray<T>(array: T[], accessor: (array: T[], name: string) => T | undefined): T[] & {
21
21
  [key: string]: T;
22
22
  };
23
- export declare function checkArguments<T>(prefix: string, schema: ZodType<T>, args: T | unknown): T;
23
+ export declare function checkArguments<T extends ZodType>(prefix: string, schema: T, args: unknown): z.infer<T>;
24
24
  export declare function tryOrThrow<P extends PromiseOrValue<unknown>>(fn: () => P, error: string | Error | ((error: Error) => Error)): P;
25
25
  export declare function tryOrThrow<P extends PromiseOrValue<unknown>>(fn: () => P, error?: Nullish<string | Error | ((error: Error) => Nullish<Error>)>): P | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "AIGNE core library for building AI-powered applications",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -71,16 +71,17 @@
71
71
  "eventsource-parser": "^3.0.1",
72
72
  "fast-deep-equal": "^3.1.3",
73
73
  "immer": "^10.1.1",
74
- "inquirer": "^12.6.0",
75
74
  "mustache": "^4.2.0",
76
75
  "nanoid": "^5.1.5",
77
76
  "p-retry": "^6.2.1",
78
77
  "raw-body": "^3.0.0",
78
+ "strict-event-emitter": "^0.5.1",
79
79
  "ufo": "^1.6.1",
80
80
  "uuid": "^11.1.0",
81
81
  "yaml": "^2.7.1",
82
82
  "zod": "^3.24.4",
83
- "zod-to-json-schema": "^3.24.5"
83
+ "zod-to-json-schema": "^3.24.5",
84
+ "@aigne/platform-helpers": "^0.1.0"
84
85
  },
85
86
  "devDependencies": {
86
87
  "@types/bun": "^1.2.12",
@@ -1,16 +0,0 @@
1
- import { type Memory, MemoryAgent, type MemoryAgentOptions } from "./memory.js";
2
- export declare const DEFAULT_MAX_MEMORY_COUNT = 10;
3
- export interface DefaultMemoryOptions extends Partial<MemoryAgentOptions> {
4
- }
5
- export declare class DefaultMemory extends MemoryAgent {
6
- constructor(options?: DefaultMemoryOptions);
7
- storage: Memory[];
8
- search(options?: {
9
- limit?: number;
10
- }): Promise<{
11
- result: Memory[];
12
- }>;
13
- create(memory: Pick<Memory, "content">): Promise<{
14
- result: Memory;
15
- }>;
16
- }