@aigne/cli 1.49.2-beta.1 → 1.50.0-beta.1

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,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.50.0-beta.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.2-beta.1...cli-v1.50.0-beta.1) (2025-09-30)
4
+
5
+
6
+ ### Features
7
+
8
+ * **cli:** support define nested commands for sub apps ([#568](https://github.com/AIGNE-io/aigne-framework/issues/568)) ([0693b80](https://github.com/AIGNE-io/aigne-framework/commit/0693b807e0f8d335010e6ad00763b07cf095e65b))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @aigne/agent-library bumped to 1.21.47-beta.1
16
+ * @aigne/agentic-memory bumped to 1.0.47-beta.1
17
+ * @aigne/aigne-hub bumped to 0.10.1-beta.1
18
+ * @aigne/core bumped to 1.62.0-beta
19
+ * @aigne/default-memory bumped to 1.2.10-beta.1
20
+ * @aigne/openai bumped to 0.16.1-beta.1
21
+ * devDependencies
22
+ * @aigne/test-utils bumped to 0.5.54-beta.1
23
+
3
24
  ## [1.49.2-beta.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.2-beta...cli-v1.49.2-beta.1) (2025-09-29)
4
25
 
5
26
 
@@ -1,5 +1,5 @@
1
1
  import type { CommandModule } from "yargs";
2
- import { type AgentInChildProcess, type LoadAIGNEInChildProcessResult } from "../utils/workers/run-aigne-in-child-process.js";
2
+ import { type AgentInChildProcess, type CLIAgentInChildProcess, type LoadAIGNEInChildProcessResult } from "../utils/workers/run-aigne-in-child-process.js";
3
3
  import { type AgentRunCommonOptions } from "../utils/yargs.js";
4
4
  export declare function createAppCommands({ argv }?: {
5
5
  argv?: string[];
@@ -8,6 +8,11 @@ export declare const agentCommandModule: ({ dir, agent, }: {
8
8
  dir: string;
9
9
  agent: AgentInChildProcess;
10
10
  }) => CommandModule<unknown, AgentRunCommonOptions>;
11
+ export declare const cliAgentCommandModule: ({ dir, parent, cliAgent, }: {
12
+ dir: string;
13
+ parent?: string[];
14
+ cliAgent: CLIAgentInChildProcess;
15
+ }) => CommandModule<unknown, AgentRunCommonOptions>;
11
16
  interface LoadApplicationOptions {
12
17
  packageName: string;
13
18
  dir: string;
@@ -1,3 +1,4 @@
1
+ import assert from "node:assert";
1
2
  import { spawn } from "node:child_process";
2
3
  import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
3
4
  import { homedir } from "node:os";
@@ -53,8 +54,8 @@ export function createAppCommands({ argv } = {}) {
53
54
  command: "$0",
54
55
  });
55
56
  }
56
- for (const agent of aigne.cli?.agents ?? []) {
57
- y.command(agentCommandModule({ dir, agent }));
57
+ for (const cliAgent of aigne.cli?.agents ?? []) {
58
+ y.command(cliAgentCommandModule({ dir, cliAgent }));
58
59
  }
59
60
  y.option("model", {
60
61
  type: "string",
@@ -152,6 +153,42 @@ export const agentCommandModule = ({ dir, agent, }) => {
152
153
  },
153
154
  };
154
155
  };
156
+ export const cliAgentCommandModule = ({ dir, parent, cliAgent, }) => {
157
+ const { agent, agents } = cliAgent;
158
+ const name = cliAgent.name || agent?.name;
159
+ assert(name, "CLI agent must have a name");
160
+ return {
161
+ command: name,
162
+ aliases: cliAgent.alias || agent?.alias || [],
163
+ describe: cliAgent.description || agent?.description || "",
164
+ builder: async (yargs) => {
165
+ if (agent) {
166
+ withAgentInputSchema(yargs, { inputSchema: jsonSchemaToZod(agent.inputSchema) });
167
+ }
168
+ if (agents?.length) {
169
+ for (const cmd of agents) {
170
+ yargs.command(cliAgentCommandModule({ dir, parent: (parent ?? []).concat(name), cliAgent: cmd }));
171
+ }
172
+ }
173
+ if (!agent)
174
+ yargs.demandCommand();
175
+ return yargs;
176
+ },
177
+ handler: async (options) => {
178
+ if (!agent)
179
+ throw new Error("CLI agent is not defined");
180
+ if (options.logLevel)
181
+ logger.level = options.logLevel;
182
+ await runAIGNEInChildProcess("invokeCLIAgentFromDir", {
183
+ dir,
184
+ parent,
185
+ agent: name,
186
+ input: options,
187
+ });
188
+ process.exit(0);
189
+ },
190
+ };
191
+ };
155
192
  export async function loadApplication(options) {
156
193
  const { dir, packageName } = options;
157
194
  const check = await checkInstallation(dir);
@@ -1,5 +1,6 @@
1
1
  import { isAbsolute, resolve } from "node:path";
2
2
  import { exists } from "@aigne/agent-library/utils/fs.js";
3
+ import { findCliAgent } from "@aigne/core/utils/agent-utils.js";
3
4
  import { z } from "zod";
4
5
  import { runEvaluationPipeline } from "../utils/evaluation/core.js";
5
6
  import { FileDataset } from "../utils/evaluation/dataset.js";
@@ -70,7 +71,7 @@ export function createEvalCommand({ aigneFilePath, } = {}) {
70
71
  const { chat } = aigne.cli;
71
72
  const agent = chat && chat.name === entryAgent
72
73
  ? chat
73
- : aigne.cli.agents[entryAgent] ||
74
+ : findCliAgent(aigne.cli, "*", entryAgent) ||
74
75
  aigne.agents[entryAgent] ||
75
76
  aigne.skills[entryAgent] ||
76
77
  aigne.mcpServer.agents[entryAgent];
@@ -80,7 +81,7 @@ export function createEvalCommand({ aigneFilePath, } = {}) {
80
81
  let evaluatorAgent;
81
82
  if (evaluatorName) {
82
83
  evaluatorAgent =
83
- aigne.cli.agents[evaluatorName] ||
84
+ findCliAgent(aigne.cli, "*", evaluatorName) ||
84
85
  aigne.agents[evaluatorName] ||
85
86
  aigne.skills[evaluatorName] ||
86
87
  aigne.mcpServer.agents[evaluatorName];
@@ -2,6 +2,7 @@ import { cp, mkdir, rm } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { isAbsolute, join, resolve } from "node:path";
4
4
  import { exists } from "@aigne/agent-library/utils/fs.js";
5
+ import { mapCliAgent } from "@aigne/core/utils/agent-utils.js";
5
6
  import { flat, isNonNullable } from "@aigne/core/utils/type-utils.js";
6
7
  import { Listr, PRESET_TIMER } from "@aigne/listr2";
7
8
  import { config } from "dotenv-flow";
@@ -11,7 +12,7 @@ import { downloadAndExtract } from "../utils/download.js";
11
12
  import { loadAIGNE } from "../utils/load-aigne.js";
12
13
  import { isUrl } from "../utils/url.js";
13
14
  import { serializeAgent } from "../utils/workers/run-aigne-in-child-process.js";
14
- import { agentCommandModule } from "./app.js";
15
+ import { agentCommandModule, cliAgentCommandModule } from "./app.js";
15
16
  export function createRunCommand({ aigneFilePath, } = {}) {
16
17
  return {
17
18
  command: "run [path] [entry-agent]",
@@ -47,10 +48,16 @@ export function createRunCommand({ aigneFilePath, } = {}) {
47
48
  });
48
49
  }
49
50
  // Allow user to run all of agents in the AIGNE instances
50
- const allAgents = flat(aigne.cli.agents, aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents);
51
+ const allAgents = flat(aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents);
51
52
  for (const agent of allAgents) {
52
53
  subYargs.command(agentCommandModule({ dir: path, agent: serializeAgent(agent) }));
53
54
  }
55
+ for (const cliAgent of aigne.cli.agents ?? []) {
56
+ subYargs.command(cliAgentCommandModule({
57
+ dir: path,
58
+ cliAgent: mapCliAgent(cliAgent, (a) => (a ? serializeAgent(a) : undefined)),
59
+ }));
60
+ }
54
61
  const argv = process.argv.slice(aigneFilePath ? 3 : 2);
55
62
  if (argv[0] === "run")
56
63
  argv.shift(); // remove 'run' command
@@ -62,8 +69,9 @@ export function createRunCommand({ aigneFilePath, } = {}) {
62
69
  if (argv[0] === "--entry-agent")
63
70
  argv.shift();
64
71
  const firstAgent = aigne.agents[0]?.name;
65
- if (!options.entryAgent && firstAgent)
72
+ if (!options.entryAgent && firstAgent && !argv.some((i) => ["-h", "--help"].includes(i))) {
66
73
  argv.unshift(firstAgent);
74
+ }
67
75
  await subYargs
68
76
  .strict()
69
77
  .demandCommand()
@@ -1,11 +1,11 @@
1
1
  import { AIGNE, type Message } from "@aigne/core";
2
2
  import { type AgentRunCommonOptions } from "../yargs.js";
3
- import { type AgentInChildProcess } from "./run-aigne-in-child-process.js";
3
+ import { type AgentInChildProcess, type CLIAgentInChildProcess } from "./run-aigne-in-child-process.js";
4
4
  export declare function loadAIGNEInChildProcess(...args: Parameters<typeof AIGNE.load>): Promise<{
5
5
  agents?: AgentInChildProcess[];
6
6
  cli?: {
7
7
  chat?: AgentInChildProcess;
8
- agents?: AgentInChildProcess[];
8
+ agents?: CLIAgentInChildProcess[];
9
9
  };
10
10
  mcpServer?: {
11
11
  agents?: AgentInChildProcess[];
@@ -13,6 +13,7 @@ export declare function loadAIGNEInChildProcess(...args: Parameters<typeof AIGNE
13
13
  }>;
14
14
  export declare function invokeCLIAgentFromDirInChildProcess(options: {
15
15
  dir: string;
16
+ parent?: string[];
16
17
  agent: string;
17
18
  input: Message & AgentRunCommonOptions;
18
19
  }): Promise<void>;
@@ -1,9 +1,10 @@
1
1
  import assert from "node:assert";
2
2
  import { AIGNE } from "@aigne/core";
3
+ import { findCliAgent, mapCliAgent } from "@aigne/core/utils/agent-utils.js";
3
4
  import { loadAIGNE } from "../load-aigne.js";
4
5
  import { runAgentWithAIGNE } from "../run-with-aigne.js";
5
6
  import { parseAgentInput } from "../yargs.js";
6
- import { serializeAgent } from "./run-aigne-in-child-process.js";
7
+ import { serializeAgent, } from "./run-aigne-in-child-process.js";
7
8
  const METHODS = {
8
9
  loadAIGNE: loadAIGNEInChildProcess,
9
10
  invokeCLIAgentFromDir: invokeCLIAgentFromDirInChildProcess,
@@ -38,7 +39,7 @@ export async function loadAIGNEInChildProcess(...args) {
38
39
  agents: aigne.agents.map(serializeAgent),
39
40
  cli: {
40
41
  chat: aigne.cli.chat ? serializeAgent(aigne.cli.chat) : undefined,
41
- agents: aigne.cli.agents.map(serializeAgent),
42
+ agents: aigne.cli.agents?.map((item) => mapCliAgent(item, serializeAgent)),
42
43
  },
43
44
  mcpServer: {
44
45
  agents: aigne.mcpServer.agents.map(serializeAgent),
@@ -52,12 +53,20 @@ export async function invokeCLIAgentFromDirInChildProcess(options) {
52
53
  });
53
54
  try {
54
55
  const { chat } = aigne.cli;
55
- const agent = chat && chat.name === options.agent
56
- ? chat
57
- : aigne.cli.agents[options.agent] ||
58
- aigne.agents[options.agent] ||
59
- aigne.skills[options.agent] ||
60
- aigne.mcpServer.agents[options.agent];
56
+ let agent;
57
+ if (chat && chat.name === options.agent) {
58
+ agent = chat;
59
+ }
60
+ else if (options.parent) {
61
+ agent = findCliAgent(aigne.cli, options.parent, options.agent);
62
+ }
63
+ else {
64
+ agent =
65
+ findCliAgent(aigne.cli, [], options.agent) ||
66
+ aigne.agents[options.agent] ||
67
+ aigne.skills[options.agent] ||
68
+ aigne.mcpServer.agents[options.agent];
69
+ }
61
70
  assert(agent, `Agent ${options.agent} not found in ${options.dir}`);
62
71
  const input = await parseAgentInput(options.input, agent);
63
72
  await runAgentWithAIGNE(aigne, agent, {
@@ -1,4 +1,5 @@
1
1
  import type { Agent } from "@aigne/core";
2
+ import type { AIGNECLIAgent } from "@aigne/core/aigne/type.js";
2
3
  import type { JsonSchema } from "@aigne/json-schema-to-zod";
3
4
  import type { invokeCLIAgentFromDirInChildProcess, loadAIGNEInChildProcess } from "./run-aigne-in-child-process-worker.js";
4
5
  export type LoadAIGNEInChildProcessResult = Awaited<ReturnType<typeof loadAIGNEInChildProcess>>;
@@ -6,6 +7,10 @@ export interface AgentInChildProcess extends Pick<Agent, "name" | "description"
6
7
  inputSchema: JsonSchema;
7
8
  outputSchema: JsonSchema;
8
9
  }
10
+ export interface CLIAgentInChildProcess extends Omit<AIGNECLIAgent, "agent" | "agents"> {
11
+ agent?: AgentInChildProcess;
12
+ agents?: CLIAgentInChildProcess[];
13
+ }
9
14
  export declare function serializeAgent(agent: Agent): AgentInChildProcess;
10
15
  export interface ChildProcessAIGNEMethods {
11
16
  loadAIGNE: typeof loadAIGNEInChildProcess;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.49.2-beta.1",
3
+ "version": "1.50.0-beta.1",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -84,13 +84,13 @@
84
84
  "yoctocolors-cjs": "^2.1.3",
85
85
  "zod": "^3.25.67",
86
86
  "zod-to-json-schema": "^3.24.6",
87
- "@aigne/agent-library": "^1.21.47-beta",
88
- "@aigne/agentic-memory": "^1.0.47-beta",
89
- "@aigne/aigne-hub": "^0.10.1-beta",
90
- "@aigne/core": "^1.61.1-beta",
91
- "@aigne/default-memory": "^1.2.10-beta",
92
- "@aigne/observability-api": "^0.11.1-beta",
93
- "@aigne/openai": "^0.16.1-beta"
87
+ "@aigne/agent-library": "^1.21.47-beta.1",
88
+ "@aigne/aigne-hub": "^0.10.1-beta.1",
89
+ "@aigne/agentic-memory": "^1.0.47-beta.1",
90
+ "@aigne/core": "^1.62.0-beta",
91
+ "@aigne/default-memory": "^1.2.10-beta.1",
92
+ "@aigne/openai": "^0.16.1-beta.1",
93
+ "@aigne/observability-api": "^0.11.1-beta"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@inquirer/testing": "^2.1.50",
@@ -107,7 +107,7 @@
107
107
  "rimraf": "^6.0.1",
108
108
  "typescript": "^5.9.2",
109
109
  "ufo": "^1.6.1",
110
- "@aigne/test-utils": "^0.5.54-beta"
110
+ "@aigne/test-utils": "^0.5.54-beta.1"
111
111
  },
112
112
  "scripts": {
113
113
  "lint": "tsc --noEmit",