@aigne/cli 1.36.4 → 1.37.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.37.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.36.4...cli-v1.37.0) (2025-08-18)
4
+
5
+
6
+ ### Features
7
+
8
+ * **cli:** add support for array inputs in CLI arguments ([#378](https://github.com/AIGNE-io/aigne-framework/issues/378)) ([827ae11](https://github.com/AIGNE-io/aigne-framework/commit/827ae112de8d1a2e997b272b759090b6e5b8d395))
9
+ * **cli:** support hide or collapse task for agents in CLI ([#381](https://github.com/AIGNE-io/aigne-framework/issues/381)) ([05b372d](https://github.com/AIGNE-io/aigne-framework/commit/05b372d431a862f7cdfa2a90bb4b7b2379bf97ab))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **cli:** only log API requests at info level and above ([#376](https://github.com/AIGNE-io/aigne-framework/issues/376)) ([03fc4d9](https://github.com/AIGNE-io/aigne-framework/commit/03fc4d9aad6e81aeae3b2eb02a62f7acade3bd77))
15
+
16
+
17
+ ### Dependencies
18
+
19
+ * The following workspace dependencies were updated
20
+ * dependencies
21
+ * @aigne/agent-library bumped to 1.21.22
22
+ * @aigne/agentic-memory bumped to 1.0.22
23
+ * @aigne/aigne-hub bumped to 0.6.4
24
+ * @aigne/core bumped to 1.51.0
25
+ * @aigne/default-memory bumped to 1.1.4
26
+ * @aigne/openai bumped to 0.11.4
27
+
3
28
  ## [1.36.4](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.36.3...cli-v1.36.4) (2025-08-16)
4
29
 
5
30
 
@@ -2,18 +2,15 @@ import assert from "node:assert";
2
2
  import { spawn } from "node:child_process";
3
3
  import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
4
4
  import { homedir } from "node:os";
5
- import { extname, join } from "node:path";
6
- import { isatty } from "node:tty";
5
+ import { join } from "node:path";
7
6
  import { loadModel } from "@aigne/aigne-hub";
8
- import { AIAgent, AIGNE, readAllString } from "@aigne/core";
9
- import { pick } from "@aigne/core/utils/type-utils.js";
7
+ import { AIGNE } from "@aigne/core";
10
8
  import { Listr, PRESET_TIMER } from "@aigne/listr2";
11
9
  import { joinURL } from "ufo";
12
- import { parse } from "yaml";
13
- import { ZodBoolean, ZodNumber, ZodObject, ZodString, ZodType } from "zod";
14
10
  import { downloadAndExtract } from "../utils/download.js";
15
11
  import { loadAIGNE } from "../utils/load-aigne.js";
16
- import { runAgentWithAIGNE, stdinHasData } from "../utils/run-with-aigne.js";
12
+ import { runAgentWithAIGNE } from "../utils/run-with-aigne.js";
13
+ import { parseAgentInput, withAgentInputSchema } from "../utils/yargs.js";
17
14
  import { serveMCPServerFromDir } from "./serve-mcp.js";
18
15
  const NPM_PACKAGE_CACHE_TIME_MS = 1000 * 60 * 60 * 24; // 1 day
19
16
  const builtinApps = [
@@ -85,50 +82,16 @@ const upgradeCommandModule = ({ name, dir, isLatest, version, }) => ({
85
82
  },
86
83
  });
87
84
  const agentCommandModule = ({ dir, agent, }) => {
88
- const inputSchema = agent.inputSchema instanceof ZodObject ? agent.inputSchema.shape : {};
89
85
  return {
90
86
  command: agent.name,
91
87
  aliases: agent.alias || [],
92
88
  describe: agent.description || "",
93
- builder: (yargs) => {
94
- for (const [option, config] of Object.entries(inputSchema)) {
95
- const innerType = innerZodType(config);
96
- yargs.option(option, {
97
- // TODO: support more types
98
- type: innerType instanceof ZodBoolean
99
- ? "boolean"
100
- : innerType instanceof ZodNumber
101
- ? "number"
102
- : "string",
103
- description: config.description,
104
- });
105
- if (!(config.isNullable() || config.isOptional())) {
106
- yargs.demandOption(option);
107
- }
108
- }
109
- return yargs
110
- .option("input", {
111
- type: "array",
112
- description: "Input to the agent, use @<file> to read from a file",
113
- alias: ["i"],
114
- })
115
- .option("format", {
116
- type: "string",
117
- description: 'Input format, can be "json" or "yaml"',
118
- choices: ["json", "yaml"],
119
- });
120
- },
89
+ builder: async (yargs) => withAgentInputSchema(yargs, agent),
121
90
  handler: async (input) => {
122
91
  await invokeCLIAgentFromDir({ dir, agent: agent.name, input });
123
92
  },
124
93
  };
125
94
  };
126
- function innerZodType(type) {
127
- if ("innerType" in type._def && type._def.innerType instanceof ZodType) {
128
- return innerZodType(type._def.innerType);
129
- }
130
- return type;
131
- }
132
95
  export async function invokeCLIAgentFromDir(options) {
133
96
  const aigne = await loadAIGNE({
134
97
  path: options.dir,
@@ -137,61 +100,13 @@ export async function invokeCLIAgentFromDir(options) {
137
100
  try {
138
101
  const agent = aigne.cli.agents[options.agent];
139
102
  assert(agent, `Agent ${options.agent} not found in ${options.dir}`);
140
- const inputSchema = agent.inputSchema instanceof ZodObject ? agent.inputSchema.shape : {};
141
- const input = Object.fromEntries(await Promise.all(Object.entries(pick(options.input, Object.keys(inputSchema))).map(async ([key, val]) => {
142
- if (typeof val === "string" && val.startsWith("@")) {
143
- const schema = inputSchema[key];
144
- val = await readFileAsInput(val, {
145
- format: schema instanceof ZodString ? "raw" : undefined,
146
- });
147
- }
148
- return [key, val];
149
- })));
150
- const rawInput = options.input.input ||
151
- (isatty(process.stdin.fd) || !(await stdinHasData())
152
- ? null
153
- : [await readAllString(process.stdin)].filter(Boolean));
154
- if (rawInput) {
155
- for (const raw of rawInput) {
156
- const parsed = raw.startsWith("@")
157
- ? await readFileAsInput(raw, { format: options.input.format })
158
- : raw;
159
- if (typeof parsed !== "string") {
160
- Object.assign(input, parsed);
161
- }
162
- else {
163
- const inputKey = agent instanceof AIAgent ? agent.inputKey : undefined;
164
- if (inputKey) {
165
- Object.assign(input, { [inputKey]: parsed });
166
- }
167
- }
168
- }
169
- }
103
+ const input = await parseAgentInput(options.input, agent);
170
104
  await runAgentWithAIGNE(aigne, agent, { input });
171
105
  }
172
106
  finally {
173
107
  await aigne.shutdown();
174
108
  }
175
109
  }
176
- async function readFileAsInput(value, { format } = {}) {
177
- if (value.startsWith("@")) {
178
- const ext = extname(value);
179
- value = await readFile(value.slice(1), "utf8");
180
- if (!format) {
181
- if (ext === ".json")
182
- format = "json";
183
- else if (ext === ".yaml" || ext === ".yml")
184
- format = "yaml";
185
- }
186
- }
187
- if (format === "json") {
188
- return JSON.parse(value);
189
- }
190
- else if (format === "yaml") {
191
- return parse(value);
192
- }
193
- return value;
194
- }
195
110
  export async function loadApplication({ name, dir, forceUpgrade = false, }) {
196
111
  name = `@aigne/${name}`;
197
112
  dir ??= join(homedir(), ".aigne", "registry.npmjs.org", name);
@@ -45,6 +45,8 @@ type Task = ReturnType<typeof promiseWithResolvers<void>> & {
45
45
  subtask: Listr;
46
46
  taskWrapper: AIGNEListrTaskWrapper;
47
47
  }>>;
48
+ agent: Agent;
49
+ input: Message;
48
50
  startTime?: number;
49
51
  endTime?: number;
50
52
  usage?: Partial<ContextUsage>;
@@ -1,6 +1,6 @@
1
1
  import { EOL } from "node:os";
2
2
  import { inspect } from "node:util";
3
- import { AIAgent, ChatModel, DEFAULT_OUTPUT_KEY, UserAgent, } from "@aigne/core";
3
+ import { AIAgent, ChatModel, DEFAULT_OUTPUT_KEY, mergeContextUsage, newEmptyContextUsage, UserAgent, } from "@aigne/core";
4
4
  import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
5
5
  import { flat, omit } from "@aigne/core/utils/type-utils.js";
6
6
  import { figures } from "@aigne/listr2";
@@ -28,13 +28,39 @@ export class TerminalTracer {
28
28
  formatResult: (result, options) => [this.formatResult(agent, context, result, options)].filter(Boolean),
29
29
  }, [], { concurrent: true });
30
30
  this.listr = listr;
31
+ const collapsedMap = new Map();
32
+ const hideContextIds = new Set();
31
33
  const onStart = async ({ context, agent, ...event }) => {
32
34
  if (agent instanceof UserAgent)
33
35
  return;
36
+ if (agent.taskRenderMode === "hide") {
37
+ hideContextIds.add(context.id);
38
+ return;
39
+ }
40
+ else if (agent.taskRenderMode === "collapse") {
41
+ collapsedMap.set(context.id, {
42
+ ancestor: { contextId: context.id },
43
+ usage: newEmptyContextUsage(),
44
+ models: new Set(),
45
+ });
46
+ }
47
+ if (context.parentId) {
48
+ if (hideContextIds.has(context.parentId)) {
49
+ hideContextIds.add(context.id);
50
+ return;
51
+ }
52
+ const collapsed = collapsedMap.get(context.parentId);
53
+ if (collapsed) {
54
+ collapsedMap.set(context.id, collapsed);
55
+ return;
56
+ }
57
+ }
34
58
  const contextId = context.id;
35
59
  const parentContextId = context.parentId;
36
60
  const task = {
37
61
  ...promiseWithResolvers(),
62
+ agent,
63
+ input: event.input,
38
64
  listr: promiseWithResolvers(),
39
65
  startTime: Date.now(),
40
66
  };
@@ -66,6 +92,34 @@ export class TerminalTracer {
66
92
  const onSuccess = async ({ context, agent, output, ...event }) => {
67
93
  const contextId = context.id;
68
94
  const parentContextId = context.parentId;
95
+ const collapsed = collapsedMap.get(contextId);
96
+ if (collapsed) {
97
+ if (agent instanceof ChatModel) {
98
+ const { usage, model } = output;
99
+ if (usage)
100
+ mergeContextUsage(collapsed.usage, usage);
101
+ if (model)
102
+ collapsed.models.add(model);
103
+ }
104
+ const task = this.tasks[collapsed.ancestor.contextId];
105
+ if (task) {
106
+ task.usage = collapsed.usage;
107
+ task.extraTitleMetadata ??= {};
108
+ if (collapsed.models.size)
109
+ task.extraTitleMetadata.model = [...collapsed.models].join(",");
110
+ const { taskWrapper } = await task.listr.promise;
111
+ taskWrapper.title = await this.formatTaskTitle(task.agent, {
112
+ input: task.input,
113
+ task,
114
+ usage: Boolean(task.usage.inputTokens || task.usage.outputTokens || task.usage.aigneHubCredits),
115
+ time: context.id === collapsed.ancestor.contextId,
116
+ });
117
+ if (context.id === collapsed.ancestor.contextId) {
118
+ task?.resolve();
119
+ }
120
+ return;
121
+ }
122
+ }
69
123
  const task = this.tasks[contextId];
70
124
  if (!task)
71
125
  return;
@@ -173,6 +227,9 @@ export class TerminalTracer {
173
227
  const items = [
174
228
  [chalk.yellow(usage.inputTokens), chalk.grey("input tokens")],
175
229
  [chalk.cyan(usage.outputTokens), chalk.grey("output tokens")],
230
+ usage.aigneHubCredits
231
+ ? [chalk.blue(usage.aigneHubCredits.toFixed()), chalk.grey("AIGNE Hub credits")]
232
+ : undefined,
176
233
  usage.agentCalls ? [chalk.magenta(usage.agentCalls), chalk.grey("agent calls")] : undefined,
177
234
  ];
178
235
  const content = items.filter((i) => !!i).map((i) => i.join(" "));
@@ -51,9 +51,11 @@ export class AIGNEListr extends Listr {
51
51
  try {
52
52
  this.ctx = {};
53
53
  this.spinner.start();
54
- const request = this.myOptions.formatRequest();
55
- if (request)
56
- console.log(request);
54
+ if (logger.enabled(LogLevel.INFO)) {
55
+ const request = this.myOptions.formatRequest();
56
+ if (request)
57
+ console.log(request);
58
+ }
57
59
  logger.logMessage = (...args) => this.logs.push(format(...args));
58
60
  for (const method of ["debug", "log", "info", "warn", "error"]) {
59
61
  console[method] = (...args) => {
@@ -63,4 +63,3 @@ export declare function runAgentWithAIGNE(aigne: AIGNE, agent: Agent, { outputKe
63
63
  } & Omit<RunAIGNECommandOptions, "input">): Promise<{
64
64
  result: Message;
65
65
  } | undefined>;
66
- export declare function stdinHasData(): Promise<boolean>;
@@ -1,21 +1,19 @@
1
- import { fstat } from "node:fs";
2
- import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
1
+ import { mkdir, stat, writeFile } from "node:fs/promises";
3
2
  import { dirname, isAbsolute, join } from "node:path";
4
3
  import { isatty } from "node:tty";
5
- import { promisify } from "node:util";
6
4
  import { exists } from "@aigne/agent-library/utils/fs.js";
7
5
  import { availableModels, parseModelOption } from "@aigne/aigne-hub";
8
- import { AIAgent, DEFAULT_OUTPUT_KEY, readAllString, UserAgent, } from "@aigne/core";
6
+ import { DEFAULT_OUTPUT_KEY, UserAgent, } from "@aigne/core";
9
7
  import { getLevelFromEnv, LogLevel, logger } from "@aigne/core/utils/logger.js";
10
- import { flat, isEmpty, tryOrThrow } from "@aigne/core/utils/type-utils.js";
8
+ import { isEmpty, tryOrThrow } from "@aigne/core/utils/type-utils.js";
11
9
  import chalk from "chalk";
12
- import { parse } from "yaml";
13
10
  import yargs from "yargs";
14
11
  import { hideBin } from "yargs/helpers";
15
- import { ZodError, ZodObject, z } from "zod";
12
+ import { ZodError, z } from "zod";
16
13
  import { TerminalTracer } from "../tracer/terminal.js";
17
14
  import { loadAIGNE } from "./load-aigne.js";
18
15
  import { DEFAULT_CHAT_INPUT_KEY, runChatLoopInTerminal, } from "./run-chat-loop.js";
16
+ import { parseAgentInput, withAgentInputSchema } from "./yargs.js";
19
17
  export const createRunAIGNECommand = (yargs) => yargs
20
18
  .option("chat", {
21
19
  describe: "Run chat loop in terminal",
@@ -80,7 +78,7 @@ export const createRunAIGNECommand = (yargs) => yargs
80
78
  .option("log-level", {
81
79
  describe: `Log level for detailed debugging information. Values: ${Object.values(LogLevel).join(", ")}`,
82
80
  type: "string",
83
- default: getLevelFromEnv(logger.options.ns) || LogLevel.INFO,
81
+ default: getLevelFromEnv(logger.options.ns) || LogLevel.SILENT,
84
82
  coerce: customZodError("--log-level", (s) => z.nativeEnum(LogLevel).parse(s)),
85
83
  })
86
84
  .option("aigne-hub-url", {
@@ -88,38 +86,11 @@ export const createRunAIGNECommand = (yargs) => yargs
88
86
  type: "string",
89
87
  });
90
88
  export async function parseAgentInputByCommander(agent, options = {}) {
91
- const inputSchemaShape = flat(agent instanceof AIAgent ? agent.inputKey : undefined, agent.inputSchema instanceof ZodObject ? Object.keys(agent.inputSchema.shape) : []);
92
- const parsedInput = await yargs().parseAsync(options.argv ?? process.argv);
93
- const input = Object.fromEntries(await Promise.all(inputSchemaShape.map(async (key) => {
94
- const k = `input${key.charAt(0).toUpperCase()}${key.slice(1)}`;
95
- let value = parsedInput[k];
96
- if (typeof value === "string" && value.startsWith("@")) {
97
- value = await readFile(value.slice(1), "utf8");
98
- }
99
- return [key, value];
100
- })));
101
- const rawInput = options.input ||
102
- (isatty(process.stdin.fd) || !(await stdinHasData())
103
- ? null
104
- : [await readAllString(process.stdin)].filter(Boolean));
105
- if (rawInput?.length) {
106
- for (let raw of rawInput) {
107
- if (raw.startsWith("@")) {
108
- raw = await readFile(raw.slice(1), "utf8");
109
- }
110
- if (options.format === "json") {
111
- Object.assign(input, JSON.parse(raw));
112
- }
113
- else if (options.format === "yaml") {
114
- Object.assign(input, parse(raw));
115
- }
116
- else {
117
- Object.assign(input, typeof options.inputKey === "string"
118
- ? { [options.inputKey]: raw }
119
- : { [DEFAULT_CHAT_INPUT_KEY]: raw });
120
- }
121
- }
122
- }
89
+ const args = await withAgentInputSchema(yargs(), agent)
90
+ .showHelpOnFail(false)
91
+ .fail(() => { })
92
+ .parseAsync(options.argv ?? process.argv);
93
+ const input = await parseAgentInput({ ...args, input: options.input || args.input }, agent);
123
94
  if (isEmpty(input)) {
124
95
  const defaultInput = options.defaultInput || process.env.INITIAL_CALL;
125
96
  Object.assign(input, typeof defaultInput === "string"
@@ -214,7 +185,3 @@ export async function runAgentWithAIGNE(aigne, agent, { outputKey, chatLoopOptio
214
185
  }
215
186
  return { result };
216
187
  }
217
- export async function stdinHasData() {
218
- const stats = await promisify(fstat)(0);
219
- return stats.isFIFO() || stats.isFile();
220
- }
@@ -0,0 +1,20 @@
1
+ import { type Agent, type Message } from "@aigne/core";
2
+ import type { Argv } from "yargs";
3
+ import { ZodType } from "zod";
4
+ export declare function inferZodType(type: ZodType, opts?: {
5
+ array?: boolean;
6
+ optional?: boolean;
7
+ }): {
8
+ type: "string" | "number" | "boolean";
9
+ array?: boolean;
10
+ optional?: boolean;
11
+ };
12
+ export declare function withAgentInputSchema(yargs: Argv, agent: Agent): Argv<{
13
+ input?: string[];
14
+ format?: "json" | "yaml";
15
+ }>;
16
+ export declare function parseAgentInput(i: Message & {
17
+ input?: string[];
18
+ format?: "json" | "yaml";
19
+ }, agent: Agent): Promise<any>;
20
+ export declare function stdinHasData(): Promise<boolean>;
@@ -0,0 +1,107 @@
1
+ import { fstat } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
+ import { extname } from "node:path";
4
+ import { isatty } from "node:tty";
5
+ import { promisify } from "node:util";
6
+ import { AIAgent, readAllString } from "@aigne/core";
7
+ import { pick } from "@aigne/core/utils/type-utils.js";
8
+ import { parse } from "yaml";
9
+ import { ZodAny, ZodArray, ZodBoolean, ZodNumber, ZodObject, ZodString, ZodType, ZodUnknown, } from "zod";
10
+ export function inferZodType(type, opts = {}) {
11
+ if (type instanceof ZodUnknown || type instanceof ZodAny) {
12
+ return { type: "string", optional: true };
13
+ }
14
+ opts.optional ??= type.isNullable() || type.isOptional();
15
+ if ("innerType" in type._def && type._def.innerType instanceof ZodType) {
16
+ return inferZodType(type._def.innerType, opts);
17
+ }
18
+ if (type instanceof ZodArray) {
19
+ return inferZodType(type.element, { ...opts, array: true });
20
+ }
21
+ return {
22
+ ...opts,
23
+ array: opts.array || undefined,
24
+ optional: opts.optional || undefined,
25
+ type: type instanceof ZodBoolean ? "boolean" : type instanceof ZodNumber ? "number" : "string",
26
+ };
27
+ }
28
+ export function withAgentInputSchema(yargs, agent) {
29
+ const inputSchema = agent.inputSchema instanceof ZodObject ? agent.inputSchema.shape : {};
30
+ for (const [option, config] of Object.entries(inputSchema)) {
31
+ const type = inferZodType(config);
32
+ yargs.option(option, {
33
+ type: type.type,
34
+ description: config.description,
35
+ array: type.array,
36
+ });
37
+ if (!type.optional) {
38
+ yargs.demandOption(option);
39
+ }
40
+ }
41
+ return yargs
42
+ .option("input", {
43
+ type: "string",
44
+ array: true,
45
+ description: "Input to the agent, use @<file> to read from a file",
46
+ alias: ["i"],
47
+ })
48
+ .option("format", {
49
+ type: "string",
50
+ description: 'Input format, can be "json" or "yaml"',
51
+ choices: ["json", "yaml"],
52
+ });
53
+ }
54
+ export async function parseAgentInput(i, agent) {
55
+ const inputSchema = agent.inputSchema instanceof ZodObject ? agent.inputSchema.shape : {};
56
+ const input = Object.fromEntries(await Promise.all(Object.entries(pick(i, Object.keys(inputSchema))).map(async ([key, val]) => {
57
+ if (typeof val === "string" && val.startsWith("@")) {
58
+ const schema = inputSchema[key];
59
+ val = await readFileAsInput(val, {
60
+ format: schema instanceof ZodString ? "raw" : undefined,
61
+ });
62
+ }
63
+ return [key, val];
64
+ })));
65
+ const rawInput = i.input ||
66
+ (isatty(process.stdin.fd) || !(await stdinHasData())
67
+ ? null
68
+ : [await readAllString(process.stdin)].filter(Boolean));
69
+ if (rawInput) {
70
+ for (const raw of rawInput) {
71
+ const parsed = raw.startsWith("@") ? await readFileAsInput(raw, { format: i.format }) : raw;
72
+ if (typeof parsed !== "string") {
73
+ Object.assign(input, parsed);
74
+ }
75
+ else {
76
+ const inputKey = agent instanceof AIAgent ? agent.inputKey : undefined;
77
+ if (inputKey) {
78
+ Object.assign(input, { [inputKey]: parsed });
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return input;
84
+ }
85
+ async function readFileAsInput(value, { format } = {}) {
86
+ if (value.startsWith("@")) {
87
+ const ext = extname(value);
88
+ value = await readFile(value.slice(1), "utf8");
89
+ if (!format) {
90
+ if (ext === ".json")
91
+ format = "json";
92
+ else if (ext === ".yaml" || ext === ".yml")
93
+ format = "yaml";
94
+ }
95
+ }
96
+ if (format === "json") {
97
+ return JSON.parse(value);
98
+ }
99
+ else if (format === "yaml") {
100
+ return parse(value);
101
+ }
102
+ return value;
103
+ }
104
+ export async function stdinHasData() {
105
+ const stats = await promisify(fstat)(0);
106
+ return stats.isFIFO() || stats.isFile();
107
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.36.4",
3
+ "version": "1.37.0",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -72,13 +72,13 @@
72
72
  "yaml": "^2.8.0",
73
73
  "yargs": "^18.0.0",
74
74
  "zod": "^3.25.67",
75
- "@aigne/agent-library": "^1.21.21",
76
- "@aigne/aigne-hub": "^0.6.3",
77
- "@aigne/agentic-memory": "^1.0.21",
78
- "@aigne/core": "^1.50.1",
79
- "@aigne/default-memory": "^1.1.3",
80
- "@aigne/openai": "^0.11.3",
81
- "@aigne/observability-api": "^0.9.0"
75
+ "@aigne/agent-library": "^1.21.22",
76
+ "@aigne/aigne-hub": "^0.6.4",
77
+ "@aigne/agentic-memory": "^1.0.22",
78
+ "@aigne/core": "^1.51.0",
79
+ "@aigne/default-memory": "^1.1.4",
80
+ "@aigne/observability-api": "^0.9.0",
81
+ "@aigne/openai": "^0.11.4"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@types/archiver": "^6.0.3",