@aigne/cli 1.47.1 → 1.48.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,38 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.48.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.48.0...cli-v1.48.1) (2025-09-18)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * use aigne hub model when aigne hub connected ([#516](https://github.com/AIGNE-io/aigne-framework/issues/516)) ([a0493d0](https://github.com/AIGNE-io/aigne-framework/commit/a0493d0ad453afd3c3734ee2730636c6bd1e08ce))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @aigne/agent-library bumped to 1.21.45
16
+ * @aigne/agentic-memory bumped to 1.0.45
17
+ * @aigne/aigne-hub bumped to 0.9.5
18
+ * @aigne/core bumped to 1.60.3
19
+ * @aigne/default-memory bumped to 1.2.8
20
+ * @aigne/openai bumped to 0.15.4
21
+ * devDependencies
22
+ * @aigne/test-utils bumped to 0.5.52
23
+
24
+ ## [1.48.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.47.1...cli-v1.48.0) (2025-09-16)
25
+
26
+
27
+ ### Features
28
+
29
+ * **cli:** support using beta apps with environments ([#511](https://github.com/AIGNE-io/aigne-framework/issues/511)) ([141b11a](https://github.com/AIGNE-io/aigne-framework/commit/141b11a7757f8a441489c9e7ab5e10df1fafe26f))
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * **cli:** tune aigne hub status and deprecate aigne hub info ([#513](https://github.com/AIGNE-io/aigne-framework/issues/513)) ([25ca2a9](https://github.com/AIGNE-io/aigne-framework/commit/25ca2a9c402e9cb2d895737c32e25e957fdefd91))
35
+
3
36
  ## [1.47.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.47.0...cli-v1.47.1) (2025-09-16)
4
37
 
5
38
 
@@ -21,3 +21,7 @@ export declare function loadApplication({ name, dir, forceUpgrade, }: {
21
21
  version: string;
22
22
  isCache?: boolean;
23
23
  }>;
24
+ export declare function getNpmTgzInfo(name: string): Promise<{
25
+ version: string;
26
+ url: any;
27
+ }>;
@@ -13,6 +13,13 @@ 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
16
+ /**
17
+ * Check if beta applications should be used based on environment variables
18
+ */
19
+ function shouldUseBetaApps() {
20
+ const envVar = process.env.AIGNE_USE_BETA_APPS;
21
+ return envVar === "true" || envVar === "1";
22
+ }
16
23
  const builtinApps = [
17
24
  {
18
25
  name: "doc-smith",
@@ -159,15 +166,20 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
159
166
  const result = await new Listr([
160
167
  {
161
168
  title: `Fetching ${name} metadata`,
162
- task: async (ctx) => {
169
+ task: async (ctx, task) => {
163
170
  const info = await getNpmTgzInfo(name);
164
171
  Object.assign(ctx, info);
172
+ const useBeta = shouldUseBetaApps();
173
+ if (useBeta && ctx.version.includes("beta")) {
174
+ task.title = `Fetching ${name} metadata (using beta version)`;
175
+ }
165
176
  },
166
177
  },
167
178
  {
168
179
  title: `Downloading ${name}`,
169
180
  skip: (ctx) => ctx.version === check?.version,
170
- task: async (ctx) => {
181
+ task: async (ctx, task) => {
182
+ task.title = `Downloading ${name}(v${ctx.version})`;
171
183
  await rm(dir, { force: true, recursive: true });
172
184
  await mkdir(dir, { recursive: true });
173
185
  await downloadAndExtract(ctx.url, dir, { strip: 1 });
@@ -240,15 +252,24 @@ async function installDependencies(dir, { log } = {}) {
240
252
  });
241
253
  await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify({ installedAt: Date.now() }, null, 2));
242
254
  }
243
- async function getNpmTgzInfo(name) {
255
+ export async function getNpmTgzInfo(name) {
244
256
  const res = await fetch(joinURL("https://registry.npmjs.org", name));
245
257
  if (!res.ok)
246
258
  throw new Error(`Failed to fetch package info for ${name}: ${res.statusText}`);
247
259
  const data = await res.json();
248
- const latestVersion = data["dist-tags"].latest;
249
- const url = data.versions[latestVersion].dist.tarball;
260
+ const useBeta = shouldUseBetaApps();
261
+ let targetVersion;
262
+ if (useBeta && data["dist-tags"].beta) {
263
+ // Use beta version if available and beta flag is set
264
+ targetVersion = data["dist-tags"].beta;
265
+ }
266
+ else {
267
+ // Fall back to latest version
268
+ targetVersion = data["dist-tags"].latest;
269
+ }
270
+ const url = data.versions[targetVersion].dist.tarball;
250
271
  return {
251
- version: latestVersion,
272
+ version: targetVersion,
252
273
  url,
253
274
  };
254
275
  }
@@ -13,6 +13,9 @@ const formatNumber = (balance) => {
13
13
  const balanceNum = String(balance).split(".")[0];
14
14
  return chalk.yellow((balanceNum || "").replace(/\B(?=(\d{3})+(?!\d))/g, ","));
15
15
  };
16
+ function formatHubInfoName(name) {
17
+ return chalk.bold(`${name}:`.padEnd(10));
18
+ }
16
19
  function printHubStatus(data) {
17
20
  const divider = "─".repeat(46);
18
21
  console.log(chalk.bold("AIGNE Hub Connection"));
@@ -23,21 +26,22 @@ function printHubStatus(data) {
23
26
  : chalk.red(`${data.status} ❌`)}`);
24
27
  console.log("");
25
28
  console.log(chalk.bold("User:"));
26
- console.log(` ${chalk.bold("Name:".padEnd(8))} ${data.user.name}`);
27
- console.log(` ${chalk.bold("DID:".padEnd(8))} ${data.user.did}`);
28
- console.log(` ${chalk.bold("Email:".padEnd(8))} ${data.user.email}`);
29
+ console.log(` ${formatHubInfoName("Name")} ${data.user.name}`);
30
+ console.log(` ${formatHubInfoName("DID")} ${data.user.did}`);
31
+ console.log(` ${formatHubInfoName("Email")} ${data.user.email}`);
29
32
  console.log("");
30
33
  if (data.enableCredit) {
31
34
  console.log(chalk.bold("Credits:"));
32
- console.log(` ${chalk.bold("Used:".padEnd(8))} ${data.credits.used.toLocaleString()}`);
33
- console.log(` ${chalk.bold("Total:".padEnd(8))} ${data.credits.total.toLocaleString()}`);
35
+ console.log(` ${formatHubInfoName("Total")} ${formatNumber(data.credits.total)}`);
36
+ console.log(` ${formatHubInfoName("Used")} ${formatNumber(data.credits.used)}`);
37
+ console.log(` ${formatHubInfoName("Available")} ${formatNumber(data.credits.available)}`);
34
38
  console.log("");
35
39
  console.log(chalk.bold("Links:"));
36
40
  if (data.links.payment) {
37
- console.log(` ${chalk.bold("Payment:".padEnd(8))} ${data.links.payment}`);
41
+ console.log(` ${formatHubInfoName("Payment")} ${data.links.payment}`);
38
42
  }
39
43
  if (data.links.profile) {
40
- console.log(` ${chalk.bold("Profile:".padEnd(8))} ${data.links.profile}`);
44
+ console.log(` ${formatHubInfoName("Credits")} ${data.links.profile}`);
41
45
  }
42
46
  }
43
47
  }
@@ -115,9 +119,8 @@ export function createHubCommand() {
115
119
  },
116
120
  })
117
121
  .command("use", "Switch to a different AIGNE Hub", useHub)
118
- .command(["status", "st"], "Show current active hub", showStatus)
122
+ .command(["status", "st"], "Show details of a connected hub", showInfo)
119
123
  .command(["remove", "rm"], "Remove a connected hub", removeHub)
120
- .command(["info", "i"], "Show details of a connected hub", showInfo)
121
124
  .demandCommand(1, "Please provide a valid hub command"),
122
125
  handler: () => { },
123
126
  };
@@ -167,14 +170,6 @@ async function useHub() {
167
170
  });
168
171
  await setDefaultHub(hubApiKey);
169
172
  }
170
- async function showStatus() {
171
- const active = await getDefaultHub();
172
- if (!active) {
173
- console.log(chalk.red("No active hub."));
174
- return;
175
- }
176
- console.log(`Active hub: ${getUrlOrigin(active)} - online`);
177
- }
178
173
  async function removeHub() {
179
174
  const hubs = await getHubs();
180
175
  if (!hubs.length) {
@@ -198,12 +193,14 @@ async function showInfo() {
198
193
  console.log(chalk.yellow("No AIGNE Hub connected."));
199
194
  return;
200
195
  }
196
+ const defaultHub = await getDefaultHub();
197
+ const defaultHubIndex = hubs.findIndex((h) => getUrlOrigin(h.apiUrl) === getUrlOrigin(defaultHub));
201
198
  const { hubApiKey } = await inquirer.prompt({
202
199
  type: "select",
203
200
  name: "hubApiKey",
204
201
  message: `Choose a hub to view info:`,
205
- choices: hubs.map((h) => ({
206
- name: getUrlOrigin(h.apiUrl),
202
+ choices: hubs.map((h, index) => ({
203
+ name: `${getUrlOrigin(h.apiUrl)} ${defaultHubIndex === index ? "(connected)" : ""}`,
207
204
  value: h.apiUrl,
208
205
  })),
209
206
  });
@@ -285,8 +282,10 @@ async function printHubDetails(url) {
285
282
  email: userInfo?.user.email || "",
286
283
  },
287
284
  credits: {
288
- used: formatNumber(userInfo?.creditBalance?.balance || "0"),
285
+ available: formatNumber(userInfo?.creditBalance?.balance || "0"),
289
286
  total: formatNumber(userInfo?.creditBalance?.total || "0"),
287
+ used: formatNumber(String(parseFloat(userInfo?.creditBalance?.total || "0") -
288
+ parseFloat(userInfo?.creditBalance?.balance || "0"))),
290
289
  },
291
290
  links: {
292
291
  payment: userInfo?.paymentLink || "",
@@ -7,7 +7,7 @@ const DEFAULT_PORT = () => tryOrThrow(() => {
7
7
  const { PORT } = process.env;
8
8
  if (!PORT)
9
9
  return 7890;
10
- const port = Number.parseInt(PORT);
10
+ const port = Number.parseInt(PORT, 10);
11
11
  if (!port || !Number.isInteger(port))
12
12
  throw new Error(`Invalid PORT: ${PORT}`);
13
13
  return port;
@@ -6,7 +6,7 @@ export const DEFAULT_PORT = () => tryOrThrow(() => {
6
6
  const { PORT } = process.env;
7
7
  if (!PORT)
8
8
  return 3000;
9
- const port = Number.parseInt(PORT);
9
+ const port = Number.parseInt(PORT, 10);
10
10
  if (!port || !Number.isInteger(port))
11
11
  throw new Error(`Invalid PORT: ${PORT}`);
12
12
  return port;
@@ -1,8 +1,10 @@
1
+ import { readFile } from "node:fs/promises";
1
2
  import { AIGNE_HUB_DEFAULT_MODEL, findModel } from "@aigne/aigne-hub";
2
3
  import { flat, pick } from "@aigne/core/utils/type-utils.js";
3
4
  import chalk from "chalk";
4
5
  import inquirer from "inquirer";
5
- import { AIGNE_HUB_PROVIDER } from "./constants.js";
6
+ import { parse, stringify } from "yaml";
7
+ import { AIGNE_ENV_FILE, AIGNE_HUB_PROVIDER } from "./constants.js";
6
8
  import { loadAIGNEHubCredential } from "./credential.js";
7
9
  export function maskApiKey(apiKey) {
8
10
  if (!apiKey || apiKey.length <= 8)
@@ -20,8 +22,9 @@ export const formatModelName = async (model, inquirerPrompt) => {
20
22
  let { provider, model: name } = parseModelOption(model);
21
23
  provider ||= AIGNE_HUB_PROVIDER;
22
24
  const { match, all } = findModel(provider);
23
- if (!match)
25
+ if (!match) {
24
26
  throw new Error(`Unsupported model: ${provider}/${name}, available providers: ${all.map((m) => m.name).join(", ")}`);
27
+ }
25
28
  if (provider.includes(AIGNE_HUB_PROVIDER)) {
26
29
  return { provider, model: name || AIGNE_HUB_DEFAULT_MODEL };
27
30
  }
@@ -29,6 +32,10 @@ export const formatModelName = async (model, inquirerPrompt) => {
29
32
  if (requireEnvs.some((name) => name && process.env[name])) {
30
33
  return { provider, model: name };
31
34
  }
35
+ const envs = parse(await readFile(AIGNE_ENV_FILE, "utf8").catch(() => stringify({})));
36
+ if (envs?.default?.AIGNE_HUB_API_URL) {
37
+ return { provider: AIGNE_HUB_PROVIDER, model: `${provider}/${name}` };
38
+ }
32
39
  const result = await inquirerPrompt({
33
40
  type: "list",
34
41
  name: "useAigneHub",
@@ -1,9 +1,7 @@
1
1
  import { joinURL } from "ufo";
2
2
  export async function getUserInfo({ baseUrl, apiKey, }) {
3
3
  const response = await fetch(joinURL(baseUrl, "/api/user/info"), {
4
- headers: {
5
- Authorization: `Bearer ${apiKey}`,
6
- },
4
+ headers: { Authorization: `Bearer ${apiKey}` },
7
5
  });
8
6
  if (!response.ok)
9
7
  throw new Error(`Failed to fetch user info: ${response.statusText}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.47.1",
3
+ "version": "1.48.1",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -47,17 +47,17 @@
47
47
  "dependencies": {
48
48
  "@aigne/listr2": "^1.0.10",
49
49
  "@aigne/marked-terminal": "^7.3.2",
50
- "@inquirer/core": "^10.2.0",
50
+ "@inquirer/core": "^10.2.2",
51
51
  "@inquirer/figures": "^1.0.13",
52
- "@inquirer/prompts": "^7.8.4",
52
+ "@inquirer/prompts": "^7.8.6",
53
53
  "@inquirer/type": "^3.0.8",
54
- "@listr2/prompt-adapter-inquirer": "^3.0.2",
55
- "@modelcontextprotocol/sdk": "^1.15.0",
56
- "@ocap/mcrypto": "^1.21.0",
57
- "@smithy/node-http-handler": "^4.1.0",
58
- "ansi-escapes": "^7.0.0",
54
+ "@listr2/prompt-adapter-inquirer": "^3.0.4",
55
+ "@modelcontextprotocol/sdk": "^1.18.0",
56
+ "@ocap/mcrypto": "^1.25.1",
57
+ "@smithy/node-http-handler": "^4.2.1",
58
+ "ansi-escapes": "^7.1.0",
59
59
  "boxen": "^8.0.1",
60
- "chalk": "^5.4.1",
60
+ "chalk": "^5.6.2",
61
61
  "cli-table3": "^0.6.5",
62
62
  "detect-port": "^2.1.0",
63
63
  "dotenv-flow": "^4.1.0",
@@ -65,46 +65,46 @@
65
65
  "glob": "^11.0.3",
66
66
  "gradient-string": "^3.0.0",
67
67
  "https-proxy-agent": "^7.0.6",
68
- "inquirer": "^12.9.4",
69
- "log-update": "^6.1.0",
70
- "marked": "^16.0.0",
68
+ "inquirer": "^12.9.6",
69
+ "log-update": "^7.0.0",
70
+ "marked": "^16.3.0",
71
71
  "nunjucks": "^3.2.4",
72
72
  "open": "^10.2.0",
73
- "openai": "^5.8.3",
73
+ "openai": "^5.20.3",
74
74
  "p-wait-for": "^5.0.2",
75
75
  "prettier": "^3.6.2",
76
76
  "tar": "^7.4.3",
77
- "terminal-image": "^3.1.1",
78
- "terminal-link": "^4.0.0",
79
- "wrap-ansi": "^9.0.0",
80
- "yaml": "^2.8.0",
77
+ "terminal-image": "^4.0.0",
78
+ "terminal-link": "^5.0.0",
79
+ "wrap-ansi": "^9.0.2",
80
+ "yaml": "^2.8.1",
81
81
  "yargs": "^18.0.0",
82
82
  "yoctocolors-cjs": "^2.1.3",
83
83
  "zod": "^3.25.67",
84
- "@aigne/agent-library": "^1.21.44",
85
- "@aigne/agentic-memory": "^1.0.44",
86
- "@aigne/core": "^1.60.2",
87
- "@aigne/aigne-hub": "^0.9.4",
88
- "@aigne/observability-api": "^0.10.4",
89
- "@aigne/default-memory": "^1.2.7",
90
- "@aigne/openai": "^0.15.3"
84
+ "@aigne/agent-library": "^1.21.45",
85
+ "@aigne/agentic-memory": "^1.0.45",
86
+ "@aigne/aigne-hub": "^0.9.5",
87
+ "@aigne/core": "^1.60.3",
88
+ "@aigne/default-memory": "^1.2.8",
89
+ "@aigne/openai": "^0.15.4",
90
+ "@aigne/observability-api": "^0.10.4"
91
91
  },
92
92
  "devDependencies": {
93
- "@inquirer/testing": "^2.1.49",
93
+ "@inquirer/testing": "^2.1.50",
94
94
  "@types/archiver": "^6.0.3",
95
- "@types/bun": "^1.2.18",
95
+ "@types/bun": "^1.2.22",
96
96
  "@types/express": "^5.0.3",
97
97
  "@types/glob": "^9.0.0",
98
98
  "@types/gradient-string": "^1.1.6",
99
- "@types/node": "^24.0.12",
99
+ "@types/node": "^24.5.1",
100
100
  "@types/yargs": "^17.0.33",
101
101
  "archiver": "^7.0.1",
102
102
  "hono": "4.8.4",
103
103
  "npm-run-all": "^4.1.5",
104
104
  "rimraf": "^6.0.1",
105
- "typescript": "^5.8.3",
105
+ "typescript": "^5.9.2",
106
106
  "ufo": "^1.6.1",
107
- "@aigne/test-utils": "^0.5.51"
107
+ "@aigne/test-utils": "^0.5.52"
108
108
  },
109
109
  "scripts": {
110
110
  "lint": "tsc --noEmit",