mu-agent 0.1.10 → 0.1.13
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 +94 -0
- package/README.md +6 -6
- package/dist/bundle/chunks/{chunk-O7IPTASE.js → chunk-3J3HSHLX.js} +22 -21
- package/dist/bundle/chunks/{chunk-DNNHZBQR.js → chunk-6Z2347ML.js} +1 -1
- 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/{chunk-FN6OEZYR.js → chunk-WDURT4ZM.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-TJPHLTRT.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 +51 -26
- package/judge/dist/chrome.js +2 -2
- package/judge/dist/import.js +833 -161
- package/judge/dist/setup.js +129 -46
- package/judge/manifest.json +1935 -349
- package/judge/mu/chunk-3NQ5BIBI.js +4773 -0
- package/judge/mu/chunk-SKGYWHW6.js +51 -0
- package/judge/mu/chunk-WQM4MV6L.js +58 -0
- package/judge/mu/cloud-code-V7FOGB4J.js +22802 -0
- package/judge/mu/dist-75PS4OC4.js +1283 -0
- package/judge/mu/index.js +4509 -32801
- package/judge/mu/multipart-parser-ZDXVIOOP.js +372 -0
- package/judge/mu/src-TVVA5ZK2.js +1409 -0
- package/kyrn/bin/kyrn-doctor +28 -3
- package/kyrn/bin/kyrn-judge-local +42 -13
- package/kyrn/bin/kyrn-ledger +16 -1
- package/kyrn/bin/mu.mjs +77 -23
- 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
|
@@ -328,6 +328,16 @@ function tiersOf(config) {
|
|
|
328
328
|
function withTiers(config, tiers) {
|
|
329
329
|
return { ...config, tiers: [...tiers] };
|
|
330
330
|
}
|
|
331
|
+
function judgeOff(config) {
|
|
332
|
+
return isRecord(config?.modes) && config.modes.default === "off";
|
|
333
|
+
}
|
|
334
|
+
function withJudge(config, on) {
|
|
335
|
+
const { default: _default, ...modes } = isRecord(config.modes) ? config.modes : {};
|
|
336
|
+
if (!on) return { ...config, modes: { default: "off", ...modes } };
|
|
337
|
+
if (!judgeOff(config)) return config;
|
|
338
|
+
const { modes: _modes, ...rest } = config;
|
|
339
|
+
return Object.keys(modes).length > 0 ? { ...rest, modes } : rest;
|
|
340
|
+
}
|
|
331
341
|
function readTextFile(path) {
|
|
332
342
|
try {
|
|
333
343
|
return readFileSync(path, "utf8");
|
|
@@ -378,14 +388,17 @@ function piAccess(runtime, agentDir2) {
|
|
|
378
388
|
storeKey: async (provider, key) => {
|
|
379
389
|
await runtime.refresh({ allowNetwork: false, providers: [provider] });
|
|
380
390
|
if (!runtime.getProvider(provider)) {
|
|
381
|
-
throw new Error(
|
|
391
|
+
throw new Error(
|
|
392
|
+
`mu has no provider named ${provider}${runtime.getError() ? `: ${runtime.getError()}` : ""}`
|
|
393
|
+
);
|
|
382
394
|
}
|
|
383
395
|
let asked = false;
|
|
384
396
|
try {
|
|
385
397
|
await runtime.login(provider, "api_key", {
|
|
386
398
|
// pi's key login asks one question, the key. Anything else is not answered, and nothing is guessed.
|
|
387
399
|
prompt: async (prompt) => {
|
|
388
|
-
if (asked || prompt.type !== "secret")
|
|
400
|
+
if (asked || prompt.type !== "secret")
|
|
401
|
+
throw new Error(`the sign-in for ${provider} asked for more than a key`);
|
|
389
402
|
asked = true;
|
|
390
403
|
return key;
|
|
391
404
|
},
|
|
@@ -459,11 +472,31 @@ function askSecret(input, output, question) {
|
|
|
459
472
|
input.resume();
|
|
460
473
|
});
|
|
461
474
|
}
|
|
475
|
+
var columnsOf = (char) => /[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe30-\ufe4f\uff00-\uff60\uffe0-\uffe6]/u.test(char) ? 2 : 1;
|
|
476
|
+
var widthOf = (text) => Array.from(text).reduce((sum, char) => sum + columnsOf(char), 0);
|
|
477
|
+
function wrapToWidth(text, width) {
|
|
478
|
+
if (!width || width < 20) return text;
|
|
479
|
+
return text.split("\n").map((line) => {
|
|
480
|
+
if (widthOf(line) <= width) return line;
|
|
481
|
+
const indent = " ".repeat(/^\s*(?:\d+\)\s+)?/.exec(line)?.[0].length ?? 0);
|
|
482
|
+
const out = [];
|
|
483
|
+
let current = "";
|
|
484
|
+
for (const word of line.trimEnd().split(/(?<=\S) (?=\S)/)) {
|
|
485
|
+
const next = current ? `${current} ${word}` : word;
|
|
486
|
+
if (current && widthOf(next) > width) {
|
|
487
|
+
out.push(current);
|
|
488
|
+
current = `${indent}${word.trimStart()}`;
|
|
489
|
+
} else current = next;
|
|
490
|
+
}
|
|
491
|
+
out.push(current);
|
|
492
|
+
return out.join("\n");
|
|
493
|
+
}).join("\n");
|
|
494
|
+
}
|
|
462
495
|
function terminalPrompter(input = process.stdin, output = process.stdout, errors = process.stderr) {
|
|
463
496
|
return {
|
|
464
|
-
say: (text) => output.write(`${text}
|
|
497
|
+
say: (text) => output.write(`${wrapToWidth(text, output.isTTY ? output.columns : void 0)}
|
|
465
498
|
`),
|
|
466
|
-
warn: (text) => errors.write(`${text}
|
|
499
|
+
warn: (text) => errors.write(`${wrapToWidth(text, errors.isTTY ? errors.columns : void 0)}
|
|
467
500
|
`),
|
|
468
501
|
ask: (question) => askLine(input, output, question),
|
|
469
502
|
secret: (question) => askSecret(input, output, question)
|
|
@@ -885,6 +918,12 @@ var SETUP_SERVICES = [
|
|
|
885
918
|
keyOptional: true
|
|
886
919
|
}
|
|
887
920
|
];
|
|
921
|
+
var FIRST_IN_ENGLISH = ["openai", "anthropic", "google", "xai", "openrouter", "opencode"];
|
|
922
|
+
function servicesInOrder(language) {
|
|
923
|
+
if (language === "zh") return SETUP_SERVICES;
|
|
924
|
+
const first = FIRST_IN_ENGLISH.flatMap((id) => SETUP_SERVICES.filter((service) => service.id === id));
|
|
925
|
+
return [...first, ...SETUP_SERVICES.filter((service) => !FIRST_IN_ENGLISH.includes(service.id))];
|
|
926
|
+
}
|
|
888
927
|
function serviceById(id) {
|
|
889
928
|
return SETUP_SERVICES.find((service) => service.id === id);
|
|
890
929
|
}
|
|
@@ -893,6 +932,9 @@ function cleanKey(raw) {
|
|
|
893
932
|
if (key.length >= 2 && (key[0] === '"' || key[0] === "'") && key.at(-1) === key[0]) key = key.slice(1, -1).trim();
|
|
894
933
|
return key;
|
|
895
934
|
}
|
|
935
|
+
function isClaudeSubscriptionToken(key) {
|
|
936
|
+
return cleanKey(key).startsWith("sk-ant-oat");
|
|
937
|
+
}
|
|
896
938
|
function servicesForKey(key) {
|
|
897
939
|
const clean = cleanKey(key);
|
|
898
940
|
return clean ? SETUP_SERVICES.filter((service) => service.keyShape?.test(clean)) : [];
|
|
@@ -939,7 +981,7 @@ function namedModel(service) {
|
|
|
939
981
|
|
|
940
982
|
// packages/kyrn-judge/src/setup/wizard.ts
|
|
941
983
|
var SETUP_DECLINED_FILE = "setup-declined";
|
|
942
|
-
var SETUP_EXIT = { done: 0, failed: 1, usage: 2, start: 3, cancelled: 130 };
|
|
984
|
+
var SETUP_EXIT = { done: 0, failed: 1, usage: 2, start: 3, signIn: 4, cancelled: 130 };
|
|
943
985
|
var SETUP_VALUE_FLAGS = [
|
|
944
986
|
"--service",
|
|
945
987
|
"--model",
|
|
@@ -970,6 +1012,10 @@ var JEV_TIERS = /* @__PURE__ */ new Set([
|
|
|
970
1012
|
]);
|
|
971
1013
|
var OPENCODE_KEY = "OPENCODE_API_KEY";
|
|
972
1014
|
var JEV_PAGE = "https://typesafe.ai";
|
|
1015
|
+
var CLAUDE_TOKEN = {
|
|
1016
|
+
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",
|
|
1017
|
+
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"
|
|
1018
|
+
};
|
|
973
1019
|
var BRANDED = /* @__PURE__ */ new Set(["openai", "anthropic", "openrouter", "google", "xai"]);
|
|
974
1020
|
var OTHER = {
|
|
975
1021
|
zh: "\u5176\u4ED6 OpenAI \u6216 Anthropic \u517C\u5BB9\u7684\u670D\u52A1",
|
|
@@ -1003,11 +1049,11 @@ function parseSetupArgs(argv) {
|
|
|
1003
1049
|
return { error: { zh: "--api \u53EA\u80FD\u662F openai \u6216 anthropic", en: "--api must be openai or anthropic" } };
|
|
1004
1050
|
}
|
|
1005
1051
|
const judge = values.get("--judge");
|
|
1006
|
-
if (judge !== void 0 && !["jev", "opencode", "free", "model", "none"].includes(judge)) {
|
|
1052
|
+
if (judge !== void 0 && !["jev", "opencode", "free", "model", "off", "none"].includes(judge)) {
|
|
1007
1053
|
return {
|
|
1008
1054
|
error: {
|
|
1009
|
-
zh: "--judge \u53EA\u80FD\u662F jev\u3001opencode\u3001free\u3001model \u6216 none",
|
|
1010
|
-
en: "--judge must be jev, opencode, free, model or none"
|
|
1055
|
+
zh: "--judge \u53EA\u80FD\u662F jev\u3001opencode\u3001free\u3001model\u3001off \u6216 none",
|
|
1056
|
+
en: "--judge must be jev, opencode, free, model, off or none"
|
|
1011
1057
|
}
|
|
1012
1058
|
};
|
|
1013
1059
|
}
|
|
@@ -1050,13 +1096,14 @@ function setupUsage(language) {
|
|
|
1050
1096
|
"\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
1097
|
"\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
1098
|
"",
|
|
1053
|
-
" --judge jev
|
|
1099
|
+
" --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
1100
|
" --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
|
-
" --
|
|
1101
|
+
" --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",
|
|
1102
|
+
" --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",
|
|
1103
|
+
" --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",
|
|
1104
|
+
" --judge none \u4E0D\u6539\u5224\u5B9A\u5668\uFF1B\u4E0D\u5199 --judge \u65F6\u4E5F\u4E0D\u6539",
|
|
1105
|
+
" --api, --name \u670D\u52A1 other \u7684\u63A5\u53E3\uFF08openai \u6216 anthropic\uFF09\u548C\u5B83\u5728 mu \u91CC\u7684\u540D\u5B57",
|
|
1106
|
+
" --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
1107
|
"",
|
|
1061
1108
|
"\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
1109
|
"\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 +1122,15 @@ function setupUsage(language) {
|
|
|
1075
1122
|
"computer that lists processes can read it. `mu setup <key>` is a shortcut for getting started; paste the key",
|
|
1076
1123
|
"at the prompt when you can.",
|
|
1077
1124
|
"",
|
|
1078
|
-
" --judge jev
|
|
1125
|
+
" --judge jev read the Jev key (TypeSafe) from stdin's second line, unless TYPESAFE_API_KEY is already set",
|
|
1079
1126
|
" --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
|
-
"
|
|
1127
|
+
" --judge free use the free Jev on OpenCode Zen (limited time, no key; the default while no key is set)",
|
|
1128
|
+
" --judge model use the model you just set up as the judge (slower, and every verdict costs tokens)",
|
|
1129
|
+
" --judge off no judge: every decision point is off, and nothing is sent to a judge",
|
|
1130
|
+
" --judge none leave the judge unchanged (the same as omitting --judge)",
|
|
1131
|
+
" --api, --name for the service `other`: its API (openai or anthropic) and its name in mu",
|
|
1132
|
+
" --yes don't ask; replace what's already set up (a subscription sign-in, a provider's",
|
|
1133
|
+
" address, the Jev key)",
|
|
1086
1134
|
"",
|
|
1087
1135
|
"Files it changes: auth.json (keys), models.json, settings.json and mu.json in ~/.mu/agent, and the .env",
|
|
1088
1136
|
"mu reads (the Jev key). Each one is backed up to ~/.mu/backups/<time>/ before it changes."
|
|
@@ -1093,7 +1141,7 @@ function label(service, language) {
|
|
|
1093
1141
|
}
|
|
1094
1142
|
function serviceList(language) {
|
|
1095
1143
|
const width = Math.max(...SETUP_SERVICES.map((service) => service.id.length));
|
|
1096
|
-
return
|
|
1144
|
+
return servicesInOrder(language).map((service) => ` ${service.id.padEnd(width)} ${label(service, language)}`).join("\n");
|
|
1097
1145
|
}
|
|
1098
1146
|
function providerIdFor(baseUrl) {
|
|
1099
1147
|
let host;
|
|
@@ -1202,10 +1250,14 @@ var Setup = class {
|
|
|
1202
1250
|
if (key || allowEmpty) return key;
|
|
1203
1251
|
}
|
|
1204
1252
|
}
|
|
1205
|
-
pasteKey() {
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1253
|
+
async pasteKey() {
|
|
1254
|
+
for (; ; ) {
|
|
1255
|
+
const key = await this.secret(
|
|
1256
|
+
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): " })
|
|
1257
|
+
);
|
|
1258
|
+
if (!isClaudeSubscriptionToken(key)) return key;
|
|
1259
|
+
this.io.warn(this.t(CLAUDE_TOKEN));
|
|
1260
|
+
}
|
|
1209
1261
|
}
|
|
1210
1262
|
async choose(question, choices) {
|
|
1211
1263
|
this.io.say(question);
|
|
@@ -1245,6 +1297,7 @@ var Setup = class {
|
|
|
1245
1297
|
key = modelKey;
|
|
1246
1298
|
this.jevFromStdin = jevKey;
|
|
1247
1299
|
}
|
|
1300
|
+
if (key !== void 0 && isClaudeSubscriptionToken(key)) throw this.fail(CLAUDE_TOKEN, SETUP_EXIT.usage);
|
|
1248
1301
|
if (this.scripted && key === void 0 && args.service === void 0) {
|
|
1249
1302
|
throw this.fail(
|
|
1250
1303
|
deps.interactive ? { zh: "\u6CA1\u6709\u5BC6\u94A5\uFF0C\u4E5F\u6CA1\u6709 --service", en: "no key or --service given" } : {
|
|
@@ -1265,7 +1318,7 @@ var Setup = class {
|
|
|
1265
1318
|
const start = await this.start(key === void 0 ? void 0 : cleanKey(key));
|
|
1266
1319
|
if (start === "subscription") {
|
|
1267
1320
|
const code2 = await this.write(void 0, void 0, await this.judge(void 0));
|
|
1268
|
-
return code2 === SETUP_EXIT.done ? this.offerSession() : code2;
|
|
1321
|
+
return code2 === SETUP_EXIT.done ? this.offerSession(true) : code2;
|
|
1269
1322
|
}
|
|
1270
1323
|
const target = await this.checked(start.service, start.key);
|
|
1271
1324
|
this.modelKey = target.key;
|
|
@@ -1321,8 +1374,8 @@ var Setup = class {
|
|
|
1321
1374
|
{ label: this.t({ zh: "\u4ECE\u5217\u8868\u91CC\u9009\u4E00\u4E2A\u670D\u52A1", en: "Choose a service from the list" }), value: "list" },
|
|
1322
1375
|
{
|
|
1323
1376
|
label: this.t({
|
|
1324
|
-
zh: "\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\uFF1AChatGPT\
|
|
1325
|
-
en: "Sign in with a subscription: ChatGPT,
|
|
1377
|
+
zh: "\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\uFF1AChatGPT\u3001Grok \u6216 Google",
|
|
1378
|
+
en: "Sign in with a subscription: ChatGPT, Grok or Google"
|
|
1326
1379
|
}),
|
|
1327
1380
|
value: "subscription"
|
|
1328
1381
|
}
|
|
@@ -1332,13 +1385,13 @@ var Setup = class {
|
|
|
1332
1385
|
const auth = this.path(join3(this.deps.paths.agentDir, "auth.json"));
|
|
1333
1386
|
this.io.say(
|
|
1334
1387
|
this.t({
|
|
1335
|
-
zh: `\u8BA2\u9605\u8D26\u53F7\u5728 mu \u91CC\u9762\u767B\u5F55\uFF1A\u542F\u52A8 mu\uFF0C\u8F93\u5165 /login\uFF0C\u9009
|
|
1336
|
-
en: `
|
|
1388
|
+
zh: `\u8BA2\u9605\u8D26\u53F7\u5728 mu \u91CC\u9762\u767B\u5F55\uFF1A\u542F\u52A8 mu\uFF0C\u8F93\u5165 /login\uFF0C\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\u3002\u767B\u5F55\u4FE1\u606F\u4FDD\u5B58\u5728 ${auth}\u3002`,
|
|
1389
|
+
en: `To use a subscription, sign in from inside mu: start mu, type /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. The sign-in is saved in ${auth}.`
|
|
1337
1390
|
})
|
|
1338
1391
|
);
|
|
1339
1392
|
return "subscription";
|
|
1340
1393
|
}
|
|
1341
|
-
if (route === "list") return this.keyFor(await this.pickService(
|
|
1394
|
+
if (route === "list") return this.keyFor(await this.pickService(servicesInOrder(this.language)), void 0);
|
|
1342
1395
|
const pasted = await this.pasteKey();
|
|
1343
1396
|
return { service: await this.serviceOf(pasted), key: pasted };
|
|
1344
1397
|
}
|
|
@@ -1385,7 +1438,7 @@ var Setup = class {
|
|
|
1385
1438
|
);
|
|
1386
1439
|
}
|
|
1387
1440
|
return this.pickService(
|
|
1388
|
-
|
|
1441
|
+
servicesInOrder(this.language).filter((service) => !service.keyless),
|
|
1389
1442
|
this.t({
|
|
1390
1443
|
zh: "mu \u8BA4\u4E0D\u51FA\u8FD9\u4E2A\u5BC6\u94A5\u3002\u5B83\u662F\u54EA\u4E2A\u670D\u52A1\u7684\uFF1F",
|
|
1391
1444
|
en: "mu doesn't recognize this key. Which service is it for?"
|
|
@@ -1607,7 +1660,7 @@ var Setup = class {
|
|
|
1607
1660
|
if (this.scripted) {
|
|
1608
1661
|
throw this.fail({
|
|
1609
1662
|
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:
|
|
1663
|
+
en: `You're signed in to ${this.name(service)} with a subscription. To use a key instead, add --yes`
|
|
1611
1664
|
});
|
|
1612
1665
|
}
|
|
1613
1666
|
const replace = await this.confirm(
|
|
@@ -1796,8 +1849,8 @@ var Setup = class {
|
|
|
1796
1849
|
}
|
|
1797
1850
|
choices.push({
|
|
1798
1851
|
label: this.t({
|
|
1799
|
-
zh: "\u6682\u65F6\u4E0D\u8981\
|
|
1800
|
-
en: "Not now:
|
|
1852
|
+
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",
|
|
1853
|
+
en: "Not now: no judge is asked and nothing is sent to one; mu uses its fallbacks"
|
|
1801
1854
|
}),
|
|
1802
1855
|
value: "none"
|
|
1803
1856
|
});
|
|
@@ -1826,6 +1879,8 @@ var Setup = class {
|
|
|
1826
1879
|
return { kind: "opencode" };
|
|
1827
1880
|
case "free":
|
|
1828
1881
|
return { kind: "free" };
|
|
1882
|
+
case "off":
|
|
1883
|
+
return { kind: "none" };
|
|
1829
1884
|
case "jev": {
|
|
1830
1885
|
const key = this.jevFromStdin;
|
|
1831
1886
|
if (!key) {
|
|
@@ -1971,14 +2026,15 @@ var Setup = class {
|
|
|
1971
2026
|
);
|
|
1972
2027
|
}
|
|
1973
2028
|
}
|
|
1974
|
-
if (judge
|
|
2029
|
+
if (judge?.kind === "none") this.writeNoJudge(backups, saved, notes);
|
|
2030
|
+
else if (judge) this.writeJudge(judge, target, model, backups, saved, notes);
|
|
1975
2031
|
} catch (error) {
|
|
1976
2032
|
if (error instanceof Stop) throw error;
|
|
1977
2033
|
let reason = error instanceof Error ? error.message : String(error);
|
|
1978
2034
|
for (const secret of [target?.key, judge?.kind === "jev" ? judge.key : void 0]) {
|
|
1979
2035
|
if (secret) reason = reason.replaceAll(secret, "\u2026");
|
|
1980
2036
|
}
|
|
1981
|
-
this.io.warn(this.t({ zh: `mu setup\uFF1A\u4FDD\u5B58\u65F6\u51FA\u9519\uFF1A${reason}`, en: `mu setup:
|
|
2037
|
+
this.io.warn(this.t({ zh: `mu setup\uFF1A\u4FDD\u5B58\u65F6\u51FA\u9519\uFF1A${reason}`, en: `mu setup: couldn't save: ${reason}` }));
|
|
1982
2038
|
if (saved.length > 0) {
|
|
1983
2039
|
this.io.warn(this.t({ zh: "\u51FA\u9519\u524D\u5DF2\u7ECF\u4FDD\u5B58\u7684\uFF1A", en: "Saved before the error:" }));
|
|
1984
2040
|
for (const entry of saved) this.io.warn(entry);
|
|
@@ -2012,6 +2068,25 @@ var Setup = class {
|
|
|
2012
2068
|
savedLine(path, what) {
|
|
2013
2069
|
return ` ${this.path(path).padEnd(30)} ${what}`;
|
|
2014
2070
|
}
|
|
2071
|
+
/** "Not now": no decision point asks a judge (the default mode "off"), so nothing goes to one. */
|
|
2072
|
+
writeNoJudge(backups, saved, notes) {
|
|
2073
|
+
const configPath = judgeConfigPath(this.deps.paths.agentDir);
|
|
2074
|
+
const config = readJsonFile(configPath);
|
|
2075
|
+
if (config.state === "unreadable") {
|
|
2076
|
+
notes.push(
|
|
2077
|
+
this.t({
|
|
2078
|
+
zh: `${this.path(configPath)} \u4E0D\u662F\u7EAF JSON\uFF0C\u6CA1\u6709\u6539\u5B83\u3002\u8BF7\u624B\u52A8\u52A0\u4E0A "modes": { "default": "off" }`,
|
|
2079
|
+
en: `${this.path(configPath)} isn't plain JSON, so it was left unchanged. Add "modes": { "default": "off" } by hand.`
|
|
2080
|
+
})
|
|
2081
|
+
);
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
const current = config.state === "ok" ? config.value : void 0;
|
|
2085
|
+
if (judgeOff(current)) return;
|
|
2086
|
+
backups.save(configPath);
|
|
2087
|
+
writeJsonFile(configPath, withJudge(current ?? {}, false));
|
|
2088
|
+
saved.push(this.savedLine(configPath, this.t({ zh: "\u5224\u5B9A\u5668\uFF1A\u5173\u95ED", en: "judge: off" })));
|
|
2089
|
+
}
|
|
2015
2090
|
writeJudge(judge, target, model, backups, saved, notes) {
|
|
2016
2091
|
const { env, paths } = this.deps;
|
|
2017
2092
|
const configPath = judgeConfigPath(paths.agentDir);
|
|
@@ -2024,6 +2099,7 @@ var Setup = class {
|
|
|
2024
2099
|
else if (judge.kind === "free") {
|
|
2025
2100
|
if (!tiersOf(current).some((tier) => tier === "jev" || tier === "jev-opencode-free")) tiers = ["jev"];
|
|
2026
2101
|
} else if (!tiersOf(current).some((tier) => JEV_TIERS.has(tier))) tiers = ["jev"];
|
|
2102
|
+
const turnOn = judgeOff(current);
|
|
2027
2103
|
if (tiers && config.state === "unreadable") {
|
|
2028
2104
|
notes.push(
|
|
2029
2105
|
this.t({
|
|
@@ -2031,11 +2107,13 @@ var Setup = class {
|
|
|
2031
2107
|
en: `${this.path(configPath)} isn't plain JSON, so it was left unchanged. Add "tiers": ${JSON.stringify(tiers)} by hand.`
|
|
2032
2108
|
})
|
|
2033
2109
|
);
|
|
2034
|
-
} else if (tiers) {
|
|
2110
|
+
} else if (tiers || turnOn) {
|
|
2035
2111
|
backups.save(configPath);
|
|
2036
|
-
|
|
2112
|
+
const next = tiers ? withTiers(current ?? {}, tiers) : current ?? {};
|
|
2113
|
+
writeJsonFile(configPath, turnOn ? withJudge(next, true) : next);
|
|
2114
|
+
const named2 = tiers ?? tiersOf(current);
|
|
2037
2115
|
saved.push(
|
|
2038
|
-
this.savedLine(configPath, this.t({ zh: `\u5224\u5B9A\u5668 ${
|
|
2116
|
+
this.savedLine(configPath, this.t({ zh: `\u5224\u5B9A\u5668 ${named2.join(", ")}`, en: `judge: ${named2.join(", ")}` }))
|
|
2039
2117
|
);
|
|
2040
2118
|
}
|
|
2041
2119
|
if (judge.kind === "jev") {
|
|
@@ -2081,14 +2159,19 @@ var Setup = class {
|
|
|
2081
2159
|
target ? this.t({
|
|
2082
2160
|
zh: "\u5728 mu \u91CC\u7528 /model \u6362\u6A21\u578B\uFF1B\u968F\u65F6\u53EF\u4EE5\u518D\u8FD0\u884C mu setup\u3002",
|
|
2083
2161
|
en: "Switch models inside mu with /model, and run mu setup again any time."
|
|
2084
|
-
}) : this.t({ zh: "\
|
|
2162
|
+
}) : this.t({ zh: "\u63A5\u4E0B\u6765\u5728 mu \u91CC\u7528 /login \u767B\u5F55\u3002", en: "Next, sign in with /login in mu." })
|
|
2085
2163
|
);
|
|
2086
2164
|
}
|
|
2087
|
-
/**
|
|
2088
|
-
|
|
2089
|
-
|
|
2165
|
+
/**
|
|
2166
|
+
* On its own, a finished setup offers a session; on a first start the launcher goes on into one anyway. After a
|
|
2167
|
+
* subscription was chosen (`signIn`), that session opens on /login: SETUP_EXIT.signIn.
|
|
2168
|
+
*/
|
|
2169
|
+
async offerSession(signIn = false) {
|
|
2170
|
+
if (this.scripted) return SETUP_EXIT.done;
|
|
2171
|
+
if (this.args.firstRun) return signIn ? SETUP_EXIT.signIn : SETUP_EXIT.done;
|
|
2090
2172
|
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
|
-
|
|
2173
|
+
if (!start) return SETUP_EXIT.done;
|
|
2174
|
+
return signIn ? SETUP_EXIT.signIn : SETUP_EXIT.start;
|
|
2092
2175
|
}
|
|
2093
2176
|
};
|
|
2094
2177
|
function existingProviders(models) {
|