@aigne/cli 1.35.1 → 1.36.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 +29 -0
- package/dist/commands/aigne.js +0 -2
- package/dist/commands/app.js +22 -6
- package/dist/commands/hub.js +40 -20
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/tracer/terminal.d.ts +4 -1
- package/dist/tracer/terminal.js +63 -45
- package/dist/utils/listr.js +3 -5
- package/dist/utils/load-aigne.js +26 -1
- package/dist/utils/run-with-aigne.js +1 -4
- package/package.json +9 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.36.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.35.1...cli-v1.36.0) (2025-08-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **core:** add priority support for agent hooks ([#358](https://github.com/AIGNE-io/aigne-framework/issues/358)) ([9196141](https://github.com/AIGNE-io/aigne-framework/commit/91961413aea171048a6afae87ffc8dc53e20fca8))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **cli:** alwasy print useage information after agent processed ([58da143](https://github.com/AIGNE-io/aigne-framework/commit/58da143329a6748005c7812723c6b3f986e07e08))
|
|
14
|
+
* **cli:** clean app folder before upgrade ([#362](https://github.com/AIGNE-io/aigne-framework/issues/362)) ([0553c50](https://github.com/AIGNE-io/aigne-framework/commit/0553c504f5d0a446397bdccb20c91921cc618167))
|
|
15
|
+
* **cli:** improve feedback in AIGNE Hub commands ([#361](https://github.com/AIGNE-io/aigne-framework/issues/361)) ([ff29a4b](https://github.com/AIGNE-io/aigne-framework/commit/ff29a4b3c7bb828ef9894482586c8c4df41a2122))
|
|
16
|
+
* **cli:** improve markdown terminal theme styling ([#360](https://github.com/AIGNE-io/aigne-framework/issues/360)) ([dc9efbb](https://github.com/AIGNE-io/aigne-framework/commit/dc9efbb477e6792f51090c4fdd6e129e90821263))
|
|
17
|
+
* **cli:** log only once in loadAIGNE ([#357](https://github.com/AIGNE-io/aigne-framework/issues/357)) ([6e6d968](https://github.com/AIGNE-io/aigne-framework/commit/6e6d96814fbc87f210522ae16daf94c1f84f311a))
|
|
18
|
+
* **cli:** prevent multiple simultaneous buy credits prompts ([#363](https://github.com/AIGNE-io/aigne-framework/issues/363)) ([b8fb459](https://github.com/AIGNE-io/aigne-framework/commit/b8fb459261fe327bcc9bfb4d163e66863cb797ec))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Dependencies
|
|
22
|
+
|
|
23
|
+
* The following workspace dependencies were updated
|
|
24
|
+
* dependencies
|
|
25
|
+
* @aigne/agent-library bumped to 1.21.20
|
|
26
|
+
* @aigne/agentic-memory bumped to 1.0.20
|
|
27
|
+
* @aigne/aigne-hub bumped to 0.5.2
|
|
28
|
+
* @aigne/core bumped to 1.50.0
|
|
29
|
+
* @aigne/default-memory bumped to 1.1.2
|
|
30
|
+
* @aigne/openai bumped to 0.11.2
|
|
31
|
+
|
|
3
32
|
## [1.35.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.35.0...cli-v1.35.1) (2025-08-13)
|
|
4
33
|
|
|
5
34
|
|
package/dist/commands/aigne.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
1
|
import yargs from "yargs";
|
|
3
2
|
import { AIGNE_CLI_VERSION } from "../constants.js";
|
|
4
3
|
import { asciiLogo } from "../utils/ascii-logo.js";
|
|
@@ -11,7 +10,6 @@ import { createServeMCPCommand } from "./serve-mcp.js";
|
|
|
11
10
|
import { createTestCommand } from "./test.js";
|
|
12
11
|
export function createAIGNECommand(options) {
|
|
13
12
|
console.log(asciiLogo);
|
|
14
|
-
console.log(`${chalk.grey("TIPS:")} run ${chalk.cyan("aigne observe")} to start the observability server.\n`);
|
|
15
13
|
return yargs()
|
|
16
14
|
.scriptName("aigne")
|
|
17
15
|
.usage("CLI for AIGNE framework")
|
package/dist/commands/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
-
import { readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { extname, join } from "node:path";
|
|
6
6
|
import { isatty } from "node:tty";
|
|
@@ -216,13 +216,21 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
|
|
|
216
216
|
title: `Downloading ${name}`,
|
|
217
217
|
skip: (ctx) => ctx.version === check?.version,
|
|
218
218
|
task: async (ctx) => {
|
|
219
|
+
await rm(dir, { force: true, recursive: true });
|
|
220
|
+
await mkdir(dir, { recursive: true });
|
|
219
221
|
await downloadAndExtract(ctx.url, dir, { strip: 1 });
|
|
220
222
|
},
|
|
221
223
|
},
|
|
222
224
|
{
|
|
223
225
|
title: "Installing dependencies",
|
|
224
|
-
task: async () => {
|
|
225
|
-
await installDependencies(dir
|
|
226
|
+
task: async (_, task) => {
|
|
227
|
+
await installDependencies(dir, {
|
|
228
|
+
log: (log) => {
|
|
229
|
+
const last = log.split("\n").findLast((i) => !!i);
|
|
230
|
+
if (last)
|
|
231
|
+
task.output = last;
|
|
232
|
+
},
|
|
233
|
+
});
|
|
226
234
|
},
|
|
227
235
|
},
|
|
228
236
|
], {
|
|
@@ -252,12 +260,20 @@ async function isInstallationAvailable(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TI
|
|
|
252
260
|
const available = installedAt ? now - installedAt < cacheTimeMs : false;
|
|
253
261
|
return { version, available };
|
|
254
262
|
}
|
|
255
|
-
async function installDependencies(dir) {
|
|
263
|
+
async function installDependencies(dir, { log } = {}) {
|
|
256
264
|
await new Promise((resolve, reject) => {
|
|
257
|
-
const child = spawn("npm", ["install", "--omit", "dev"
|
|
265
|
+
const child = spawn("npm", ["install", "--omit", "dev", "--verbose"], {
|
|
266
|
+
cwd: dir,
|
|
267
|
+
stdio: "pipe",
|
|
268
|
+
});
|
|
269
|
+
child.stdout.on("data", (data) => {
|
|
270
|
+
log?.(data.toString());
|
|
271
|
+
});
|
|
258
272
|
let stderr = "";
|
|
259
273
|
child.stderr.on("data", (data) => {
|
|
260
|
-
|
|
274
|
+
const str = data.toString();
|
|
275
|
+
log?.(str);
|
|
276
|
+
stderr += str;
|
|
261
277
|
});
|
|
262
278
|
child.on("error", (error) => reject(error));
|
|
263
279
|
child.on("exit", (code) => {
|
package/dist/commands/hub.js
CHANGED
|
@@ -24,13 +24,19 @@ function printHubStatus(data) {
|
|
|
24
24
|
console.log(` ${chalk.bold("DID:".padEnd(8))} ${data.user.did}`);
|
|
25
25
|
console.log(` ${chalk.bold("Email:".padEnd(8))} ${data.user.email}`);
|
|
26
26
|
console.log("");
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
if (data.enableCredit) {
|
|
28
|
+
console.log(chalk.bold("Credits:"));
|
|
29
|
+
console.log(` ${chalk.bold("Used:".padEnd(8))} ${data.credits.used.toLocaleString()}`);
|
|
30
|
+
console.log(` ${chalk.bold("Total:".padEnd(8))} ${data.credits.total.toLocaleString()}`);
|
|
31
|
+
console.log("");
|
|
32
|
+
console.log(chalk.bold("Links:"));
|
|
33
|
+
if (data.links.payment) {
|
|
34
|
+
console.log(` ${chalk.bold("Payment:".padEnd(8))} ${data.links.payment}`);
|
|
35
|
+
}
|
|
36
|
+
if (data.links.profile) {
|
|
37
|
+
console.log(` ${chalk.bold("Profile:".padEnd(8))} ${data.links.profile}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
async function getHubs() {
|
|
36
42
|
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
@@ -61,29 +67,26 @@ const getDefaultHub = async () => {
|
|
|
61
67
|
};
|
|
62
68
|
async function formatHubsList(statusList) {
|
|
63
69
|
if (statusList?.length === 0) {
|
|
64
|
-
console.log(chalk.yellow("No AIGNE Hub
|
|
70
|
+
console.log(chalk.yellow("No AIGNE Hub connected."));
|
|
65
71
|
console.log("Use 'aigne hub connect' to connect to a hub.");
|
|
66
72
|
return;
|
|
67
73
|
}
|
|
68
74
|
const defaultHub = await getDefaultHub();
|
|
69
75
|
const table = new Table({
|
|
70
|
-
head: ["URL", "ACTIVE"
|
|
71
|
-
colWidths: [
|
|
76
|
+
head: ["URL", "ACTIVE"],
|
|
77
|
+
colWidths: [70, 10],
|
|
72
78
|
style: {
|
|
73
79
|
head: ["cyan"],
|
|
74
80
|
border: ["grey"],
|
|
75
81
|
},
|
|
76
82
|
});
|
|
77
|
-
console.log(chalk.blue("AIGNE Hubs:\n"));
|
|
83
|
+
console.log(chalk.blue("Connected AIGNE Hubs:\n"));
|
|
78
84
|
for (const status of statusList) {
|
|
79
85
|
const isConnected = new URL(status.apiUrl).origin === new URL(defaultHub).origin;
|
|
80
|
-
table.push([
|
|
81
|
-
status.apiUrl,
|
|
82
|
-
isConnected ? "*" : "-",
|
|
83
|
-
isConnected ? "Connected" : "Not connected",
|
|
84
|
-
]);
|
|
86
|
+
table.push([status.apiUrl, isConnected ? "YES" : "NO"]);
|
|
85
87
|
}
|
|
86
88
|
console.log(table.toString());
|
|
89
|
+
console.log(chalk.blue("Use 'aigne hub use' to switch to a different hub."));
|
|
87
90
|
}
|
|
88
91
|
export function createHubCommand() {
|
|
89
92
|
return {
|
|
@@ -91,7 +94,23 @@ export function createHubCommand() {
|
|
|
91
94
|
describe: "Manage AIGNE Hub connections",
|
|
92
95
|
builder: (yargs) => yargs
|
|
93
96
|
.command(["list", "ls"], "List all connected AIGNE Hubs", listHubs)
|
|
94
|
-
.command(
|
|
97
|
+
.command({
|
|
98
|
+
command: "connect [url]",
|
|
99
|
+
describe: "Connect to an AIGNE Hub",
|
|
100
|
+
builder: (yargs) => yargs.positional("url", {
|
|
101
|
+
type: "string",
|
|
102
|
+
describe: "The URL of the AIGNE Hub to connect to",
|
|
103
|
+
default: null,
|
|
104
|
+
}),
|
|
105
|
+
handler: (args) => {
|
|
106
|
+
if (args.url) {
|
|
107
|
+
saveAndConnect(args.url);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
connectHub();
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
})
|
|
95
114
|
.command("use", "Switch to a different AIGNE Hub", useHub)
|
|
96
115
|
.command(["status", "st"], "Show current active hub", showStatus)
|
|
97
116
|
.command(["remove", "rm"], "Remove a connected hub", removeHub)
|
|
@@ -131,7 +150,7 @@ async function connectHub() {
|
|
|
131
150
|
async function useHub() {
|
|
132
151
|
const hubs = await getHubs();
|
|
133
152
|
if (!hubs.length) {
|
|
134
|
-
console.log(chalk.yellow("No AIGNE Hub
|
|
153
|
+
console.log(chalk.yellow("No AIGNE Hub connected."));
|
|
135
154
|
return;
|
|
136
155
|
}
|
|
137
156
|
const { hubApiKey } = await inquirer.prompt({
|
|
@@ -156,7 +175,7 @@ async function showStatus() {
|
|
|
156
175
|
async function removeHub() {
|
|
157
176
|
const hubs = await getHubs();
|
|
158
177
|
if (!hubs.length) {
|
|
159
|
-
console.log(chalk.yellow("No AIGNE Hub
|
|
178
|
+
console.log(chalk.yellow("No AIGNE Hub connected."));
|
|
160
179
|
return;
|
|
161
180
|
}
|
|
162
181
|
const { hubApiKey } = await inquirer.prompt({
|
|
@@ -173,7 +192,7 @@ async function removeHub() {
|
|
|
173
192
|
async function showInfo() {
|
|
174
193
|
const hubs = await getHubs();
|
|
175
194
|
if (!hubs.length) {
|
|
176
|
-
console.log(chalk.yellow("No AIGNE Hub
|
|
195
|
+
console.log(chalk.yellow("No AIGNE Hub connected."));
|
|
177
196
|
return;
|
|
178
197
|
}
|
|
179
198
|
const { hubApiKey } = await inquirer.prompt({
|
|
@@ -267,5 +286,6 @@ async function printHubDetails(url) {
|
|
|
267
286
|
payment: userInfo?.paymentLink || "",
|
|
268
287
|
profile: userInfo?.profileLink || "",
|
|
269
288
|
},
|
|
289
|
+
enableCredit: userInfo?.enableCredit || false,
|
|
270
290
|
});
|
|
271
291
|
}
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
|
@@ -4,3 +4,4 @@ import { DefaultMemory } from "@aigne/default-memory";
|
|
|
4
4
|
const require = createRequire(import.meta.url);
|
|
5
5
|
export const AIGNE_CLI_VERSION = require("../package.json").version;
|
|
6
6
|
export const availableMemories = [DefaultMemory, AgenticMemory];
|
|
7
|
+
export const AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE = "NOT_ENOUGH";
|
|
@@ -4,7 +4,6 @@ import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
|
|
|
4
4
|
import { type Listr } from "@aigne/listr2";
|
|
5
5
|
import { type AIGNEListrTaskWrapper } from "../utils/listr.js";
|
|
6
6
|
export interface TerminalTracerOptions {
|
|
7
|
-
printRequest?: boolean;
|
|
8
7
|
outputKey?: string;
|
|
9
8
|
}
|
|
10
9
|
export declare class TerminalTracer {
|
|
@@ -16,6 +15,10 @@ export declare class TerminalTracer {
|
|
|
16
15
|
result: Message;
|
|
17
16
|
context: Context<import("@aigne/core").UserContext>;
|
|
18
17
|
}>;
|
|
18
|
+
private listr?;
|
|
19
|
+
private proxiedPrompts;
|
|
20
|
+
private buyCreditsPromptPromise;
|
|
21
|
+
private promptBuyCredits;
|
|
19
22
|
formatTokenUsage(usage: Partial<ContextUsage>, extra?: {
|
|
20
23
|
[key: string]: string;
|
|
21
24
|
}): string;
|
package/dist/tracer/terminal.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { EOL } from "node:os";
|
|
2
2
|
import { inspect } from "node:util";
|
|
3
3
|
import { AIAgent, ChatModel, DEFAULT_OUTPUT_KEY, UserAgent, } from "@aigne/core";
|
|
4
|
-
import { LogLevel, logger } from "@aigne/core/utils/logger.js";
|
|
5
4
|
import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
|
|
6
5
|
import { flat, omit } from "@aigne/core/utils/type-utils.js";
|
|
7
6
|
import { figures } from "@aigne/listr2";
|
|
@@ -9,6 +8,7 @@ import { markedTerminal } from "@aigne/marked-terminal";
|
|
|
9
8
|
import * as prompts from "@inquirer/prompts";
|
|
10
9
|
import chalk from "chalk";
|
|
11
10
|
import { Marked } from "marked";
|
|
11
|
+
import { AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE } from "../constants.js";
|
|
12
12
|
import { AIGNEListr, AIGNEListrRenderer } from "../utils/listr.js";
|
|
13
13
|
import { highlightUrl } from "../utils/string-utils.js";
|
|
14
14
|
import { parseDuration } from "../utils/time.js";
|
|
@@ -24,29 +24,10 @@ export class TerminalTracer {
|
|
|
24
24
|
await this.context.observer?.serve();
|
|
25
25
|
const context = this.context.newContext({ reset: true });
|
|
26
26
|
const listr = new AIGNEListr({
|
|
27
|
-
formatRequest: (options) => this.options
|
|
28
|
-
? this.formatRequest(agent, context, input, options)
|
|
29
|
-
: undefined,
|
|
27
|
+
formatRequest: (options) => this.formatRequest(agent, context, input, options),
|
|
30
28
|
formatResult: (result, options) => [this.formatResult(agent, context, result, options)].filter(Boolean),
|
|
31
29
|
}, [], { concurrent: true });
|
|
32
|
-
|
|
33
|
-
get: (_target, prop) => {
|
|
34
|
-
// biome-ignore lint/performance/noDynamicNamespaceImportAccess: we need to access prompts dynamically
|
|
35
|
-
const method = prompts[prop];
|
|
36
|
-
if (typeof method !== "function")
|
|
37
|
-
return undefined;
|
|
38
|
-
return async (config) => {
|
|
39
|
-
const renderer = listr["renderer"] instanceof AIGNEListrRenderer ? listr["renderer"] : undefined;
|
|
40
|
-
await renderer?.pause();
|
|
41
|
-
try {
|
|
42
|
-
return await method({ ...config });
|
|
43
|
-
}
|
|
44
|
-
finally {
|
|
45
|
-
await renderer?.resume();
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
},
|
|
49
|
-
});
|
|
30
|
+
this.listr = listr;
|
|
50
31
|
const onStart = async ({ context, agent, ...event }) => {
|
|
51
32
|
if (agent instanceof UserAgent)
|
|
52
33
|
return;
|
|
@@ -80,7 +61,7 @@ export class TerminalTracer {
|
|
|
80
61
|
else {
|
|
81
62
|
listr.add(listrTask);
|
|
82
63
|
}
|
|
83
|
-
return { options: { prompts: proxiedPrompts } };
|
|
64
|
+
return { options: { prompts: this.proxiedPrompts } };
|
|
84
65
|
};
|
|
85
66
|
const onSuccess = async ({ context, agent, output, ...event }) => {
|
|
86
67
|
const contextId = context.id;
|
|
@@ -109,20 +90,8 @@ export class TerminalTracer {
|
|
|
109
90
|
task.resolve();
|
|
110
91
|
};
|
|
111
92
|
const onError = async ({ context, agent, error, ...event }) => {
|
|
112
|
-
if ("type" in error && error.type ===
|
|
113
|
-
const retry = await
|
|
114
|
-
message: highlightUrl(error.message),
|
|
115
|
-
choices: [
|
|
116
|
-
{
|
|
117
|
-
name: "I have bought some credits, try again",
|
|
118
|
-
value: "retry",
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
name: "Exit",
|
|
122
|
-
value: "exit",
|
|
123
|
-
},
|
|
124
|
-
],
|
|
125
|
-
});
|
|
93
|
+
if ("type" in error && error.type === AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE) {
|
|
94
|
+
const retry = await this.promptBuyCredits(error);
|
|
126
95
|
console.log("");
|
|
127
96
|
if (retry === "retry") {
|
|
128
97
|
return { retry: true };
|
|
@@ -145,6 +114,7 @@ export class TerminalTracer {
|
|
|
145
114
|
const result = await listr.run(() => context.invoke(agent, input, {
|
|
146
115
|
...options,
|
|
147
116
|
hooks: flat({
|
|
117
|
+
priority: "high",
|
|
148
118
|
onStart,
|
|
149
119
|
onSuccess,
|
|
150
120
|
onError,
|
|
@@ -154,6 +124,51 @@ export class TerminalTracer {
|
|
|
154
124
|
}));
|
|
155
125
|
return { result, context };
|
|
156
126
|
}
|
|
127
|
+
listr;
|
|
128
|
+
proxiedPrompts = new Proxy({}, {
|
|
129
|
+
get: (_target, prop) => {
|
|
130
|
+
// biome-ignore lint/performance/noDynamicNamespaceImportAccess: we need to access prompts dynamically
|
|
131
|
+
const method = prompts[prop];
|
|
132
|
+
if (typeof method !== "function")
|
|
133
|
+
return undefined;
|
|
134
|
+
return async (config) => {
|
|
135
|
+
const renderer = this.listr?.["renderer"] instanceof AIGNEListrRenderer
|
|
136
|
+
? this.listr["renderer"]
|
|
137
|
+
: undefined;
|
|
138
|
+
await renderer?.pause();
|
|
139
|
+
try {
|
|
140
|
+
return await method({ ...config });
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await renderer?.resume();
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
buyCreditsPromptPromise;
|
|
149
|
+
async promptBuyCredits(error) {
|
|
150
|
+
// Avoid multiple agents asking for credits, we will only show the prompt once
|
|
151
|
+
this.buyCreditsPromptPromise ??= (async () => {
|
|
152
|
+
const retry = await this.proxiedPrompts.select({
|
|
153
|
+
message: highlightUrl(error.message),
|
|
154
|
+
choices: [
|
|
155
|
+
{
|
|
156
|
+
name: "I have bought some credits, try again",
|
|
157
|
+
value: "retry",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "Exit",
|
|
161
|
+
value: "exit",
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
});
|
|
165
|
+
return retry;
|
|
166
|
+
})();
|
|
167
|
+
return this.buyCreditsPromptPromise.finally(() => {
|
|
168
|
+
// Clear the promise so that we can show the prompt again if needed
|
|
169
|
+
this.buyCreditsPromptPromise = undefined;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
157
172
|
formatTokenUsage(usage, extra) {
|
|
158
173
|
const items = [
|
|
159
174
|
[chalk.yellow(usage.inputTokens), chalk.grey("input tokens")],
|
|
@@ -192,13 +207,15 @@ export class TerminalTracer {
|
|
|
192
207
|
}
|
|
193
208
|
}
|
|
194
209
|
},
|
|
195
|
-
}, markedTerminal({ forceHyperLink: false }
|
|
210
|
+
}, markedTerminal({ forceHyperLink: false }, {
|
|
211
|
+
theme: {
|
|
212
|
+
string: chalk.green,
|
|
213
|
+
},
|
|
214
|
+
}));
|
|
196
215
|
get outputKey() {
|
|
197
216
|
return this.options.outputKey || DEFAULT_OUTPUT_KEY;
|
|
198
217
|
}
|
|
199
218
|
formatRequest(agent, _context, m = {}, { running = false } = {}) {
|
|
200
|
-
if (!logger.enabled(LogLevel.INFO))
|
|
201
|
-
return;
|
|
202
219
|
const prefix = `${chalk.grey(figures.pointer)} 💬 `;
|
|
203
220
|
const inputKey = agent instanceof AIAgent ? agent.inputKey : undefined;
|
|
204
221
|
const msg = inputKey ? m[inputKey] : undefined;
|
|
@@ -207,14 +224,15 @@ export class TerminalTracer {
|
|
|
207
224
|
const json = Object.keys(message).length > 0
|
|
208
225
|
? inspect(message, { colors: true, ...(running ? this.runningInspectOptions : undefined) })
|
|
209
226
|
: undefined;
|
|
210
|
-
|
|
227
|
+
const r = [text, json].filter(Boolean).join(EOL).trim();
|
|
228
|
+
if (!r)
|
|
229
|
+
return undefined;
|
|
230
|
+
return `${prefix}${r}`;
|
|
211
231
|
}
|
|
212
232
|
formatResult(agent, context, m = {}, { running = false } = {}) {
|
|
213
233
|
const { isTTY } = process.stdout;
|
|
214
234
|
const outputKey = this.outputKey || (agent instanceof AIAgent ? agent.outputKey : undefined);
|
|
215
|
-
const prefix =
|
|
216
|
-
? `${chalk.grey(figures.tick)} 🤖 ${this.formatTokenUsage(context.usage)}`
|
|
217
|
-
: null;
|
|
235
|
+
const prefix = `${chalk.grey(figures.tick)} 🤖 ${this.formatTokenUsage(context.usage)}`;
|
|
218
236
|
const msg = outputKey ? m[outputKey] : undefined;
|
|
219
237
|
const message = outputKey ? omit(m, outputKey) : m;
|
|
220
238
|
const text = msg && typeof msg === "string"
|
|
@@ -225,7 +243,7 @@ export class TerminalTracer {
|
|
|
225
243
|
const json = Object.keys(message).length > 0
|
|
226
244
|
? inspect(message, { colors: isTTY, ...(running ? this.runningInspectOptions : undefined) })
|
|
227
245
|
: undefined;
|
|
228
|
-
return [prefix, text, json].filter(Boolean).join(EOL);
|
|
246
|
+
return [prefix, text, json].filter(Boolean).join(EOL.repeat(2));
|
|
229
247
|
}
|
|
230
248
|
runningInspectOptions = {
|
|
231
249
|
maxArrayLength: 3,
|
package/dist/utils/listr.js
CHANGED
|
@@ -51,11 +51,9 @@ export class AIGNEListr extends Listr {
|
|
|
51
51
|
try {
|
|
52
52
|
this.ctx = {};
|
|
53
53
|
this.spinner.start();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
console.log(request);
|
|
58
|
-
}
|
|
54
|
+
const request = this.myOptions.formatRequest();
|
|
55
|
+
if (request)
|
|
56
|
+
console.log(request);
|
|
59
57
|
logger.logMessage = (...args) => this.logs.push(format(...args));
|
|
60
58
|
for (const method of ["debug", "log", "info", "warn", "error"]) {
|
|
61
59
|
console[method] = (...args) => {
|
package/dist/utils/load-aigne.js
CHANGED
|
@@ -2,14 +2,35 @@ import { existsSync, mkdirSync } from "node:fs";
|
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { AIGNE_ENV_FILE, checkConnectionStatus, AIGNE_HUB_URL as DEFAULT_AIGNE_HUB_URL, formatModelName, loadModel, parseModelOption, } from "@aigne/aigne-hub";
|
|
5
|
+
import { AIGNE_ENV_FILE, checkConnectionStatus, AIGNE_HUB_URL as DEFAULT_AIGNE_HUB_URL, formatModelName, loadModel, maskApiKey, parseModelOption, } from "@aigne/aigne-hub";
|
|
6
6
|
import { AIGNE } from "@aigne/core";
|
|
7
7
|
import { loadAIGNEFile } from "@aigne/core/loader/index.js";
|
|
8
|
+
import boxen from "boxen";
|
|
9
|
+
import chalk from "chalk";
|
|
8
10
|
import inquirer from "inquirer";
|
|
9
11
|
import { parse, stringify } from "yaml";
|
|
10
12
|
import { availableMemories } from "../constants.js";
|
|
11
13
|
const isTest = process.env.CI || process.env.NODE_ENV === "test";
|
|
12
14
|
const mockInquirerPrompt = (() => Promise.resolve({ useAigneHub: true }));
|
|
15
|
+
let printed = false;
|
|
16
|
+
function printChatModelInfoBox(model) {
|
|
17
|
+
if (printed)
|
|
18
|
+
return;
|
|
19
|
+
printed = true;
|
|
20
|
+
const credential = model.getCredential();
|
|
21
|
+
const lines = [`${chalk.cyan("Provider")}: ${chalk.green(model.name.replace("ChatModel", ""))}`];
|
|
22
|
+
if (credential?.model) {
|
|
23
|
+
lines.push(`${chalk.cyan("Model")}: ${chalk.green(credential?.model)}`);
|
|
24
|
+
}
|
|
25
|
+
if (credential?.url) {
|
|
26
|
+
lines.push(`${chalk.cyan("API URL")}: ${chalk.green(credential?.url || "N/A")}`);
|
|
27
|
+
}
|
|
28
|
+
if (credential?.apiKey) {
|
|
29
|
+
lines.push(`${chalk.cyan("API Key")}: ${chalk.green(maskApiKey(credential?.apiKey))}`);
|
|
30
|
+
}
|
|
31
|
+
console.log(boxen(lines.join("\n"), { padding: 1, borderStyle: "classic", borderColor: "cyan" }));
|
|
32
|
+
console.log("");
|
|
33
|
+
}
|
|
13
34
|
async function prepareAIGNEConfig(options, inquirerPromptFn) {
|
|
14
35
|
const aigneDir = join(homedir(), ".aigne");
|
|
15
36
|
if (!existsSync(aigneDir)) {
|
|
@@ -40,6 +61,7 @@ export async function loadAIGNE({ path, options, modelOptions, actionOptions, })
|
|
|
40
61
|
const model = await loadModel(parseModelOption(formattedModelName));
|
|
41
62
|
return await AIGNE.load(path, { loadModel, memories: availableMemories, model });
|
|
42
63
|
}
|
|
64
|
+
console.log(`${chalk.grey("TIPS:")} run ${chalk.cyan("aigne observe")} to start the observability server.\n`);
|
|
43
65
|
const model = await loadModel({
|
|
44
66
|
...parseModelOption(formattedModelName),
|
|
45
67
|
temperature,
|
|
@@ -47,6 +69,9 @@ export async function loadAIGNE({ path, options, modelOptions, actionOptions, })
|
|
|
47
69
|
presencePenalty,
|
|
48
70
|
frequencyPenalty,
|
|
49
71
|
}, modelOptions, { aigneHubUrl: AIGNE_HUB_URL, inquirerPromptFn: actionOptions?.inquirerPromptFn });
|
|
72
|
+
if (model) {
|
|
73
|
+
printChatModelInfoBox(model);
|
|
74
|
+
}
|
|
50
75
|
if (path) {
|
|
51
76
|
return await AIGNE.load(path, { loadModel, memories: availableMemories, model });
|
|
52
77
|
}
|
|
@@ -203,10 +203,7 @@ export async function runAgentWithAIGNE(aigne, agent, { outputKey, chatLoopOptio
|
|
|
203
203
|
});
|
|
204
204
|
return;
|
|
205
205
|
}
|
|
206
|
-
const tracer = new TerminalTracer(aigne.newContext(), {
|
|
207
|
-
printRequest: logger.enabled(LogLevel.INFO),
|
|
208
|
-
outputKey,
|
|
209
|
-
});
|
|
206
|
+
const tracer = new TerminalTracer(aigne.newContext(), { outputKey });
|
|
210
207
|
const { result } = await tracer.run(agent, options.input ?? {});
|
|
211
208
|
if (options.output) {
|
|
212
209
|
const message = result[outputKey || DEFAULT_OUTPUT_KEY];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.0",
|
|
4
4
|
"description": "Your command center for agent development",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@listr2/prompt-adapter-inquirer": "^3.0.1",
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
54
54
|
"@smithy/node-http-handler": "^4.1.0",
|
|
55
|
+
"boxen": "^8.0.1",
|
|
55
56
|
"chalk": "^5.4.1",
|
|
56
57
|
"cli-table3": "^0.6.5",
|
|
57
58
|
"detect-port": "^2.1.0",
|
|
@@ -71,13 +72,13 @@
|
|
|
71
72
|
"yaml": "^2.8.0",
|
|
72
73
|
"yargs": "^18.0.0",
|
|
73
74
|
"zod": "^3.25.67",
|
|
74
|
-
"@aigne/
|
|
75
|
-
"@aigne/agentic-memory": "^1.0.
|
|
76
|
-
"@aigne/
|
|
77
|
-
"@aigne/core": "^1.
|
|
78
|
-
"@aigne/
|
|
79
|
-
"@aigne/openai": "^0.11.
|
|
80
|
-
"@aigne/
|
|
75
|
+
"@aigne/aigne-hub": "^0.5.2",
|
|
76
|
+
"@aigne/agentic-memory": "^1.0.20",
|
|
77
|
+
"@aigne/agent-library": "^1.21.20",
|
|
78
|
+
"@aigne/core": "^1.50.0",
|
|
79
|
+
"@aigne/default-memory": "^1.1.2",
|
|
80
|
+
"@aigne/openai": "^0.11.2",
|
|
81
|
+
"@aigne/observability-api": "^0.9.0"
|
|
81
82
|
},
|
|
82
83
|
"devDependencies": {
|
|
83
84
|
"@types/archiver": "^6.0.3",
|