@model-go/cli 0.1.3 → 0.1.5-rc.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/README.md +1 -1
- package/package.json +1 -2
- package/scripts/install-wizard.js +56 -0
- package/scripts/install.js +48 -13
- package/checksums.txt +0 -6
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ The CLI talks to a named environment. Two are built in:
|
|
|
44
44
|
| Env | Base URL |
|
|
45
45
|
| ------ | ---------------------------- |
|
|
46
46
|
| `cn` | `https://api.modelgo.com` |
|
|
47
|
-
| `intl` | `https://api.modelgo.
|
|
47
|
+
| `intl` | `https://api.modelgo.ai` |
|
|
48
48
|
|
|
49
49
|
The active environment defaults to `cn`. Switch it, or register your own:
|
|
50
50
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@model-go/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5-rc.1",
|
|
4
4
|
"description": "The official CLI for modelgo. Pairs with AI agent skills so AI agents can operate modelgo on your behalf.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"modelgo": "scripts/run.js"
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"scripts/install.js",
|
|
18
18
|
"scripts/install-wizard.js",
|
|
19
19
|
"scripts/run.js",
|
|
20
|
-
"checksums.txt",
|
|
21
20
|
"LICENSE",
|
|
22
21
|
"README.md"
|
|
23
22
|
],
|
|
@@ -34,6 +34,15 @@ const messages = {
|
|
|
34
34
|
done: "安装完成!\n试试跟你的 AI 工具(Claude Code、Codex 等)说:\"用 modelgo 跟我打个招呼\"",
|
|
35
35
|
cancelled: "安装已取消",
|
|
36
36
|
nonTtyHint: "非交互模式,已完成 npm 全局安装 + skills 安装。",
|
|
37
|
+
envPrompt: "请选择环境 / Select environment",
|
|
38
|
+
envCN: "国内(api.modelgo.com)",
|
|
39
|
+
envIntl: "国际(api.modelgo.ai)",
|
|
40
|
+
envDone: "已切换到 %s 环境",
|
|
41
|
+
envFail: "环境切换失败,可稍后运行: modelgo env use %s",
|
|
42
|
+
authPrompt: "现在登录 modelgo 吗?(将通过浏览器授权,也可稍后再登录)",
|
|
43
|
+
authDone: "登录成功",
|
|
44
|
+
authSkip: "已跳过登录。稍后运行: modelgo auth login",
|
|
45
|
+
authFail: "登录失败,可稍后运行: modelgo auth login",
|
|
37
46
|
},
|
|
38
47
|
en: {
|
|
39
48
|
setup: "Setting up modelgo CLI...",
|
|
@@ -49,6 +58,15 @@ const messages = {
|
|
|
49
58
|
done: "You are all set!\nTry asking your AI tool (Claude Code, Codex, etc.): \"Have modelgo say hello to me\"",
|
|
50
59
|
cancelled: "Installation cancelled",
|
|
51
60
|
nonTtyHint: "Non-interactive mode. Completed global install + skills install.",
|
|
61
|
+
envPrompt: "Select environment",
|
|
62
|
+
envCN: "China (api.modelgo.com)",
|
|
63
|
+
envIntl: "International (api.modelgo.ai)",
|
|
64
|
+
envDone: "Switched to %s environment",
|
|
65
|
+
envFail: "Failed to switch env. Run later: modelgo env use %s",
|
|
66
|
+
authPrompt: "Log in to modelgo now? (browser authorization; you can also log in later)",
|
|
67
|
+
authDone: "Logged in",
|
|
68
|
+
authSkip: "Skipped login. Run later: modelgo auth login",
|
|
69
|
+
authFail: "Login failed. Run later: modelgo auth login",
|
|
52
70
|
},
|
|
53
71
|
};
|
|
54
72
|
|
|
@@ -200,6 +218,42 @@ async function stepInstallSkills(msg, isInteractive) {
|
|
|
200
218
|
}
|
|
201
219
|
}
|
|
202
220
|
|
|
221
|
+
async function stepSelectEnv(msg) {
|
|
222
|
+
const env = handleCancel(
|
|
223
|
+
await p.select({
|
|
224
|
+
message: msg.envPrompt,
|
|
225
|
+
options: [
|
|
226
|
+
{ value: "cn", label: msg.envCN },
|
|
227
|
+
{ value: "intl", label: msg.envIntl },
|
|
228
|
+
],
|
|
229
|
+
}),
|
|
230
|
+
msg
|
|
231
|
+
);
|
|
232
|
+
try {
|
|
233
|
+
// `modelgo` is on PATH after the global install in stepInstallGlobally.
|
|
234
|
+
runSilent("modelgo", ["env", "use", env], { timeout: 15000 });
|
|
235
|
+
p.log.success(fmt(msg.envDone, env));
|
|
236
|
+
} catch (_) {
|
|
237
|
+
p.log.warn(fmt(msg.envFail, env));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function stepAuthLogin(msg) {
|
|
242
|
+
const wantLogin = handleCancel(await p.confirm({ message: msg.authPrompt }), msg);
|
|
243
|
+
if (!wantLogin) {
|
|
244
|
+
p.log.info(msg.authSkip);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
// `auth login` prints a verification URL and blocks polling until the user
|
|
249
|
+
// approves in the browser — inherit stdio so the URL and progress show.
|
|
250
|
+
execCmd("modelgo", ["auth", "login"], { stdio: "inherit" });
|
|
251
|
+
p.log.success(msg.authDone);
|
|
252
|
+
} catch (_) {
|
|
253
|
+
p.log.warn(msg.authFail);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
203
257
|
// ---------------------------------------------------------------------------
|
|
204
258
|
// Main
|
|
205
259
|
// ---------------------------------------------------------------------------
|
|
@@ -213,6 +267,8 @@ async function main() {
|
|
|
213
267
|
p.intro(msg.setup);
|
|
214
268
|
await stepInstallGlobally(msg, isInteractive);
|
|
215
269
|
await stepInstallSkills(msg, isInteractive);
|
|
270
|
+
await stepSelectEnv(msg);
|
|
271
|
+
await stepAuthLogin(msg);
|
|
216
272
|
p.outro(msg.done);
|
|
217
273
|
} else {
|
|
218
274
|
console.log(msg.setup);
|
package/scripts/install.js
CHANGED
|
@@ -31,6 +31,13 @@ const ext = isWindows ? ".zip" : ".tar.gz";
|
|
|
31
31
|
const archiveName = `${NAME}-${VERSION}-${platform}-${arch}${ext}`;
|
|
32
32
|
const GITHUB_URL = `https://github.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
|
|
33
33
|
|
|
34
|
+
// checksums.txt is published by goreleaser alongside the release artifacts.
|
|
35
|
+
// We fetch it from the release at install time rather than bundling it in the
|
|
36
|
+
// npm package: a bundled copy generated locally (goreleaser --snapshot) can
|
|
37
|
+
// never match the CI-built release artifacts' names or SHAs.
|
|
38
|
+
const CHECKSUMS_NAME = "checksums.txt";
|
|
39
|
+
const GITHUB_CHECKSUMS_URL = `https://github.com/${REPO}/releases/download/v${VERSION}/${CHECKSUMS_NAME}`;
|
|
40
|
+
|
|
34
41
|
const binDir = path.join(__dirname, "..", "bin");
|
|
35
42
|
const dest = path.join(binDir, NAME + (isWindows ? ".exe" : ""));
|
|
36
43
|
|
|
@@ -184,6 +191,21 @@ function download(url, destPath) {
|
|
|
184
191
|
execFileSync("curl", args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
185
192
|
}
|
|
186
193
|
|
|
194
|
+
// Try each URL in order, returning once one succeeds. Throws the last error if
|
|
195
|
+
// all fail.
|
|
196
|
+
function downloadFirst(urls, destPath) {
|
|
197
|
+
let lastErr;
|
|
198
|
+
for (const url of urls) {
|
|
199
|
+
try {
|
|
200
|
+
download(url, destPath);
|
|
201
|
+
return;
|
|
202
|
+
} catch (e) {
|
|
203
|
+
lastErr = e;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
throw lastErr;
|
|
207
|
+
}
|
|
208
|
+
|
|
187
209
|
function extractZipWindows(archivePath, destDir) {
|
|
188
210
|
const psOpts = ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command"];
|
|
189
211
|
const psStdio = ["ignore", "inherit", "inherit"];
|
|
@@ -228,20 +250,33 @@ function install() {
|
|
|
228
250
|
const archivePath = path.join(tmpDir, archiveName);
|
|
229
251
|
|
|
230
252
|
try {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
253
|
+
downloadFirst(downloadUrls, archivePath);
|
|
254
|
+
|
|
255
|
+
// Fetch the authoritative checksums.txt from the same release (GitHub
|
|
256
|
+
// first, then mirrors). If it can't be fetched (restricted network),
|
|
257
|
+
// skip verification rather than block the install — the binary itself
|
|
258
|
+
// came from an allowlisted host over HTTPS.
|
|
259
|
+
const checksumsUrls = [
|
|
260
|
+
GITHUB_CHECKSUMS_URL,
|
|
261
|
+
...resolveMirrorUrls(process.env, CHECKSUMS_NAME, VERSION),
|
|
262
|
+
];
|
|
263
|
+
for (const u of checksumsUrls) ALLOWED_HOSTS.add(new URL(u).hostname);
|
|
264
|
+
const checksumsPath = path.join(tmpDir, CHECKSUMS_NAME);
|
|
265
|
+
let checksumsFetched = true;
|
|
266
|
+
try {
|
|
267
|
+
downloadFirst(checksumsUrls, checksumsPath);
|
|
268
|
+
} catch (e) {
|
|
269
|
+
checksumsFetched = false;
|
|
270
|
+
console.error(
|
|
271
|
+
`[WARN] could not fetch ${CHECKSUMS_NAME} from release ` +
|
|
272
|
+
`(${e.message}); skipping checksum verification`
|
|
273
|
+
);
|
|
241
274
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const expectedHash =
|
|
275
|
+
// A fetched-but-incomplete checksums.txt is a real integrity problem and
|
|
276
|
+
// must fail loudly, so parse outside the network try/catch above.
|
|
277
|
+
const expectedHash = checksumsFetched
|
|
278
|
+
? getExpectedChecksum(archiveName, tmpDir)
|
|
279
|
+
: null;
|
|
245
280
|
verifyChecksum(archivePath, expectedHash);
|
|
246
281
|
|
|
247
282
|
if (isWindows) {
|
package/checksums.txt
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
d2301f86bdccb4225e959062382d20108eaac2ce023456f306485b8addcacacc modelgo-0.1.2-rc.1-SNAPSHOT-7701312-darwin-amd64.tar.gz
|
|
2
|
-
88480f50f971139c72866d73a69a67368a08a260c96b71e04add4eb7d6676ecf modelgo-0.1.2-rc.1-SNAPSHOT-7701312-darwin-arm64.tar.gz
|
|
3
|
-
9bc1719a182e3b996a793491775fd501da419a6c526d2b8a7cb2e72479cd9e1c modelgo-0.1.2-rc.1-SNAPSHOT-7701312-linux-amd64.tar.gz
|
|
4
|
-
534554cb7b7fff278260b4e030fcbe30a0029c146d46980493a1d902e65c7669 modelgo-0.1.2-rc.1-SNAPSHOT-7701312-linux-arm64.tar.gz
|
|
5
|
-
13cfa7761480b595fab0e1c3400c299013d29eaca3643282f2817b872b7d89d1 modelgo-0.1.2-rc.1-SNAPSHOT-7701312-windows-amd64.zip
|
|
6
|
-
3d57522bf6cfaeaded3ea3b6db4cf4afd8ddd4f0fbf0bcea71241531898a939c modelgo-0.1.2-rc.1-SNAPSHOT-7701312-windows-arm64.zip
|