@aigne/cli 1.34.0 → 1.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/dist/commands/aigne.js +2 -2
- package/dist/commands/hub.d.ts +2 -0
- package/dist/commands/hub.js +271 -0
- package/package.json +8 -8
- package/dist/commands/connect.d.ts +0 -13
- package/dist/commands/connect.js +0 -125
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.35.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.35.0...cli-v1.35.1) (2025-08-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Dependencies
|
|
7
|
+
|
|
8
|
+
* The following workspace dependencies were updated
|
|
9
|
+
* dependencies
|
|
10
|
+
* @aigne/aigne-hub bumped to 0.5.1
|
|
11
|
+
|
|
12
|
+
## [1.35.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.34.1...cli-v1.35.0) (2025-08-13)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* **cli:** support aigne hub commond ([#352](https://github.com/AIGNE-io/aigne-framework/issues/352)) ([0341f19](https://github.com/AIGNE-io/aigne-framework/commit/0341f190229b42c5d2ab8a8616597359f35543a7))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Dependencies
|
|
21
|
+
|
|
22
|
+
* The following workspace dependencies were updated
|
|
23
|
+
* dependencies
|
|
24
|
+
* @aigne/aigne-hub bumped to 0.5.0
|
|
25
|
+
|
|
26
|
+
## [1.34.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.34.0...cli-v1.34.1) (2025-08-12)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Dependencies
|
|
30
|
+
|
|
31
|
+
* The following workspace dependencies were updated
|
|
32
|
+
* dependencies
|
|
33
|
+
* @aigne/agent-library bumped to 1.21.19
|
|
34
|
+
* @aigne/agentic-memory bumped to 1.0.19
|
|
35
|
+
* @aigne/aigne-hub bumped to 0.4.10
|
|
36
|
+
* @aigne/core bumped to 1.49.1
|
|
37
|
+
* @aigne/default-memory bumped to 1.1.1
|
|
38
|
+
* @aigne/openai bumped to 0.11.1
|
|
39
|
+
|
|
3
40
|
## [1.34.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.33.1...cli-v1.34.0) (2025-08-12)
|
|
4
41
|
|
|
5
42
|
|
package/dist/commands/aigne.js
CHANGED
|
@@ -3,8 +3,8 @@ import yargs from "yargs";
|
|
|
3
3
|
import { AIGNE_CLI_VERSION } from "../constants.js";
|
|
4
4
|
import { asciiLogo } from "../utils/ascii-logo.js";
|
|
5
5
|
import { createAppCommands } from "./app.js";
|
|
6
|
-
import { createConnectCommand } from "./connect.js";
|
|
7
6
|
import { createCreateCommand } from "./create.js";
|
|
7
|
+
import { createHubCommand } from "./hub.js";
|
|
8
8
|
import { createObservabilityCommand } from "./observe.js";
|
|
9
9
|
import { createRunCommand } from "./run.js";
|
|
10
10
|
import { createServeMCPCommand } from "./serve-mcp.js";
|
|
@@ -21,8 +21,8 @@ export function createAIGNECommand(options) {
|
|
|
21
21
|
.command(createCreateCommand())
|
|
22
22
|
.command(createServeMCPCommand(options))
|
|
23
23
|
.command(createObservabilityCommand())
|
|
24
|
-
.command(createConnectCommand())
|
|
25
24
|
.command(createAppCommands())
|
|
25
|
+
.command(createHubCommand())
|
|
26
26
|
.demandCommand()
|
|
27
27
|
.alias("help", "h")
|
|
28
28
|
.alias("version", "v")
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { AIGNE_ENV_FILE, AIGNE_HUB_URL, connectToAIGNEHub, isTest } from "@aigne/aigne-hub";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import Table from "cli-table3";
|
|
6
|
+
import inquirer from "inquirer";
|
|
7
|
+
import { parse, stringify } from "yaml";
|
|
8
|
+
import { getUserInfo } from "../utils/aigne-hub-user.js";
|
|
9
|
+
const formatNumber = (balance) => {
|
|
10
|
+
const balanceNum = String(balance).split(".")[0];
|
|
11
|
+
return chalk.yellow((balanceNum || "").replace(/\B(?=(\d{3})+(?!\d))/g, ","));
|
|
12
|
+
};
|
|
13
|
+
function printHubStatus(data) {
|
|
14
|
+
const divider = "─".repeat(46);
|
|
15
|
+
console.log(chalk.bold("AIGNE Hub Connection"));
|
|
16
|
+
console.log(chalk.gray(divider));
|
|
17
|
+
console.log(`${chalk.bold("Hub:".padEnd(10))} ${data.hub}`);
|
|
18
|
+
console.log(`${chalk.bold("Status:".padEnd(10))} ${data.status === "Connected"
|
|
19
|
+
? chalk.green(`${data.status} ✅`)
|
|
20
|
+
: chalk.red(`${data.status} ❌`)}`);
|
|
21
|
+
console.log("");
|
|
22
|
+
console.log(chalk.bold("User:"));
|
|
23
|
+
console.log(` ${chalk.bold("Name:".padEnd(8))} ${data.user.name}`);
|
|
24
|
+
console.log(` ${chalk.bold("DID:".padEnd(8))} ${data.user.did}`);
|
|
25
|
+
console.log(` ${chalk.bold("Email:".padEnd(8))} ${data.user.email}`);
|
|
26
|
+
console.log("");
|
|
27
|
+
console.log(chalk.bold("Credits:"));
|
|
28
|
+
console.log(` ${chalk.bold("Used:".padEnd(8))} ${data.credits.used.toLocaleString()}`);
|
|
29
|
+
console.log(` ${chalk.bold("Total:".padEnd(8))} ${data.credits.total.toLocaleString()}`);
|
|
30
|
+
console.log("");
|
|
31
|
+
console.log(chalk.bold("Links:"));
|
|
32
|
+
console.log(` ${chalk.bold("Payment:".padEnd(8))} ${data.links.payment}`);
|
|
33
|
+
console.log(` ${chalk.bold("Profile:".padEnd(8))} ${data.links.profile}`);
|
|
34
|
+
}
|
|
35
|
+
async function getHubs() {
|
|
36
|
+
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const data = await readFile(AIGNE_ENV_FILE, "utf8");
|
|
41
|
+
const envs = parse(data);
|
|
42
|
+
const statusList = [];
|
|
43
|
+
for (const [host, config] of Object.entries(envs)) {
|
|
44
|
+
if (host !== "default") {
|
|
45
|
+
statusList.push({
|
|
46
|
+
host,
|
|
47
|
+
apiUrl: config.AIGNE_HUB_API_URL,
|
|
48
|
+
apiKey: config.AIGNE_HUB_API_KEY,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return statusList;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const getDefaultHub = async () => {
|
|
59
|
+
const envs = parse(await readFile(AIGNE_ENV_FILE, "utf8").catch(() => stringify({})));
|
|
60
|
+
return envs?.default?.AIGNE_HUB_API_URL || AIGNE_HUB_URL;
|
|
61
|
+
};
|
|
62
|
+
async function formatHubsList(statusList) {
|
|
63
|
+
if (statusList?.length === 0) {
|
|
64
|
+
console.log(chalk.yellow("No AIGNE Hub configured."));
|
|
65
|
+
console.log("Use 'aigne hub connect' to connect to a hub.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const defaultHub = await getDefaultHub();
|
|
69
|
+
const table = new Table({
|
|
70
|
+
head: ["URL", "ACTIVE", "STATUS"],
|
|
71
|
+
colWidths: [50, 10, 20],
|
|
72
|
+
style: {
|
|
73
|
+
head: ["cyan"],
|
|
74
|
+
border: ["grey"],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
console.log(chalk.blue("AIGNE Hubs:\n"));
|
|
78
|
+
for (const status of statusList) {
|
|
79
|
+
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
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
console.log(table.toString());
|
|
87
|
+
}
|
|
88
|
+
export function createHubCommand() {
|
|
89
|
+
return {
|
|
90
|
+
command: "hub <command>",
|
|
91
|
+
describe: "Manage AIGNE Hub connections",
|
|
92
|
+
builder: (yargs) => yargs
|
|
93
|
+
.command(["list", "ls"], "List all connected AIGNE Hubs", listHubs)
|
|
94
|
+
.command("connect", "Connect to an AIGNE Hub", connectHub)
|
|
95
|
+
.command("use", "Switch to a different AIGNE Hub", useHub)
|
|
96
|
+
.command(["status", "st"], "Show current active hub", showStatus)
|
|
97
|
+
.command(["remove", "rm"], "Remove a connected hub", removeHub)
|
|
98
|
+
.command(["info", "i"], "Show details of a connected hub", showInfo)
|
|
99
|
+
.demandCommand(1, "Please provide a valid hub command"),
|
|
100
|
+
handler: () => { },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const listHubs = async () => {
|
|
104
|
+
const list = await getHubs();
|
|
105
|
+
await formatHubsList(list);
|
|
106
|
+
};
|
|
107
|
+
async function connectHub() {
|
|
108
|
+
const defaultUrl = "https://hub.aigne.io";
|
|
109
|
+
const { isOfficial } = await inquirer.prompt({
|
|
110
|
+
type: "select",
|
|
111
|
+
name: "isOfficial",
|
|
112
|
+
message: `Choose a hub to connect:`,
|
|
113
|
+
choices: [
|
|
114
|
+
{ name: `Official Hub (${defaultUrl})`, value: true },
|
|
115
|
+
{ name: `Custom Hub URL`, value: false },
|
|
116
|
+
],
|
|
117
|
+
default: true,
|
|
118
|
+
});
|
|
119
|
+
let currentUrl = defaultUrl;
|
|
120
|
+
if (!isOfficial) {
|
|
121
|
+
const { customUrl } = await inquirer.prompt({
|
|
122
|
+
type: "input",
|
|
123
|
+
name: "customUrl",
|
|
124
|
+
message: "Enter the URL of your AIGNE Hub:",
|
|
125
|
+
validate: validateUrl,
|
|
126
|
+
});
|
|
127
|
+
currentUrl = customUrl;
|
|
128
|
+
}
|
|
129
|
+
await saveAndConnect(currentUrl);
|
|
130
|
+
}
|
|
131
|
+
async function useHub() {
|
|
132
|
+
const hubs = await getHubs();
|
|
133
|
+
if (!hubs.length) {
|
|
134
|
+
console.log(chalk.yellow("No AIGNE Hub configured."));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const { hubApiKey } = await inquirer.prompt({
|
|
138
|
+
type: "select",
|
|
139
|
+
name: "hubApiKey",
|
|
140
|
+
message: `Choose a hub to switch to:`,
|
|
141
|
+
choices: hubs.map((h) => ({
|
|
142
|
+
name: new URL(h.apiUrl).origin,
|
|
143
|
+
value: h.apiUrl,
|
|
144
|
+
})),
|
|
145
|
+
});
|
|
146
|
+
await setDefaultHub(hubApiKey);
|
|
147
|
+
}
|
|
148
|
+
async function showStatus() {
|
|
149
|
+
const active = await getDefaultHub();
|
|
150
|
+
if (!active) {
|
|
151
|
+
console.log(chalk.red("No active hub."));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
console.log(`Active hub: ${active} - online`);
|
|
155
|
+
}
|
|
156
|
+
async function removeHub() {
|
|
157
|
+
const hubs = await getHubs();
|
|
158
|
+
if (!hubs.length) {
|
|
159
|
+
console.log(chalk.yellow("No AIGNE Hub configured."));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const { hubApiKey } = await inquirer.prompt({
|
|
163
|
+
type: "select",
|
|
164
|
+
name: "hubApiKey",
|
|
165
|
+
message: `Choose a hub to remove:`,
|
|
166
|
+
choices: hubs.map((h) => ({
|
|
167
|
+
name: new URL(h.apiUrl).origin,
|
|
168
|
+
value: h.apiUrl,
|
|
169
|
+
})),
|
|
170
|
+
});
|
|
171
|
+
await deleteHub(hubApiKey);
|
|
172
|
+
}
|
|
173
|
+
async function showInfo() {
|
|
174
|
+
const hubs = await getHubs();
|
|
175
|
+
if (!hubs.length) {
|
|
176
|
+
console.log(chalk.yellow("No AIGNE Hub configured."));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const { hubApiKey } = await inquirer.prompt({
|
|
180
|
+
type: "select",
|
|
181
|
+
name: "hubApiKey",
|
|
182
|
+
message: `Choose a hub to view info:`,
|
|
183
|
+
choices: hubs.map((h) => ({
|
|
184
|
+
name: new URL(h.apiUrl).origin,
|
|
185
|
+
value: h.apiUrl,
|
|
186
|
+
})),
|
|
187
|
+
});
|
|
188
|
+
await printHubDetails(hubApiKey);
|
|
189
|
+
}
|
|
190
|
+
function validateUrl(input) {
|
|
191
|
+
try {
|
|
192
|
+
const url = new URL(input);
|
|
193
|
+
return url.protocol.startsWith("http") ? true : "Must be http or https";
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return "Invalid URL";
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function saveAndConnect(url) {
|
|
200
|
+
const envs = parse(await readFile(AIGNE_ENV_FILE, "utf8").catch(() => stringify({})));
|
|
201
|
+
const host = new URL(url).host;
|
|
202
|
+
if (envs[host]) {
|
|
203
|
+
await setDefaultHub(envs[host]?.AIGNE_HUB_API_URL || "");
|
|
204
|
+
console.log(chalk.green(`✓ Hub ${envs[host]?.AIGNE_HUB_API_URL} connected successfully.`));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
if (isTest) {
|
|
209
|
+
writeFile(AIGNE_ENV_FILE, stringify({
|
|
210
|
+
"hub.aigne.io": {
|
|
211
|
+
AIGNE_HUB_API_KEY: "test-key",
|
|
212
|
+
AIGNE_HUB_API_URL: "https://hub.aigne.io/ai-kit",
|
|
213
|
+
},
|
|
214
|
+
default: {
|
|
215
|
+
AIGNE_HUB_API_URL: "https://hub.aigne.io/ai-kit",
|
|
216
|
+
},
|
|
217
|
+
}));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
await connectToAIGNEHub(url);
|
|
221
|
+
console.log(chalk.green(`✓ Hub ${url} connected successfully.`));
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error(chalk.red("✗ Failed to connect:"), error.message);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function setDefaultHub(url) {
|
|
228
|
+
const envs = parse(await readFile(AIGNE_ENV_FILE, "utf8").catch(() => stringify({})));
|
|
229
|
+
const host = new URL(url).host;
|
|
230
|
+
if (!envs[host]) {
|
|
231
|
+
console.error(chalk.red("✗ Hub not found"));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
await writeFile(AIGNE_ENV_FILE, stringify({ ...envs, default: { AIGNE_HUB_API_URL: envs[host]?.AIGNE_HUB_API_URL } }));
|
|
235
|
+
console.log(chalk.green(`✓ Switched active hub to ${url}`));
|
|
236
|
+
}
|
|
237
|
+
async function deleteHub(url) {
|
|
238
|
+
const envs = parse(await readFile(AIGNE_ENV_FILE, "utf8").catch(() => stringify({})));
|
|
239
|
+
const host = new URL(url).host;
|
|
240
|
+
delete envs[host];
|
|
241
|
+
if (envs.default?.AIGNE_HUB_API_URL && new URL(envs.default?.AIGNE_HUB_API_URL).host === host) {
|
|
242
|
+
delete envs.default;
|
|
243
|
+
}
|
|
244
|
+
await writeFile(AIGNE_ENV_FILE, stringify(envs));
|
|
245
|
+
console.log(chalk.green(`✓ Hub ${url} removed`));
|
|
246
|
+
}
|
|
247
|
+
async function printHubDetails(url) {
|
|
248
|
+
const envs = parse(await readFile(AIGNE_ENV_FILE, "utf8").catch(() => stringify({})));
|
|
249
|
+
const host = new URL(url).host;
|
|
250
|
+
const userInfo = await getUserInfo({
|
|
251
|
+
baseUrl: envs[host]?.AIGNE_HUB_API_URL || "",
|
|
252
|
+
apiKey: envs[host]?.AIGNE_HUB_API_KEY || "",
|
|
253
|
+
}).catch(() => null);
|
|
254
|
+
printHubStatus({
|
|
255
|
+
hub: url,
|
|
256
|
+
status: userInfo ? "Connected" : "Not connected",
|
|
257
|
+
user: {
|
|
258
|
+
name: userInfo?.user.fullName || "",
|
|
259
|
+
did: userInfo?.user.did || "",
|
|
260
|
+
email: userInfo?.user.email || "",
|
|
261
|
+
},
|
|
262
|
+
credits: {
|
|
263
|
+
used: formatNumber(userInfo?.creditBalance?.balance || "0"),
|
|
264
|
+
total: formatNumber(userInfo?.creditBalance?.total || "0"),
|
|
265
|
+
},
|
|
266
|
+
links: {
|
|
267
|
+
payment: userInfo?.paymentLink || "",
|
|
268
|
+
profile: userInfo?.profileLink || "",
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.1",
|
|
4
4
|
"description": "Your command center for agent development",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
54
54
|
"@smithy/node-http-handler": "^4.1.0",
|
|
55
55
|
"chalk": "^5.4.1",
|
|
56
|
+
"cli-table3": "^0.6.5",
|
|
56
57
|
"detect-port": "^2.1.0",
|
|
57
58
|
"dotenv-flow": "^4.1.0",
|
|
58
59
|
"express": "^5.1.0",
|
|
@@ -63,7 +64,6 @@
|
|
|
63
64
|
"log-update": "^6.1.0",
|
|
64
65
|
"marked": "^16.0.0",
|
|
65
66
|
"nunjucks": "^3.2.4",
|
|
66
|
-
"open": "10.1.2",
|
|
67
67
|
"openai": "^5.8.3",
|
|
68
68
|
"prettier": "^3.6.2",
|
|
69
69
|
"tar": "^7.4.3",
|
|
@@ -71,13 +71,13 @@
|
|
|
71
71
|
"yaml": "^2.8.0",
|
|
72
72
|
"yargs": "^18.0.0",
|
|
73
73
|
"zod": "^3.25.67",
|
|
74
|
-
"@aigne/agent-library": "^1.21.
|
|
75
|
-
"@aigne/agentic-memory": "^1.0.
|
|
76
|
-
"@aigne/aigne-hub": "^0.
|
|
77
|
-
"@aigne/core": "^1.49.
|
|
78
|
-
"@aigne/default-memory": "^1.1.0",
|
|
74
|
+
"@aigne/agent-library": "^1.21.19",
|
|
75
|
+
"@aigne/agentic-memory": "^1.0.19",
|
|
76
|
+
"@aigne/aigne-hub": "^0.5.1",
|
|
77
|
+
"@aigne/core": "^1.49.1",
|
|
79
78
|
"@aigne/observability-api": "^0.9.0",
|
|
80
|
-
"@aigne/openai": "^0.11.
|
|
79
|
+
"@aigne/openai": "^0.11.1",
|
|
80
|
+
"@aigne/default-memory": "^1.1.1"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@types/archiver": "^6.0.3",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { CommandModule } from "yargs";
|
|
2
|
-
interface ConnectOptions {
|
|
3
|
-
url?: string;
|
|
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>;
|
|
12
|
-
export declare function createConnectCommand(): CommandModule<unknown, ConnectOptions>;
|
|
13
|
-
export {};
|
package/dist/commands/connect.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { AIGNE_ENV_FILE, AIGNE_HUB_URL, connectToAIGNEHub } from "@aigne/aigne-hub";
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
import { parse, stringify } from "yaml";
|
|
6
|
-
import { getUserInfo } from "../utils/aigne-hub-user.js";
|
|
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() {
|
|
12
|
-
if (!existsSync(AIGNE_ENV_FILE)) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
const data = await readFile(AIGNE_ENV_FILE, "utf8");
|
|
17
|
-
const envs = parse(data);
|
|
18
|
-
const statusList = [];
|
|
19
|
-
for (const [host, config] of Object.entries(envs)) {
|
|
20
|
-
statusList.push({
|
|
21
|
-
host,
|
|
22
|
-
apiUrl: config.AIGNE_HUB_API_URL,
|
|
23
|
-
apiKey: config.AIGNE_HUB_API_KEY,
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
return statusList;
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export async function displayStatus(statusList) {
|
|
33
|
-
if (statusList.length === 0) {
|
|
34
|
-
console.log(chalk.yellow("No AIGNE Hub connections found."));
|
|
35
|
-
console.log("Use 'aigne connect <url>' to connect to a hub.");
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
console.log(chalk.cyan("AIGNE Hub Connection Status:\n"));
|
|
39
|
-
const defaultStatus = statusList.find((status) => status.host === "default")?.apiUrl || AIGNE_HUB_URL;
|
|
40
|
-
for (const status of statusList.filter((status) => status.host !== "default")) {
|
|
41
|
-
const userInfo = await getUserInfo({ baseUrl: status.apiUrl, apiKey: status.apiKey }).catch(() => null);
|
|
42
|
-
const isConnected = new URL(status.apiUrl).origin === new URL(defaultStatus).origin;
|
|
43
|
-
const statusIcon = isConnected ? chalk.green("✓") : "•";
|
|
44
|
-
const statusText = isConnected ? "Connected" : "Not connected";
|
|
45
|
-
console.log(`${statusIcon} ${chalk.bold(status.host)}`);
|
|
46
|
-
console.log(` Status: ${statusText}`);
|
|
47
|
-
if (userInfo) {
|
|
48
|
-
console.log(` User: ${userInfo?.user.fullName}`);
|
|
49
|
-
console.log(` User DID: ${userInfo?.user.did}`);
|
|
50
|
-
if (userInfo?.user.email) {
|
|
51
|
-
console.log(` Email: ${userInfo?.user.email}`);
|
|
52
|
-
}
|
|
53
|
-
if (userInfo?.creditBalance) {
|
|
54
|
-
const balance = formatNumber(userInfo?.creditBalance?.balance);
|
|
55
|
-
const total = formatNumber(userInfo?.creditBalance?.total);
|
|
56
|
-
console.log(` Credits: ${balance} / ${total}`);
|
|
57
|
-
}
|
|
58
|
-
console.log(` Payment URL: ${userInfo?.paymentLink ? chalk.green(userInfo.paymentLink) : chalk.red("N/A")}`);
|
|
59
|
-
console.log(` Profile URL: ${userInfo?.profileLink ? chalk.green(userInfo.profileLink) : chalk.red("N/A")}`);
|
|
60
|
-
}
|
|
61
|
-
console.log("");
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export function createConnectCommand() {
|
|
65
|
-
return {
|
|
66
|
-
command: "connect [url]",
|
|
67
|
-
describe: "Manage AIGNE Hub connections",
|
|
68
|
-
builder: (yargs) => {
|
|
69
|
-
return yargs
|
|
70
|
-
.positional("url", {
|
|
71
|
-
describe: "URL to the AIGNE Hub server",
|
|
72
|
-
type: "string",
|
|
73
|
-
default: "https://hub.aigne.io/",
|
|
74
|
-
})
|
|
75
|
-
.command({
|
|
76
|
-
command: "status",
|
|
77
|
-
describe: "Show current connection status",
|
|
78
|
-
handler: async () => {
|
|
79
|
-
const statusList = await getConnectionStatus();
|
|
80
|
-
await displayStatus(statusList);
|
|
81
|
-
},
|
|
82
|
-
})
|
|
83
|
-
.command({
|
|
84
|
-
command: "switch",
|
|
85
|
-
describe: "Switch to a different AIGNE Hub",
|
|
86
|
-
handler: async (argv) => {
|
|
87
|
-
const url = argv.url;
|
|
88
|
-
console.log("Switching to AIGNE Hub: ", chalk.blue(url));
|
|
89
|
-
if (!url) {
|
|
90
|
-
console.error(chalk.red("✗ Please provide a URL to the AIGNE Hub server"));
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
const data = await readFile(AIGNE_ENV_FILE, "utf8");
|
|
94
|
-
const envs = parse(data);
|
|
95
|
-
let host = "";
|
|
96
|
-
try {
|
|
97
|
-
host = new URL(url).host;
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
console.error(chalk.red("✗ Invalid URL"));
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
if (!envs[host]) {
|
|
104
|
-
console.error(chalk.red("✗ AIGNE Hub already connected"));
|
|
105
|
-
process.exit(1);
|
|
106
|
-
}
|
|
107
|
-
await writeFile(AIGNE_ENV_FILE, stringify({ ...envs, default: { AIGNE_HUB_API_URL: envs[host]?.AIGNE_HUB_API_URL } }));
|
|
108
|
-
console.log(chalk.green("✓ Successfully connected to AIGNE Hub"));
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
},
|
|
112
|
-
handler: async (argv) => {
|
|
113
|
-
const url = argv.url || "https://hub.aigne.io/";
|
|
114
|
-
console.log(chalk.cyan(`Connecting to AIGNE Hub: ${url}`));
|
|
115
|
-
try {
|
|
116
|
-
await connectToAIGNEHub(url);
|
|
117
|
-
console.log(chalk.green("✓ Successfully connected to AIGNE Hub"));
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
console.error(chalk.red("✗ Failed to connect to AIGNE Hub:"), error.message);
|
|
121
|
-
process.exit(1);
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
}
|