mu-agent 0.1.10 → 0.1.14
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 +122 -0
- package/README.md +7 -7
- package/dist/bundle/chunks/{chunk-DNNHZBQR.js → chunk-6Z2347ML.js} +1 -1
- package/dist/bundle/chunks/{chunk-FN6OEZYR.js → chunk-AN7MSYCK.js} +1 -1
- package/dist/bundle/chunks/{chunk-O7IPTASE.js → chunk-BK7M6BDT.js} +22 -21
- package/dist/bundle/chunks/{chunk-X234222Q.js → chunk-DYTENXHX.js} +2 -2
- package/dist/bundle/chunks/{chunk-RAQ6TU76.js → chunk-FLHKNMLQ.js} +1 -1
- package/dist/bundle/chunks/chunk-LHRPMXVI.js +2 -0
- package/dist/bundle/chunks/{chunk-HZNN636Z.js → chunk-LT2C56HV.js} +1 -1
- package/dist/bundle/chunks/{chunk-SGOTYFMT.js → chunk-MF3VB62R.js} +1 -1
- package/dist/bundle/chunks/{chunk-QOEEJKS4.js → chunk-URBBMV3M.js} +1 -1
- package/dist/bundle/chunks/{chunk-VJLOQZKR.js → chunk-WCJNJQO5.js} +1 -1
- package/dist/bundle/chunks/{cli-722OL3K5.js → cli-M4YBZZ6Q.js} +1 -1
- package/dist/bundle/chunks/{easter-egg-3d-6H34EDGX.js → easter-egg-3d-VFY3YRQR.js} +1 -1
- package/dist/bundle/chunks/{execute-KVSEIDWL.js → execute-FKI7Y4XR.js} +1 -1
- package/dist/bundle/chunks/{runtime-O3ELDOM7.js → runtime-IKE5OQIW.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-IKEARUOZ.js → virtual-modules-U6MRV5BC.js} +1 -1
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/docs/settings.md +1 -1
- package/judge/dist/auth.js +54 -26
- package/judge/dist/chrome.js +2 -2
- package/judge/dist/import.js +833 -161
- package/judge/dist/setup.js +142 -48
- package/judge/manifest.json +2048 -394
- package/judge/mu/chunk-3NQ5BIBI.js +4773 -0
- package/judge/mu/chunk-6XRUK3PM.js +51 -0
- package/judge/mu/chunk-WQM4MV6L.js +58 -0
- package/judge/mu/cloud-code-XR7SZMJC.js +22802 -0
- package/judge/mu/dist-75PS4OC4.js +1283 -0
- package/judge/mu/index.js +4949 -32969
- package/judge/mu/multipart-parser-ZDXVIOOP.js +372 -0
- package/judge/mu/src-TVVA5ZK2.js +1409 -0
- package/kyrn/bin/kyrn-doctor +67 -14
- package/kyrn/bin/kyrn-judge-local +42 -13
- package/kyrn/bin/kyrn-ledger +16 -1
- package/kyrn/bin/mu.mjs +101 -29
- package/kyrn/local-judge/server.py +26 -14
- package/package.json +6 -3
- package/dist/bundle/chunks/chunk-BSS6T6KQ.js +0 -2
package/judge/dist/setup.js
CHANGED
|
@@ -200,6 +200,13 @@ function backupStamp(now) {
|
|
|
200
200
|
const two = (value) => String(value).padStart(2, "0");
|
|
201
201
|
return `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())}T${two(now.getHours())}-${two(now.getMinutes())}-${two(now.getSeconds())}`;
|
|
202
202
|
}
|
|
203
|
+
var holdsNothing = (file) => {
|
|
204
|
+
try {
|
|
205
|
+
return /^\s*(\{\s*\})?\s*$/.test(readFileSync(file, "utf8"));
|
|
206
|
+
} catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
203
210
|
var Backups = class {
|
|
204
211
|
root;
|
|
205
212
|
stamp;
|
|
@@ -209,9 +216,13 @@ var Backups = class {
|
|
|
209
216
|
this.root = join2(home2, "backups");
|
|
210
217
|
this.stamp = backupStamp(now);
|
|
211
218
|
}
|
|
212
|
-
/**
|
|
219
|
+
/**
|
|
220
|
+
* Copies `file` the first time it is about to change in this run. A file that does not exist, or holds nothing (empty,
|
|
221
|
+
* or the `{}` pi writes to auth.json when it first starts), has nothing to keep: a first setup makes no backup folder
|
|
222
|
+
* and does not say it kept the previous files.
|
|
223
|
+
*/
|
|
213
224
|
save(file) {
|
|
214
|
-
if (this.saved.has(file) || !existsSync2(file)) return;
|
|
225
|
+
if (this.saved.has(file) || !existsSync2(file) || holdsNothing(file)) return;
|
|
215
226
|
const folder = this.folder();
|
|
216
227
|
const copy = join2(folder, basename(file));
|
|
217
228
|
copyFileSync(file, copy);
|
|
@@ -328,6 +339,16 @@ function tiersOf(config) {
|
|
|
328
339
|
function withTiers(config, tiers) {
|
|
329
340
|
return { ...config, tiers: [...tiers] };
|
|
330
341
|
}
|
|
342
|
+
function judgeOff(config) {
|
|
343
|
+
return isRecord(config?.modes) && config.modes.default === "off";
|
|
344
|
+
}
|
|
345
|
+
function withJudge(config, on) {
|
|
346
|
+
const { default: _default, ...modes } = isRecord(config.modes) ? config.modes : {};
|
|
347
|
+
if (!on) return { ...config, modes: { default: "off", ...modes } };
|
|
348
|
+
if (!judgeOff(config)) return config;
|
|
349
|
+
const { modes: _modes, ...rest } = config;
|
|
350
|
+
return Object.keys(modes).length > 0 ? { ...rest, modes } : rest;
|
|
351
|
+
}
|
|
331
352
|
function readTextFile(path) {
|
|
332
353
|
try {
|
|
333
354
|
return readFileSync(path, "utf8");
|
|
@@ -378,14 +399,17 @@ function piAccess(runtime, agentDir2) {
|
|
|
378
399
|
storeKey: async (provider, key) => {
|
|
379
400
|
await runtime.refresh({ allowNetwork: false, providers: [provider] });
|
|
380
401
|
if (!runtime.getProvider(provider)) {
|
|
381
|
-
throw new Error(
|
|
402
|
+
throw new Error(
|
|
403
|
+
`mu has no provider named ${provider}${runtime.getError() ? `: ${runtime.getError()}` : ""}`
|
|
404
|
+
);
|
|
382
405
|
}
|
|
383
406
|
let asked = false;
|
|
384
407
|
try {
|
|
385
408
|
await runtime.login(provider, "api_key", {
|
|
386
409
|
// pi's key login asks one question, the key. Anything else is not answered, and nothing is guessed.
|
|
387
410
|
prompt: async (prompt) => {
|
|
388
|
-
if (asked || prompt.type !== "secret")
|
|
411
|
+
if (asked || prompt.type !== "secret")
|
|
412
|
+
throw new Error(`the sign-in for ${provider} asked for more than a key`);
|
|
389
413
|
asked = true;
|
|
390
414
|
return key;
|
|
391
415
|
},
|
|
@@ -459,11 +483,31 @@ function askSecret(input, output, question) {
|
|
|
459
483
|
input.resume();
|
|
460
484
|
});
|
|
461
485
|
}
|
|
486
|
+
var columnsOf = (char) => /[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe30-\ufe4f\uff00-\uff60\uffe0-\uffe6]/u.test(char) ? 2 : 1;
|
|
487
|
+
var widthOf = (text) => Array.from(text).reduce((sum, char) => sum + columnsOf(char), 0);
|
|
488
|
+
function wrapToWidth(text, width) {
|
|
489
|
+
if (!width || width < 20) return text;
|
|
490
|
+
return text.split("\n").map((line) => {
|
|
491
|
+
if (widthOf(line) <= width) return line;
|
|
492
|
+
const indent = " ".repeat(/^\s*(?:\d+\)\s+)?/.exec(line)?.[0].length ?? 0);
|
|
493
|
+
const out = [];
|
|
494
|
+
let current = "";
|
|
495
|
+
for (const word of line.trimEnd().split(/(?<=\S) (?=\S)/)) {
|
|
496
|
+
const next = current ? `${current} ${word}` : word;
|
|
497
|
+
if (current && widthOf(next) > width) {
|
|
498
|
+
out.push(current);
|
|
499
|
+
current = `${indent}${word.trimStart()}`;
|
|
500
|
+
} else current = next;
|
|
501
|
+
}
|
|
502
|
+
out.push(current);
|
|
503
|
+
return out.join("\n");
|
|
504
|
+
}).join("\n");
|
|
505
|
+
}
|
|
462
506
|
function terminalPrompter(input = process.stdin, output = process.stdout, errors = process.stderr) {
|
|
463
507
|
return {
|
|
464
|
-
say: (text) => output.write(`${text}
|
|
508
|
+
say: (text) => output.write(`${wrapToWidth(text, output.isTTY ? output.columns : void 0)}
|
|
465
509
|
`),
|
|
466
|
-
warn: (text) => errors.write(`${text}
|
|
510
|
+
warn: (text) => errors.write(`${wrapToWidth(text, errors.isTTY ? errors.columns : void 0)}
|
|
467
511
|
`),
|
|
468
512
|
ask: (question) => askLine(input, output, question),
|
|
469
513
|
secret: (question) => askSecret(input, output, question)
|
|
@@ -885,6 +929,12 @@ var SETUP_SERVICES = [
|
|
|
885
929
|
keyOptional: true
|
|
886
930
|
}
|
|
887
931
|
];
|
|
932
|
+
var FIRST_IN_ENGLISH = ["openai", "anthropic", "google", "xai", "openrouter", "opencode"];
|
|
933
|
+
function servicesInOrder(language) {
|
|
934
|
+
if (language === "zh") return SETUP_SERVICES;
|
|
935
|
+
const first = FIRST_IN_ENGLISH.flatMap((id) => SETUP_SERVICES.filter((service) => service.id === id));
|
|
936
|
+
return [...first, ...SETUP_SERVICES.filter((service) => !FIRST_IN_ENGLISH.includes(service.id))];
|
|
937
|
+
}
|
|
888
938
|
function serviceById(id) {
|
|
889
939
|
return SETUP_SERVICES.find((service) => service.id === id);
|
|
890
940
|
}
|
|
@@ -893,6 +943,9 @@ function cleanKey(raw) {
|
|
|
893
943
|
if (key.length >= 2 && (key[0] === '"' || key[0] === "'") && key.at(-1) === key[0]) key = key.slice(1, -1).trim();
|
|
894
944
|
return key;
|
|
895
945
|
}
|
|
946
|
+
function isClaudeSubscriptionToken(key) {
|
|
947
|
+
return cleanKey(key).startsWith("sk-ant-oat");
|
|
948
|
+
}
|
|
896
949
|
function servicesForKey(key) {
|
|
897
950
|
const clean = cleanKey(key);
|
|
898
951
|
return clean ? SETUP_SERVICES.filter((service) => service.keyShape?.test(clean)) : [];
|
|
@@ -939,7 +992,7 @@ function namedModel(service) {
|
|
|
939
992
|
|
|
940
993
|
// packages/kyrn-judge/src/setup/wizard.ts
|
|
941
994
|
var SETUP_DECLINED_FILE = "setup-declined";
|
|
942
|
-
var SETUP_EXIT = { done: 0, failed: 1, usage: 2, start: 3, cancelled: 130 };
|
|
995
|
+
var SETUP_EXIT = { done: 0, failed: 1, usage: 2, start: 3, signIn: 4, cancelled: 130 };
|
|
943
996
|
var SETUP_VALUE_FLAGS = [
|
|
944
997
|
"--service",
|
|
945
998
|
"--model",
|
|
@@ -970,6 +1023,10 @@ var JEV_TIERS = /* @__PURE__ */ new Set([
|
|
|
970
1023
|
]);
|
|
971
1024
|
var OPENCODE_KEY = "OPENCODE_API_KEY";
|
|
972
1025
|
var JEV_PAGE = "https://typesafe.ai";
|
|
1026
|
+
var CLAUDE_TOKEN = {
|
|
1027
|
+
zh: "\u8FD9\u662F Claude \u8BA2\u9605\u4EE4\u724C\uFF08claude setup-token \u751F\u6210\u7684\uFF09\uFF0C\u4E0D\u662F API \u5BC6\u94A5\u3002Anthropic \u4E0D\u5141\u8BB8\u5176\u4ED6\u5E94\u7528\u4F7F\u7528 Claude \u8BA2\u9605\uFF0C\u6240\u4EE5 mu \u7528\u4E0D\u4E86\u5B83\u3002\u8BF7\u6539\u7528 Anthropic API \u5BC6\u94A5\uFF08sk-ant-api\u2026\uFF09\uFF0C\u5728\u8FD9\u91CC\u521B\u5EFA\uFF1Ahttps://platform.claude.com/settings/keys",
|
|
1028
|
+
en: "That's a Claude subscription token (from claude setup-token), not an API key. Anthropic doesn't allow other apps to use a Claude subscription, so mu can't use it. Use an Anthropic API key (sk-ant-api\u2026) instead; create one at https://platform.claude.com/settings/keys"
|
|
1029
|
+
};
|
|
973
1030
|
var BRANDED = /* @__PURE__ */ new Set(["openai", "anthropic", "openrouter", "google", "xai"]);
|
|
974
1031
|
var OTHER = {
|
|
975
1032
|
zh: "\u5176\u4ED6 OpenAI \u6216 Anthropic \u517C\u5BB9\u7684\u670D\u52A1",
|
|
@@ -1003,11 +1060,11 @@ function parseSetupArgs(argv) {
|
|
|
1003
1060
|
return { error: { zh: "--api \u53EA\u80FD\u662F openai \u6216 anthropic", en: "--api must be openai or anthropic" } };
|
|
1004
1061
|
}
|
|
1005
1062
|
const judge = values.get("--judge");
|
|
1006
|
-
if (judge !== void 0 && !["jev", "opencode", "free", "model", "none"].includes(judge)) {
|
|
1063
|
+
if (judge !== void 0 && !["jev", "opencode", "free", "model", "off", "none"].includes(judge)) {
|
|
1007
1064
|
return {
|
|
1008
1065
|
error: {
|
|
1009
|
-
zh: "--judge \u53EA\u80FD\u662F jev\u3001opencode\u3001free\u3001model \u6216 none",
|
|
1010
|
-
en: "--judge must be jev, opencode, free, model or none"
|
|
1066
|
+
zh: "--judge \u53EA\u80FD\u662F jev\u3001opencode\u3001free\u3001model\u3001off \u6216 none",
|
|
1067
|
+
en: "--judge must be jev, opencode, free, model, off or none"
|
|
1011
1068
|
}
|
|
1012
1069
|
};
|
|
1013
1070
|
}
|
|
@@ -1050,13 +1107,14 @@ function setupUsage(language) {
|
|
|
1050
1107
|
"\u4E3A\u4EC0\u4E48\u811A\u672C\u8981\u4ECE\u6807\u51C6\u8F93\u5165\u7ED9\u5BC6\u94A5\uFF1A\u5199\u5728\u547D\u4EE4\u884C\u4E0A\u7684\u5BC6\u94A5\u4F1A\u7559\u5728 shell \u7684\u5386\u53F2\u8BB0\u5F55\u91CC\uFF0C",
|
|
1051
1108
|
"\u8FD9\u53F0\u7535\u8111\u4E0A\u80FD\u5217\u51FA\u8FDB\u7A0B\u7684\u7A0B\u5E8F\u4E5F\u90FD\u770B\u5F97\u5230\u5B83\u3002mu setup <\u5BC6\u94A5> \u53EA\u662F\u4E3A\u4E86\u4E0A\u624B\u5FEB\uFF1B\u80FD\u5728\u63D0\u793A\u91CC\u7C98\u8D34\u5C31\u7C98\u8D34\u3002",
|
|
1052
1109
|
"",
|
|
1053
|
-
" --judge jev
|
|
1110
|
+
" --judge jev Jev \u5BC6\u94A5\uFF08TypeSafe\uFF09\u5199\u5728\u6807\u51C6\u8F93\u5165\u7684\u7B2C\u4E8C\u884C\uFF1B\u5DF2\u7ECF\u8BBE\u7F6E\u4E86 TYPESAFE_API_KEY \u5C31\u4E0D\u7528",
|
|
1054
1111
|
" --judge opencode OpenCode Zen \u4E0A\u7684 Jev\uFF0C\u7528 OpenCode \u7684\u5BC6\u94A5\uFF08--service opencode \u6216 OPENCODE_API_KEY\uFF09",
|
|
1055
|
-
" --judge free
|
|
1056
|
-
" --judge model
|
|
1057
|
-
" --judge
|
|
1058
|
-
" --
|
|
1059
|
-
" --
|
|
1112
|
+
" --judge free OpenCode Zen \u4E0A\u9650\u65F6\u514D\u8D39\u7684 Jev\uFF0C\u4E0D\u7528\u5BC6\u94A5\uFF08\u6CA1\u6709\u5BC6\u94A5\u65F6\u672C\u6765\u5C31\u7528\u5B83\uFF09",
|
|
1113
|
+
" --judge model \u7528\u521A\u8BBE\u7F6E\u7684\u6A21\u578B\u5F53\u5224\u5B9A\u5668\uFF08\u66F4\u6162\uFF0C\u6BCF\u6B21\u5224\u65AD\u90FD\u82B1 token\uFF09",
|
|
1114
|
+
" --judge off \u4E0D\u7528\u5224\u5B9A\u5668\uFF1A\u6240\u6709\u5224\u5B9A\u70B9\u5173\u95ED\uFF0C\u4EC0\u4E48\u90FD\u4E0D\u53D1\u7ED9\u5224\u5B9A\u5668",
|
|
1115
|
+
" --judge none \u4E0D\u6539\u5224\u5B9A\u5668\uFF1B\u4E0D\u5199 --judge \u65F6\u4E5F\u4E0D\u6539",
|
|
1116
|
+
" --api, --name \u670D\u52A1 other \u7684\u63A5\u53E3\uFF08openai \u6216 anthropic\uFF09\u548C\u5B83\u5728 mu \u91CC\u7684\u540D\u5B57",
|
|
1117
|
+
" --yes \u4E0D\u63D0\u95EE\uFF1B\u66FF\u6362\u5DF2\u6709\u7684\u8BBE\u7F6E\uFF08\u8BA2\u9605\u767B\u5F55\u3001\u540C\u540D\u670D\u52A1\u7684\u5730\u5740\u3001Jev \u5BC6\u94A5\uFF09",
|
|
1060
1118
|
"",
|
|
1061
1119
|
"\u4F1A\u6539\u52A8\u7684\u6587\u4EF6\uFF1A~/.mu/agent \u91CC\u7684 auth.json\uFF08\u5BC6\u94A5\uFF09\u3001models.json\u3001settings.json\u3001mu.json\uFF0C",
|
|
1062
1120
|
"\u4EE5\u53CA mu \u8BFB\u53D6\u7684 .env\uFF08Jev \u5BC6\u94A5\uFF09\u3002\u6BCF\u4E2A\u6587\u4EF6\u6539\u52A8\u524D\u90FD\u4F1A\u5148\u590D\u5236\u5230 ~/.mu/backups/<\u65F6\u95F4>/\u3002"
|
|
@@ -1075,14 +1133,15 @@ function setupUsage(language) {
|
|
|
1075
1133
|
"computer that lists processes can read it. `mu setup <key>` is a shortcut for getting started; paste the key",
|
|
1076
1134
|
"at the prompt when you can.",
|
|
1077
1135
|
"",
|
|
1078
|
-
" --judge jev
|
|
1136
|
+
" --judge jev read the Jev key (TypeSafe) from stdin's second line, unless TYPESAFE_API_KEY is already set",
|
|
1079
1137
|
" --judge opencode use Jev on OpenCode Zen with an OpenCode key (--service opencode or OPENCODE_API_KEY)",
|
|
1080
|
-
" --judge free
|
|
1081
|
-
" --judge model
|
|
1082
|
-
" --judge
|
|
1083
|
-
" --
|
|
1084
|
-
" --
|
|
1085
|
-
"
|
|
1138
|
+
" --judge free use the free Jev on OpenCode Zen (limited time, no key; the default while no key is set)",
|
|
1139
|
+
" --judge model use the model you just set up as the judge (slower, and every verdict costs tokens)",
|
|
1140
|
+
" --judge off no judge: every decision point is off, and nothing is sent to a judge",
|
|
1141
|
+
" --judge none leave the judge unchanged (the same as omitting --judge)",
|
|
1142
|
+
" --api, --name for the service `other`: its API (openai or anthropic) and its name in mu",
|
|
1143
|
+
" --yes don't ask; replace what's already set up (a subscription sign-in, a provider's",
|
|
1144
|
+
" address, the Jev key)",
|
|
1086
1145
|
"",
|
|
1087
1146
|
"Files it changes: auth.json (keys), models.json, settings.json and mu.json in ~/.mu/agent, and the .env",
|
|
1088
1147
|
"mu reads (the Jev key). Each one is backed up to ~/.mu/backups/<time>/ before it changes."
|
|
@@ -1093,7 +1152,7 @@ function label(service, language) {
|
|
|
1093
1152
|
}
|
|
1094
1153
|
function serviceList(language) {
|
|
1095
1154
|
const width = Math.max(...SETUP_SERVICES.map((service) => service.id.length));
|
|
1096
|
-
return
|
|
1155
|
+
return servicesInOrder(language).map((service) => ` ${service.id.padEnd(width)} ${label(service, language)}`).join("\n");
|
|
1097
1156
|
}
|
|
1098
1157
|
function providerIdFor(baseUrl) {
|
|
1099
1158
|
let host;
|
|
@@ -1202,10 +1261,14 @@ var Setup = class {
|
|
|
1202
1261
|
if (key || allowEmpty) return key;
|
|
1203
1262
|
}
|
|
1204
1263
|
}
|
|
1205
|
-
pasteKey() {
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1264
|
+
async pasteKey() {
|
|
1265
|
+
for (; ; ) {
|
|
1266
|
+
const key = await this.secret(
|
|
1267
|
+
this.t({ zh: "\u7C98\u8D34 API \u5BC6\u94A5\uFF08\u4E0D\u4F1A\u663E\u793A\u51FA\u6765\uFF09\uFF1A", en: "Paste the API key (it won't be shown): " })
|
|
1268
|
+
);
|
|
1269
|
+
if (!isClaudeSubscriptionToken(key)) return key;
|
|
1270
|
+
this.io.warn(this.t(CLAUDE_TOKEN));
|
|
1271
|
+
}
|
|
1209
1272
|
}
|
|
1210
1273
|
async choose(question, choices) {
|
|
1211
1274
|
this.io.say(question);
|
|
@@ -1245,6 +1308,7 @@ var Setup = class {
|
|
|
1245
1308
|
key = modelKey;
|
|
1246
1309
|
this.jevFromStdin = jevKey;
|
|
1247
1310
|
}
|
|
1311
|
+
if (key !== void 0 && isClaudeSubscriptionToken(key)) throw this.fail(CLAUDE_TOKEN, SETUP_EXIT.usage);
|
|
1248
1312
|
if (this.scripted && key === void 0 && args.service === void 0) {
|
|
1249
1313
|
throw this.fail(
|
|
1250
1314
|
deps.interactive ? { zh: "\u6CA1\u6709\u5BC6\u94A5\uFF0C\u4E5F\u6CA1\u6709 --service", en: "no key or --service given" } : {
|
|
@@ -1265,7 +1329,7 @@ var Setup = class {
|
|
|
1265
1329
|
const start = await this.start(key === void 0 ? void 0 : cleanKey(key));
|
|
1266
1330
|
if (start === "subscription") {
|
|
1267
1331
|
const code2 = await this.write(void 0, void 0, await this.judge(void 0));
|
|
1268
|
-
return code2 === SETUP_EXIT.done ? this.offerSession() : code2;
|
|
1332
|
+
return code2 === SETUP_EXIT.done ? this.offerSession(true) : code2;
|
|
1269
1333
|
}
|
|
1270
1334
|
const target = await this.checked(start.service, start.key);
|
|
1271
1335
|
this.modelKey = target.key;
|
|
@@ -1321,8 +1385,8 @@ var Setup = class {
|
|
|
1321
1385
|
{ label: this.t({ zh: "\u4ECE\u5217\u8868\u91CC\u9009\u4E00\u4E2A\u670D\u52A1", en: "Choose a service from the list" }), value: "list" },
|
|
1322
1386
|
{
|
|
1323
1387
|
label: this.t({
|
|
1324
|
-
zh: "\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\uFF1AChatGPT\
|
|
1325
|
-
en: "Sign in with a subscription: ChatGPT,
|
|
1388
|
+
zh: "\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\uFF1AChatGPT\u3001Grok \u6216 Google",
|
|
1389
|
+
en: "Sign in with a subscription: ChatGPT, Grok or Google"
|
|
1326
1390
|
}),
|
|
1327
1391
|
value: "subscription"
|
|
1328
1392
|
}
|
|
@@ -1332,13 +1396,13 @@ var Setup = class {
|
|
|
1332
1396
|
const auth = this.path(join3(this.deps.paths.agentDir, "auth.json"));
|
|
1333
1397
|
this.io.say(
|
|
1334
1398
|
this.t({
|
|
1335
|
-
zh: `\u8BA2\u9605\u8D26\u53F7\u5728 mu \u91CC\
|
|
1336
|
-
en: `
|
|
1399
|
+
zh: `\u8BA2\u9605\u8D26\u53F7\u5728 mu \u91CC\u7528 /login \u767B\u5F55\uFF1A\u9009 Sign in with an account\uFF0C\u518D\u9009 OpenAI\uFF08ChatGPT\uFF09\u3001xAI\uFF08Grok\uFF09\u6216 Google \u7684\u4E00\u9879\uFF0C\u6309\u63D0\u793A\u5728\u6D4F\u89C8\u5668\u91CC\u5B8C\u6210\u3002setup \u63A5\u7740\u542F\u52A8 mu \u65F6\uFF0C/login \u5DF2\u7ECF\u6253\u5F00\u3002\u767B\u5F55\u4FE1\u606F\u4FDD\u5B58\u5728 ${auth}\u3002`,
|
|
1400
|
+
en: `You sign in to a subscription inside mu, with /login: choose Sign in with an account, then OpenAI for ChatGPT, xAI for Grok, or one of the Google sign-ins, and finish in the browser. When setup starts mu, /login is already open. The sign-in is saved in ${auth}.`
|
|
1337
1401
|
})
|
|
1338
1402
|
);
|
|
1339
1403
|
return "subscription";
|
|
1340
1404
|
}
|
|
1341
|
-
if (route === "list") return this.keyFor(await this.pickService(
|
|
1405
|
+
if (route === "list") return this.keyFor(await this.pickService(servicesInOrder(this.language)), void 0);
|
|
1342
1406
|
const pasted = await this.pasteKey();
|
|
1343
1407
|
return { service: await this.serviceOf(pasted), key: pasted };
|
|
1344
1408
|
}
|
|
@@ -1385,7 +1449,7 @@ var Setup = class {
|
|
|
1385
1449
|
);
|
|
1386
1450
|
}
|
|
1387
1451
|
return this.pickService(
|
|
1388
|
-
|
|
1452
|
+
servicesInOrder(this.language).filter((service) => !service.keyless),
|
|
1389
1453
|
this.t({
|
|
1390
1454
|
zh: "mu \u8BA4\u4E0D\u51FA\u8FD9\u4E2A\u5BC6\u94A5\u3002\u5B83\u662F\u54EA\u4E2A\u670D\u52A1\u7684\uFF1F",
|
|
1391
1455
|
en: "mu doesn't recognize this key. Which service is it for?"
|
|
@@ -1607,7 +1671,7 @@ var Setup = class {
|
|
|
1607
1671
|
if (this.scripted) {
|
|
1608
1672
|
throw this.fail({
|
|
1609
1673
|
zh: `${this.name(service)} \u5DF2\u7ECF\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\u4E86\u3002\u8981\u6539\u5B58\u5BC6\u94A5\uFF0C\u52A0\u4E0A --yes`,
|
|
1610
|
-
en:
|
|
1674
|
+
en: `You're signed in to ${this.name(service)} with a subscription. To use a key instead, add --yes`
|
|
1611
1675
|
});
|
|
1612
1676
|
}
|
|
1613
1677
|
const replace = await this.confirm(
|
|
@@ -1796,8 +1860,8 @@ var Setup = class {
|
|
|
1796
1860
|
}
|
|
1797
1861
|
choices.push({
|
|
1798
1862
|
label: this.t({
|
|
1799
|
-
zh: "\u6682\u65F6\u4E0D\u8981\
|
|
1800
|
-
en: "Not now:
|
|
1863
|
+
zh: "\u6682\u65F6\u4E0D\u8981\uFF1A\u4E0D\u95EE\u5224\u5B9A\u5668\uFF0C\u4EC0\u4E48\u90FD\u4E0D\u53D1\u7ED9\u5B83\uFF0Cmu \u6309\u9ED8\u8BA4\u89C4\u5219\u5DE5\u4F5C",
|
|
1864
|
+
en: "Not now: no judge is asked and nothing is sent to one; mu uses its fallbacks"
|
|
1801
1865
|
}),
|
|
1802
1866
|
value: "none"
|
|
1803
1867
|
});
|
|
@@ -1826,6 +1890,8 @@ var Setup = class {
|
|
|
1826
1890
|
return { kind: "opencode" };
|
|
1827
1891
|
case "free":
|
|
1828
1892
|
return { kind: "free" };
|
|
1893
|
+
case "off":
|
|
1894
|
+
return { kind: "none" };
|
|
1829
1895
|
case "jev": {
|
|
1830
1896
|
const key = this.jevFromStdin;
|
|
1831
1897
|
if (!key) {
|
|
@@ -1971,14 +2037,15 @@ var Setup = class {
|
|
|
1971
2037
|
);
|
|
1972
2038
|
}
|
|
1973
2039
|
}
|
|
1974
|
-
if (judge
|
|
2040
|
+
if (judge?.kind === "none") this.writeNoJudge(backups, saved, notes);
|
|
2041
|
+
else if (judge) this.writeJudge(judge, target, model, backups, saved, notes);
|
|
1975
2042
|
} catch (error) {
|
|
1976
2043
|
if (error instanceof Stop) throw error;
|
|
1977
2044
|
let reason = error instanceof Error ? error.message : String(error);
|
|
1978
2045
|
for (const secret of [target?.key, judge?.kind === "jev" ? judge.key : void 0]) {
|
|
1979
2046
|
if (secret) reason = reason.replaceAll(secret, "\u2026");
|
|
1980
2047
|
}
|
|
1981
|
-
this.io.warn(this.t({ zh: `mu setup\uFF1A\u4FDD\u5B58\u65F6\u51FA\u9519\uFF1A${reason}`, en: `mu setup:
|
|
2048
|
+
this.io.warn(this.t({ zh: `mu setup\uFF1A\u4FDD\u5B58\u65F6\u51FA\u9519\uFF1A${reason}`, en: `mu setup: couldn't save: ${reason}` }));
|
|
1982
2049
|
if (saved.length > 0) {
|
|
1983
2050
|
this.io.warn(this.t({ zh: "\u51FA\u9519\u524D\u5DF2\u7ECF\u4FDD\u5B58\u7684\uFF1A", en: "Saved before the error:" }));
|
|
1984
2051
|
for (const entry of saved) this.io.warn(entry);
|
|
@@ -2012,6 +2079,25 @@ var Setup = class {
|
|
|
2012
2079
|
savedLine(path, what) {
|
|
2013
2080
|
return ` ${this.path(path).padEnd(30)} ${what}`;
|
|
2014
2081
|
}
|
|
2082
|
+
/** "Not now": no decision point asks a judge (the default mode "off"), so nothing goes to one. */
|
|
2083
|
+
writeNoJudge(backups, saved, notes) {
|
|
2084
|
+
const configPath = judgeConfigPath(this.deps.paths.agentDir);
|
|
2085
|
+
const config = readJsonFile(configPath);
|
|
2086
|
+
if (config.state === "unreadable") {
|
|
2087
|
+
notes.push(
|
|
2088
|
+
this.t({
|
|
2089
|
+
zh: `${this.path(configPath)} \u4E0D\u662F\u7EAF JSON\uFF0C\u6CA1\u6709\u6539\u5B83\u3002\u8BF7\u624B\u52A8\u52A0\u4E0A "modes": { "default": "off" }`,
|
|
2090
|
+
en: `${this.path(configPath)} isn't plain JSON, so it was left unchanged. Add "modes": { "default": "off" } by hand.`
|
|
2091
|
+
})
|
|
2092
|
+
);
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
2095
|
+
const current = config.state === "ok" ? config.value : void 0;
|
|
2096
|
+
if (judgeOff(current)) return;
|
|
2097
|
+
backups.save(configPath);
|
|
2098
|
+
writeJsonFile(configPath, withJudge(current ?? {}, false));
|
|
2099
|
+
saved.push(this.savedLine(configPath, this.t({ zh: "\u5224\u5B9A\u5668\uFF1A\u5173\u95ED", en: "judge: off" })));
|
|
2100
|
+
}
|
|
2015
2101
|
writeJudge(judge, target, model, backups, saved, notes) {
|
|
2016
2102
|
const { env, paths } = this.deps;
|
|
2017
2103
|
const configPath = judgeConfigPath(paths.agentDir);
|
|
@@ -2024,6 +2110,7 @@ var Setup = class {
|
|
|
2024
2110
|
else if (judge.kind === "free") {
|
|
2025
2111
|
if (!tiersOf(current).some((tier) => tier === "jev" || tier === "jev-opencode-free")) tiers = ["jev"];
|
|
2026
2112
|
} else if (!tiersOf(current).some((tier) => JEV_TIERS.has(tier))) tiers = ["jev"];
|
|
2113
|
+
const turnOn = judgeOff(current);
|
|
2027
2114
|
if (tiers && config.state === "unreadable") {
|
|
2028
2115
|
notes.push(
|
|
2029
2116
|
this.t({
|
|
@@ -2031,11 +2118,13 @@ var Setup = class {
|
|
|
2031
2118
|
en: `${this.path(configPath)} isn't plain JSON, so it was left unchanged. Add "tiers": ${JSON.stringify(tiers)} by hand.`
|
|
2032
2119
|
})
|
|
2033
2120
|
);
|
|
2034
|
-
} else if (tiers) {
|
|
2121
|
+
} else if (tiers || turnOn) {
|
|
2035
2122
|
backups.save(configPath);
|
|
2036
|
-
|
|
2123
|
+
const next = tiers ? withTiers(current ?? {}, tiers) : current ?? {};
|
|
2124
|
+
writeJsonFile(configPath, turnOn ? withJudge(next, true) : next);
|
|
2125
|
+
const named2 = tiers ?? tiersOf(current);
|
|
2037
2126
|
saved.push(
|
|
2038
|
-
this.savedLine(configPath, this.t({ zh: `\u5224\u5B9A\u5668 ${
|
|
2127
|
+
this.savedLine(configPath, this.t({ zh: `\u5224\u5B9A\u5668 ${named2.join(", ")}`, en: `judge: ${named2.join(", ")}` }))
|
|
2039
2128
|
);
|
|
2040
2129
|
}
|
|
2041
2130
|
if (judge.kind === "jev") {
|
|
@@ -2081,14 +2170,19 @@ var Setup = class {
|
|
|
2081
2170
|
target ? this.t({
|
|
2082
2171
|
zh: "\u5728 mu \u91CC\u7528 /model \u6362\u6A21\u578B\uFF1B\u968F\u65F6\u53EF\u4EE5\u518D\u8FD0\u884C mu setup\u3002",
|
|
2083
2172
|
en: "Switch models inside mu with /model, and run mu setup again any time."
|
|
2084
|
-
}) : this.t({ zh: "\
|
|
2173
|
+
}) : this.t({ zh: "\u63A5\u4E0B\u6765\u5728 mu \u91CC\u7528 /login \u767B\u5F55\u3002", en: "Next, sign in with /login in mu." })
|
|
2085
2174
|
);
|
|
2086
2175
|
}
|
|
2087
|
-
/**
|
|
2088
|
-
|
|
2089
|
-
|
|
2176
|
+
/**
|
|
2177
|
+
* On its own, a finished setup offers a session; on a first start the launcher goes on into one anyway. After a
|
|
2178
|
+
* subscription was chosen (`signIn`), that session opens on /login: SETUP_EXIT.signIn.
|
|
2179
|
+
*/
|
|
2180
|
+
async offerSession(signIn = false) {
|
|
2181
|
+
if (this.scripted) return SETUP_EXIT.done;
|
|
2182
|
+
if (this.args.firstRun) return signIn ? SETUP_EXIT.signIn : SETUP_EXIT.done;
|
|
2090
2183
|
const start = await this.confirm(this.t({ zh: "\u73B0\u5728\u542F\u52A8 mu \u5417\uFF1F[Y/n] ", en: "Start mu now? [Y/n] " }), true);
|
|
2091
|
-
|
|
2184
|
+
if (!start) return SETUP_EXIT.done;
|
|
2185
|
+
return signIn ? SETUP_EXIT.signIn : SETUP_EXIT.start;
|
|
2092
2186
|
}
|
|
2093
2187
|
};
|
|
2094
2188
|
function existingProviders(models) {
|