@aigne/cli 1.52.0-beta → 1.52.0-beta.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
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.52.0-beta.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.52.0-beta...cli-v1.52.0-beta.1) (2025-10-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* add validate/required support for terminal input ([#651](https://github.com/AIGNE-io/aigne-framework/issues/651)) ([3d7f94c](https://github.com/AIGNE-io/aigne-framework/commit/3d7f94c32c8ec7bebb8f71fb16ddd3dd74a2d255))
|
|
9
|
+
* improve model name parsing to handle complex model identifiers ([#654](https://github.com/AIGNE-io/aigne-framework/issues/654)) ([4b7faea](https://github.com/AIGNE-io/aigne-framework/commit/4b7faea97f33db34a51c49dde3d6c1cf2679f0cd))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Dependencies
|
|
13
|
+
|
|
14
|
+
* The following workspace dependencies were updated
|
|
15
|
+
* dependencies
|
|
16
|
+
* @aigne/afs-system-fs bumped to 1.0.2-beta.1
|
|
17
|
+
* @aigne/agent-library bumped to 1.21.49-beta.1
|
|
18
|
+
* @aigne/agentic-memory bumped to 1.0.49-beta.1
|
|
19
|
+
* @aigne/aigne-hub bumped to 0.10.3-beta.1
|
|
20
|
+
* @aigne/core bumped to 1.64.0-beta.1
|
|
21
|
+
* @aigne/default-memory bumped to 1.2.12-beta.1
|
|
22
|
+
* @aigne/openai bumped to 0.16.3-beta.1
|
|
23
|
+
* devDependencies
|
|
24
|
+
* @aigne/test-utils bumped to 0.5.56-beta.1
|
|
25
|
+
|
|
3
26
|
## [1.52.0-beta](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.51.0...cli-v1.52.0-beta) (2025-10-21)
|
|
4
27
|
|
|
5
28
|
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { render } from "ink";
|
|
2
|
+
export declare function terminalInput({ render: r, ...options }?: {
|
|
2
3
|
message?: string;
|
|
3
4
|
default?: string;
|
|
4
5
|
inline?: boolean;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
validate?: (input: string) => string | boolean | Promise<string | boolean>;
|
|
8
|
+
render?: typeof render;
|
|
5
9
|
}): Promise<string>;
|
|
10
|
+
export declare function TerminalInput(props: {
|
|
11
|
+
message?: string;
|
|
12
|
+
default?: string;
|
|
13
|
+
inline?: boolean;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
validate?: (input: string) => string | boolean | Promise<string | boolean>;
|
|
16
|
+
onSubmit: (input: string) => void;
|
|
17
|
+
onError: (error: Error) => void;
|
|
18
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,30 +2,37 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { ExitPromptError } from "@inquirer/core";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { Box, render, Text, useInput } from "ink";
|
|
5
|
-
import { useState } from "react";
|
|
5
|
+
import { useRef, useState } from "react";
|
|
6
6
|
import { useTextBuffer } from "./text-buffer.js";
|
|
7
|
-
export async function terminalInput(options = {}) {
|
|
7
|
+
export async function terminalInput({ render: r = render, ...options } = {}) {
|
|
8
8
|
return new Promise((resolve, reject) => {
|
|
9
|
-
|
|
9
|
+
const handleSigInt = () => {
|
|
10
10
|
reject(new Error("Input aborted"));
|
|
11
|
-
}
|
|
12
|
-
|
|
11
|
+
};
|
|
12
|
+
process.addListener("SIGINT", handleSigInt);
|
|
13
|
+
const clean = () => process.removeListener("SIGINT", handleSigInt);
|
|
14
|
+
const app = r(_jsx(TerminalInput, { ...options, onSubmit: (value) => {
|
|
13
15
|
app.unmount();
|
|
14
16
|
resolve(value);
|
|
17
|
+
clean();
|
|
15
18
|
}, onError: (error) => {
|
|
16
19
|
app.unmount();
|
|
17
20
|
reject(error);
|
|
21
|
+
clean();
|
|
18
22
|
} }), { exitOnCtrlC: false });
|
|
19
23
|
});
|
|
20
24
|
}
|
|
21
|
-
function
|
|
25
|
+
export function TerminalInput(props) {
|
|
22
26
|
const buffer = useTextBuffer({
|
|
23
27
|
initialText: props.default || "",
|
|
24
28
|
initialCursorOffset: props.default?.length || 0,
|
|
25
29
|
isValidPath: () => false,
|
|
26
30
|
viewport: { width: 80, height: 1 },
|
|
27
31
|
});
|
|
32
|
+
const textRef = useRef(buffer.text);
|
|
33
|
+
textRef.current = buffer.text;
|
|
28
34
|
const [status, setStatus] = useState("input");
|
|
35
|
+
const [errorMessage, setErrorMessage] = useState();
|
|
29
36
|
useInput((character, key) => {
|
|
30
37
|
if (character === "c" && key.ctrl) {
|
|
31
38
|
setStatus("error");
|
|
@@ -35,10 +42,37 @@ function Input(props) {
|
|
|
35
42
|
return;
|
|
36
43
|
}
|
|
37
44
|
if (key.return) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
const input = textRef.current || props.default || "";
|
|
46
|
+
setStatus("validating");
|
|
47
|
+
setErrorMessage(undefined);
|
|
48
|
+
// Handle validation
|
|
49
|
+
const validateInput = async () => {
|
|
50
|
+
try {
|
|
51
|
+
// Check required validation first
|
|
52
|
+
if (props.required && !input.trim()) {
|
|
53
|
+
setErrorMessage("You must provide a value");
|
|
54
|
+
setStatus("input");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Run custom validation if provided
|
|
58
|
+
if (props.validate) {
|
|
59
|
+
const result = await props.validate(input);
|
|
60
|
+
if (result !== true) {
|
|
61
|
+
setErrorMessage(typeof result === "string" ? result : "You must provide a valid value");
|
|
62
|
+
setStatus("input");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Validation passed
|
|
67
|
+
setStatus("success");
|
|
68
|
+
props.onSubmit(input);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
setErrorMessage(error instanceof Error ? error.message : "Validation error");
|
|
72
|
+
setStatus("input");
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
validateInput();
|
|
42
76
|
return;
|
|
43
77
|
}
|
|
44
78
|
else if (key.backspace)
|
|
@@ -59,6 +93,7 @@ function Input(props) {
|
|
|
59
93
|
buffer.move("end");
|
|
60
94
|
else {
|
|
61
95
|
buffer.handleInput({ ...key, name: character, sequence: character, paste: false });
|
|
96
|
+
setErrorMessage(undefined);
|
|
62
97
|
}
|
|
63
98
|
});
|
|
64
99
|
const lines = [...buffer.lines];
|
|
@@ -72,10 +107,11 @@ function Input(props) {
|
|
|
72
107
|
}
|
|
73
108
|
const label = props.message && chalk.bold(props.message);
|
|
74
109
|
const inline = props.inline !== false;
|
|
75
|
-
return (_jsxs(Box, { flexDirection: inline ? "row" : "column", children: [_jsxs(Text, { children: [PREFIX[status], " ", !inline && label] }), _jsx(Box, { flexShrink: 1, flexGrow: 1, marginLeft: inline ? 0 : 2, marginRight: 1, children: _jsxs(Text, { children: [!!label && inline && `${label} `, lines.join("\n")] }) })] }));
|
|
110
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: inline ? "row" : "column", children: [_jsxs(Text, { children: [PREFIX[status], " ", !inline && label] }), _jsx(Box, { flexShrink: 1, flexGrow: 1, marginLeft: inline ? 0 : 2, marginRight: 1, children: _jsxs(Text, { children: [!!label && inline && `${label} `, lines.join("\n")] }) })] }), errorMessage && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "red", children: errorMessage }) }))] }));
|
|
76
111
|
}
|
|
77
112
|
const PREFIX = {
|
|
78
113
|
input: chalk.blue("?"),
|
|
114
|
+
validating: chalk.yellow("⋯"),
|
|
79
115
|
success: chalk.green("✔"),
|
|
80
116
|
error: chalk.red("✘"),
|
|
81
117
|
};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ChatModel, ChatModelInputOptions, ImageModel, ImageModelInputOptions } from "@aigne/core";
|
|
2
2
|
import type { LoadCredentialOptions } from "./type.js";
|
|
3
3
|
export declare function maskApiKey(apiKey?: string): string | undefined;
|
|
4
|
-
export declare const parseModelOption: (model: string) => {
|
|
5
|
-
provider: string | undefined;
|
|
6
|
-
model: string | undefined;
|
|
7
|
-
};
|
|
8
4
|
export declare const formatModelName: (model: string, inquirerPrompt: NonNullable<LoadCredentialOptions["inquirerPromptFn"]>) => Promise<{
|
|
9
5
|
provider: string;
|
|
10
6
|
model?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { AIGNE_HUB_DEFAULT_MODEL, AIGNE_HUB_URL, findImageModel, findModel, } from "@aigne/aigne-hub";
|
|
2
|
+
import { AIGNE_HUB_DEFAULT_MODEL, AIGNE_HUB_URL, findImageModel, findModel, parseModel, } from "@aigne/aigne-hub";
|
|
3
3
|
import { flat, omit } from "@aigne/core/utils/type-utils.js";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import inquirer from "inquirer";
|
|
@@ -13,13 +13,8 @@ export function maskApiKey(apiKey) {
|
|
|
13
13
|
const end = apiKey.slice(-4);
|
|
14
14
|
return `${start}${"*".repeat(8)}${end}`;
|
|
15
15
|
}
|
|
16
|
-
export const parseModelOption = (model) => {
|
|
17
|
-
model = model.replace(":", "/");
|
|
18
|
-
const { provider, name } = model.match(/(?<provider>[^/]*)(\/(?<name>.*))?/)?.groups ?? {};
|
|
19
|
-
return { provider: provider?.replace(/-/g, ""), model: name };
|
|
20
|
-
};
|
|
21
16
|
export const formatModelName = async (model, inquirerPrompt) => {
|
|
22
|
-
let { provider, model: name } =
|
|
17
|
+
let { provider, model: name } = parseModel(model);
|
|
23
18
|
provider ||= AIGNE_HUB_PROVIDER;
|
|
24
19
|
const { match, all } = findModel(provider);
|
|
25
20
|
if (!match) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.52.0-beta",
|
|
3
|
+
"version": "1.52.0-beta.1",
|
|
4
4
|
"description": "Your command center for agent development",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -89,14 +89,14 @@
|
|
|
89
89
|
"yoctocolors-cjs": "^2.1.3",
|
|
90
90
|
"zod": "^3.25.67",
|
|
91
91
|
"zod-to-json-schema": "^3.24.6",
|
|
92
|
-
"@aigne/afs-system-fs": "^1.0.2-beta",
|
|
93
|
-
"@aigne/
|
|
94
|
-
"@aigne/
|
|
95
|
-
"@aigne/
|
|
96
|
-
"@aigne/
|
|
97
|
-
"@aigne/default-memory": "^1.2.12-beta",
|
|
98
|
-
"@aigne/
|
|
99
|
-
"@aigne/
|
|
92
|
+
"@aigne/afs-system-fs": "^1.0.2-beta.1",
|
|
93
|
+
"@aigne/agent-library": "^1.21.49-beta.1",
|
|
94
|
+
"@aigne/agentic-memory": "^1.0.49-beta.1",
|
|
95
|
+
"@aigne/core": "^1.64.0-beta.1",
|
|
96
|
+
"@aigne/aigne-hub": "^0.10.3-beta.1",
|
|
97
|
+
"@aigne/default-memory": "^1.2.12-beta.1",
|
|
98
|
+
"@aigne/openai": "^0.16.3-beta.1",
|
|
99
|
+
"@aigne/observability-api": "^0.11.3-beta"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
102
|
"@inquirer/testing": "^2.1.50",
|
|
@@ -109,11 +109,12 @@
|
|
|
109
109
|
"@types/yargs": "^17.0.33",
|
|
110
110
|
"archiver": "^7.0.1",
|
|
111
111
|
"hono": "4.8.4",
|
|
112
|
+
"ink-testing-library": "^4.0.0",
|
|
112
113
|
"npm-run-all": "^4.1.5",
|
|
113
114
|
"rimraf": "^6.0.1",
|
|
114
115
|
"typescript": "^5.9.2",
|
|
115
116
|
"ufo": "^1.6.1",
|
|
116
|
-
"@aigne/test-utils": "^0.5.56-beta"
|
|
117
|
+
"@aigne/test-utils": "^0.5.56-beta.1"
|
|
117
118
|
},
|
|
118
119
|
"scripts": {
|
|
119
120
|
"lint": "tsc --noEmit",
|