@aigne/cli 1.24.1 → 1.25.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 +31 -0
- package/dist/commands/run.js +12 -15
- package/dist/commands/serve-mcp.js +2 -6
- package/dist/commands/test.js +2 -6
- package/dist/constants.js +9 -0
- package/dist/utils/load-aigne.d.ts +19 -0
- package/dist/utils/load-aigne.js +209 -0
- package/package.json +19 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.25.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.24.1...cli-v1.25.0) (2025-07-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **cli:** support aigne hub connect and model use ([#267](https://github.com/AIGNE-io/aigne-framework/issues/267)) ([8e5a32a](https://github.com/AIGNE-io/aigne-framework/commit/8e5a32afc64593137153d7407bde13837312ac70))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* ci lint ([#278](https://github.com/AIGNE-io/aigne-framework/issues/278)) ([b23dea9](https://github.com/AIGNE-io/aigne-framework/commit/b23dea98bf91082ce7429b766dff28cfa5163cd9))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Dependencies
|
|
17
|
+
|
|
18
|
+
* The following workspace dependencies were updated
|
|
19
|
+
* dependencies
|
|
20
|
+
* @aigne/agent-library bumped to 1.21.4
|
|
21
|
+
* @aigne/agentic-memory bumped to 1.0.4
|
|
22
|
+
* @aigne/aigne-hub bumped to 0.2.0
|
|
23
|
+
* @aigne/anthropic bumped to 0.10.0
|
|
24
|
+
* @aigne/bedrock bumped to 0.8.4
|
|
25
|
+
* @aigne/core bumped to 1.38.0
|
|
26
|
+
* @aigne/deepseek bumped to 0.7.4
|
|
27
|
+
* @aigne/default-memory bumped to 1.0.4
|
|
28
|
+
* @aigne/gemini bumped to 0.8.4
|
|
29
|
+
* @aigne/ollama bumped to 0.7.4
|
|
30
|
+
* @aigne/open-router bumped to 0.7.4
|
|
31
|
+
* @aigne/openai bumped to 0.10.4
|
|
32
|
+
* @aigne/xai bumped to 0.7.4
|
|
33
|
+
|
|
3
34
|
## [1.24.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.24.0...cli-v1.24.1) (2025-07-22)
|
|
4
35
|
|
|
5
36
|
|
package/dist/commands/run.js
CHANGED
|
@@ -2,16 +2,16 @@ import assert from "node:assert";
|
|
|
2
2
|
import { cp, mkdir, rm } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { isAbsolute, join, resolve } from "node:path";
|
|
5
|
-
import { AIGNE } from "@aigne/core";
|
|
6
|
-
import { loadModel } from "@aigne/core/loader/index.js";
|
|
7
5
|
import { logger } from "@aigne/core/utils/logger.js";
|
|
8
6
|
import { isNonNullable } from "@aigne/core/utils/type-utils.js";
|
|
9
7
|
import { Listr, PRESET_TIMER } from "@aigne/listr2";
|
|
8
|
+
import { select } from "@inquirer/prompts";
|
|
9
|
+
import { ListrInquirerPromptAdapter } from "@listr2/prompt-adapter-inquirer";
|
|
10
10
|
import { config } from "dotenv-flow";
|
|
11
|
-
import { availableMemories, availableModels } from "../constants.js";
|
|
12
11
|
import { isV1Package, toAIGNEPackage } from "../utils/agent-v1.js";
|
|
13
12
|
import { downloadAndExtract } from "../utils/download.js";
|
|
14
|
-
import {
|
|
13
|
+
import { loadAIGNE } from "../utils/load-aigne.js";
|
|
14
|
+
import { createRunAIGNECommand, parseAgentInputByCommander, runAgentWithAIGNE, } from "../utils/run-with-aigne.js";
|
|
15
15
|
export function createRunCommand({ aigneFilePath } = {}) {
|
|
16
16
|
return createRunAIGNECommand()
|
|
17
17
|
.description("Run AIGNE from the specified agent")
|
|
@@ -43,12 +43,16 @@ export function createRunCommand({ aigneFilePath } = {}) {
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
title: "Initialize AIGNE",
|
|
46
|
-
task: async (ctx) => {
|
|
46
|
+
task: async (ctx, task) => {
|
|
47
47
|
// Load env files in the aigne directory
|
|
48
48
|
config({ path: dir, silent: true });
|
|
49
|
-
const aigne = await loadAIGNE(dir, {
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const aigne = await loadAIGNE(dir, { ...options, model: options.model || process.env.MODEL }, {
|
|
50
|
+
inquirerPromptFn: (prompt) => {
|
|
51
|
+
return task
|
|
52
|
+
.prompt(ListrInquirerPromptAdapter)
|
|
53
|
+
.run(select, prompt)
|
|
54
|
+
.then((res) => ({ [prompt.name]: res }));
|
|
55
|
+
},
|
|
52
56
|
});
|
|
53
57
|
ctx.aigne = aigne;
|
|
54
58
|
},
|
|
@@ -97,13 +101,6 @@ ${aigne.agents.map((agent) => ` - ${agent.name}`).join("\n")}
|
|
|
97
101
|
.showHelpAfterError(true)
|
|
98
102
|
.showSuggestionAfterError(true);
|
|
99
103
|
}
|
|
100
|
-
async function loadAIGNE(path, options) {
|
|
101
|
-
const models = availableModels();
|
|
102
|
-
const model = options.model
|
|
103
|
-
? await loadModel(models, parseModelOption(options.model))
|
|
104
|
-
: undefined;
|
|
105
|
-
return await AIGNE.load(path, { models, memories: availableMemories, model });
|
|
106
|
-
}
|
|
107
104
|
async function downloadPackage(url, cacheDir) {
|
|
108
105
|
await rm(cacheDir, { recursive: true, force: true });
|
|
109
106
|
await mkdir(cacheDir, { recursive: true });
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { isAbsolute, resolve } from "node:path";
|
|
2
|
-
import { AIGNE } from "@aigne/core";
|
|
3
2
|
import { tryOrThrow } from "@aigne/core/utils/type-utils.js";
|
|
4
3
|
import { Command } from "commander";
|
|
5
|
-
import {
|
|
4
|
+
import { loadAIGNE } from "../utils/load-aigne.js";
|
|
6
5
|
import { serveMCPServer } from "../utils/serve-mcp.js";
|
|
7
6
|
const DEFAULT_PORT = () => tryOrThrow(() => {
|
|
8
7
|
const { PORT } = process.env;
|
|
@@ -24,10 +23,7 @@ export function createServeMCPCommand({ aigneFilePath } = {}) {
|
|
|
24
23
|
const path = aigneFilePath || options.path;
|
|
25
24
|
const absolutePath = isAbsolute(path) ? path : resolve(process.cwd(), path);
|
|
26
25
|
const port = options.port || DEFAULT_PORT();
|
|
27
|
-
const aigne = await
|
|
28
|
-
models: availableModels(),
|
|
29
|
-
memories: availableMemories,
|
|
30
|
-
});
|
|
26
|
+
const aigne = await loadAIGNE(absolutePath);
|
|
31
27
|
await serveMCPServer({
|
|
32
28
|
aigne,
|
|
33
29
|
host: options.host,
|
package/dist/commands/test.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { isAbsolute, resolve } from "node:path";
|
|
4
|
-
import { AIGNE } from "@aigne/core";
|
|
5
4
|
import { Command } from "commander";
|
|
6
|
-
import {
|
|
5
|
+
import { loadAIGNE } from "../utils/load-aigne.js";
|
|
7
6
|
export function createTestCommand({ aigneFilePath } = {}) {
|
|
8
7
|
return new Command("test")
|
|
9
8
|
.description("Run tests in the specified agents directory")
|
|
@@ -11,10 +10,7 @@ export function createTestCommand({ aigneFilePath } = {}) {
|
|
|
11
10
|
.action(async (options) => {
|
|
12
11
|
const path = aigneFilePath || options.path;
|
|
13
12
|
const absolutePath = isAbsolute(path) ? path : resolve(process.cwd(), path);
|
|
14
|
-
const aigne = await
|
|
15
|
-
models: availableModels(),
|
|
16
|
-
memories: availableMemories,
|
|
17
|
-
});
|
|
13
|
+
const aigne = await loadAIGNE(absolutePath);
|
|
18
14
|
assert(aigne.rootDir);
|
|
19
15
|
spawnSync("node", ["--test"], { cwd: aigne.rootDir, stdio: "inherit" });
|
|
20
16
|
})
|
package/dist/constants.js
CHANGED
|
@@ -28,14 +28,17 @@ export function availableModels() {
|
|
|
28
28
|
return [
|
|
29
29
|
{
|
|
30
30
|
name: OpenAIChatModel.name,
|
|
31
|
+
apiKeyEnvName: "OPENAI_API_KEY",
|
|
31
32
|
create: (params) => new OpenAIChatModel({ ...params, clientOptions }),
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
35
|
name: AnthropicChatModel.name,
|
|
36
|
+
apiKeyEnvName: "ANTHROPIC_API_KEY",
|
|
35
37
|
create: (params) => new AnthropicChatModel({ ...params, clientOptions }),
|
|
36
38
|
},
|
|
37
39
|
{
|
|
38
40
|
name: BedrockChatModel.name,
|
|
41
|
+
apiKeyEnvName: "AWS_ACCESS_KEY_ID",
|
|
39
42
|
create: (params) => new BedrockChatModel({
|
|
40
43
|
...params,
|
|
41
44
|
clientOptions: {
|
|
@@ -46,26 +49,32 @@ export function availableModels() {
|
|
|
46
49
|
},
|
|
47
50
|
{
|
|
48
51
|
name: DeepSeekChatModel.name,
|
|
52
|
+
apiKeyEnvName: "DEEPSEEK_API_KEY",
|
|
49
53
|
create: (params) => new DeepSeekChatModel({ ...params, clientOptions }),
|
|
50
54
|
},
|
|
51
55
|
{
|
|
52
56
|
name: GeminiChatModel.name,
|
|
57
|
+
apiKeyEnvName: "GEMINI_API_KEY",
|
|
53
58
|
create: (params) => new GeminiChatModel({ ...params, clientOptions }),
|
|
54
59
|
},
|
|
55
60
|
{
|
|
56
61
|
name: OllamaChatModel.name,
|
|
62
|
+
apiKeyEnvName: "OLLAMA_API_KEY",
|
|
57
63
|
create: (params) => new OllamaChatModel({ ...params, clientOptions }),
|
|
58
64
|
},
|
|
59
65
|
{
|
|
60
66
|
name: OpenRouterChatModel.name,
|
|
67
|
+
apiKeyEnvName: "OPEN_ROUTER_API_KEY",
|
|
61
68
|
create: (params) => new OpenRouterChatModel({ ...params, clientOptions }),
|
|
62
69
|
},
|
|
63
70
|
{
|
|
64
71
|
name: XAIChatModel.name,
|
|
72
|
+
apiKeyEnvName: "XAI_API_KEY",
|
|
65
73
|
create: (params) => new XAIChatModel({ ...params, clientOptions }),
|
|
66
74
|
},
|
|
67
75
|
{
|
|
68
76
|
name: AIGNEHubChatModel.name,
|
|
77
|
+
apiKeyEnvName: "AIGNE_HUB_API_KEY",
|
|
69
78
|
create: (params) => new AIGNEHubChatModel({ ...params, clientOptions }),
|
|
70
79
|
},
|
|
71
80
|
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AIGNE } from "@aigne/core";
|
|
2
|
+
import { type RunAIGNECommandOptions } from "./run-with-aigne.js";
|
|
3
|
+
export interface RunOptions extends RunAIGNECommandOptions {
|
|
4
|
+
path: string;
|
|
5
|
+
entryAgent?: string;
|
|
6
|
+
cacheDir?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function loadAIGNE(path: string, options?: RunOptions, checkAuthorizeOptions?: {
|
|
9
|
+
inquirerPromptFn?: (prompt: {
|
|
10
|
+
type: string;
|
|
11
|
+
name: string;
|
|
12
|
+
message: string;
|
|
13
|
+
choices: {
|
|
14
|
+
name: string;
|
|
15
|
+
value: any;
|
|
16
|
+
}[];
|
|
17
|
+
default: any;
|
|
18
|
+
}) => Promise<any>;
|
|
19
|
+
}): Promise<AIGNE<import("@aigne/core").UserContext>>;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { appendFile, readFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { AIGNE } from "@aigne/core";
|
|
6
|
+
import { loadModel } from "@aigne/core/loader/index.js";
|
|
7
|
+
import { AesCrypter } from "@ocap/mcrypto/lib/crypter/aes-legacy.js";
|
|
8
|
+
import crypto from "crypto";
|
|
9
|
+
import inquirer from "inquirer";
|
|
10
|
+
import open from "open";
|
|
11
|
+
import pWaitFor from "p-wait-for";
|
|
12
|
+
import { joinURL, withQuery } from "ufo";
|
|
13
|
+
import { parse, stringify } from "yaml";
|
|
14
|
+
import { availableMemories, availableModels } from "../constants.js";
|
|
15
|
+
import { parseModelOption } from "./run-with-aigne.js";
|
|
16
|
+
const aes = new AesCrypter();
|
|
17
|
+
const decrypt = (m, s, i) => aes.decrypt(m, crypto.pbkdf2Sync(i, s, 256, 32, "sha512").toString("hex"));
|
|
18
|
+
const escapeFn = (str) => str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
19
|
+
const encodeEncryptionKey = (key) => escapeFn(Buffer.from(key).toString("base64"));
|
|
20
|
+
const request = async (config) => {
|
|
21
|
+
const response = await fetch(config.url, { method: config.method || "GET" });
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
24
|
+
}
|
|
25
|
+
const data = await response.json();
|
|
26
|
+
return { data };
|
|
27
|
+
};
|
|
28
|
+
const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
|
|
29
|
+
const ACCESS_KEY_PREFIX = "/api/access-key";
|
|
30
|
+
const ACCESS_KEY_SESSION_API = `${ACCESS_KEY_PREFIX}/session`;
|
|
31
|
+
const fetchConfigs = async ({ connectUrl, sessionId, fetchInterval, fetchTimeout, }) => {
|
|
32
|
+
const sessionURL = withQuery(joinURL(connectUrl, ACCESS_KEY_SESSION_API), { sid: sessionId });
|
|
33
|
+
const condition = async () => {
|
|
34
|
+
const { data: session } = await request({ url: sessionURL });
|
|
35
|
+
return Boolean(session.accessKeyId && session.accessKeySecret);
|
|
36
|
+
};
|
|
37
|
+
await pWaitFor(condition, { interval: fetchInterval, timeout: fetchTimeout });
|
|
38
|
+
const { data: session } = await request({ url: sessionURL });
|
|
39
|
+
await request({ url: sessionURL, method: "DELETE" });
|
|
40
|
+
return {
|
|
41
|
+
...session,
|
|
42
|
+
accessKeyId: session.accessKeyId,
|
|
43
|
+
accessKeySecret: decrypt(session.accessKeySecret, session.accessKeyId, session.challenge),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
function baseWrapSpinner(_, waiting) {
|
|
47
|
+
return Promise.resolve(waiting());
|
|
48
|
+
}
|
|
49
|
+
async function createConnect({ connectUrl, openPage, fetchInterval = 3 * 1000, retry = 1500, source = "Blocklet CLI", connectAction = "connect-cli", wrapSpinner = baseWrapSpinner, closeOnSuccess, intervalFetchConfig, }) {
|
|
50
|
+
try {
|
|
51
|
+
const startSessionURL = joinURL(connectUrl, ACCESS_KEY_SESSION_API);
|
|
52
|
+
const { data: session } = await request({ url: startSessionURL, method: "POST" });
|
|
53
|
+
const token = session.id;
|
|
54
|
+
const pageUrl = withQuery(joinURL(connectUrl, connectAction), {
|
|
55
|
+
__token__: encodeEncryptionKey(token),
|
|
56
|
+
source,
|
|
57
|
+
closeOnSuccess,
|
|
58
|
+
cli: true,
|
|
59
|
+
appName: " AIGNE CLI",
|
|
60
|
+
appLogo: "https://www.aigne.io/favicon.ico?imageFilter=resize&w=32",
|
|
61
|
+
});
|
|
62
|
+
openPage?.(pageUrl);
|
|
63
|
+
return await wrapSpinner(`Waiting for connection: ${connectUrl}`, async () => {
|
|
64
|
+
const checkAuthorizeStatus = intervalFetchConfig ?? fetchConfigs;
|
|
65
|
+
const authorizeStatus = await checkAuthorizeStatus({
|
|
66
|
+
connectUrl,
|
|
67
|
+
sessionId: token,
|
|
68
|
+
fetchTimeout: retry * fetchInterval,
|
|
69
|
+
fetchInterval: retry,
|
|
70
|
+
});
|
|
71
|
+
return authorizeStatus;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
console.error(e);
|
|
76
|
+
throw e;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const AGENT_HUB_PROVIDER = "aignehub";
|
|
80
|
+
const DEFAULT_AIGNE_HUB_MODEL = "openai/gpt-4o";
|
|
81
|
+
const DEFAULT_AIGNE_HUB_PROVIDER_MODEL = `${AGENT_HUB_PROVIDER}:${DEFAULT_AIGNE_HUB_MODEL}`;
|
|
82
|
+
const DEFAULT_URL = "https://hub.aigne.io/";
|
|
83
|
+
const formatModelName = async (models, model, inquirerPrompt) => {
|
|
84
|
+
if (process.env.NODE_ENV === "test")
|
|
85
|
+
return model;
|
|
86
|
+
if (!model)
|
|
87
|
+
return DEFAULT_AIGNE_HUB_PROVIDER_MODEL;
|
|
88
|
+
const { provider, name } = parseModelOption(model);
|
|
89
|
+
if (!provider || !name) {
|
|
90
|
+
return DEFAULT_AIGNE_HUB_PROVIDER_MODEL;
|
|
91
|
+
}
|
|
92
|
+
const providerName = provider.replace(/-/g, "");
|
|
93
|
+
if (providerName.includes(AGENT_HUB_PROVIDER)) {
|
|
94
|
+
return model;
|
|
95
|
+
}
|
|
96
|
+
const m = models.find((m) => m.name.toLowerCase().includes(providerName.toLowerCase()));
|
|
97
|
+
if (!m)
|
|
98
|
+
throw new Error(`Unsupported model: ${provider} ${name}`);
|
|
99
|
+
if (m.apiKeyEnvName && process.env[m.apiKeyEnvName]) {
|
|
100
|
+
return model;
|
|
101
|
+
}
|
|
102
|
+
const result = await inquirerPrompt({
|
|
103
|
+
type: "list",
|
|
104
|
+
name: "useAigneHub",
|
|
105
|
+
message: `Seems no API Key configured for ${provider}/${name}, select your preferred way to continue:`,
|
|
106
|
+
choices: [
|
|
107
|
+
{
|
|
108
|
+
name: `Connect to AIGNE Hub to use ${name} (Recommended since free credits available)`,
|
|
109
|
+
value: true,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: `Exit and bring my owner API Key by set ${m.apiKeyEnvName}`,
|
|
113
|
+
value: false,
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
default: true,
|
|
117
|
+
});
|
|
118
|
+
if (!result.useAigneHub)
|
|
119
|
+
return model;
|
|
120
|
+
return `${AGENT_HUB_PROVIDER}:${provider}/${name}`;
|
|
121
|
+
};
|
|
122
|
+
export async function loadAIGNE(path, options, checkAuthorizeOptions) {
|
|
123
|
+
const models = availableModels();
|
|
124
|
+
const AIGNE_ENV_FILE = join(homedir(), ".aigne", "aigne-hub-connected.yaml");
|
|
125
|
+
const AIGNE_HUB_URL = process.env.AIGNE_HUB_API_URL || DEFAULT_URL;
|
|
126
|
+
const connectUrl = joinURL(new URL(AIGNE_HUB_URL).origin, WELLKNOWN_SERVICE_PATH_PREFIX);
|
|
127
|
+
const inquirerPrompt = (checkAuthorizeOptions?.inquirerPromptFn ??
|
|
128
|
+
inquirer.prompt);
|
|
129
|
+
let accessKeyOptions = {};
|
|
130
|
+
const modelName = await formatModelName(models, options?.model || "", inquirerPrompt);
|
|
131
|
+
if (!process.env.CI) {
|
|
132
|
+
if ((modelName.toLocaleLowerCase() || "").includes(AGENT_HUB_PROVIDER)) {
|
|
133
|
+
const { origin, host } = new URL(AIGNE_HUB_URL);
|
|
134
|
+
try {
|
|
135
|
+
// 检查 aigne-hub access token
|
|
136
|
+
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
137
|
+
throw new Error("AIGNE_HUB_API_KEY file not found, need to login first");
|
|
138
|
+
}
|
|
139
|
+
const data = await readFile(AIGNE_ENV_FILE, "utf8");
|
|
140
|
+
if (!data.includes("AIGNE_HUB_API_KEY")) {
|
|
141
|
+
throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
|
|
142
|
+
}
|
|
143
|
+
const envs = parse(data);
|
|
144
|
+
if (!envs[host]) {
|
|
145
|
+
throw new Error("AIGNE_HUB_API_KEY host not found, need to login first");
|
|
146
|
+
}
|
|
147
|
+
const env = envs[host];
|
|
148
|
+
if (!env.AIGNE_HUB_API_KEY) {
|
|
149
|
+
throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
|
|
150
|
+
}
|
|
151
|
+
accessKeyOptions = {
|
|
152
|
+
accessKey: env.AIGNE_HUB_API_KEY,
|
|
153
|
+
url: joinURL(env.AIGNE_HUB_API_URL),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (error instanceof Error && error.message.includes("login first")) {
|
|
158
|
+
// If none or invalid, prompt the user to proceed
|
|
159
|
+
const subscribePrompt = await inquirerPrompt({
|
|
160
|
+
type: "list",
|
|
161
|
+
name: "subscribe",
|
|
162
|
+
message: "No LLM API Keys or AIGNE Hub connections found, select your preferred way to continue:",
|
|
163
|
+
choices: [
|
|
164
|
+
{
|
|
165
|
+
name: "Connect to AIGNE Hub with just a few clicks, free credits eligible for new users (Recommended)",
|
|
166
|
+
value: true,
|
|
167
|
+
},
|
|
168
|
+
{ name: "Exit and configure my own LLM API Keys", value: false },
|
|
169
|
+
],
|
|
170
|
+
default: true,
|
|
171
|
+
});
|
|
172
|
+
if (!subscribePrompt.subscribe) {
|
|
173
|
+
console.warn("The AIGNE Hub connection has been cancelled");
|
|
174
|
+
process.exit(0);
|
|
175
|
+
}
|
|
176
|
+
const BLOCKLET_JSON_PATH = "__blocklet__.js?type=json";
|
|
177
|
+
const blockletInfo = await fetch(joinURL(origin, BLOCKLET_JSON_PATH));
|
|
178
|
+
const blocklet = await blockletInfo.json();
|
|
179
|
+
const aigneHubMount = (blocklet?.componentMountPoints || []).find((m) => m.did === "z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ");
|
|
180
|
+
try {
|
|
181
|
+
const result = await createConnect({
|
|
182
|
+
connectUrl: connectUrl,
|
|
183
|
+
connectAction: "gen-simple-access-key",
|
|
184
|
+
source: `@aigne/cli connect to AIGNE hub`,
|
|
185
|
+
closeOnSuccess: true,
|
|
186
|
+
openPage: (pageUrl) => open(pageUrl),
|
|
187
|
+
});
|
|
188
|
+
accessKeyOptions = {
|
|
189
|
+
accessKey: result.accessKeySecret,
|
|
190
|
+
url: joinURL(origin, aigneHubMount?.mountPoint || ""),
|
|
191
|
+
};
|
|
192
|
+
// After redirection, write the AIGNE Hub access token
|
|
193
|
+
await appendFile(AIGNE_ENV_FILE, stringify({
|
|
194
|
+
[host]: {
|
|
195
|
+
AIGNE_HUB_API_KEY: accessKeyOptions.accessKey,
|
|
196
|
+
AIGNE_HUB_API_URL: accessKeyOptions.url,
|
|
197
|
+
},
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
console.error(error);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const model = await loadModel(models, parseModelOption(modelName), undefined, accessKeyOptions);
|
|
208
|
+
return await AIGNE.load(path, { models, memories: availableMemories, model });
|
|
209
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "cli for AIGNE framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -37,10 +37,14 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@aigne/listr2": "^1.0.10",
|
|
39
39
|
"@aigne/marked-terminal": "^7.3.2",
|
|
40
|
+
"@inquirer/prompts": "^7.6.0",
|
|
41
|
+
"@listr2/prompt-adapter-inquirer": "^3.0.1",
|
|
40
42
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
43
|
+
"@ocap/mcrypto": "^1.21.0",
|
|
41
44
|
"@smithy/node-http-handler": "^4.1.0",
|
|
42
45
|
"chalk": "^5.4.1",
|
|
43
46
|
"commander": "^14.0.0",
|
|
47
|
+
"crypto": "^1.0.1",
|
|
44
48
|
"detect-port": "^2.1.0",
|
|
45
49
|
"dotenv-flow": "^4.1.0",
|
|
46
50
|
"express": "^5.1.0",
|
|
@@ -49,25 +53,26 @@
|
|
|
49
53
|
"https-proxy-agent": "^7.0.6",
|
|
50
54
|
"inquirer": "^12.7.0",
|
|
51
55
|
"marked": "^16.0.0",
|
|
56
|
+
"open": "10.1.2",
|
|
52
57
|
"prettier": "^3.6.2",
|
|
53
58
|
"tar": "^7.4.3",
|
|
54
59
|
"wrap-ansi": "^9.0.0",
|
|
55
60
|
"yaml": "^2.8.0",
|
|
56
61
|
"zod": "^3.25.67",
|
|
57
|
-
"@aigne/
|
|
58
|
-
"@aigne/
|
|
59
|
-
"@aigne/
|
|
60
|
-
"@aigne/anthropic": "^0.
|
|
61
|
-
"@aigne/core": "^1.
|
|
62
|
-
"@aigne/
|
|
63
|
-
"@aigne/
|
|
64
|
-
"@aigne/
|
|
65
|
-
"@aigne/gemini": "^0.8.
|
|
62
|
+
"@aigne/agentic-memory": "^1.0.4",
|
|
63
|
+
"@aigne/agent-library": "^1.21.4",
|
|
64
|
+
"@aigne/bedrock": "^0.8.4",
|
|
65
|
+
"@aigne/anthropic": "^0.10.0",
|
|
66
|
+
"@aigne/core": "^1.38.0",
|
|
67
|
+
"@aigne/aigne-hub": "^0.2.0",
|
|
68
|
+
"@aigne/deepseek": "^0.7.4",
|
|
69
|
+
"@aigne/default-memory": "^1.0.4",
|
|
70
|
+
"@aigne/gemini": "^0.8.4",
|
|
71
|
+
"@aigne/ollama": "^0.7.4",
|
|
66
72
|
"@aigne/observability-api": "^0.8.0",
|
|
67
|
-
"@aigne/
|
|
68
|
-
"@aigne/open-router": "^0.7.
|
|
69
|
-
"@aigne/
|
|
70
|
-
"@aigne/xai": "^0.7.3"
|
|
73
|
+
"@aigne/openai": "^0.10.4",
|
|
74
|
+
"@aigne/open-router": "^0.7.4",
|
|
75
|
+
"@aigne/xai": "^0.7.4"
|
|
71
76
|
},
|
|
72
77
|
"devDependencies": {
|
|
73
78
|
"@types/archiver": "^6.0.3",
|