@aigne/cli 1.5.1-4 → 1.6.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 +14 -0
- package/dist/commands/run.js +5 -1
- package/dist/tracer/terminal.d.ts +0 -6
- package/dist/tracer/terminal.js +26 -48
- package/dist/utils/run-chat-loop.d.ts +0 -1
- package/dist/utils/run-chat-loop.js +0 -5
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.5.1...cli-v1.6.0) (2025-04-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **cli:** add --verbose option for run command ([#82](https://github.com/AIGNE-io/aigne-framework/issues/82)) ([7adf8be](https://github.com/AIGNE-io/aigne-framework/commit/7adf8be34963e714268457ab8b2ffeb945da5721))
|
|
9
|
+
|
|
10
|
+
## [1.5.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.5.0...cli-v1.5.1) (2025-04-22)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* use bunwrapper launch examples ([#79](https://github.com/AIGNE-io/aigne-framework/issues/79)) ([55022e2](https://github.com/AIGNE-io/aigne-framework/commit/55022e20bb253bac608dad3024600da91e093a69))
|
|
16
|
+
|
|
3
17
|
## [1.5.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.4.0...cli-v1.5.0) (2025-04-22)
|
|
4
18
|
|
|
5
19
|
|
package/dist/commands/run.js
CHANGED
|
@@ -4,6 +4,7 @@ import { homedir } from "node:os";
|
|
|
4
4
|
import { isAbsolute, join, resolve } from "node:path";
|
|
5
5
|
import { ExecutionEngine } from "@aigne/core";
|
|
6
6
|
import { loadModel } from "@aigne/core/loader/index.js";
|
|
7
|
+
import { logger } from "@aigne/core/utils/logger.js";
|
|
7
8
|
import { isNonNullable } from "@aigne/core/utils/type-utils.js";
|
|
8
9
|
import { Listr, PRESET_TIMER } from "@aigne/listr2";
|
|
9
10
|
import { Command } from "commander";
|
|
@@ -18,7 +19,10 @@ export function createRunCommand() {
|
|
|
18
19
|
.option("--download-dir <dir>", "Directory to download the package to (defaults to the ~/.aigne/xxx)")
|
|
19
20
|
.option("--model-provider <provider>", "Model provider to use, available providers: openai, claude, xai (defaults to the aigne.yaml definition or openai)")
|
|
20
21
|
.option("--model-name <model>", "Model name to use, available models depend on the provider (defaults to the aigne.yaml definition or gpt-4o-mini)")
|
|
22
|
+
.option("--verbose", "Enable verbose logging", false)
|
|
21
23
|
.action(async (path, options) => {
|
|
24
|
+
if (options.verbose)
|
|
25
|
+
logger.enable("*");
|
|
22
26
|
const { downloadDir, dir } = prepareDirs(path, options);
|
|
23
27
|
const { engine, agent } = await new Listr([
|
|
24
28
|
{
|
|
@@ -78,7 +82,7 @@ export function createRunCommand() {
|
|
|
78
82
|
assert(engine);
|
|
79
83
|
assert(agent);
|
|
80
84
|
const user = engine.call(agent);
|
|
81
|
-
await runChatLoopInTerminal(user
|
|
85
|
+
await runChatLoopInTerminal(user);
|
|
82
86
|
await engine.shutdown();
|
|
83
87
|
})
|
|
84
88
|
.showHelpAfterError(true)
|
|
@@ -3,7 +3,6 @@ import type { ContextUsage } from "@aigne/core/execution-engine/usage";
|
|
|
3
3
|
import { type DefaultRenderer, Listr, type ListrRenderer, type ListrTaskWrapper } from "@aigne/listr2";
|
|
4
4
|
import { promiseWithResolvers } from "../utils/promise-with-resolvers.js";
|
|
5
5
|
export interface TerminalTracerOptions {
|
|
6
|
-
verbose?: boolean;
|
|
7
6
|
aiResponsePrefix?: (context: Context) => string;
|
|
8
7
|
}
|
|
9
8
|
export declare class TerminalTracer {
|
|
@@ -16,11 +15,6 @@ export declare class TerminalTracer {
|
|
|
16
15
|
result: Message;
|
|
17
16
|
context: Context;
|
|
18
17
|
}>;
|
|
19
|
-
protected wrap(str: string): string;
|
|
20
|
-
formatAgentStartedOutput(agent: Agent, data: Message): string;
|
|
21
|
-
formatAgentSucceedOutput(agent: Agent, data: Message): string;
|
|
22
|
-
formatAgentFailedOutput(agent: Agent, data: Error): string;
|
|
23
|
-
formatMessage(data: unknown): string;
|
|
24
18
|
formatTokenUsage(usage: Partial<ContextUsage>, extra?: {
|
|
25
19
|
[key: string]: string;
|
|
26
20
|
}): string;
|
package/dist/tracer/terminal.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { EOL } from "node:os";
|
|
2
|
-
import { inspect } from "node:util";
|
|
2
|
+
import { format, inspect } from "node:util";
|
|
3
3
|
import { ChatModel, MESSAGE_KEY, } from "@aigne/core";
|
|
4
|
+
import { logger } from "@aigne/core/utils/logger.js";
|
|
4
5
|
import { mergeAgentResponseChunk, readableStreamToAsyncIterator, } from "@aigne/core/utils/stream-utils.js";
|
|
5
|
-
import { Listr, ListrDefaultRendererLogLevels, Spinner,
|
|
6
|
+
import { Listr, ListrDefaultRendererLogLevels, Spinner, } from "@aigne/listr2";
|
|
7
|
+
import { markedTerminal } from "@aigne/marked-terminal";
|
|
6
8
|
import chalk from "chalk";
|
|
7
9
|
import { Marked } from "marked";
|
|
8
|
-
import { markedTerminal } from "marked-terminal";
|
|
9
10
|
import wrap from "wrap-ansi";
|
|
10
|
-
import { z } from "zod";
|
|
11
11
|
import { promiseWithResolvers } from "../utils/promise-with-resolvers.js";
|
|
12
12
|
import { parseDuration } from "../utils/time.js";
|
|
13
|
-
const DEBUG_DEPTH = z.number().int().default(2).safeParse(Number(process.env.DEBUG_DEPTH)).data;
|
|
14
13
|
export class TerminalTracer {
|
|
15
14
|
context;
|
|
16
15
|
options;
|
|
@@ -25,14 +24,11 @@ export class TerminalTracer {
|
|
|
25
24
|
const context = this.context.newContext({ reset: true });
|
|
26
25
|
const listr = new AIGNEListr({
|
|
27
26
|
formatResult: (result) => {
|
|
28
|
-
return [
|
|
29
|
-
this.wrap(this.options.aiResponsePrefix?.(context) || ""),
|
|
30
|
-
this.wrap(this.formatAIResponse(result)),
|
|
31
|
-
];
|
|
27
|
+
return [this.options.aiResponsePrefix?.(context) || "", this.formatAIResponse(result)];
|
|
32
28
|
},
|
|
33
29
|
}, [], {
|
|
34
30
|
concurrent: true,
|
|
35
|
-
forceTTY:
|
|
31
|
+
forceTTY: true,
|
|
36
32
|
rendererOptions: {
|
|
37
33
|
collapseSubtasks: false,
|
|
38
34
|
writeBottomBarDirectly: true,
|
|
@@ -42,7 +38,7 @@ export class TerminalTracer {
|
|
|
42
38
|
},
|
|
43
39
|
},
|
|
44
40
|
});
|
|
45
|
-
const onAgentStarted = async ({ contextId, parentContextId, agent,
|
|
41
|
+
const onAgentStarted = async ({ contextId, parentContextId, agent, timestamp, }) => {
|
|
46
42
|
const task = {
|
|
47
43
|
...promiseWithResolvers(),
|
|
48
44
|
listr: promiseWithResolvers(),
|
|
@@ -71,10 +67,6 @@ export class TerminalTracer {
|
|
|
71
67
|
else {
|
|
72
68
|
listr.add(listrTask);
|
|
73
69
|
}
|
|
74
|
-
const { taskWrapper } = await task.listr.promise;
|
|
75
|
-
if (this.options.verbose) {
|
|
76
|
-
taskWrapper.output = this.formatAgentStartedOutput(agent, input);
|
|
77
|
-
}
|
|
78
70
|
};
|
|
79
71
|
const onAgentSucceed = async ({ agent, contextId, parentContextId, output, timestamp, }) => {
|
|
80
72
|
const task = this.tasks[contextId];
|
|
@@ -90,9 +82,6 @@ export class TerminalTracer {
|
|
|
90
82
|
task.extraTitleMetadata.model = model;
|
|
91
83
|
}
|
|
92
84
|
taskWrapper.title = this.formatTaskTitle(agent, { task, usage: true, time: true });
|
|
93
|
-
if (this.options.verbose) {
|
|
94
|
-
taskWrapper.output = this.formatAgentSucceedOutput(agent, output);
|
|
95
|
-
}
|
|
96
85
|
if (!parentContextId || !this.tasks[parentContextId]) {
|
|
97
86
|
Object.assign(ctx, output);
|
|
98
87
|
}
|
|
@@ -105,7 +94,6 @@ export class TerminalTracer {
|
|
|
105
94
|
task.endTime = timestamp;
|
|
106
95
|
const { taskWrapper } = await task.listr.promise;
|
|
107
96
|
taskWrapper.title = this.formatTaskTitle(agent, { task, usage: true, time: true });
|
|
108
|
-
taskWrapper.output = this.formatAgentFailedOutput(agent, error);
|
|
109
97
|
task.reject(error);
|
|
110
98
|
};
|
|
111
99
|
context.on("agentStarted", onAgentStarted);
|
|
@@ -123,30 +111,6 @@ export class TerminalTracer {
|
|
|
123
111
|
context.off("agentFailed", onAgentFailed);
|
|
124
112
|
}
|
|
125
113
|
}
|
|
126
|
-
wrap(str) {
|
|
127
|
-
return wrap(str, process.stdout.columns ?? 80, {
|
|
128
|
-
hard: true,
|
|
129
|
-
trim: false,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
formatAgentStartedOutput(agent, data) {
|
|
133
|
-
return `\
|
|
134
|
-
${chalk.grey(figures.pointer)} call agent ${agent.name} started with input:
|
|
135
|
-
${this.formatMessage(data)}`;
|
|
136
|
-
}
|
|
137
|
-
formatAgentSucceedOutput(agent, data) {
|
|
138
|
-
return `\
|
|
139
|
-
${chalk.grey(figures.tick)} call agent ${agent.name} succeed with output:
|
|
140
|
-
${this.formatMessage(data)}`;
|
|
141
|
-
}
|
|
142
|
-
formatAgentFailedOutput(agent, data) {
|
|
143
|
-
return `\
|
|
144
|
-
${chalk.grey(figures.cross)} call agent ${agent.name} failed with error:
|
|
145
|
-
${this.formatMessage(data)}`;
|
|
146
|
-
}
|
|
147
|
-
formatMessage(data) {
|
|
148
|
-
return inspect(data, { colors: true, depth: DEBUG_DEPTH });
|
|
149
|
-
}
|
|
150
114
|
formatTokenUsage(usage, extra) {
|
|
151
115
|
const items = [
|
|
152
116
|
[chalk.yellow(usage.inputTokens), chalk.grey("input tokens")],
|
|
@@ -173,7 +137,7 @@ ${this.formatMessage(data)}`;
|
|
|
173
137
|
title += ` ${this.formatTimeUsage(task.startTime, task.endTime)}`;
|
|
174
138
|
return title;
|
|
175
139
|
}
|
|
176
|
-
marked = new Marked().use(markedTerminal());
|
|
140
|
+
marked = new Marked().use(markedTerminal({ forceHyperLink: false }));
|
|
177
141
|
formatAIResponse({ [MESSAGE_KEY]: msg, ...message } = {}) {
|
|
178
142
|
const text = msg && typeof msg === "string" ? this.marked.parse(msg, { async: false }).trim() : undefined;
|
|
179
143
|
const json = Object.keys(message).length > 0 ? inspect(message, { colors: true }) : undefined;
|
|
@@ -184,6 +148,7 @@ class AIGNEListr extends Listr {
|
|
|
184
148
|
myOptions;
|
|
185
149
|
result = {};
|
|
186
150
|
isStreamRunning = false;
|
|
151
|
+
logs = [];
|
|
187
152
|
constructor(myOptions, ...args) {
|
|
188
153
|
super(...args);
|
|
189
154
|
this.myOptions = myOptions;
|
|
@@ -197,17 +162,24 @@ class AIGNEListr extends Listr {
|
|
|
197
162
|
"",
|
|
198
163
|
tasks,
|
|
199
164
|
"",
|
|
200
|
-
...
|
|
165
|
+
...this.myOptions.formatResult(this.result).map((i) => this.wrap(i)),
|
|
201
166
|
this.isStreamRunning ? spinner.fetch() : "",
|
|
202
167
|
];
|
|
203
|
-
return [l.join(EOL), output];
|
|
168
|
+
return [l.join(EOL), [output, ...this.logs.splice(0)].filter(Boolean).join(EOL)];
|
|
204
169
|
};
|
|
205
170
|
// @ts-ignore initialize the renderer
|
|
206
171
|
this.renderer = renderer;
|
|
207
172
|
}
|
|
208
173
|
async run(stream) {
|
|
209
|
-
|
|
210
|
-
|
|
174
|
+
const originalLog = logger.log;
|
|
175
|
+
try {
|
|
176
|
+
logger.log = (...args) => this.logs.push(format(...args));
|
|
177
|
+
this.add({ task: () => this.extractStream(stream) });
|
|
178
|
+
return await super.run().then(() => ({ ...this.result }));
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
logger.log = originalLog;
|
|
182
|
+
}
|
|
211
183
|
}
|
|
212
184
|
async extractStream(stream) {
|
|
213
185
|
this.isStreamRunning = true;
|
|
@@ -218,4 +190,10 @@ class AIGNEListr extends Listr {
|
|
|
218
190
|
this.isStreamRunning = false;
|
|
219
191
|
return this.result;
|
|
220
192
|
}
|
|
193
|
+
wrap(str) {
|
|
194
|
+
return wrap(str, process.stdout.columns ?? 80, {
|
|
195
|
+
hard: true,
|
|
196
|
+
trim: false,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
221
199
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { createMessage } from "@aigne/core";
|
|
2
|
-
import { logger } from "@aigne/core/utils/logger.js";
|
|
3
2
|
import { figures } from "@aigne/listr2";
|
|
4
3
|
import chalk from "chalk";
|
|
5
4
|
import inquirer from "inquirer";
|
|
6
5
|
import { TerminalTracer } from "../tracer/terminal.js";
|
|
7
6
|
export async function runChatLoopInTerminal(userAgent, options = {}) {
|
|
8
7
|
const { initialCall = process.env.INITIAL_CALL, skipLoop = process.env.SKIP_LOOP === "true" } = options;
|
|
9
|
-
options.verbose ??= logger.enabled("aigne:core");
|
|
10
|
-
// Disable the logger, use TerminalTracer instead
|
|
11
|
-
logger.disable();
|
|
12
8
|
let prompt;
|
|
13
9
|
if (options?.welcome)
|
|
14
10
|
console.log(options.welcome);
|
|
@@ -49,7 +45,6 @@ export async function runChatLoopInTerminal(userAgent, options = {}) {
|
|
|
49
45
|
}
|
|
50
46
|
async function callAgent(userAgent, input, options) {
|
|
51
47
|
const tracer = new TerminalTracer(userAgent.context, {
|
|
52
|
-
verbose: options.verbose,
|
|
53
48
|
aiResponsePrefix: (context) => {
|
|
54
49
|
return `${chalk.grey(figures.tick)} 🤖 ${tracer.formatTokenUsage(context.usage)}`;
|
|
55
50
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "cli for AIGNE framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@aigne/listr2": "^1.0.8",
|
|
39
|
+
"@aigne/marked-terminal": "^7.3.1",
|
|
39
40
|
"@modelcontextprotocol/sdk": "^1.9.0",
|
|
40
41
|
"chalk": "^5.4.1",
|
|
41
42
|
"commander": "^13.1.0",
|
|
@@ -44,7 +45,6 @@
|
|
|
44
45
|
"gradient-string": "^3.0.0",
|
|
45
46
|
"inquirer": "^12.5.2",
|
|
46
47
|
"marked": "^15.0.9",
|
|
47
|
-
"marked-terminal": "^7.3.0",
|
|
48
48
|
"openai": "^4.94.0",
|
|
49
49
|
"prettier": "^3.5.3",
|
|
50
50
|
"pretty-error": "^4.0.0",
|