@aigne/cli 1.45.0 → 1.46.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,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.46.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.45.0...cli-v1.46.0) (2025-09-10)
4
+
5
+
6
+ ### Features
7
+
8
+ * support custom model for every agents ([#472](https://github.com/AIGNE-io/aigne-framework/issues/472)) ([0bda78a](https://github.com/AIGNE-io/aigne-framework/commit/0bda78a2ebf537e953d855882d68cb37d94d1d10))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **cli:** load AIGNE in a child process to ensure app is available ([#475](https://github.com/AIGNE-io/aigne-framework/issues/475)) ([c8201b5](https://github.com/AIGNE-io/aigne-framework/commit/c8201b51accc4a9d047394f235df53725733f726))
14
+ * **cli:** run default agent if `entry-agent` argument not present ([#473](https://github.com/AIGNE-io/aigne-framework/issues/473)) ([8c46672](https://github.com/AIGNE-io/aigne-framework/commit/8c4667206a2336e74db07442dc296ef9f9265a0b))
15
+
16
+
17
+ ### Dependencies
18
+
19
+ * The following workspace dependencies were updated
20
+ * dependencies
21
+ * @aigne/agent-library bumped to 1.21.42
22
+ * @aigne/agentic-memory bumped to 1.0.42
23
+ * @aigne/aigne-hub bumped to 0.9.1
24
+ * @aigne/core bumped to 1.60.0
25
+ * @aigne/default-memory bumped to 1.2.5
26
+ * @aigne/observability-api bumped to 0.10.3
27
+ * @aigne/openai bumped to 0.15.1
28
+ * devDependencies
29
+ * @aigne/test-utils bumped to 0.5.49
30
+
3
31
  ## [1.45.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.44.3...cli-v1.45.0) (2025-09-09)
4
32
 
5
33
 
@@ -1,4 +1,4 @@
1
- import { type Agent, AIGNE, type Message } from "@aigne/core";
1
+ import type { Agent, AIGNE, Message } from "@aigne/core";
2
2
  import type { CommandModule } from "yargs";
3
3
  import { type AgentRunCommonOptions } from "../utils/yargs.js";
4
4
  export declare function createAppCommands(): CommandModule[];
@@ -3,13 +3,13 @@ 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
5
  import { join } from "node:path";
6
- import { AIGNE } from "@aigne/core";
7
6
  import { logger } from "@aigne/core/utils/logger.js";
8
7
  import { Listr, PRESET_TIMER } from "@aigne/listr2";
9
8
  import { joinURL } from "ufo";
10
9
  import { downloadAndExtract } from "../utils/download.js";
11
10
  import { loadAIGNE } from "../utils/load-aigne.js";
12
11
  import { runAgentWithAIGNE } from "../utils/run-with-aigne.js";
12
+ import { safeLoadAIGNE } from "../utils/workers/load-aigne.js";
13
13
  import { parseAgentInput, withAgentInputSchema, } from "../utils/yargs.js";
14
14
  import { serveMCPServerFromDir } from "./serve-mcp.js";
15
15
  const NPM_PACKAGE_CACHE_TIME_MS = 1000 * 60 * 60 * 24; // 1 day
@@ -94,6 +94,7 @@ export const agentCommandModule = ({ dir, agent, }) => {
94
94
  if (options.logLevel)
95
95
  logger.level = options.logLevel;
96
96
  await invokeCLIAgentFromDir({ dir, agent: agent.name, input: options });
97
+ process.exit(0);
97
98
  },
98
99
  };
99
100
  };
@@ -127,7 +128,7 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
127
128
  dir ??= join(homedir(), ".aigne", "registry.npmjs.org", name);
128
129
  let check = forceUpgrade ? undefined : await isInstallationAvailable(dir);
129
130
  if (check?.available) {
130
- const aigne = await AIGNE.load(dir).catch((error) => {
131
+ const aigne = await safeLoadAIGNE(dir).catch((error) => {
131
132
  console.warn(`⚠️ Failed to load ${name}, trying to reinstall:`, error.message);
132
133
  });
133
134
  if (aigne) {
@@ -177,7 +178,7 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
177
178
  },
178
179
  }).run();
179
180
  return {
180
- aigne: await AIGNE.load(dir),
181
+ aigne: await safeLoadAIGNE(dir),
181
182
  dir,
182
183
  version: result.version,
183
184
  };
@@ -3,4 +3,5 @@ export declare function createRunCommand({ aigneFilePath, }?: {
3
3
  aigneFilePath?: string;
4
4
  }): CommandModule<unknown, {
5
5
  path?: string;
6
+ entryAgent?: string;
6
7
  }>;
@@ -1,6 +1,7 @@
1
1
  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
+ import { exists } from "@aigne/agent-library/utils/fs.js";
4
5
  import { flat, isNonNullable } from "@aigne/core/utils/type-utils.js";
5
6
  import { Listr, PRESET_TIMER } from "@aigne/listr2";
6
7
  import { config } from "dotenv-flow";
@@ -8,10 +9,11 @@ import yargs from "yargs";
8
9
  import { isV1Package, toAIGNEPackage } from "../utils/agent-v1.js";
9
10
  import { downloadAndExtract } from "../utils/download.js";
10
11
  import { loadAIGNE } from "../utils/load-aigne.js";
12
+ import { isUrl } from "../utils/url.js";
11
13
  import { agentCommandModule } from "./app.js";
12
14
  export function createRunCommand({ aigneFilePath, } = {}) {
13
15
  return {
14
- command: "run [path]",
16
+ command: "run [path] [entry-agent]",
15
17
  describe: "Run AIGNE for the specified path",
16
18
  builder: async (yargs) => {
17
19
  return yargs
@@ -19,16 +21,23 @@ export function createRunCommand({ aigneFilePath, } = {}) {
19
21
  type: "string",
20
22
  describe: "Path to the agents directory or URL to an aigne project",
21
23
  default: ".",
24
+ })
25
+ .positional("entry-agent", {
26
+ type: "string",
27
+ describe: "Name of the agent to run (defaults to the entry agent if not specified)",
22
28
  })
23
29
  .help(false)
24
30
  .version(false)
25
31
  .strict(false);
26
32
  },
27
33
  handler: async (options) => {
28
- const p = aigneFilePath || options.path;
29
- if (!p)
30
- throw new Error("No path specified");
31
- const { aigne, path } = await loadApplication(p);
34
+ if (!options.entryAgent && options.path) {
35
+ if (!(await exists(options.path)) && !isUrl(options.path)) {
36
+ options.entryAgent = options.path;
37
+ options.path = undefined;
38
+ }
39
+ }
40
+ const { aigne, path } = await loadApplication(aigneFilePath || options.path || ".");
32
41
  const subYargs = yargs().scriptName("").usage("aigne run <path> <agent> [...options]");
33
42
  if (aigne.cli.chat) {
34
43
  subYargs.command({
@@ -37,7 +46,8 @@ export function createRunCommand({ aigneFilePath, } = {}) {
37
46
  });
38
47
  }
39
48
  // Allow user to run all of agents in the AIGNE instances
40
- for (const agent of flat(aigne.cli.agents, aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents)) {
49
+ const allAgents = flat(aigne.cli.agents, aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents);
50
+ for (const agent of allAgents) {
41
51
  subYargs.command(agentCommandModule({ dir: path, agent }));
42
52
  }
43
53
  const argv = process.argv.slice(aigneFilePath ? 3 : 2);
@@ -50,6 +60,9 @@ export function createRunCommand({ aigneFilePath, } = {}) {
50
60
  argv.shift(); // remove path/url args
51
61
  if (argv[0] === "--entry-agent")
52
62
  argv.shift();
63
+ const firstAgent = aigne.agents[0]?.name;
64
+ if (!options.entryAgent && firstAgent)
65
+ argv.unshift(firstAgent);
53
66
  await subYargs
54
67
  .strict()
55
68
  .demandCommand()
@@ -12,7 +12,8 @@ export function maskApiKey(apiKey) {
12
12
  return `${start}${"*".repeat(8)}${end}`;
13
13
  }
14
14
  export const parseModelOption = (model) => {
15
- const { provider, name } = model.match(/(?<provider>[^:]*)(:(?<name>.*))?/)?.groups ?? {};
15
+ model = model.replace(":", "/");
16
+ const { provider, name } = model.match(/(?<provider>[^/]*)(\/(?<name>.*))?/)?.groups ?? {};
16
17
  return { provider: provider?.replace(/-/g, ""), model: name };
17
18
  };
18
19
  export const formatModelName = async (model, inquirerPrompt) => {
@@ -0,0 +1 @@
1
+ export declare function isUrl(s: string): boolean;
@@ -0,0 +1,3 @@
1
+ export function isUrl(s) {
2
+ return /^https?:\/\/\S+/.test(s);
3
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { AIGNE } from "@aigne/core";
2
+ process.on("message", async ({ method, args }) => {
3
+ try {
4
+ if (method !== "AIGNE.load")
5
+ throw new Error(`Unknown method: ${method}`);
6
+ await AIGNE.load(...args);
7
+ process.send?.({ method, status: "success" });
8
+ }
9
+ catch (error) {
10
+ process.send?.({ method, status: "error", message: error.message });
11
+ }
12
+ process.exit(0);
13
+ });
@@ -0,0 +1,2 @@
1
+ import { AIGNE } from "@aigne/core";
2
+ export declare function safeLoadAIGNE(...args: Parameters<typeof AIGNE.load>): Promise<ReturnType<typeof AIGNE.load>>;
@@ -0,0 +1,24 @@
1
+ import { fork } from "node:child_process";
2
+ import { join } from "node:path";
3
+ import { AIGNE } from "@aigne/core";
4
+ export async function safeLoadAIGNE(...args) {
5
+ await new Promise((resolve, reject) => {
6
+ const child = fork(join(import.meta.dirname, "./load-aigne-worker.js"), { timeout: 600e3 });
7
+ child.on("message", ({ method, message, status }) => {
8
+ if (method !== "AIGNE.load")
9
+ reject(new Error(`Unknown method: ${method}`));
10
+ else if (status === "error")
11
+ reject(new Error(`Failed to load AIGNE: ${message}`));
12
+ else if (status === "success")
13
+ resolve();
14
+ });
15
+ child.on("exit", (code) => {
16
+ if (code !== 0)
17
+ reject(new Error(`Child process exited with code ${code}`));
18
+ else
19
+ resolve();
20
+ });
21
+ child.send({ method: "AIGNE.load", args });
22
+ });
23
+ return AIGNE.load(...args);
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.45.0",
3
+ "version": "1.46.0",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -81,13 +81,13 @@
81
81
  "yargs": "^18.0.0",
82
82
  "yoctocolors-cjs": "^2.1.3",
83
83
  "zod": "^3.25.67",
84
- "@aigne/agentic-memory": "^1.0.41",
85
- "@aigne/core": "^1.59.0",
86
- "@aigne/agent-library": "^1.21.41",
87
- "@aigne/aigne-hub": "^0.9.0",
88
- "@aigne/default-memory": "^1.2.4",
89
- "@aigne/openai": "^0.15.0",
90
- "@aigne/observability-api": "^0.10.2"
84
+ "@aigne/agentic-memory": "^1.0.42",
85
+ "@aigne/core": "^1.60.0",
86
+ "@aigne/default-memory": "^1.2.5",
87
+ "@aigne/agent-library": "^1.21.42",
88
+ "@aigne/aigne-hub": "^0.9.1",
89
+ "@aigne/openai": "^0.15.1",
90
+ "@aigne/observability-api": "^0.10.3"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@inquirer/testing": "^2.1.49",
@@ -104,7 +104,7 @@
104
104
  "rimraf": "^6.0.1",
105
105
  "typescript": "^5.8.3",
106
106
  "ufo": "^1.6.1",
107
- "@aigne/test-utils": "^0.5.48"
107
+ "@aigne/test-utils": "^0.5.49"
108
108
  },
109
109
  "scripts": {
110
110
  "lint": "tsc --noEmit",
@@ -30,7 +30,27 @@ OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
30
30
  ### Start the Project
31
31
 
32
32
  ```bash
33
- aigne run
33
+ aigne run --input "Hello, what can you help me with?"
34
+ ```
35
+
36
+ use the following command to pipe input from the terminal:
37
+
38
+ ```bash
39
+ echo "Hello, what can you help me with?" | aigne run
40
+ ```
41
+
42
+ use the following command to start an interactive chat session:
43
+
44
+ ```bash
45
+ aigne run --chat
46
+ ```
47
+
48
+ help:
49
+
50
+ ```bash
51
+ aigne run -h # show help of project
52
+
53
+ aigne run chat -h # show help of agent
34
54
  ```
35
55
 
36
56
  ## Testing