@aigne/cli 1.26.0 → 1.26.1-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.
@@ -4,67 +4,90 @@ import { dirname, isAbsolute, join } from "node:path";
4
4
  import { isatty } from "node:tty";
5
5
  import { promisify } from "node:util";
6
6
  import { exists } from "@aigne/agent-library/utils/fs.js";
7
- import { AIGNE, DEFAULT_OUTPUT_KEY, readAllString, UserAgent, } from "@aigne/core";
7
+ import { AIAgent, AIGNE, DEFAULT_OUTPUT_KEY, readAllString, UserAgent, } from "@aigne/core";
8
8
  import { loadModel } from "@aigne/core/loader/index.js";
9
9
  import { getLevelFromEnv, LogLevel, logger } from "@aigne/core/utils/logger.js";
10
- import { isEmpty, isNonNullable, tryOrThrow, } from "@aigne/core/utils/type-utils.js";
10
+ import { flat, isEmpty, tryOrThrow, } from "@aigne/core/utils/type-utils.js";
11
11
  import chalk from "chalk";
12
- import { Command } from "commander";
13
12
  import { parse } from "yaml";
13
+ import yargs from "yargs";
14
14
  import { ZodError, ZodObject, z } from "zod";
15
15
  import { availableModels } from "../constants.js";
16
16
  import { TerminalTracer } from "../tracer/terminal.js";
17
17
  import { DEFAULT_CHAT_INPUT_KEY, runChatLoopInTerminal, } from "./run-chat-loop.js";
