@aigne/cli 1.28.0 → 1.30.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 +53 -0
- package/dist/commands/aigne.js +2 -0
- package/dist/commands/app.d.ts +4 -1
- package/dist/commands/app.js +48 -18
- package/dist/commands/connect.d.ts +7 -0
- package/dist/commands/connect.js +14 -5
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -76
- package/dist/utils/load-aigne.d.ts +7 -3
- package/dist/utils/load-aigne.js +41 -33
- package/dist/utils/run-with-aigne.js +8 -4
- package/package.json +8 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.30.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.29.0...cli-v1.30.0) (2025-08-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **cli:** add `--model` option for aigne applications ([#302](https://github.com/AIGNE-io/aigne-framework/issues/302)) ([5d63743](https://github.com/AIGNE-io/aigne-framework/commit/5d63743b8a47be64fd49245983f4f2f9da3197a0))
|
|
9
|
+
* **cli:** add `upgrade` command for aigne app ([#299](https://github.com/AIGNE-io/aigne-framework/issues/299)) ([1bf461a](https://github.com/AIGNE-io/aigne-framework/commit/1bf461ab644b2d810ef81cd3092475496dfc7ddc))
|
|
10
|
+
* support google model and skip check mode when connected to Hub ([#300](https://github.com/AIGNE-io/aigne-framework/issues/300)) ([e992c0f](https://github.com/AIGNE-io/aigne-framework/commit/e992c0f3335a7c512fa807d5b8ad10c9c3bf2351))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **cli:** indicator not responsive in macos terminal ([#304](https://github.com/AIGNE-io/aigne-framework/issues/304)) ([336f75b](https://github.com/AIGNE-io/aigne-framework/commit/336f75b8a7dfaf28d78e9a4cfcb4ac8c6a29c469))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Dependencies
|
|
19
|
+
|
|
20
|
+
* The following workspace dependencies were updated
|
|
21
|
+
* dependencies
|
|
22
|
+
* @aigne/agent-library bumped to 1.21.9
|
|
23
|
+
* @aigne/agentic-memory bumped to 1.0.9
|
|
24
|
+
* @aigne/aigne-hub bumped to 0.4.0
|
|
25
|
+
* @aigne/openai bumped to 0.10.9
|
|
26
|
+
* @aigne/core bumped to 1.42.0
|
|
27
|
+
* @aigne/default-memory bumped to 1.0.9
|
|
28
|
+
* @aigne/observability-api bumped to 0.9.0
|
|
29
|
+
|
|
30
|
+
## [1.29.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.28.0...cli-v1.29.0) (2025-07-31)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Features
|
|
34
|
+
|
|
35
|
+
* **cli:** add alias support for agent ([#297](https://github.com/AIGNE-io/aigne-framework/issues/297)) ([fa166ab](https://github.com/AIGNE-io/aigne-framework/commit/fa166ab66d19e89ddd32c34e1470450eb4fbdbbd))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Dependencies
|
|
39
|
+
|
|
40
|
+
* The following workspace dependencies were updated
|
|
41
|
+
* dependencies
|
|
42
|
+
* @aigne/agent-library bumped to 1.21.8
|
|
43
|
+
* @aigne/agentic-memory bumped to 1.0.8
|
|
44
|
+
* @aigne/aigne-hub bumped to 0.3.2
|
|
45
|
+
* @aigne/anthropic bumped to 0.10.4
|
|
46
|
+
* @aigne/bedrock bumped to 0.8.8
|
|
47
|
+
* @aigne/core bumped to 1.41.0
|
|
48
|
+
* @aigne/deepseek bumped to 0.7.8
|
|
49
|
+
* @aigne/default-memory bumped to 1.0.8
|
|
50
|
+
* @aigne/gemini bumped to 0.8.8
|
|
51
|
+
* @aigne/ollama bumped to 0.7.8
|
|
52
|
+
* @aigne/open-router bumped to 0.7.8
|
|
53
|
+
* @aigne/openai bumped to 0.10.8
|
|
54
|
+
* @aigne/xai bumped to 0.7.8
|
|
55
|
+
|
|
3
56
|
## [1.28.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.27.0...cli-v1.28.0) (2025-07-31)
|
|
4
57
|
|
|
5
58
|
|
package/dist/commands/aigne.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import yargs from "yargs";
|
|
2
3
|
import { AIGNE_CLI_VERSION } from "../constants.js";
|
|
3
4
|
import { asciiLogo } from "../utils/ascii-logo.js";
|
|
@@ -10,6 +11,7 @@ import { createServeMCPCommand } from "./serve-mcp.js";
|
|
|
10
11
|
import { createTestCommand } from "./test.js";
|
|
11
12
|
export function createAIGNECommand(options) {
|
|
12
13
|
console.log(asciiLogo);
|
|
14
|
+
console.log(`${chalk.grey("TIPS:")} use ${chalk.greenBright("aigne observe")} to start the observability server.\n`);
|
|
13
15
|
return yargs()
|
|
14
16
|
.scriptName("aigne")
|
|
15
17
|
.usage("CLI for AIGNE framework")
|
package/dist/commands/app.d.ts
CHANGED
|
@@ -7,13 +7,16 @@ export declare function invokeCLIAgentFromDir(options: {
|
|
|
7
7
|
input: Message & {
|
|
8
8
|
input?: string[];
|
|
9
9
|
format?: "yaml" | "json";
|
|
10
|
+
model?: string;
|
|
10
11
|
};
|
|
11
12
|
}): Promise<void>;
|
|
12
|
-
export declare function loadApplication({ name, dir, }: {
|
|
13
|
+
export declare function loadApplication({ name, dir, forceUpgrade, }: {
|
|
13
14
|
name: string;
|
|
14
15
|
dir?: string;
|
|
16
|
+
forceUpgrade?: boolean;
|
|
15
17
|
}): Promise<{
|
|
16
18
|
aigne: AIGNE;
|
|
17
19
|
dir: string;
|
|
18
20
|
version: string;
|
|
21
|
+
isCache?: boolean;
|
|
19
22
|
}>;
|
package/dist/commands/app.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
-
import {
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
3
|
import { readFile, 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";
|
|
7
|
+
import { loadModel } from "@aigne/aigne-hub";
|
|
7
8
|
import { AIAgent, AIGNE, readAllString } from "@aigne/core";
|
|
8
9
|
import { pick } from "@aigne/core/utils/type-utils.js";
|
|
9
10
|
import { Listr, PRESET_TIMER } from "@aigne/listr2";
|
|
10
11
|
import { joinURL } from "ufo";
|
|
11
12
|
import { parse } from "yaml";
|
|
12
13
|
import { ZodObject, ZodString } from "zod";
|
|
13
|
-
import { availableModels } from "../constants.js";
|
|
14
14
|
import { downloadAndExtract } from "../utils/download.js";
|
|
15
15
|
import { loadAIGNE } from "../utils/load-aigne.js";
|
|
16
16
|
import { runAgentWithAIGNE, stdinHasData } from "../utils/run-with-aigne.js";
|
|
@@ -29,8 +29,14 @@ export function createAppCommands() {
|
|
|
29
29
|
describe: app.describe,
|
|
30
30
|
aliases: app.aliases,
|
|
31
31
|
builder: async (yargs) => {
|
|
32
|
-
const { aigne, dir, version } = await loadApplication({ name: app.name });
|
|
33
|
-
yargs
|
|
32
|
+
const { aigne, dir, version, isCache } = await loadApplication({ name: app.name });
|
|
33
|
+
yargs
|
|
34
|
+
.option("model", {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Model to use for the application, example: openai:gpt-4.1 or google:gemini-2.5-flash",
|
|
37
|
+
})
|
|
38
|
+
.command(serveMcpCommandModule({ name: app.name, dir }))
|
|
39
|
+
.command(upgradeCommandModule({ name: app.name, dir, isLatest: !isCache, version }));
|
|
34
40
|
for (const agent of aigne.cli?.agents ?? []) {
|
|
35
41
|
yargs.command(agentCommandModule({ dir, agent }));
|
|
36
42
|
}
|
|
@@ -64,10 +70,25 @@ const serveMcpCommandModule = ({ name, dir, }) => ({
|
|
|
64
70
|
await serveMCPServerFromDir({ ...options, dir });
|
|
65
71
|
},
|
|
66
72
|
});
|
|
73
|
+
const upgradeCommandModule = ({ name, dir, isLatest, version, }) => ({
|
|
74
|
+
command: "upgrade",
|
|
75
|
+
describe: `Upgrade ${name} to the latest version`,
|
|
76
|
+
handler: async () => {
|
|
77
|
+
if (!isLatest) {
|
|
78
|
+
const result = await loadApplication({ name, dir, forceUpgrade: true });
|
|
79
|
+
if (version !== result.version) {
|
|
80
|
+
console.log(`\n✅ Upgraded ${name} to version ${version}`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
console.log(`\n✅ ${name} is already at the latest version (${version})`);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
67
87
|
const agentCommandModule = ({ dir, agent, }) => {
|
|
68
88
|
const inputSchema = agent.inputSchema instanceof ZodObject ? agent.inputSchema.shape : {};
|
|
69
89
|
return {
|
|
70
90
|
command: agent.name,
|
|
91
|
+
aliases: agent.alias || [],
|
|
71
92
|
describe: agent.description || "",
|
|
72
93
|
builder: (yargs) => {
|
|
73
94
|
for (const [option, config] of Object.entries(inputSchema)) {
|
|
@@ -98,7 +119,7 @@ const agentCommandModule = ({ dir, agent, }) => {
|
|
|
98
119
|
};
|
|
99
120
|
};
|
|
100
121
|
export async function invokeCLIAgentFromDir(options) {
|
|
101
|
-
const aigne = await loadAIGNE(options.dir);
|
|
122
|
+
const aigne = await loadAIGNE(options.dir, { model: options.input.model });
|
|
102
123
|
try {
|
|
103
124
|
const agent = aigne.cli.agents[options.agent];
|
|
104
125
|
assert(agent, `Agent ${options.agent} not found in ${options.dir}`);
|
|
@@ -157,27 +178,28 @@ async function readFileAsInput(value, { format } = {}) {
|
|
|
157
178
|
}
|
|
158
179
|
return value;
|
|
159
180
|
}
|
|
160
|
-
export async function loadApplication({ name, dir, }) {
|
|
181
|
+
export async function loadApplication({ name, dir, forceUpgrade = false, }) {
|
|
161
182
|
name = `@aigne/${name}`;
|
|
162
183
|
dir ??= join(homedir(), ".aigne", "registry.npmjs.org", name);
|
|
163
|
-
const check = await isInstallationAvailable(dir);
|
|
184
|
+
const check = forceUpgrade ? undefined : await isInstallationAvailable(dir);
|
|
164
185
|
if (check?.available) {
|
|
165
186
|
return {
|
|
166
|
-
aigne: await AIGNE.load(dir, {
|
|
187
|
+
aigne: await AIGNE.load(dir, { loadModel }),
|
|
167
188
|
dir,
|
|
168
189
|
version: check.version,
|
|
190
|
+
isCache: true,
|
|
169
191
|
};
|
|
170
192
|
}
|
|
171
193
|
const result = await new Listr([
|
|
172
194
|
{
|
|
173
|
-
title:
|
|
195
|
+
title: `Fetching ${name} metadata`,
|
|
174
196
|
task: async (ctx) => {
|
|
175
197
|
const info = await getNpmTgzInfo(name);
|
|
176
198
|
Object.assign(ctx, info);
|
|
177
199
|
},
|
|
178
200
|
},
|
|
179
201
|
{
|
|
180
|
-
title:
|
|
202
|
+
title: `Downloading ${name}`,
|
|
181
203
|
skip: (ctx) => ctx.version === check?.version,
|
|
182
204
|
task: async (ctx) => {
|
|
183
205
|
await downloadAndExtract(ctx.url, dir, { strip: 1 });
|
|
@@ -198,7 +220,7 @@ export async function loadApplication({ name, dir, }) {
|
|
|
198
220
|
},
|
|
199
221
|
}).run();
|
|
200
222
|
return {
|
|
201
|
-
aigne: await AIGNE.load(dir, {
|
|
223
|
+
aigne: await AIGNE.load(dir, { loadModel }),
|
|
202
224
|
dir,
|
|
203
225
|
version: result.version,
|
|
204
226
|
};
|
|
@@ -218,14 +240,22 @@ async function isInstallationAvailable(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TI
|
|
|
218
240
|
return { version, available };
|
|
219
241
|
}
|
|
220
242
|
async function installDependencies(dir) {
|
|
221
|
-
|
|
222
|
-
cwd: dir,
|
|
223
|
-
|
|
243
|
+
await new Promise((resolve, reject) => {
|
|
244
|
+
const child = spawn("npm", ["install", "--omit", "dev"], { cwd: dir, stdio: "pipe" });
|
|
245
|
+
let stderr = "";
|
|
246
|
+
child.stderr.on("data", (data) => {
|
|
247
|
+
stderr += data.toString();
|
|
248
|
+
});
|
|
249
|
+
child.on("error", (error) => reject(error));
|
|
250
|
+
child.on("exit", (code) => {
|
|
251
|
+
if (code === 0)
|
|
252
|
+
resolve();
|
|
253
|
+
else {
|
|
254
|
+
console.error(stderr);
|
|
255
|
+
reject(new Error(`npm install failed with code ${code}`));
|
|
256
|
+
}
|
|
257
|
+
});
|
|
224
258
|
});
|
|
225
|
-
if (status !== 0) {
|
|
226
|
-
console.error(stderr.toString());
|
|
227
|
-
throw new Error(`Failed to install dependencies in ${dir}`);
|
|
228
|
-
}
|
|
229
259
|
await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify({ installedAt: Date.now() }, null, 2));
|
|
230
260
|
}
|
|
231
261
|
async function getNpmTgzInfo(name) {
|
|
@@ -2,5 +2,12 @@ import type { CommandModule } from "yargs";
|
|
|
2
2
|
interface ConnectOptions {
|
|
3
3
|
url?: string;
|
|
4
4
|
}
|
|
5
|
+
interface StatusInfo {
|
|
6
|
+
host: string;
|
|
7
|
+
apiUrl: string;
|
|
8
|
+
apiKey: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function getConnectionStatus(): Promise<StatusInfo[]>;
|
|
11
|
+
export declare function displayStatus(statusList: StatusInfo[]): Promise<void>;
|
|
5
12
|
export declare function createConnectCommand(): CommandModule<unknown, ConnectOptions>;
|
|
6
13
|
export {};
|
package/dist/commands/connect.js
CHANGED
|
@@ -4,7 +4,11 @@ import chalk from "chalk";
|
|
|
4
4
|
import { parse } from "yaml";
|
|
5
5
|
import { getUserInfo } from "../utils/aigne-hub-user.js";
|
|
6
6
|
import { AIGNE_ENV_FILE, connectToAIGNEHub } from "../utils/load-aigne.js";
|
|
7
|
-
|
|
7
|
+
const formatNumber = (balance) => {
|
|
8
|
+
const balanceNum = String(balance).split(".")[0];
|
|
9
|
+
return chalk.yellow((balanceNum || "").replace(/\B(?=(\d{3})+(?!\d))/g, ","));
|
|
10
|
+
};
|
|
11
|
+
export async function getConnectionStatus() {
|
|
8
12
|
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
9
13
|
return [];
|
|
10
14
|
}
|
|
@@ -25,7 +29,7 @@ async function getConnectionStatus() {
|
|
|
25
29
|
return [];
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
|
-
async function displayStatus(statusList) {
|
|
32
|
+
export async function displayStatus(statusList) {
|
|
29
33
|
if (statusList.length === 0) {
|
|
30
34
|
console.log(chalk.yellow("No AIGNE Hub connections found."));
|
|
31
35
|
console.log("Use 'aigne connect <url>' to connect to a hub.");
|
|
@@ -46,11 +50,16 @@ async function displayStatus(statusList) {
|
|
|
46
50
|
console.log(` Status: ${statusText}`);
|
|
47
51
|
if (userInfo) {
|
|
48
52
|
console.log(` User: ${userInfo?.user.fullName}`);
|
|
49
|
-
console.log(`
|
|
53
|
+
console.log(` User DID: ${userInfo?.user.did}`);
|
|
54
|
+
if (userInfo?.user.email) {
|
|
55
|
+
console.log(` Email: ${userInfo?.user.email}`);
|
|
56
|
+
}
|
|
50
57
|
if (userInfo?.creditBalance) {
|
|
51
|
-
|
|
58
|
+
const balance = formatNumber(userInfo?.creditBalance?.balance);
|
|
59
|
+
const total = formatNumber(userInfo?.creditBalance?.total);
|
|
60
|
+
console.log(` Plan: ${balance} / ${total}`);
|
|
52
61
|
}
|
|
53
|
-
console.log(` Billing URL: ${userInfo?.paymentLink}`);
|
|
62
|
+
console.log(` Billing URL: ${userInfo?.paymentLink ? chalk.green(userInfo.paymentLink) : chalk.red("N/A")}`);
|
|
54
63
|
}
|
|
55
64
|
console.log("");
|
|
56
65
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { LoadableModel } from "@aigne/core/loader/index.js";
|
|
2
1
|
import { DefaultMemory } from "@aigne/default-memory";
|
|
3
2
|
export declare const AIGNE_CLI_VERSION: any;
|
|
4
|
-
export declare function availableModels(): LoadableModel[];
|
|
5
3
|
export declare const availableMemories: (typeof DefaultMemory)[];
|
package/dist/constants.js
CHANGED
|
@@ -1,82 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { AgenticMemory } from "@aigne/agentic-memory";
|
|
3
|
-
import { AIGNEHubChatModel } from "@aigne/aigne-hub";
|
|
4
|
-
import { AnthropicChatModel } from "@aigne/anthropic";
|
|
5
|
-
import { BedrockChatModel } from "@aigne/bedrock";
|
|
6
|
-
import { DeepSeekChatModel } from "@aigne/deepseek";
|
|
7
3
|
import { DefaultMemory } from "@aigne/default-memory";
|
|
8
|
-
import { GeminiChatModel } from "@aigne/gemini";
|
|
9
|
-
import { OllamaChatModel } from "@aigne/ollama";
|
|
10
|
-
import { OpenRouterChatModel } from "@aigne/open-router";
|
|
11
|
-
import { OpenAIChatModel } from "@aigne/openai";
|
|
12
|
-
import { XAIChatModel } from "@aigne/xai";
|
|
13
|
-
import { NodeHttpHandler, streamCollector } from "@smithy/node-http-handler";
|
|
14
|
-
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
15
4
|
const require = createRequire(import.meta.url);
|
|
16
5
|
export const AIGNE_CLI_VERSION = require("../package.json").version;
|
|
17
|
-
export function availableModels() {
|
|
18
|
-
const proxy = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy", "ALL_PROXY", "all_proxy"]
|
|
19
|
-
.map((i) => process.env[i])
|
|
20
|
-
.filter(Boolean)[0];
|
|
21
|
-
const httpAgent = proxy ? new HttpsProxyAgent(proxy) : undefined;
|
|
22
|
-
const clientOptions = {
|
|
23
|
-
fetchOptions: {
|
|
24
|
-
// @ts-ignore
|
|
25
|
-
agent: httpAgent,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
return [
|
|
29
|
-
{
|
|
30
|
-
name: OpenAIChatModel.name,
|
|
31
|
-
apiKeyEnvName: "OPENAI_API_KEY",
|
|
32
|
-
create: (params) => new OpenAIChatModel({ ...params, clientOptions }),
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
name: AnthropicChatModel.name,
|
|
36
|
-
apiKeyEnvName: "ANTHROPIC_API_KEY",
|
|
37
|
-
create: (params) => new AnthropicChatModel({ ...params, clientOptions }),
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: BedrockChatModel.name,
|
|
41
|
-
apiKeyEnvName: "AWS_ACCESS_KEY_ID",
|
|
42
|
-
create: (params) => new BedrockChatModel({
|
|
43
|
-
...params,
|
|
44
|
-
clientOptions: {
|
|
45
|
-
requestHandler: NodeHttpHandler.create({ httpAgent, httpsAgent: httpAgent }),
|
|
46
|
-
streamCollector,
|
|
47
|
-
},
|
|
48
|
-
}),
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: DeepSeekChatModel.name,
|
|
52
|
-
apiKeyEnvName: "DEEPSEEK_API_KEY",
|
|
53
|
-
create: (params) => new DeepSeekChatModel({ ...params, clientOptions }),
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: GeminiChatModel.name,
|
|
57
|
-
apiKeyEnvName: "GEMINI_API_KEY",
|
|
58
|
-
create: (params) => new GeminiChatModel({ ...params, clientOptions }),
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: OllamaChatModel.name,
|
|
62
|
-
apiKeyEnvName: "OLLAMA_API_KEY",
|
|
63
|
-
create: (params) => new OllamaChatModel({ ...params, clientOptions }),
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: OpenRouterChatModel.name,
|
|
67
|
-
apiKeyEnvName: "OPEN_ROUTER_API_KEY",
|
|
68
|
-
create: (params) => new OpenRouterChatModel({ ...params, clientOptions }),
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: XAIChatModel.name,
|
|
72
|
-
apiKeyEnvName: "XAI_API_KEY",
|
|
73
|
-
create: (params) => new XAIChatModel({ ...params, clientOptions }),
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: AIGNEHubChatModel.name,
|
|
77
|
-
apiKeyEnvName: "AIGNE_HUB_API_KEY",
|
|
78
|
-
create: (params) => new AIGNEHubChatModel({ ...params, clientOptions }),
|
|
79
|
-
},
|
|
80
|
-
];
|
|
81
|
-
}
|
|
82
6
|
export const availableMemories = [DefaultMemory, AgenticMemory];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { availableModels } from "@aigne/aigne-hub";
|
|
1
2
|
import { AIGNE } from "@aigne/core";
|
|
2
|
-
import type { LoadableModel } from "@aigne/core/loader/index.js";
|
|
3
3
|
import inquirer from "inquirer";
|
|
4
4
|
import { type RunAIGNECommandOptions } from "./run-with-aigne.js";
|
|
5
5
|
export declare const decrypt: (m: string, s: string, i: string) => string;
|
|
@@ -40,7 +40,7 @@ interface CreateConnectOptions {
|
|
|
40
40
|
}) => Promise<FetchResult>;
|
|
41
41
|
}
|
|
42
42
|
export declare function createConnect({ connectUrl, openPage, fetchInterval, retry, source, connectAction, wrapSpinner, closeOnSuccess, intervalFetchConfig, }: CreateConnectOptions): Promise<FetchResult>;
|
|
43
|
-
export declare const formatModelName: (models:
|
|
43
|
+
export declare const formatModelName: (models: ReturnType<typeof availableModels>, model: string, inquirerPrompt: typeof inquirer.prompt) => Promise<string>;
|
|
44
44
|
export declare function connectToAIGNEHub(url: string): Promise<{
|
|
45
45
|
accessKey: string;
|
|
46
46
|
url: string;
|
|
@@ -48,7 +48,11 @@ export declare function connectToAIGNEHub(url: string): Promise<{
|
|
|
48
48
|
accessKey: undefined;
|
|
49
49
|
url: undefined;
|
|
50
50
|
}>;
|
|
51
|
-
export declare
|
|
51
|
+
export declare const checkConnectionStatus: (host: string) => Promise<{
|
|
52
|
+
apiKey: any;
|
|
53
|
+
url: string;
|
|
54
|
+
}>;
|
|
55
|
+
export declare function loadAIGNE(path: string, options?: Pick<RunOptions, "model">, actionOptions?: {
|
|
52
56
|
inquirerPromptFn?: (prompt: {
|
|
53
57
|
type: string;
|
|
54
58
|
name: string;
|
package/dist/utils/load-aigne.js
CHANGED
|
@@ -2,8 +2,9 @@ import { existsSync, mkdirSync } from "node:fs";
|
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { availableModels, findModel, loadModel } from "@aigne/aigne-hub";
|
|
5
6
|
import { AIGNE } from "@aigne/core";
|
|
6
|
-
import { loadAIGNEFile
|
|
7
|
+
import { loadAIGNEFile } from "@aigne/core/loader/index.js";
|
|
7
8
|
import { logger } from "@aigne/core/utils/logger.js";
|
|
8
9
|
import { AesCrypter } from "@ocap/mcrypto/lib/crypter/aes-legacy.js";
|
|
9
10
|
import crypto from "crypto";
|
|
@@ -12,7 +13,7 @@ import open from "open";
|
|
|
12
13
|
import pWaitFor from "p-wait-for";
|
|
13
14
|
import { joinURL, withQuery } from "ufo";
|
|
14
15
|
import { parse, stringify } from "yaml";
|
|
15
|
-
import { availableMemories
|
|
16
|
+
import { availableMemories } from "../constants.js";
|
|
16
17
|
import { parseModelOption } from "./run-with-aigne.js";
|
|
17
18
|
const aes = new AesCrypter();
|
|
18
19
|
export const decrypt = (m, s, i) => aes.decrypt(m, crypto.pbkdf2Sync(i, s, 256, 32, "sha512").toString("hex"));
|
|
@@ -104,10 +105,11 @@ export const formatModelName = async (models, model, inquirerPrompt) => {
|
|
|
104
105
|
if (providerName.includes(AGENT_HUB_PROVIDER)) {
|
|
105
106
|
return model;
|
|
106
107
|
}
|
|
107
|
-
const m = models
|
|
108
|
+
const m = findModel(models, providerName);
|
|
108
109
|
if (!m)
|
|
109
110
|
throw new Error(`Unsupported model: ${provider} ${name}`);
|
|
110
|
-
|
|
111
|
+
const apiKeyEnvName = Array.isArray(m.apiKeyEnvName) ? m.apiKeyEnvName : [m.apiKeyEnvName];
|
|
112
|
+
if (apiKeyEnvName.some((name) => name && process.env[name])) {
|
|
111
113
|
return model;
|
|
112
114
|
}
|
|
113
115
|
if (TEST_ENV) {
|
|
@@ -123,7 +125,7 @@ export const formatModelName = async (models, model, inquirerPrompt) => {
|
|
|
123
125
|
value: true,
|
|
124
126
|
},
|
|
125
127
|
{
|
|
126
|
-
name: `Exit and bring my owner API Key by set ${
|
|
128
|
+
name: `Exit and bring my owner API Key by set ${apiKeyEnvName.join(", ")}`,
|
|
127
129
|
value: false,
|
|
128
130
|
},
|
|
129
131
|
],
|
|
@@ -175,42 +177,48 @@ export async function connectToAIGNEHub(url) {
|
|
|
175
177
|
return { accessKey: undefined, url: undefined };
|
|
176
178
|
}
|
|
177
179
|
}
|
|
180
|
+
export const checkConnectionStatus = async (host) => {
|
|
181
|
+
// aigne-hub access token
|
|
182
|
+
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
183
|
+
throw new Error("AIGNE_HUB_API_KEY file not found, need to login first");
|
|
184
|
+
}
|
|
185
|
+
const data = await readFile(AIGNE_ENV_FILE, "utf8");
|
|
186
|
+
if (!data.includes("AIGNE_HUB_API_KEY")) {
|
|
187
|
+
throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
|
|
188
|
+
}
|
|
189
|
+
const envs = parse(data);
|
|
190
|
+
if (!envs[host]) {
|
|
191
|
+
throw new Error("AIGNE_HUB_API_KEY host not found, need to login first");
|
|
192
|
+
}
|
|
193
|
+
const env = envs[host];
|
|
194
|
+
if (!env.AIGNE_HUB_API_KEY) {
|
|
195
|
+
throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
apiKey: env.AIGNE_HUB_API_KEY,
|
|
199
|
+
url: joinURL(env.AIGNE_HUB_API_URL),
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const mockInquirerPrompt = (() => Promise.resolve({ useAigneHub: true }));
|
|
178
203
|
export async function loadAIGNE(path, options, actionOptions) {
|
|
179
204
|
const models = availableModels();
|
|
180
205
|
const AIGNE_HUB_URL = process.env.AIGNE_HUB_API_URL || DEFAULT_URL;
|
|
181
206
|
const connectUrl = joinURL(new URL(AIGNE_HUB_URL).origin, WELLKNOWN_SERVICE_PATH_PREFIX);
|
|
182
207
|
const inquirerPrompt = (actionOptions?.inquirerPromptFn ??
|
|
183
208
|
inquirer.prompt);
|
|
209
|
+
const { host } = new URL(AIGNE_HUB_URL);
|
|
184
210
|
const { aigne } = await loadAIGNEFile(path).catch(() => ({ aigne: null }));
|
|
185
|
-
|
|
186
|
-
const
|
|
211
|
+
const result = await checkConnectionStatus(host).catch(() => null);
|
|
212
|
+
const alreadyConnected = Boolean(result?.apiKey);
|
|
213
|
+
const modelName = await formatModelName(models, options?.model || `${aigne?.model?.provider ?? ""}:${aigne?.model?.name ?? ""}`, alreadyConnected ? mockInquirerPrompt : inquirerPrompt);
|
|
214
|
+
let credential = {};
|
|
187
215
|
if (TEST_ENV && !actionOptions?.runTest) {
|
|
188
|
-
const model = await loadModel(
|
|
189
|
-
return await AIGNE.load(path, {
|
|
216
|
+
const model = await loadModel(parseModelOption(modelName));
|
|
217
|
+
return await AIGNE.load(path, { loadModel, memories: availableMemories, model });
|
|
190
218
|
}
|
|
191
219
|
if ((modelName.toLocaleLowerCase() || "").includes(AGENT_HUB_PROVIDER)) {
|
|
192
|
-
const { host } = new URL(AIGNE_HUB_URL);
|
|
193
220
|
try {
|
|
194
|
-
|
|
195
|
-
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
196
|
-
throw new Error("AIGNE_HUB_API_KEY file not found, need to login first");
|
|
197
|
-
}
|
|
198
|
-
const data = await readFile(AIGNE_ENV_FILE, "utf8");
|
|
199
|
-
if (!data.includes("AIGNE_HUB_API_KEY")) {
|
|
200
|
-
throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
|
|
201
|
-
}
|
|
202
|
-
const envs = parse(data);
|
|
203
|
-
if (!envs[host]) {
|
|
204
|
-
throw new Error("AIGNE_HUB_API_KEY host not found, need to login first");
|
|
205
|
-
}
|
|
206
|
-
const env = envs[host];
|
|
207
|
-
if (!env.AIGNE_HUB_API_KEY) {
|
|
208
|
-
throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
|
|
209
|
-
}
|
|
210
|
-
accessKeyOptions = {
|
|
211
|
-
accessKey: env.AIGNE_HUB_API_KEY,
|
|
212
|
-
url: joinURL(env.AIGNE_HUB_API_URL),
|
|
213
|
-
};
|
|
221
|
+
credential = await checkConnectionStatus(host);
|
|
214
222
|
}
|
|
215
223
|
catch (error) {
|
|
216
224
|
if (error instanceof Error && error.message.includes("login first")) {
|
|
@@ -232,10 +240,10 @@ export async function loadAIGNE(path, options, actionOptions) {
|
|
|
232
240
|
console.warn("The AIGNE Hub connection has been cancelled");
|
|
233
241
|
process.exit(0);
|
|
234
242
|
}
|
|
235
|
-
|
|
243
|
+
credential = await connectToAIGNEHub(connectUrl);
|
|
236
244
|
}
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
|
-
const model = await loadModel(
|
|
240
|
-
return await AIGNE.load(path, {
|
|
247
|
+
const model = await loadModel(parseModelOption(modelName), undefined, credential);
|
|
248
|
+
return await AIGNE.load(path, { loadModel, memories: availableMemories, model });
|
|
241
249
|
}
|
|
@@ -4,8 +4,8 @@ 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 { availableModels, loadModel } from "@aigne/aigne-hub";
|
|
7
8
|
import { AIAgent, AIGNE, DEFAULT_OUTPUT_KEY, readAllString, UserAgent, } from "@aigne/core";
|
|
8
|
-
import { loadModel } from "@aigne/core/loader/index.js";
|
|
9
9
|
import { getLevelFromEnv, LogLevel, logger } from "@aigne/core/utils/logger.js";
|
|
10
10
|
import { flat, isEmpty, tryOrThrow } from "@aigne/core/utils/type-utils.js";
|
|
11
11
|
import chalk from "chalk";
|
|
@@ -13,7 +13,6 @@ import { parse } from "yaml";
|
|
|
13
13
|
import yargs from "yargs";
|
|
14
14
|
import { hideBin } from "yargs/helpers";
|
|
15
15
|
import { ZodError, ZodObject, z } from "zod";
|
|
16
|
-
import { availableModels } from "../constants.js";
|
|
17
16
|
import { TerminalTracer } from "../tracer/terminal.js";
|
|
18
17
|
import { DEFAULT_CHAT_INPUT_KEY, runChatLoopInTerminal, } from "./run-chat-loop.js";
|
|
19
18
|
export const createRunAIGNECommand = (yargs) => yargs
|
|
@@ -24,7 +23,12 @@ export const createRunAIGNECommand = (yargs) => yargs
|
|
|
24
23
|
})
|
|
25
24
|
.option("model", {
|
|
26
25
|
describe: `AI model to use in format 'provider[:model]' where model is optional. Examples: 'openai' or 'openai:gpt-4o-mini'. Available providers: ${availableModels()
|
|
27
|
-
.map((i) =>
|
|
26
|
+
.map((i) => {
|
|
27
|
+
if (typeof i.name === "string") {
|
|
28
|
+
return i.name.toLowerCase().replace(/ChatModel$/i, "");
|
|
29
|
+
}
|
|
30
|
+
return i.name.map((n) => n.toLowerCase().replace(/ChatModel$/i, ""));
|
|
31
|
+
})
|
|
28
32
|
.join(", ")} (default: openai)`,
|
|
29
33
|
type: "string",
|
|
30
34
|
})
|
|
@@ -129,7 +133,7 @@ export async function runWithAIGNE(agentCreator, { argv = process.argv, chatLoop
|
|
|
129
133
|
if (options.logLevel) {
|
|
130
134
|
logger.level = options.logLevel;
|
|
131
135
|
}
|
|
132
|
-
const model = await loadModel(
|
|
136
|
+
const model = await loadModel({
|
|
133
137
|
...parseModelOption(options.model),
|
|
134
138
|
temperature: options.temperature,
|
|
135
139
|
topP: options.topP,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0",
|
|
4
4
|
"description": "cli for AIGNE framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -70,20 +70,13 @@
|
|
|
70
70
|
"yaml": "^2.8.0",
|
|
71
71
|
"yargs": "^18.0.0",
|
|
72
72
|
"zod": "^3.25.67",
|
|
73
|
-
"@aigne/
|
|
74
|
-
"@aigne/
|
|
75
|
-
"@aigne/aigne-hub": "^0.
|
|
76
|
-
"@aigne/
|
|
77
|
-
"@aigne/
|
|
78
|
-
"@aigne/core": "^1.
|
|
79
|
-
"@aigne/
|
|
80
|
-
"@aigne/gemini": "^0.8.7",
|
|
81
|
-
"@aigne/deepseek": "^0.7.7",
|
|
82
|
-
"@aigne/observability-api": "^0.8.2",
|
|
83
|
-
"@aigne/ollama": "^0.7.7",
|
|
84
|
-
"@aigne/open-router": "^0.7.7",
|
|
85
|
-
"@aigne/openai": "^0.10.7",
|
|
86
|
-
"@aigne/xai": "^0.7.7"
|
|
73
|
+
"@aigne/agent-library": "^1.21.9",
|
|
74
|
+
"@aigne/agentic-memory": "^1.0.9",
|
|
75
|
+
"@aigne/aigne-hub": "^0.4.0",
|
|
76
|
+
"@aigne/openai": "^0.10.9",
|
|
77
|
+
"@aigne/default-memory": "^1.0.9",
|
|
78
|
+
"@aigne/core": "^1.42.0",
|
|
79
|
+
"@aigne/observability-api": "^0.9.0"
|
|
87
80
|
},
|
|
88
81
|
"devDependencies": {
|
|
89
82
|
"@types/archiver": "^6.0.3",
|