18
- export const createRunAIGNECommand = (name = "run") => new Command(name)
19
- .allowUnknownOption(true)
20
- .allowExcessArguments(true)
21
- .description("Run agent with AIGNE in terminal")
22
- .option("--chat", "Run chat loop in terminal", false)
23
- .option("--model <provider[:model]>", `AI model to use in format 'provider[:model]' where model is optional. Examples: 'openai' or 'openai:gpt-4o-mini'. Available providers: ${availableModels()
24
- .map((i) => i.name.toLowerCase().replace(/ChatModel$/i, ""))
25
- .join(", ")} (default: openai)`)
26
- .option("--temperature <temperature>", "Temperature for the model (controls randomness, higher values produce more random outputs). Range: 0.0-2.0", customZodError("--temperature", (s) => z.coerce.number().min(0).max(2).parse(s)))
27
- .option("--top-p <top-p>", "Top P (nucleus sampling) parameter for the model (controls diversity). Range: 0.0-1.0", customZodError("--top-p", (s) => z.coerce.number().min(0).max(1).parse(s)))
28
- .option("--presence-penalty <presence-penalty>", "Presence penalty for the model (penalizes repeating the same tokens). Range: -2.0 to 2.0", customZodError("--presence-penalty", (s) => z.coerce.number().min(-2).max(2).parse(s)))
29
- .option("--frequency-penalty <frequency-penalty>", "Frequency penalty for the model (penalizes frequency of token usage). Range: -2.0 to 2.0", customZodError("--frequency-penalty", (s) => z.coerce.number().min(-2).max(2).parse(s)))
30
- .option("--input -i <input...>", "Input to the agent, use @<file> to read from a file")
31
- .option("--format <format>", "Input format for the agent (available: text, json, yaml default: text)")
32
- .option("--output -o <output>", "Output file to save the result (default: stdout)")
33
- .option("--output-key <output-key>", "Key in the result to save to the output file", DEFAULT_OUTPUT_KEY)
34
- .option("--force", "Truncate the output file if it exists, and create directory if the output path is not exists", false)
35
- .option("--log-level <level>", `Log level for detailed debugging information. Values: ${Object.values(LogLevel).join(", ")}`, customZodError("--log-level", (s) => z.nativeEnum(LogLevel).parse(s)), getLevelFromEnv(logger.options.ns) || LogLevel.INFO);
18
+ export const createRunAIGNECommand = (yargs) => yargs
19
+ .option("chat", {
20
+ describe: "Run chat loop in terminal",
21
+ type: "boolean",
22
+ default: false,
23
+ })
24
+ .option("model", {
25
+ describe: `AI model to use in format 'provider[:model]' where model is optional. Examples: 'openai' or 'openai:gpt-4o-mini'. Available providers: ${availableModels()
26
+ .map((i) => i.name.toLowerCase().replace(/ChatModel$/i, ""))
27
+ .join(", ")} (default: openai)`,
28
+ type: "string",
29
+ })
30
+ .option("temperature", {
31
+ describe: "Temperature for the model (controls randomness, higher values produce more random outputs). Range: 0.0-2.0",
32
+ type: "number",
33
+ coerce: customZodError("--temperature", (s) => z.coerce.number().min(0).max(2).parse(s)),
34
+ })
35
+ .option("top-p", {
36
+ describe: "Top P (nucleus sampling) parameter for the model (controls diversity). Range: 0.0-1.0",
37
+ type: "number",
38
+ coerce: customZodError("--top-p", (s) => z.coerce.number().min(0).max(1).parse(s)),
39
+ })
40
+ .option("presence-penalty", {
41
+ describe: "Presence penalty for the model (penalizes repeating the same tokens). Range: -2.0 to 2.0",
42
+ type: "number",
43
+ coerce: customZodError("--presence-penalty", (s) => z.coerce.number().min(-2).max(2).parse(s)),
44
+ })
45
+ .option("frequency-penalty", {
46
+ describe: "Frequency penalty for the model (penalizes frequency of token usage). Range: -2.0 to 2.0",
47
+ type: "number",
48
+ coerce: customZodError("--frequency-penalty", (s) => z.coerce.number().min(-2).max(2).parse(s)),
49
+ })
50
+ .option("input", {
51
+ describe: "Input to the agent, use @<file> to read from a file",
52
+ type: "array",
53
+ alias: "i",
54
+ })
55
+ .option("format", {
56
+ describe: "Input format for the agent (available: text, json, yaml default: text)",
57
+ type: "string",
58
+ })
59
+ .option("output", {
60
+ describe: "Output file to save the result (default: stdout)",
61
+ type: "string",
62
+ alias: "o",
63
+ })
64
+ .option("output-key", {
65
+ describe: "Key in the result to save to the output file",
66
+ type: "string",
67
+ default: DEFAULT_OUTPUT_KEY,
68
+ })
69
+ .option("force", {
70
+ describe: "Truncate the output file if it exists, and create directory if the output path is not exists",
71
+ type: "boolean",
72
+ default: false,
73
+ })
74
+ .option("log-level", {
75
+ describe: `Log level for detailed debugging information. Values: ${Object.values(LogLevel).join(", ")}`,
76
+ type: "string",
77
+ default: getLevelFromEnv(logger.options.ns) || LogLevel.INFO,
78
+ coerce: customZodError("--log-level", (s) => z.nativeEnum(LogLevel).parse(s)),
79
+ });
36
80
  export async function parseAgentInputByCommander(agent, options = {}) {
37
- const cmd = new Command()
38
- .description(`Run agent ${agent.name} with AIGNE`)
39
- .allowUnknownOption(true)
40
- .allowExcessArguments(true);
41
- const inputSchemaShape = agent.inputSchema instanceof ZodObject ? Object.keys(agent.inputSchema.shape) : [];
42
- for (const option of inputSchemaShape) {
43
- cmd.option(`--input-${option} <${option}>`);
44
- }
45
- const input = await new Promise((resolve, reject) => {
46
- cmd
47
- .action(async (agentInputOptions) => {
48
- try {
49
- const input = Object.fromEntries((await Promise.all(Object.entries(agentInputOptions).map(async ([key, value]) => {
50
- let k = key.replace(/^input/, "");
51
- k = k.charAt(0).toLowerCase() + k.slice(1);
52
- if (!k)
53
- return null;
54
- if (typeof value === "string" && value.startsWith("@")) {
55
- value = await readFile(value.slice(1), "utf8");
56
- }
57
- return [k, value];
58
- }))).filter(isNonNullable));
59
- resolve(input);
60
- }
61
- catch (error) {
62
- reject(error);
63
- }
64
- })
65
- .parseAsync(options.argv ?? process.argv)
66
- .catch((error) => reject(error));
67
- });
81
+ const inputSchemaShape = flat(agent instanceof AIAgent ? agent.inputKey : undefined, agent.inputSchema instanceof ZodObject ? Object.keys(agent.inputSchema.shape) : []);
82
+ const parsedInput = await yargs().parseAsync(options.argv ?? process.argv);
83
+ const input = Object.fromEntries(await Promise.all(inputSchemaShape.map(async (key) => {
84
+ const k = `input${key.charAt(0).toUpperCase()}${key.slice(1)}`;
85
+ let value = parsedInput[k];
86
+ if (typeof value === "string" && value.startsWith("@")) {
87
+ value = await readFile(value.slice(1), "utf8");
88
+ }
89
+ return [key, value];
90
+ })));
68
91
  const rawInput = options.input ||
69
92
  (isatty(process.stdin.fd) || !(await stdinHasData())
70
93
  ? null
@@ -96,14 +119,12 @@ export async function parseAgentInputByCommander(agent, options = {}) {
96
119
  return input;
97
120
  }
98
121
  export const parseModelOption = (model) => {
99
- const { provider, name } = (model || process.env.MODEL)?.match(/(?<provider>[^:]+)(:(?<name>(\S+)))?/)?.groups ?? {};
122
+ const { provider, name } = (model || process.env.MODEL)?.match(/(?<provider>[^:]*)(:(?<name>(\S+)))?/)?.groups ?? {};
100
123
  return { provider, name };
101
124
  };
102
125
  export async function runWithAIGNE(agentCreator, { argv = process.argv, chatLoopOptions, modelOptions, outputKey, } = {}) {
103
- await createRunAIGNECommand()
104
- .showHelpAfterError(true)
105
- .showSuggestionAfterError(true)
106
- .action(async (options) => {
126
+ await yargs()
127
+ .command("$0", "Run an agent with AIGNE", (yargs) => createRunAIGNECommand(yargs), async (options) => {
107
128
  if (options.logLevel) {
108
129
  logger.level = options.logLevel;
109
130
  }
@@ -134,6 +155,8 @@ export async function runWithAIGNE(agentCreator, { argv = process.argv, chatLoop
134
155
  await aigne.shutdown();
135
156
  }
136
157
  })
158
+ .alias("h", "help")
159
+ .alias("v", "version")
137
160
  .parseAsync(argv)
138
161
  .catch((error) => {
139
162
  console.error(`${chalk.red("Error:")} ${error.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.26.0",
3
+ "version": "1.26.1-1",
4
4
  "description": "cli for AIGNE framework",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -44,6 +44,7 @@
44
44
  "dependencies": {
45
45
  "@aigne/listr2": "^1.0.10",
46
46
  "@aigne/marked-terminal": "^7.3.2",
47
+ "@blocklet/aigne-hub": "^0.2.17",
47
48
  "@inquirer/prompts": "^7.6.0",
48
49
  "@inquirer/type": "^3.0.8",
49
50
  "@listr2/prompt-adapter-inquirer": "^3.0.1",
@@ -51,7 +52,6 @@
51
52
  "@ocap/mcrypto": "^1.21.0",
52
53
  "@smithy/node-http-handler": "^4.1.0",
53
54
  "chalk": "^5.4.1",
54
- "commander": "^14.0.0",
55
55
  "crypto": "^1.0.1",
56
56
  "detect-port": "^2.1.0",
57
57
  "dotenv-flow": "^4.1.0",
@@ -69,21 +69,22 @@
69
69
  "tar": "^7.4.3",
70
70
  "wrap-ansi": "^9.0.0",
71
71
  "yaml": "^2.8.0",
72
+ "yargs": "^18.0.0",
72
73
  "zod": "^3.25.67",
73
74
  "@aigne/agentic-memory": "^1.0.6",
74
- "@aigne/agent-library": "^1.21.6",
75
75
  "@aigne/aigne-hub": "^0.2.2",
76
76
  "@aigne/anthropic": "^0.10.2",
77
- "@aigne/deepseek": "^0.7.6",
77
+ "@aigne/agent-library": "^1.21.6",
78
78
  "@aigne/bedrock": "^0.8.6",
79
79
  "@aigne/core": "^1.39.0",
80
+ "@aigne/deepseek": "^0.7.6",
80
81
  "@aigne/default-memory": "^1.0.6",
81
- "@aigne/gemini": "^0.8.6",
82
- "@aigne/ollama": "^0.7.6",
83
82
  "@aigne/observability-api": "^0.8.2",
83
+ "@aigne/ollama": "^0.7.6",
84
84
  "@aigne/open-router": "^0.7.6",
85
- "@aigne/openai": "^0.10.6",
86
- "@aigne/xai": "^0.7.6"
85
+ "@aigne/xai": "^0.7.6",
86
+ "@aigne/gemini": "^0.8.6",
87
+ "@aigne/openai": "^0.10.6"
87
88
  },
88
89
  "devDependencies": {
89
90
  "@types/archiver": "^6.0.3",
@@ -92,6 +93,7 @@
92
93
  "@types/glob": "^9.0.0",
93
94
  "@types/gradient-string": "^1.1.6",
94
95
  "@types/node": "^24.0.12",
96
+ "@types/yargs": "^17.0.33",
95
97
  "archiver": "^7.0.1",
96
98
  "hono": "4.8.4",
97
99
  "npm-run-all": "^4.1.5",