mu-agent 0.1.7 → 0.1.10
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 +52 -0
- package/README.md +34 -29
- package/dist/bundle/chunks/anthropic-messages-4PAJY4R6.js +6 -0
- package/dist/bundle/chunks/anthropic.js +2 -2
- package/dist/bundle/chunks/azure-openai-responses-Y4BBWQ3N.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +12 -9
- package/dist/bundle/chunks/{chunk-TRDNDS6A.js → chunk-3V45WARH.js} +6 -3
- package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-5AGIVGSV.js} +3 -3
- package/dist/bundle/chunks/chunk-6QGV3IWD.js +6 -0
- package/dist/bundle/chunks/chunk-7CBJINYJ.js +20 -0
- package/dist/bundle/chunks/{chunk-DRQDKNXA.js → chunk-7DDKXS2Q.js} +1 -1
- package/dist/bundle/chunks/chunk-BSS6T6KQ.js +2 -0
- package/dist/bundle/chunks/chunk-CF5GWZHW.js +31 -0
- package/dist/bundle/chunks/chunk-DNNHZBQR.js +4 -0
- package/dist/bundle/chunks/chunk-FN6OEZYR.js +2 -0
- package/dist/bundle/chunks/chunk-FTJT2X6E.js +2 -0
- package/dist/bundle/chunks/chunk-HZNN636Z.js +130 -0
- package/dist/bundle/chunks/{chunk-4L3WN2XY.js → chunk-JXWJOIH4.js} +1 -1
- package/dist/bundle/chunks/{chunk-4O2SCVYF.js → chunk-KIDDRTZP.js} +4 -4
- package/dist/bundle/chunks/chunk-LMNWTX2L.js +11 -0
- package/dist/bundle/chunks/chunk-LPXNMA2W.js +2 -0
- package/dist/bundle/chunks/{chunk-6CYCI3EJ.js → chunk-LVVZS2NO.js} +1 -1
- package/dist/bundle/chunks/chunk-NN4BEPYX.js +2 -0
- package/dist/bundle/chunks/chunk-O7IPTASE.js +1221 -0
- package/dist/bundle/chunks/chunk-PMRZO46Y.js +2 -0
- package/dist/bundle/chunks/chunk-QOEEJKS4.js +9 -0
- package/dist/bundle/chunks/chunk-R4VPBBDS.js +2 -0
- package/dist/bundle/chunks/chunk-RAQ6TU76.js +2 -0
- package/dist/bundle/chunks/chunk-RDZVAGPR.js +2 -0
- package/dist/bundle/chunks/chunk-SGOTYFMT.js +91 -0
- package/dist/bundle/chunks/chunk-TMTOQ7H7.js +2 -0
- package/dist/bundle/chunks/chunk-UKVNB6C4.js +2 -0
- package/dist/bundle/chunks/chunk-VJLOQZKR.js +9 -0
- package/dist/bundle/chunks/chunk-WCGU75WO.js +11 -0
- package/dist/bundle/chunks/chunk-X234222Q.js +64 -0
- package/dist/bundle/chunks/cli-722OL3K5.js +51 -0
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-MEZHQVNP.js +2 -0
- package/dist/bundle/chunks/codemode-worker.js +478 -0
- package/dist/bundle/chunks/easter-egg-3d-6H34EDGX.js +2 -0
- package/dist/bundle/chunks/execute-KVSEIDWL.js +499 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-C44KRRZ4.js → google-generative-ai-D2VJQBTK.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-25DUXPTJ.js → google-vertex-SQG2BO6C.js} +1 -1
- package/dist/bundle/chunks/https-proxy-agent-LVOO5TPL.js +13 -0
- package/dist/bundle/chunks/image-resize-worker.js +1 -1
- package/dist/bundle/chunks/{jiti-loader-C3NU2SDH.js → jiti-loader-GL4HJFAD.js} +1 -1
- package/dist/bundle/chunks/{jiti-static-loader-E6ANQD5T.js → jiti-static-loader-2RCDI6B4.js} +1 -1
- package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-4AVRLBHM.js} +2 -2
- package/dist/bundle/chunks/llama-cpp-classify-5YHLY3RC.js +22 -0
- package/dist/bundle/chunks/mistral-conversations-BDARVJTT.js +5 -0
- package/dist/bundle/chunks/{multipart-parser-SQ6GDJL7.js → multipart-parser-FMGQ7342.js} +1 -1
- package/dist/bundle/chunks/{node-TWVVAGPO.js → node-AUOGOBCN.js} +1 -1
- package/dist/bundle/chunks/node-KCMANYC2.js +16 -0
- package/dist/bundle/chunks/openai-chatgpt.js +86 -0
- package/dist/bundle/chunks/openai-codex-responses-CECGTDYD.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +2 -2
- package/dist/bundle/chunks/openai-completions-UOA7MELD.js +7 -0
- package/dist/bundle/chunks/openai-decisions-HLM372N6.js +5 -0
- package/dist/bundle/chunks/openai-responses-TII7ZY5X.js +3 -0
- package/dist/bundle/chunks/{openrouter-images-JVEJN44Q.js → openrouter-images-7T452AS5.js} +1 -1
- package/dist/bundle/chunks/openrouter.js +2 -2
- package/dist/bundle/chunks/{pi-messages-TM5SOOIW.js → pi-messages-2UDKLKOO.js} +1 -1
- package/dist/bundle/chunks/radius.js +2 -2
- package/dist/bundle/chunks/runtime-O3ELDOM7.js +2 -0
- package/dist/bundle/chunks/{src-UK77SYZE.js → src-QKGKDFSU.js} +1 -1
- package/dist/bundle/chunks/typesafe-system-one-KNCICMO5.js +2 -0
- package/dist/bundle/chunks/virtual-modules-IKEARUOZ.js +2 -0
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/export-html/template.js +37 -16
- package/dist/modes/interactive/theme/dark.json +60 -73
- package/dist/modes/interactive/theme/light.json +58 -70
- package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
- package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/system-theme.js +546 -0
- package/dist/modes/interactive/theme/system-theme.js.map +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +43 -9
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +121 -79
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.d.ts +28 -0
- package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.js +105 -0
- package/dist/modes/interactive/theme/theme-schema.js.map +1 -0
- package/dist/modes/interactive/theme/theme-tokens.d.ts +257 -0
- package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-tokens.js +94 -0
- package/dist/modes/interactive/theme/theme-tokens.js.map +1 -0
- package/dist/modes/interactive/theme/theme.d.ts +47 -56
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +149 -143
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/dist/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/docs/cli-integration.md +1 -1
- package/docs/cli.md +78 -13
- package/docs/codemode.md +230 -0
- package/docs/compaction.md +5 -5
- package/docs/configuration.md +2 -0
- package/docs/custom-provider.md +53 -1
- package/docs/docs.json +21 -1
- package/docs/environment-variables.md +5 -3
- package/docs/extensions.md +172 -10
- package/docs/index.md +1 -1
- package/docs/json.md +3 -3
- package/docs/keybindings.md +7 -6
- package/docs/llama-cpp.md +21 -1
- package/docs/mcp.md +272 -0
- package/docs/message-types.md +22 -4
- package/docs/models-configuration.md +187 -0
- package/docs/models.md +100 -2
- package/docs/nvidia-rtx-llama-cpp.md +96 -0
- package/docs/packages.md +1 -1
- package/docs/providers.md +66 -6
- package/docs/quickstart.md +16 -2
- package/docs/rpc-commands.md +9 -3
- package/docs/rpc.md +3 -1
- package/docs/sdk.md +8 -3
- package/docs/security.md +2 -0
- package/docs/session-format.md +5 -1
- package/docs/sessions.md +1 -1
- package/docs/settings.md +30 -8
- package/docs/terminal-setup.md +14 -0
- package/docs/themes.md +31 -7
- package/docs/tui.md +71 -1
- package/docs/usage.md +2 -2
- package/docs/virtual-models.md +114 -0
- package/docs/windows.md +2 -0
- package/examples/README.md +1 -4
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/built-in-tool-renderer.ts +16 -40
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
- package/examples/extensions/dynamic-resources/dynamic.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/jev-router.ts +113 -0
- package/examples/extensions/minimal-mode.ts +28 -101
- package/examples/extensions/overlay-test.ts +2 -2
- package/examples/extensions/plan-mode/index.ts +6 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/index.ts +4 -6
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-client.ts +1 -1
- package/examples/rpc-extension-ui.ts +1 -1
- package/examples/sdk/14-codemode-mcp.ts +61 -0
- package/examples/sdk/README.md +2 -1
- package/judge/THIRD_PARTY_NOTICES.md +63 -0
- package/judge/dist/auth.js +169 -123
- package/judge/dist/import.js +36 -30
- package/judge/dist/setup.js +250 -120
- package/judge/manifest.json +1008 -316
- package/judge/{dist/kyrn-judge.js → mu/index.js} +6933 -5995
- package/judge/themes/mu-dark.json +80 -0
- package/judge/themes/mu-light.json +80 -0
- package/kyrn/bin/kyrn-doctor +75 -25
- package/kyrn/bin/kyrn-judge-local +2 -2
- package/kyrn/bin/kyrn-ledger +1 -1
- package/kyrn/bin/mu.mjs +149 -107
- package/package.json +4 -5
- package/dist/bundle/chunks/anthropic-messages-VMESUHQ7.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-K232MQFF.js +0 -2
- package/dist/bundle/chunks/chunk-A3JYRWB6.js +0 -2
- package/dist/bundle/chunks/chunk-AYFRR3OD.js +0 -2
- package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +0 -42
- package/dist/bundle/chunks/chunk-FU4XQUSL.js +0 -11
- package/dist/bundle/chunks/chunk-GNYZK6XN.js +0 -2
- package/dist/bundle/chunks/chunk-HEMXN7VJ.js +0 -1653
- package/dist/bundle/chunks/chunk-MVPXOVOJ.js +0 -2
- package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
- package/dist/bundle/chunks/chunk-V7IXECST.js +0 -11
- package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NR2TDCXU.js +0 -2
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +0 -13
- package/dist/bundle/chunks/mistral-conversations-6IHQOR4R.js +0 -5
- package/dist/bundle/chunks/node-O3RIBJRH.js +0 -16
- package/dist/bundle/chunks/openai-codex-responses-3UAYOSSR.js +0 -10
- package/dist/bundle/chunks/openai-completions-FIEQGWAH.js +0 -7
- package/dist/bundle/chunks/openai-responses-OZJXLHFC.js +0 -2
- package/dist/bundle/chunks/typesafe-system-one-VKYX4OGY.js +0 -2
- package/dist/bundle/chunks/virtual-modules-V7SXVVLP.js +0 -2
- package/dist/modes/interactive/theme/theme-json.d.ts +0 -85
- package/dist/modes/interactive/theme/theme-json.d.ts.map +0 -1
- package/dist/modes/interactive/theme/theme-json.js +0 -132
- package/dist/modes/interactive/theme/theme-json.js.map +0 -1
- package/dist/modes/interactive/theme/theme-schema.json +0 -361
- package/examples/plugins/pi-example-plugin/README.md +0 -38
- package/examples/plugins/pi-example-plugin/package.json +0 -10
- package/examples/plugins/pi-example-plugin/src/contract.ts +0 -13
- package/examples/plugins/pi-example-plugin/src/session.ts +0 -24
- package/examples/plugins/pi-example-plugin/src/tui.ts +0 -31
package/judge/dist/setup.js
CHANGED
|
@@ -201,8 +201,11 @@ function backupStamp(now) {
|
|
|
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
203
|
var Backups = class {
|
|
204
|
+
root;
|
|
205
|
+
stamp;
|
|
206
|
+
made;
|
|
207
|
+
saved = /* @__PURE__ */ new Set();
|
|
204
208
|
constructor(home2, now) {
|
|
205
|
-
this.saved = /* @__PURE__ */ new Set();
|
|
206
209
|
this.root = join2(home2, "backups");
|
|
207
210
|
this.stamp = backupStamp(now);
|
|
208
211
|
}
|
|
@@ -587,6 +590,10 @@ async function checkKey({
|
|
|
587
590
|
fetch,
|
|
588
591
|
timeoutMs = CHECK_TIMEOUT_MS
|
|
589
592
|
}) {
|
|
593
|
+
if (kind === "opencode-key") {
|
|
594
|
+
const refused = await opencodeRefuses(baseUrl, key, fetch, timeoutMs);
|
|
595
|
+
if (refused) return { ok: false, problem: refused };
|
|
596
|
+
}
|
|
590
597
|
const request = checkRequest(kind, baseUrl, key);
|
|
591
598
|
const url = request.url.split("?")[0];
|
|
592
599
|
let response;
|
|
@@ -634,42 +641,68 @@ function explainProblem(problem, context, language) {
|
|
|
634
641
|
const host = hostOf(problem.url);
|
|
635
642
|
const seconds = Math.round((context.timeoutMs ?? CHECK_TIMEOUT_MS) / 1e3);
|
|
636
643
|
const local = /^(localhost|127\.|\[::1\])/.test(host);
|
|
637
|
-
const proxyHint = language === "zh" ? context.proxy ? `\u8FD9\u6B21\u8BF7\u6C42\u8D70\u4E86\u4EE3\u7406\uFF08${context.proxy}\uFF09\uFF0C\u786E\u8BA4\u4EE3\u7406\u6B63\u5728\u8FD0\u884C\u3002` : "\u5982\u679C\u9700\u8981\u4EE3\u7406\uFF1A\u8BBE\u7F6E HTTPS_PROXY\uFF0C\u6216\u5728 ~/.mu/agent/settings.json \u91CC\u5199 httpProxy\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C mu setup\u3002" : context.proxy ? `The request went through your proxy (${context.proxy})
|
|
644
|
+
const proxyHint = language === "zh" ? context.proxy ? `\u8FD9\u6B21\u8BF7\u6C42\u8D70\u4E86\u4EE3\u7406\uFF08${context.proxy}\uFF09\uFF0C\u786E\u8BA4\u4EE3\u7406\u6B63\u5728\u8FD0\u884C\u3002` : "\u5982\u679C\u9700\u8981\u4EE3\u7406\uFF1A\u8BBE\u7F6E HTTPS_PROXY\uFF0C\u6216\u5728 ~/.mu/agent/settings.json \u91CC\u5199 httpProxy\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C mu setup\u3002" : context.proxy ? `The request went through your proxy (${context.proxy}). Check that it's running.` : "If you need a proxy, set HTTPS_PROXY (or httpProxy in ~/.mu/agent/settings.json) and run mu setup again.";
|
|
638
645
|
const said = problem.said ? language === "zh" ? `\uFF08\u670D\u52A1\u7684\u539F\u8BDD\uFF1A${problem.said}\uFF09` : ` (The service said: ${problem.said})` : "";
|
|
639
646
|
const zh = language === "zh";
|
|
640
647
|
switch (problem.kind) {
|
|
641
648
|
case "key":
|
|
642
|
-
return zh ? `${service} \u4E0D\u63A5\u53D7\u8FD9\u4E2A\u5BC6\u94A5\u3002\u68C0\u67E5\u662F\u5426\u5B8C\u6574\u590D\u5236\uFF0C\u4EE5\u53CA\u5B83\u786E\u5B9E\u662F ${service} \u7684\u5BC6\u94A5\u3002` : `${service}
|
|
649
|
+
return zh ? `${service} \u4E0D\u63A5\u53D7\u8FD9\u4E2A\u5BC6\u94A5\u3002\u68C0\u67E5\u662F\u5426\u5B8C\u6574\u590D\u5236\uFF0C\u4EE5\u53CA\u5B83\u786E\u5B9E\u662F ${service} \u7684\u5BC6\u94A5\u3002` : `${service} didn't accept this key. Check that you copied all of it and that it's ${article(service)} key.`;
|
|
643
650
|
case "refused":
|
|
644
|
-
return zh ? `${service} \u62D2\u7EDD\u4E86\u8FD9\u4E2A\u5BC6\u94A5\uFF08HTTP 403\uFF09\uFF1A\u53EF\u80FD\u662F\u5BC6\u94A5\u4E0D\u5BF9\uFF0C\u6216\u5B83\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\u3002${said}` : `${service} refused this key (HTTP 403)
|
|
651
|
+
return zh ? `${service} \u62D2\u7EDD\u4E86\u8FD9\u4E2A\u5BC6\u94A5\uFF08HTTP 403\uFF09\uFF1A\u53EF\u80FD\u662F\u5BC6\u94A5\u4E0D\u5BF9\uFF0C\u6216\u5B83\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\u3002${said}` : `${service} refused this key (HTTP 403). The key may be wrong or lack access.${said}`;
|
|
645
652
|
case "permission":
|
|
646
|
-
return zh ? "\u8FD9\u4E2A\u5BC6\u94A5\u6709\u6548\uFF0C\u4F46\u6CA1\u6709\u8BFB\u53D6\u6A21\u578B\u5217\u8868\u7684\u6743\u9650\uFF08\u53D7\u9650\u5BC6\u94A5\uFF09\u3002\u7ED9\u5B83\u8BFB\u53D6\u6A21\u578B\u7684\u6743\u9650\uFF0C\u6216\u6362\u4E00\u4E2A\u5BC6\u94A5\u3002" : "The key works
|
|
653
|
+
return zh ? "\u8FD9\u4E2A\u5BC6\u94A5\u6709\u6548\uFF0C\u4F46\u6CA1\u6709\u8BFB\u53D6\u6A21\u578B\u5217\u8868\u7684\u6743\u9650\uFF08\u53D7\u9650\u5BC6\u94A5\uFF09\u3002\u7ED9\u5B83\u8BFB\u53D6\u6A21\u578B\u7684\u6743\u9650\uFF0C\u6216\u6362\u4E00\u4E2A\u5BC6\u94A5\u3002" : "The key works but can't list models (it's a restricted key). Give it permission to read models, or use another key.";
|
|
647
654
|
case "balance":
|
|
648
655
|
return zh ? `${service} \u7684\u8D26\u6237\u6CA1\u6709\u4F59\u989D\u6216\u989D\u5EA6\u4E86\u3002\u5145\u503C\u540E\u91CD\u65B0\u8FD0\u884C mu setup\u3002` : `The ${service} account has no balance or quota left. Top it up, then run mu setup again.`;
|
|
649
656
|
case "region":
|
|
650
|
-
return zh ? `${service} \u4E0D\u5411\u4F60\u6240\u5728\u7684\u5730\u533A\u63D0\u4F9B\u670D\u52A1\u3002\u9700\u8981\u4E00\u4E2A\u4F4D\u4E8E\u652F\u6301\u5730\u533A\u7684\u4EE3\u7406\u6216 VPN\u3002${proxyHint}` : `${service}
|
|
657
|
+
return zh ? `${service} \u4E0D\u5411\u4F60\u6240\u5728\u7684\u5730\u533A\u63D0\u4F9B\u670D\u52A1\u3002\u9700\u8981\u4E00\u4E2A\u4F4D\u4E8E\u652F\u6301\u5730\u533A\u7684\u4EE3\u7406\u6216 VPN\u3002${proxyHint}` : `${service} isn't available in the region this request came from. You need a proxy or VPN in a supported region. ${proxyHint}`;
|
|
651
658
|
case "rate":
|
|
652
|
-
return zh ? `${service} \u8BF4\u8BF7\u6C42\u592A\u9891\u7E41\u3002\u7B49\u4E00\u5206\u949F\u518D\u8BD5\u3002` : `${service}
|
|
659
|
+
return zh ? `${service} \u8BF4\u8BF7\u6C42\u592A\u9891\u7E41\u3002\u7B49\u4E00\u5206\u949F\u518D\u8BD5\u3002` : `${service} is getting too many requests from you. Wait a minute and try again.`;
|
|
653
660
|
case "address":
|
|
654
|
-
return zh ? `${problem.url} \u8FD9\u4E2A\u5730\u5740\u4E0D\u5B58\u5728\uFF08HTTP 404\uFF09\uFF1A\u5730\u5740\u586B\u9519\u4E86\u3002` : `Nothing
|
|
661
|
+
return zh ? `${problem.url} \u8FD9\u4E2A\u5730\u5740\u4E0D\u5B58\u5728\uFF08HTTP 404\uFF09\uFF1A\u5730\u5740\u586B\u9519\u4E86\u3002` : `Nothing was found at ${problem.url} (HTTP 404). Check the address.`;
|
|
655
662
|
case "server":
|
|
656
|
-
return zh ? `${service} \u81EA\u5DF1\u51FA\u9519\u4E86\uFF08HTTP ${problem.status}\uFF09\u3002\u8FC7\u4E00\u4F1A\u513F\u518D\u8BD5\u3002` : `${service}
|
|
663
|
+
return zh ? `${service} \u81EA\u5DF1\u51FA\u9519\u4E86\uFF08HTTP ${problem.status}\uFF09\u3002\u8FC7\u4E00\u4F1A\u513F\u518D\u8BD5\u3002` : `${service} returned a server error (HTTP ${problem.status}). Try again later.`;
|
|
657
664
|
case "response":
|
|
658
|
-
return zh ? `${problem.url} \u6709\u56DE\u5E94\uFF0C\u4F46\u4E0D\u662F\u6A21\u578B\u5217\u8868\uFF1A\u68C0\u67E5\u5730\u5740\u548C\u63A5\u53E3\u7C7B\u578B\u3002` : `${problem.url}
|
|
665
|
+
return zh ? `${problem.url} \u6709\u56DE\u5E94\uFF0C\u4F46\u4E0D\u662F\u6A21\u578B\u5217\u8868\uFF1A\u68C0\u67E5\u5730\u5740\u548C\u63A5\u53E3\u7C7B\u578B\u3002` : `${problem.url} responded, but not with a list of models. Check the address and the API type.`;
|
|
659
666
|
case "timeout":
|
|
660
|
-
return zh ? `${seconds} \u79D2\u5185 ${host} \u6CA1\u6709\u56DE\u5E94\u3002\u7F51\u7EDC\u53EF\u80FD\u4E0D\u901A\uFF1A\u6709\u4E9B\u5730\u533A\u8981\u7528\u4EE3\u7406\u6216 VPN \u624D\u80FD\u8BBF\u95EE\u3002${proxyHint}` : `No
|
|
667
|
+
return zh ? `${seconds} \u79D2\u5185 ${host} \u6CA1\u6709\u56DE\u5E94\u3002\u7F51\u7EDC\u53EF\u80FD\u4E0D\u901A\uFF1A\u6709\u4E9B\u5730\u533A\u8981\u7528\u4EE3\u7406\u6216 VPN \u624D\u80FD\u8BBF\u95EE\u3002${proxyHint}` : `No response from ${host} within ${seconds} s. The network may be blocking it; some regions need a proxy or VPN. ${proxyHint}`;
|
|
661
668
|
case "dns":
|
|
662
|
-
return zh ? `\u627E\u4E0D\u5230 ${host}\uFF1A\u6CA1\u6709\u8054\u7F51\uFF0C\u6216\u8FD9\u91CC\u89E3\u6790\u4E0D\u4E86\u8FD9\u4E2A\u57DF\u540D\u3002${proxyHint}` : `
|
|
669
|
+
return zh ? `\u627E\u4E0D\u5230 ${host}\uFF1A\u6CA1\u6709\u8054\u7F51\uFF0C\u6216\u8FD9\u91CC\u89E3\u6790\u4E0D\u4E86\u8FD9\u4E2A\u57DF\u540D\u3002${proxyHint}` : `Couldn't resolve ${host}. Check your internet connection and DNS. ${proxyHint}`;
|
|
663
670
|
case "connection":
|
|
664
671
|
if (local) {
|
|
665
|
-
return zh ? `${host} \u4E0A\u6CA1\u6709\u670D\u52A1\u5728\u76D1\u542C\uFF1A\u5B83\u542F\u52A8\u4E86\u5417\uFF1F` : `Nothing is listening at ${host}
|
|
672
|
+
return zh ? `${host} \u4E0A\u6CA1\u6709\u670D\u52A1\u5728\u76D1\u542C\uFF1A\u5B83\u542F\u52A8\u4E86\u5417\uFF1F` : `Nothing is listening at ${host}. Is the service running?`;
|
|
666
673
|
}
|
|
667
|
-
return zh ? `\u8FDE\u4E0D\u4E0A ${host}\u3002${proxyHint}` : `
|
|
674
|
+
return zh ? `\u8FDE\u4E0D\u4E0A ${host}\u3002${proxyHint}` : `Couldn't connect to ${host}. ${proxyHint}`;
|
|
668
675
|
case "tls":
|
|
669
|
-
return zh ? `\u548C ${host} \u7684\u5B89\u5168\u8FDE\u63A5\u5931\u8D25\u4E86\uFF1A\u53EF\u80FD\u6709\u4EE3\u7406\u6216\u9632\u706B\u5899\u5728\u62E6\u622A HTTPS\u3002` : `The secure connection to ${host} failed
|
|
676
|
+
return zh ? `\u548C ${host} \u7684\u5B89\u5168\u8FDE\u63A5\u5931\u8D25\u4E86\uFF1A\u53EF\u80FD\u6709\u4EE3\u7406\u6216\u9632\u706B\u5899\u5728\u62E6\u622A HTTPS\u3002` : `The secure connection to ${host} failed. A proxy or firewall may be intercepting HTTPS.`;
|
|
670
677
|
default:
|
|
671
|
-
return zh ? `${service} \u62D2\u7EDD\u4E86\u8FD9\u6B21\u68C0\u67E5\uFF08HTTP ${problem.status ?? "?"}\uFF09\u3002${said}` : `${service}
|
|
678
|
+
return zh ? `${service} \u62D2\u7EDD\u4E86\u8FD9\u6B21\u68C0\u67E5\uFF08HTTP ${problem.status ?? "?"}\uFF09\u3002${said}` : `${service} rejected the check (HTTP ${problem.status ?? "?"}).${said}`;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
async function opencodeRefuses(baseUrl, key, fetch, timeoutMs) {
|
|
682
|
+
const url = `${baseUrl.replace(/\/+$/, "")}/systemone`;
|
|
683
|
+
let response;
|
|
684
|
+
try {
|
|
685
|
+
response = await fetch(url, {
|
|
686
|
+
method: "POST",
|
|
687
|
+
headers: { "content-type": "application/json", ...key ? { authorization: `Bearer ${key}` } : {} },
|
|
688
|
+
body: JSON.stringify({
|
|
689
|
+
model: "jev-1.13-free",
|
|
690
|
+
state: "mu setup is checking a key.",
|
|
691
|
+
questions: { check: { type: "noul", instructions: "Is this a key check?" } }
|
|
692
|
+
}),
|
|
693
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
694
|
+
});
|
|
695
|
+
} catch (error) {
|
|
696
|
+
return { kind: classifyFailure(error), url };
|
|
672
697
|
}
|
|
698
|
+
if (response.ok) return void 0;
|
|
699
|
+
const text = await response.text().catch(() => "");
|
|
700
|
+
return {
|
|
701
|
+
kind: classifyAnswer(response.status, text),
|
|
702
|
+
url,
|
|
703
|
+
status: response.status,
|
|
704
|
+
said: safeMessage(messageOf(text), key) || void 0
|
|
705
|
+
};
|
|
673
706
|
}
|
|
674
707
|
|
|
675
708
|
// packages/kyrn-judge/src/setup/services.ts
|
|
@@ -773,6 +806,17 @@ var SETUP_SERVICES = [
|
|
|
773
806
|
builtIn: true,
|
|
774
807
|
check: "openrouter-key"
|
|
775
808
|
},
|
|
809
|
+
{
|
|
810
|
+
id: "opencode",
|
|
811
|
+
name: "OpenCode Zen",
|
|
812
|
+
baseUrls: ["https://opencode.ai/inference/v1"],
|
|
813
|
+
api: "openai-completions",
|
|
814
|
+
models: ["kimi-k2.6"],
|
|
815
|
+
keyPage: "https://opencode.ai/auth",
|
|
816
|
+
providers: ["opencode"],
|
|
817
|
+
builtIn: true,
|
|
818
|
+
check: "opencode-key"
|
|
819
|
+
},
|
|
776
820
|
{
|
|
777
821
|
id: "openai",
|
|
778
822
|
name: "OpenAI",
|
|
@@ -915,7 +959,16 @@ var SETUP_FLAGS = {
|
|
|
915
959
|
"--key-stdin": "keyStdin"
|
|
916
960
|
};
|
|
917
961
|
var JEV_KEY_NAMES = ["TYPESAFE_API_KEY", "MU_JUDGE_OPENROUTER_API_KEY", "AI_GATEWAY_API_KEY"];
|
|
918
|
-
var JEV_TIERS = /* @__PURE__ */ new Set([
|
|
962
|
+
var JEV_TIERS = /* @__PURE__ */ new Set([
|
|
963
|
+
"jev",
|
|
964
|
+
"jev-direct",
|
|
965
|
+
"jev-openrouter",
|
|
966
|
+
"jev-gateway",
|
|
967
|
+
"jev-opencode",
|
|
968
|
+
"jev-opencode-free",
|
|
969
|
+
"jev-cloudflare"
|
|
970
|
+
]);
|
|
971
|
+
var OPENCODE_KEY = "OPENCODE_API_KEY";
|
|
919
972
|
var JEV_PAGE = "https://typesafe.ai";
|
|
920
973
|
var BRANDED = /* @__PURE__ */ new Set(["openai", "anthropic", "openrouter", "google", "xai"]);
|
|
921
974
|
var OTHER = {
|
|
@@ -924,7 +977,7 @@ var OTHER = {
|
|
|
924
977
|
};
|
|
925
978
|
var NOT_READY = {
|
|
926
979
|
zh: "Ollama \u8FD8\u6CA1\u51C6\u5907\u597D\uFF08\u7528 `ollama serve` \u542F\u52A8\u5B83\uFF0C\u518D\u62C9\u53D6\u4E00\u4E2A\u6A21\u578B\uFF09\u3002",
|
|
927
|
-
en: "Ollama
|
|
980
|
+
en: "Ollama isn't ready yet. Start it with `ollama serve`, then pull a model."
|
|
928
981
|
};
|
|
929
982
|
function parseSetupArgs(argv) {
|
|
930
983
|
const values = /* @__PURE__ */ new Map();
|
|
@@ -947,22 +1000,27 @@ function parseSetupArgs(argv) {
|
|
|
947
1000
|
}
|
|
948
1001
|
const api = values.get("--api");
|
|
949
1002
|
if (api !== void 0 && api !== "openai" && api !== "anthropic") {
|
|
950
|
-
return { error: { zh: "--api \u53EA\u80FD\u662F openai \u6216 anthropic", en: "--api
|
|
1003
|
+
return { error: { zh: "--api \u53EA\u80FD\u662F openai \u6216 anthropic", en: "--api must be openai or anthropic" } };
|
|
951
1004
|
}
|
|
952
1005
|
const judge = values.get("--judge");
|
|
953
|
-
if (judge !== void 0 &&
|
|
954
|
-
return {
|
|
1006
|
+
if (judge !== void 0 && !["jev", "opencode", "free", "model", "none"].includes(judge)) {
|
|
1007
|
+
return {
|
|
1008
|
+
error: {
|
|
1009
|
+
zh: "--judge \u53EA\u80FD\u662F jev\u3001opencode\u3001free\u3001model \u6216 none",
|
|
1010
|
+
en: "--judge must be jev, opencode, free, model or none"
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
955
1013
|
}
|
|
956
1014
|
const service = values.get("--service");
|
|
957
1015
|
if (service !== void 0 && !serviceById(service)) {
|
|
958
1016
|
return {
|
|
959
1017
|
error: {
|
|
960
1018
|
zh: `\u6CA1\u6709\u53EB ${service} \u7684\u670D\u52A1\uFF08mu setup --list \u5217\u51FA\u5168\u90E8\uFF09`,
|
|
961
|
-
en: `
|
|
1019
|
+
en: `no service named ${service} (mu setup --list shows them all)`
|
|
962
1020
|
}
|
|
963
1021
|
};
|
|
964
1022
|
}
|
|
965
|
-
if (words.length > 1) return { error: { zh: "\u53EA\u80FD\u7ED9\u4E00\u4E2A\u5BC6\u94A5", en: "give one key
|
|
1023
|
+
if (words.length > 1) return { error: { zh: "\u53EA\u80FD\u7ED9\u4E00\u4E2A\u5BC6\u94A5", en: "give at most one key" } };
|
|
966
1024
|
return {
|
|
967
1025
|
help: flags.has("help"),
|
|
968
1026
|
list: flags.has("list"),
|
|
@@ -985,7 +1043,7 @@ function setupUsage(language) {
|
|
|
985
1043
|
"",
|
|
986
1044
|
" mu setup \u5728\u7EC8\u7AEF\u91CC\u4E00\u6B65\u4E00\u6B65\u95EE",
|
|
987
1045
|
" mu setup <\u5BC6\u94A5> \u4ECE\u4E00\u4E2A API \u5BC6\u94A5\u5F00\u59CB\uFF1Amu \u6309\u5BC6\u94A5\u7684\u6837\u5B50\u8BA4\u51FA\u5B83\u5C5E\u4E8E\u54EA\u4E2A\u670D\u52A1",
|
|
988
|
-
" mu setup --service <id> --key-stdin [--model <id>] [--base-url <\u5730\u5740>] [--judge
|
|
1046
|
+
" mu setup --service <id> --key-stdin [--model <id>] [--base-url <\u5730\u5740>] [--judge <\u5224\u5B9A\u5668>] [--yes]",
|
|
989
1047
|
" \u7ED9\u811A\u672C\u7528\uFF1A\u5BC6\u94A5\u4ECE\u6807\u51C6\u8F93\u5165\u8BFB\u53D6",
|
|
990
1048
|
" mu setup --list mu \u8BA4\u8BC6\u7684\u670D\u52A1\u548C\u5B83\u4EEC\u7684 id",
|
|
991
1049
|
"",
|
|
@@ -993,6 +1051,8 @@ function setupUsage(language) {
|
|
|
993
1051
|
"\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",
|
|
994
1052
|
"",
|
|
995
1053
|
" --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
|
+
" --judge opencode OpenCode Zen \u4E0A\u7684 Jev\uFF0C\u7528 OpenCode \u7684\u5BC6\u94A5\uFF08--service opencode \u6216 OPENCODE_API_KEY\uFF09",
|
|
1055
|
+
" --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",
|
|
996
1056
|
" --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",
|
|
997
1057
|
" --judge none \u4E0D\u6539\u5224\u5B9A\u5668\uFF1B\u4E0D\u5199 --judge \u65F6\u4E5F\u4E0D\u6539",
|
|
998
1058
|
" --api, --name \u670D\u52A1 other \u7684\u63A5\u53E3\uFF08openai \u6216 anthropic\uFF09\u548C\u5B83\u5728 mu \u91CC\u7684\u540D\u5B57",
|
|
@@ -1003,27 +1063,29 @@ function setupUsage(language) {
|
|
|
1003
1063
|
].join("\n");
|
|
1004
1064
|
}
|
|
1005
1065
|
return [
|
|
1006
|
-
"mu setup: connect a model for mu to work with, and choose
|
|
1066
|
+
"mu setup: connect a model for mu to work with, and choose a judge.",
|
|
1007
1067
|
"",
|
|
1008
|
-
" mu setup
|
|
1009
|
-
" mu setup <key> starts from an API key
|
|
1010
|
-
" mu setup --service <id> --key-stdin [--model <id>] [--base-url <url>] [--judge
|
|
1011
|
-
" for scripts: the key
|
|
1012
|
-
" mu setup --list the services mu knows
|
|
1068
|
+
" mu setup walks you through it, one question at a time",
|
|
1069
|
+
" mu setup <key> starts from an API key and detects its service from the key's format",
|
|
1070
|
+
" mu setup --service <id> --key-stdin [--model <id>] [--base-url <url>] [--judge <judge>] [--yes]",
|
|
1071
|
+
" for scripts: reads the key from stdin",
|
|
1072
|
+
" mu setup --list lists the services mu knows and their ids",
|
|
1013
1073
|
"",
|
|
1014
|
-
"Why stdin for scripts: a key on the command line stays in your shell
|
|
1015
|
-
"computer that lists processes can read it. `mu setup <key>` is
|
|
1016
|
-
"prompt when you can.",
|
|
1074
|
+
"Why stdin for scripts: a key on the command line stays in your shell history, and any program on this",
|
|
1075
|
+
"computer that lists processes can read it. `mu setup <key>` is a shortcut for getting started; paste the key",
|
|
1076
|
+
"at the prompt when you can.",
|
|
1017
1077
|
"",
|
|
1018
|
-
" --judge jev the Jev key (TypeSafe)
|
|
1019
|
-
" --judge
|
|
1020
|
-
" --judge
|
|
1078
|
+
" --judge jev read the Jev key (TypeSafe) from stdin's second line, unless TYPESAFE_API_KEY is already set",
|
|
1079
|
+
" --judge opencode use Jev on OpenCode Zen with an OpenCode key (--service opencode or OPENCODE_API_KEY)",
|
|
1080
|
+
" --judge free use the free Jev on OpenCode Zen (limited time, no key; the default while no key is set)",
|
|
1081
|
+
" --judge model use the model you just set up as the judge (slower, and every verdict costs tokens)",
|
|
1082
|
+
" --judge none leave the judge unchanged (the same as omitting --judge)",
|
|
1021
1083
|
" --api, --name for the service `other`: its API (openai or anthropic) and its name in mu",
|
|
1022
|
-
" --yes
|
|
1023
|
-
"
|
|
1084
|
+
" --yes don't ask; replace what's already set up (a subscription sign-in, a provider's address,",
|
|
1085
|
+
" the Jev key)",
|
|
1024
1086
|
"",
|
|
1025
|
-
"Files: auth.json (keys), models.json, settings.json and mu.json in ~/.mu/agent, and the .env
|
|
1026
|
-
"(the Jev key). Each is
|
|
1087
|
+
"Files it changes: auth.json (keys), models.json, settings.json and mu.json in ~/.mu/agent, and the .env",
|
|
1088
|
+
"mu reads (the Jev key). Each one is backed up to ~/.mu/backups/<time>/ before it changes."
|
|
1027
1089
|
].join("\n");
|
|
1028
1090
|
}
|
|
1029
1091
|
function label(service, language) {
|
|
@@ -1070,12 +1132,25 @@ function jevKeyAt(env, envFileText) {
|
|
|
1070
1132
|
return void 0;
|
|
1071
1133
|
}
|
|
1072
1134
|
var Stop = class extends Error {
|
|
1135
|
+
code;
|
|
1073
1136
|
constructor(code) {
|
|
1074
1137
|
super(`mu setup stopped (${code})`);
|
|
1075
1138
|
this.code = code;
|
|
1076
1139
|
}
|
|
1077
1140
|
};
|
|
1078
1141
|
var Setup = class {
|
|
1142
|
+
args;
|
|
1143
|
+
deps;
|
|
1144
|
+
io;
|
|
1145
|
+
language;
|
|
1146
|
+
/** No questions: a script, or --yes. */
|
|
1147
|
+
scripted;
|
|
1148
|
+
/** The second line of stdin, for --judge jev. */
|
|
1149
|
+
jevFromStdin;
|
|
1150
|
+
/** The key given for the model: a Jev key is never the same one. */
|
|
1151
|
+
modelKey;
|
|
1152
|
+
/** The provider id a service of one's own (`other`) gets in mu. */
|
|
1153
|
+
customName;
|
|
1079
1154
|
constructor(args, deps) {
|
|
1080
1155
|
this.args = args;
|
|
1081
1156
|
this.deps = deps;
|
|
@@ -1129,7 +1204,7 @@ var Setup = class {
|
|
|
1129
1204
|
}
|
|
1130
1205
|
pasteKey() {
|
|
1131
1206
|
return this.secret(
|
|
1132
|
-
this.t({ zh: "\u7C98\u8D34 API \u5BC6\u94A5\uFF08\u4E0D\u4F1A\u663E\u793A\u51FA\u6765\uFF09\uFF1A", en: "Paste the API key (it
|
|
1207
|
+
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): " })
|
|
1133
1208
|
);
|
|
1134
1209
|
}
|
|
1135
1210
|
async choose(question, choices) {
|
|
@@ -1141,7 +1216,7 @@ var Setup = class {
|
|
|
1141
1216
|
if (answer === "") return choices[0].value;
|
|
1142
1217
|
const number = Number(answer);
|
|
1143
1218
|
if (Number.isInteger(number) && number >= 1 && number <= choices.length) return choices[number - 1].value;
|
|
1144
|
-
this.io.say(this.t({ zh: `\u8BF7\u8F93\u5165 ${range} \u4E4B\u95F4\u7684\u6570\u5B57\u3002`, en: `Type a number from ${
|
|
1219
|
+
this.io.say(this.t({ zh: `\u8BF7\u8F93\u5165 ${range} \u4E4B\u95F4\u7684\u6570\u5B57\u3002`, en: `Type a number from 1 to ${choices.length}.` }));
|
|
1145
1220
|
}
|
|
1146
1221
|
}
|
|
1147
1222
|
async confirm(question, yes) {
|
|
@@ -1161,7 +1236,7 @@ var Setup = class {
|
|
|
1161
1236
|
throw this.fail(
|
|
1162
1237
|
{
|
|
1163
1238
|
zh: "--key-stdin \u4ECE\u7BA1\u9053\u8BFB\u5BC6\u94A5\u3002\u5728\u7EC8\u7AEF\u91CC\u8BF7\u76F4\u63A5\u8FD0\u884C mu setup\uFF0C\u5728\u63D0\u793A\u91CC\u7C98\u8D34\u5BC6\u94A5\uFF08\u4E0D\u4F1A\u663E\u793A\uFF09\u3002",
|
|
1164
|
-
en: "--key-stdin reads the key from a pipe. In a terminal, run mu setup and paste the key at
|
|
1239
|
+
en: "--key-stdin reads the key from a pipe. In a terminal, run mu setup and paste the key at the prompt (it won't be shown)."
|
|
1165
1240
|
},
|
|
1166
1241
|
SETUP_EXIT.usage
|
|
1167
1242
|
);
|
|
@@ -1172,9 +1247,9 @@ var Setup = class {
|
|
|
1172
1247
|
}
|
|
1173
1248
|
if (this.scripted && key === void 0 && args.service === void 0) {
|
|
1174
1249
|
throw this.fail(
|
|
1175
|
-
deps.interactive ? { zh: "\u6CA1\u6709\u5BC6\u94A5\uFF0C\u4E5F\u6CA1\u6709 --service", en: "no key
|
|
1250
|
+
deps.interactive ? { zh: "\u6CA1\u6709\u5BC6\u94A5\uFF0C\u4E5F\u6CA1\u6709 --service", en: "no key or --service given" } : {
|
|
1176
1251
|
zh: "\u95EE\u9898\u8981\u5728\u7EC8\u7AEF\u91CC\u56DE\u7B54\u3002\u811A\u672C\u91CC\u7528\uFF1Amu setup --service <id> --key-stdin\uFF08\u89C1 mu setup --help\uFF09",
|
|
1177
|
-
en: "
|
|
1252
|
+
en: "no terminal to ask in. In a script, use mu setup --service <id> --key-stdin (see mu setup --help)"
|
|
1178
1253
|
},
|
|
1179
1254
|
SETUP_EXIT.usage
|
|
1180
1255
|
);
|
|
@@ -1183,7 +1258,7 @@ var Setup = class {
|
|
|
1183
1258
|
this.io.say(
|
|
1184
1259
|
this.t({
|
|
1185
1260
|
zh: "mu setup\uFF1A\u7ED9 mu \u63A5\u4E0A\u4E00\u4E2A\u5E72\u6D3B\u7684\u6A21\u578B\uFF0C\u518D\u9009\u4E00\u4E2A\u5224\u5B9A\u5668\u3002",
|
|
1186
|
-
en: "mu setup: connect a model for mu to work with, and choose
|
|
1261
|
+
en: "mu setup: connect a model for mu to work with, and choose a judge."
|
|
1187
1262
|
})
|
|
1188
1263
|
);
|
|
1189
1264
|
}
|
|
@@ -1221,7 +1296,7 @@ var Setup = class {
|
|
|
1221
1296
|
this.io.say(
|
|
1222
1297
|
this.t({
|
|
1223
1298
|
zh: "\u597D\u7684\uFF0C\u4EE5\u540E\u4E0D\u518D\u95EE\u4E86\u3002\u9700\u8981\u65F6\u8FD0\u884C mu setup\uFF0C\u6216\u5728 mu \u91CC\u8F93\u5165 /login\u3002",
|
|
1224
|
-
en: "OK, mu
|
|
1299
|
+
en: "OK, mu won't ask again. Run mu setup whenever you're ready, or type /login inside mu."
|
|
1225
1300
|
})
|
|
1226
1301
|
);
|
|
1227
1302
|
return false;
|
|
@@ -1233,29 +1308,32 @@ var Setup = class {
|
|
|
1233
1308
|
const named2 = this.args.service === void 0 ? void 0 : serviceById(this.args.service);
|
|
1234
1309
|
if (named2) return this.keyFor(named2, key);
|
|
1235
1310
|
if (key !== void 0) return { service: await this.serviceOf(key), key };
|
|
1236
|
-
const route = await this.choose(
|
|
1237
|
-
{
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
label: this.t({
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1311
|
+
const route = await this.choose(
|
|
1312
|
+
this.t({ zh: "mu \u7528\u4EC0\u4E48\u65B9\u5F0F\u8FDE\u63A5\u6A21\u578B\uFF1F", en: "How should mu connect to a model?" }),
|
|
1313
|
+
[
|
|
1314
|
+
{
|
|
1315
|
+
label: this.t({
|
|
1316
|
+
zh: "\u7C98\u8D34 API \u5BC6\u94A5\uFF08mu \u4F1A\u8BA4\u51FA\u5B83\u5C5E\u4E8E\u54EA\u4E2A\u670D\u52A1\uFF09",
|
|
1317
|
+
en: "Paste an API key (mu detects which service it belongs to)"
|
|
1318
|
+
}),
|
|
1319
|
+
value: "key"
|
|
1320
|
+
},
|
|
1321
|
+
{ label: this.t({ zh: "\u4ECE\u5217\u8868\u91CC\u9009\u4E00\u4E2A\u670D\u52A1", en: "Choose a service from the list" }), value: "list" },
|
|
1322
|
+
{
|
|
1323
|
+
label: this.t({
|
|
1324
|
+
zh: "\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\uFF1AChatGPT\u3001Claude\u3001Grok \u6216 Google",
|
|
1325
|
+
en: "Sign in with a subscription: ChatGPT, Claude, Grok or Google"
|
|
1326
|
+
}),
|
|
1327
|
+
value: "subscription"
|
|
1328
|
+
}
|
|
1329
|
+
]
|
|
1330
|
+
);
|
|
1253
1331
|
if (route === "subscription") {
|
|
1254
1332
|
const auth = this.path(join3(this.deps.paths.agentDir, "auth.json"));
|
|
1255
1333
|
this.io.say(
|
|
1256
1334
|
this.t({
|
|
1257
1335
|
zh: `\u8BA2\u9605\u8D26\u53F7\u5728 mu \u91CC\u9762\u767B\u5F55\uFF1A\u542F\u52A8 mu\uFF0C\u8F93\u5165 /login\uFF0C\u9009 ChatGPT\uFF08OpenAI Codex\uFF09\u3001Claude\u3001Grok \u6216 Google\uFF0C\u6309\u63D0\u793A\u5728\u6D4F\u89C8\u5668\u91CC\u5B8C\u6210\u3002\u767B\u5F55\u4FE1\u606F\u4FDD\u5B58\u5728 ${auth}\u3002`,
|
|
1258
|
-
en: `
|
|
1336
|
+
en: `Subscriptions sign in from inside mu: start mu, type /login, choose ChatGPT (OpenAI Codex), Claude, Grok or Google, and finish in the browser. The sign-in is saved in ${auth}.`
|
|
1259
1337
|
})
|
|
1260
1338
|
);
|
|
1261
1339
|
return "subscription";
|
|
@@ -1289,10 +1367,10 @@ var Setup = class {
|
|
|
1289
1367
|
throw this.fail(
|
|
1290
1368
|
matches.length > 1 ? {
|
|
1291
1369
|
zh: `${this.names(matches)} \u7684\u5BC6\u94A5\u957F\u5F97\u4E00\u6837\u3002\u7528 --service \u8BF4\u660E\u662F\u54EA\u5BB6\uFF1A${matches.map((service) => service.id).join(" \u6216 ")}`,
|
|
1292
|
-
en:
|
|
1370
|
+
en: `${this.names(matches)} keys look the same. Choose one with --service ${matches.map((service) => service.id).join(" or ")}`
|
|
1293
1371
|
} : {
|
|
1294
1372
|
zh: "\u8BA4\u4E0D\u51FA\u8FD9\u4E2A\u5BC6\u94A5\u5C5E\u4E8E\u54EA\u4E2A\u670D\u52A1\u3002\u7528 --service <id> \u8BF4\u660E\uFF08mu setup --list \u5217\u51FA\u5168\u90E8\uFF09",
|
|
1295
|
-
en: "this key's
|
|
1373
|
+
en: "mu doesn't recognize this key's format. Say which service it's for with --service <id> (mu setup --list)"
|
|
1296
1374
|
},
|
|
1297
1375
|
SETUP_EXIT.usage
|
|
1298
1376
|
);
|
|
@@ -1302,7 +1380,7 @@ var Setup = class {
|
|
|
1302
1380
|
matches,
|
|
1303
1381
|
this.t({
|
|
1304
1382
|
zh: `${this.names(matches)} \u7684\u5BC6\u94A5\u957F\u5F97\u4E00\u6837\u3002\u8FD9\u4E2A\u5BC6\u94A5\u662F\u54EA\u5BB6\u7684\uFF1Fmu \u53EA\u628A\u5BC6\u94A5\u53D1\u7ED9\u5B83\u6240\u5C5E\u7684\u670D\u52A1\u3002`,
|
|
1305
|
-
en:
|
|
1383
|
+
en: `${this.names(matches)} keys look the same. Which service is this key for? mu only sends a key to the service it belongs to.`
|
|
1306
1384
|
})
|
|
1307
1385
|
);
|
|
1308
1386
|
}
|
|
@@ -1310,7 +1388,7 @@ var Setup = class {
|
|
|
1310
1388
|
SETUP_SERVICES.filter((service) => !service.keyless),
|
|
1311
1389
|
this.t({
|
|
1312
1390
|
zh: "mu \u8BA4\u4E0D\u51FA\u8FD9\u4E2A\u5BC6\u94A5\u3002\u5B83\u662F\u54EA\u4E2A\u670D\u52A1\u7684\uFF1F",
|
|
1313
|
-
en: "mu
|
|
1391
|
+
en: "mu doesn't recognize this key. Which service is it for?"
|
|
1314
1392
|
})
|
|
1315
1393
|
);
|
|
1316
1394
|
}
|
|
@@ -1321,9 +1399,7 @@ var Setup = class {
|
|
|
1321
1399
|
let key = given;
|
|
1322
1400
|
if (key === void 0 && !this.scripted) {
|
|
1323
1401
|
if (service.keyPage) {
|
|
1324
|
-
this.io.say(
|
|
1325
|
-
this.t({ zh: `\u5BC6\u94A5\u5728\u8FD9\u91CC\u521B\u5EFA\uFF1A${service.keyPage}`, en: `Keys are made at ${service.keyPage}` })
|
|
1326
|
-
);
|
|
1402
|
+
this.io.say(this.t({ zh: `\u5BC6\u94A5\u5728\u8FD9\u91CC\u521B\u5EFA\uFF1A${service.keyPage}`, en: `Create a key at ${service.keyPage}` }));
|
|
1327
1403
|
}
|
|
1328
1404
|
key = await this.pasteKey();
|
|
1329
1405
|
}
|
|
@@ -1341,7 +1417,7 @@ var Setup = class {
|
|
|
1341
1417
|
this.io.warn(
|
|
1342
1418
|
this.t({
|
|
1343
1419
|
zh: `\u6CE8\u610F\uFF1A\u8FD9\u4E2A\u5BC6\u94A5\u770B\u8D77\u6765\u662F ${this.names(matches)} \u7684\uFF1B\u6309 --service \u53D1\u7ED9 ${this.name(service)}\u3002`,
|
|
1344
|
-
en: `Note: this key looks like ${article(this.names(matches))} key; it
|
|
1420
|
+
en: `Note: this key looks like ${article(this.names(matches))} key; sending it to ${this.name(service)}, as --service says.`
|
|
1345
1421
|
})
|
|
1346
1422
|
);
|
|
1347
1423
|
return { service, key };
|
|
@@ -1388,11 +1464,14 @@ var Setup = class {
|
|
|
1388
1464
|
);
|
|
1389
1465
|
if (/^https?:\/\/[^\s/]+/i.test(baseUrl)) break;
|
|
1390
1466
|
this.io.say(
|
|
1391
|
-
this.t({
|
|
1467
|
+
this.t({
|
|
1468
|
+
zh: "\u5730\u5740\u4EE5 http:// \u6216 https:// \u5F00\u5934\u3002",
|
|
1469
|
+
en: "The address must start with http:// or https://."
|
|
1470
|
+
})
|
|
1392
1471
|
);
|
|
1393
1472
|
}
|
|
1394
1473
|
}
|
|
1395
|
-
const api = args.api === "anthropic" ? "anthropic-messages" : args.api === "openai" || this.scripted ? "openai-completions" : await this.choose(this.t({ zh: "\u5B83\u7528\u54EA\u79CD\u63A5\u53E3\uFF1F", en: "Which API does it
|
|
1474
|
+
const api = args.api === "anthropic" ? "anthropic-messages" : args.api === "openai" || this.scripted ? "openai-completions" : await this.choose(this.t({ zh: "\u5B83\u7528\u54EA\u79CD\u63A5\u53E3\uFF1F", en: "Which API does it use?" }), [
|
|
1396
1475
|
{
|
|
1397
1476
|
label: this.t({
|
|
1398
1477
|
zh: "OpenAI \u517C\u5BB9\uFF08chat completions\uFF09",
|
|
@@ -1414,7 +1493,7 @@ var Setup = class {
|
|
|
1414
1493
|
const typed = await this.ask(
|
|
1415
1494
|
this.t({
|
|
1416
1495
|
zh: `\u7ED9\u5B83\u8D77\u4E2A\u7B80\u77ED\u7684\u540D\u5B57\uFF08\u5B57\u6BCD\u3001\u6570\u5B57\u3001-\uFF09[${provider}]\uFF1A`,
|
|
1417
|
-
en: `A short name for it in mu (letters, digits
|
|
1496
|
+
en: `A short name for it in mu (letters, digits and -) [${provider}]: `
|
|
1418
1497
|
})
|
|
1419
1498
|
);
|
|
1420
1499
|
if (typed) provider = typed.toLowerCase().replace(/[^a-z0-9-]+/g, "-");
|
|
@@ -1443,7 +1522,7 @@ var Setup = class {
|
|
|
1443
1522
|
key = await this.secret(
|
|
1444
1523
|
this.t({
|
|
1445
1524
|
zh: "\u7C98\u8D34\u5B83\u7684 API \u5BC6\u94A5\uFF1B\u4E0D\u9700\u8981\u5BC6\u94A5\u5C31\u76F4\u63A5\u56DE\u8F66\uFF08\u4E0D\u4F1A\u663E\u793A\uFF09\uFF1A",
|
|
1446
|
-
en: "Paste its API key, or press Enter if it
|
|
1525
|
+
en: "Paste its API key, or press Enter if it doesn't need one (it won't be shown): "
|
|
1447
1526
|
}),
|
|
1448
1527
|
true
|
|
1449
1528
|
) || void 0;
|
|
@@ -1462,15 +1541,15 @@ var Setup = class {
|
|
|
1462
1541
|
choices.push({ label: this.t({ zh: "\u518D\u8BD5\u4E00\u6B21", en: "Try again" }), value: "again" });
|
|
1463
1542
|
if (result.problem.kind !== "key") {
|
|
1464
1543
|
choices.push({
|
|
1465
|
-
label: this.t({ zh: "\u4E0D\u68C0\u67E5\u4E86\uFF0C\u7167\u6837\u4FDD\u5B58", en: "Save it without
|
|
1544
|
+
label: this.t({ zh: "\u4E0D\u68C0\u67E5\u4E86\uFF0C\u7167\u6837\u4FDD\u5B58", en: "Save it without checking" }),
|
|
1466
1545
|
value: "unchecked"
|
|
1467
1546
|
});
|
|
1468
1547
|
}
|
|
1469
1548
|
choices.push({
|
|
1470
|
-
label: this.t({ zh: "\u5230\u6B64\u4E3A\u6B62\uFF08\u4EC0\u4E48\u90FD\u4E0D\u6539\uFF09", en: "Stop here (nothing
|
|
1549
|
+
label: this.t({ zh: "\u5230\u6B64\u4E3A\u6B62\uFF08\u4EC0\u4E48\u90FD\u4E0D\u6539\uFF09", en: "Stop here (change nothing)" }),
|
|
1471
1550
|
value: "stop"
|
|
1472
1551
|
});
|
|
1473
|
-
const next = await this.choose(this.t({ zh: "\u63A5\u4E0B\u6765\u600E\u4E48\u529E\uFF1F", en: "What
|
|
1552
|
+
const next = await this.choose(this.t({ zh: "\u63A5\u4E0B\u6765\u600E\u4E48\u529E\uFF1F", en: "What next?" }), choices);
|
|
1474
1553
|
if (next === "stop") throw this.cancelled();
|
|
1475
1554
|
if (next === "unchecked") return { service, reach: reaches[0], key };
|
|
1476
1555
|
if (next === "key") key = await this.pasteKey();
|
|
@@ -1486,10 +1565,10 @@ var Setup = class {
|
|
|
1486
1565
|
this.io.say(
|
|
1487
1566
|
key ? this.t({
|
|
1488
1567
|
zh: `\u6B63\u5728\u7528 ${where}\u68C0\u67E5\u5BC6\u94A5\u2026\u2026`,
|
|
1489
|
-
en: `Checking the key with ${this.name(service)} (${hostOf2(reach.baseUrl)})
|
|
1568
|
+
en: `Checking the key with ${this.name(service)} (${hostOf2(reach.baseUrl)})\u2026`
|
|
1490
1569
|
}) : this.t({
|
|
1491
1570
|
zh: `\u6B63\u5728\u68C0\u67E5 ${where}\u2026\u2026`,
|
|
1492
|
-
en: `Checking ${this.name(service)} (${hostOf2(reach.baseUrl)})
|
|
1571
|
+
en: `Checking ${this.name(service)} (${hostOf2(reach.baseUrl)})\u2026`
|
|
1493
1572
|
})
|
|
1494
1573
|
);
|
|
1495
1574
|
const result = await checkKey({
|
|
@@ -1504,7 +1583,7 @@ var Setup = class {
|
|
|
1504
1583
|
this.io.say(
|
|
1505
1584
|
count === void 0 ? this.t({ zh: "\u5BC6\u94A5\u53EF\u4EE5\u7528\u3002", en: "The key works." }) : this.t({
|
|
1506
1585
|
zh: `\u53EF\u4EE5\u7528\uFF1A\u5217\u51FA\u4E86 ${count} \u4E2A\u6A21\u578B\u3002`,
|
|
1507
|
-
en: `It works: ${count} model${count === 1 ? "" : "s"}
|
|
1586
|
+
en: `It works: ${count} model${count === 1 ? "" : "s"} available.`
|
|
1508
1587
|
})
|
|
1509
1588
|
);
|
|
1510
1589
|
return { ok: true, reach, listed: result.models };
|
|
@@ -1528,13 +1607,13 @@ var Setup = class {
|
|
|
1528
1607
|
if (this.scripted) {
|
|
1529
1608
|
throw this.fail({
|
|
1530
1609
|
zh: `${this.name(service)} \u5DF2\u7ECF\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\u4E86\u3002\u8981\u6539\u5B58\u5BC6\u94A5\uFF0C\u52A0\u4E0A --yes`,
|
|
1531
|
-
en: `${this.name(service)} is signed in with a subscription. To
|
|
1610
|
+
en: `${this.name(service)} is signed in with a subscription. To use a key instead, add --yes`
|
|
1532
1611
|
});
|
|
1533
1612
|
}
|
|
1534
1613
|
const replace = await this.confirm(
|
|
1535
1614
|
this.t({
|
|
1536
1615
|
zh: `\u4F60\u5DF2\u7ECF\u7528\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\u4E86 ${this.name(service)}\u3002\u6539\u7528\u8FD9\u4E2A\u5BC6\u94A5\u5417\uFF1F\u767B\u5F55\u4F1A\u88AB\u66FF\u6362\uFF08\u7559\u6709\u5907\u4EFD\uFF09\u3002[y/N] `,
|
|
1537
|
-
en: `You
|
|
1616
|
+
en: `You're signed in to ${this.name(service)} with a subscription. Use this key instead? It replaces the sign-in (a backup is kept). [y/N] `
|
|
1538
1617
|
}),
|
|
1539
1618
|
false
|
|
1540
1619
|
);
|
|
@@ -1547,7 +1626,7 @@ var Setup = class {
|
|
|
1547
1626
|
if (readJsonFile(path).state !== "unreadable") return;
|
|
1548
1627
|
throw this.fail({
|
|
1549
1628
|
zh: `${this.path(path)} \u4E0D\u662F\u7EAF JSON\uFF08\u4E5F\u8BB8\u6709\u6CE8\u91CA\u6216\u5199\u9519\u4E86\uFF09\uFF0Cmu setup \u4E0D\u6539\u5199\u5B83\u3002\u5148\u4FEE\u597D\u5B83\uFF0C\u6216\u624B\u52A8\u628A\u670D\u52A1\u52A0\u8FDB\u53BB\u3002`,
|
|
1550
|
-
en: `${this.path(path)}
|
|
1629
|
+
en: `${this.path(path)} isn't plain JSON (it may have comments or a typo), so mu setup won't rewrite it. Fix it, or add the service by hand.`
|
|
1551
1630
|
});
|
|
1552
1631
|
}
|
|
1553
1632
|
// -----------------------------------------------------------------------------------------------------------
|
|
@@ -1560,7 +1639,7 @@ var Setup = class {
|
|
|
1560
1639
|
this.io.say(
|
|
1561
1640
|
this.t({
|
|
1562
1641
|
zh: `\u6CE8\u610F\uFF1A${this.name(service)} \u6CA1\u6709\u5217\u51FA ${this.args.model}\uFF0C\u7167\u6837\u4F7F\u7528\u3002`,
|
|
1563
|
-
en: `Note: ${this.name(service)}
|
|
1642
|
+
en: `Note: ${this.name(service)} doesn't list ${this.args.model}; using it anyway.`
|
|
1564
1643
|
})
|
|
1565
1644
|
);
|
|
1566
1645
|
}
|
|
@@ -1576,14 +1655,14 @@ var Setup = class {
|
|
|
1576
1655
|
if (options.length === 0) {
|
|
1577
1656
|
const none = service.keyless ? NOT_READY : {
|
|
1578
1657
|
zh: `${this.name(service)} \u6CA1\u6709\u5217\u51FA\u6A21\u578B\u3002`,
|
|
1579
|
-
en: `${this.name(service)}
|
|
1658
|
+
en: `${this.name(service)} doesn't list any models.`
|
|
1580
1659
|
};
|
|
1581
1660
|
if (this.scripted) {
|
|
1582
|
-
throw this.fail({ zh: `${none.zh}\u53EF\u4EE5\u7528 --model \u6307\u5B9A\u4E00\u4E2A\u3002`, en: `${none.en}
|
|
1661
|
+
throw this.fail({ zh: `${none.zh}\u53EF\u4EE5\u7528 --model \u6307\u5B9A\u4E00\u4E2A\u3002`, en: `${none.en} Specify one with --model.` });
|
|
1583
1662
|
}
|
|
1584
1663
|
this.io.say(this.t(none));
|
|
1585
1664
|
for (; ; ) {
|
|
1586
|
-
const typed = await this.ask(this.t({ zh: "\u8981\u7528\u7684\u6A21\u578B\u540D\uFF1A", en: "
|
|
1665
|
+
const typed = await this.ask(this.t({ zh: "\u8981\u7528\u7684\u6A21\u578B\u540D\uFF1A", en: "Name of the model to use: " }));
|
|
1587
1666
|
if (typed) return typed;
|
|
1588
1667
|
}
|
|
1589
1668
|
}
|
|
@@ -1599,7 +1678,7 @@ var Setup = class {
|
|
|
1599
1678
|
this.io.say(
|
|
1600
1679
|
this.t({
|
|
1601
1680
|
zh: ` \uFF08\u8FD8\u6709 ${more} \u4E2A\uFF0C\u8F93\u5165\u540D\u5B57\u4E5F\u53EF\u4EE5\uFF09`,
|
|
1602
|
-
en: ` (${more} more
|
|
1681
|
+
en: ` (${more} more; type a name to use one of them)`
|
|
1603
1682
|
})
|
|
1604
1683
|
);
|
|
1605
1684
|
}
|
|
@@ -1617,7 +1696,7 @@ var Setup = class {
|
|
|
1617
1696
|
this.io.say(
|
|
1618
1697
|
this.t({
|
|
1619
1698
|
zh: `\u8BF7\u8F93\u5165 1-${shown.length} \u4E4B\u95F4\u7684\u6570\u5B57\uFF0C\u6216\u6A21\u578B\u540D\u3002`,
|
|
1620
|
-
en: `Type a number from 1
|
|
1699
|
+
en: `Type a number from 1 to ${shown.length}, or a model name.`
|
|
1621
1700
|
})
|
|
1622
1701
|
);
|
|
1623
1702
|
}
|
|
@@ -1633,13 +1712,13 @@ var Setup = class {
|
|
|
1633
1712
|
if (this.scripted) {
|
|
1634
1713
|
throw this.fail({
|
|
1635
1714
|
zh: `models.json \u91CC\u7684 ${target.reach.provider} \u6307\u5411 ${old}\u3002\u8981\u6539\u6210 ${target.reach.baseUrl}\uFF0C\u52A0\u4E0A --yes`,
|
|
1636
|
-
en: `models.json
|
|
1715
|
+
en: `models.json already points ${target.reach.provider} at ${old}. To point it at ${target.reach.baseUrl}, add --yes`
|
|
1637
1716
|
});
|
|
1638
1717
|
}
|
|
1639
1718
|
const move = await this.confirm(
|
|
1640
1719
|
this.t({
|
|
1641
1720
|
zh: `models.json \u91CC\u5DF2\u7ECF\u6709 ${target.reach.provider}\uFF0C\u5730\u5740\u662F ${old}\u3002\u6539\u6210 ${target.reach.baseUrl} \u5417\uFF1F[y/N] `,
|
|
1642
|
-
en: `models.json already
|
|
1721
|
+
en: `models.json already points ${target.reach.provider} at ${old}. Point it at ${target.reach.baseUrl} instead? [y/N] `
|
|
1643
1722
|
}),
|
|
1644
1723
|
false
|
|
1645
1724
|
);
|
|
@@ -1652,33 +1731,65 @@ var Setup = class {
|
|
|
1652
1731
|
const { env, paths } = this.deps;
|
|
1653
1732
|
const envText = readTextFile(paths.envFile);
|
|
1654
1733
|
const existing = jevKeyAt(env, envText);
|
|
1655
|
-
|
|
1734
|
+
const opencode = model?.provider === "opencode" || Boolean(env[OPENCODE_KEY]) || !(OPENCODE_KEY in env) && envText !== void 0 && Boolean(envFileValue(envText, OPENCODE_KEY)) || await this.deps.pi.credential("opencode") !== void 0;
|
|
1735
|
+
if (this.scripted) return this.scriptedJudge(model, envText, existing !== void 0, opencode);
|
|
1656
1736
|
const where = existing ? existing.where === "env" ? this.t({ zh: `\u73AF\u5883\u53D8\u91CF ${existing.name}`, en: `${existing.name} in your environment` }) : this.t({
|
|
1657
1737
|
zh: `${this.path(paths.envFile)} \u91CC\u7684 ${existing.name}`,
|
|
1658
1738
|
en: `${existing.name} in ${this.path(paths.envFile)}`
|
|
1659
1739
|
}) : void 0;
|
|
1660
1740
|
const choices = [];
|
|
1741
|
+
const keyless = !opencode && !where;
|
|
1742
|
+
if (keyless) {
|
|
1743
|
+
choices.push({
|
|
1744
|
+
label: this.t({
|
|
1745
|
+
zh: "Jev \u514D\u8D39\u7248\uFF08\u63A8\u8350\uFF09\uFF0C\u5728 OpenCode Zen \u4E0A\uFF1A\u4E0D\u7528\u5BC6\u94A5\uFF0C\u9650\u65F6\u514D\u8D39\uFF1B\u4EE5\u540E\u52A0\u4E86\u5BC6\u94A5\u81EA\u52A8\u6362\u7528",
|
|
1746
|
+
en: "Free Jev on OpenCode Zen (recommended): no key needed, free for a limited time; a key you add later takes over"
|
|
1747
|
+
}),
|
|
1748
|
+
value: "free"
|
|
1749
|
+
});
|
|
1750
|
+
}
|
|
1751
|
+
if (opencode && !where) {
|
|
1752
|
+
choices.push({
|
|
1753
|
+
label: this.t({
|
|
1754
|
+
zh: "Jev\uFF08\u63A8\u8350\uFF09\uFF0C\u5728 OpenCode Zen \u4E0A\uFF0C\u7528\u4F60\u7684 OpenCode \u5BC6\u94A5\uFF0C\u6309\u6B21\u8BA1\u8D39",
|
|
1755
|
+
en: "Jev on OpenCode Zen with your OpenCode key (recommended), billed per call"
|
|
1756
|
+
}),
|
|
1757
|
+
value: "opencode"
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1661
1760
|
if (where) {
|
|
1662
1761
|
choices.push({
|
|
1663
1762
|
label: this.t({
|
|
1664
1763
|
zh: `Jev\uFF08\u63A8\u8350\uFF09\uFF0C\u7528\u5DF2\u7ECF\u8BBE\u7F6E\u7684\u5BC6\u94A5\uFF08${where}\uFF09`,
|
|
1665
|
-
en: `Jev
|
|
1764
|
+
en: `Jev with the key that's already set (recommended): ${where}`
|
|
1666
1765
|
}),
|
|
1667
1766
|
value: "keep"
|
|
1668
1767
|
});
|
|
1669
1768
|
}
|
|
1670
1769
|
choices.push({
|
|
1671
|
-
label: where ? this.t({ zh: "Jev\uFF0C\u6362\u4E00\u4E2A\u65B0\u5BC6\u94A5", en: "Jev
|
|
1672
|
-
zh: `Jev\
|
|
1673
|
-
en: `Jev
|
|
1770
|
+
label: where ? this.t({ zh: "Jev\uFF0C\u6362\u4E00\u4E2A\u65B0\u5BC6\u94A5", en: "Jev with a new key" }) : opencode ? this.t({
|
|
1771
|
+
zh: `Jev\uFF0C\u7528 TypeSafe \u7684\u5BC6\u94A5\uFF1A${JEV_PAGE}`,
|
|
1772
|
+
en: `Jev with a TypeSafe key: ${JEV_PAGE}`
|
|
1773
|
+
}) : this.t({
|
|
1774
|
+
zh: `Jev\uFF0C\u7528\u81EA\u5DF1\u7684\u5BC6\u94A5\uFF1A\u6BCF\u4E2A\u95EE\u9898\u7EA6 0.3 \u79D2\uFF0C\u6309\u6B21\u8BA1\u8D39\u3002\u5BC6\u94A5\u5728 TypeSafe \u7533\u8BF7\uFF1A${JEV_PAGE}`,
|
|
1775
|
+
en: `Jev with your own key: about 0.3 s per question, billed per call. Get a key from TypeSafe: ${JEV_PAGE}`
|
|
1674
1776
|
}),
|
|
1675
1777
|
value: "jev"
|
|
1676
1778
|
});
|
|
1779
|
+
if (!keyless) {
|
|
1780
|
+
choices.push({
|
|
1781
|
+
label: this.t({
|
|
1782
|
+
zh: "Jev \u514D\u8D39\u7248\uFF0C\u5728 OpenCode Zen \u4E0A\uFF1A\u4E0D\u7528\u5BC6\u94A5\uFF0C\u9650\u65F6\u514D\u8D39",
|
|
1783
|
+
en: "Free Jev on OpenCode Zen: no key needed, free for a limited time"
|
|
1784
|
+
}),
|
|
1785
|
+
value: "free"
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1677
1788
|
if (model) {
|
|
1678
1789
|
choices.push({
|
|
1679
1790
|
label: this.t({
|
|
1680
1791
|
zh: `\u521A\u8BBE\u7F6E\u7684\u6A21\u578B\uFF08${model.provider}/${model.model}\uFF09\uFF1A\u66F4\u6162\uFF0C\u800C\u4E14\u6BCF\u6B21\u5224\u65AD\u90FD\u8981\u82B1 token`,
|
|
1681
|
-
en: `The model you just set up (${model.provider}/${model.model}): slower, and every
|
|
1792
|
+
en: `The model you just set up (${model.provider}/${model.model}): slower, and every verdict costs tokens`
|
|
1682
1793
|
}),
|
|
1683
1794
|
value: "model"
|
|
1684
1795
|
});
|
|
@@ -1686,22 +1797,35 @@ var Setup = class {
|
|
|
1686
1797
|
choices.push({
|
|
1687
1798
|
label: this.t({
|
|
1688
1799
|
zh: "\u6682\u65F6\u4E0D\u8981\uFF1Amu \u5C31\u50CF pi \u4E00\u6837\u5DE5\u4F5C\uFF0C\u6CA1\u6709\u5224\u5B9A\u5668\u56DE\u7B54",
|
|
1689
|
-
en: "Not now: mu
|
|
1800
|
+
en: "Not now: mu works like plain pi, with no judge"
|
|
1690
1801
|
}),
|
|
1691
1802
|
value: "none"
|
|
1692
1803
|
});
|
|
1693
1804
|
const picked = await this.choose(
|
|
1694
1805
|
this.t({
|
|
1695
1806
|
zh: "mu \u5DE5\u4F5C\u65F6\u8981\u505A\u5F88\u591A\u5C0F\u5224\u65AD\uFF1A\u8FD9\u6761\u6D88\u606F\u8BE5\u600E\u4E48\u5904\u7406\u3001\u8FD9\u4E00\u6B65\u4F1A\u4E0D\u4F1A\u8FDD\u53CD\u4F60\u5B9A\u7684\u89C4\u5219\u2026\u2026\u5224\u5B9A\u5668\u8D1F\u8D23\u56DE\u7B54\u3002\u9009\u54EA\u4E2A\u5224\u5B9A\u5668\uFF1F",
|
|
1696
|
-
en: "mu
|
|
1807
|
+
en: "As it works, mu faces many small decisions: how to handle a message, whether a step breaks your rules. A judge answers them. Which judge do you want?"
|
|
1697
1808
|
}),
|
|
1698
1809
|
choices
|
|
1699
1810
|
);
|
|
1700
1811
|
if (picked === "jev") return { kind: "jev", key: await this.jevKey() };
|
|
1701
1812
|
return { kind: picked };
|
|
1702
1813
|
}
|
|
1703
|
-
scriptedJudge(model, envText, keySet) {
|
|
1814
|
+
scriptedJudge(model, envText, keySet, opencode) {
|
|
1704
1815
|
switch (this.args.judge) {
|
|
1816
|
+
case "opencode":
|
|
1817
|
+
if (!opencode) {
|
|
1818
|
+
throw this.fail(
|
|
1819
|
+
{
|
|
1820
|
+
zh: "--judge opencode \u9700\u8981 OpenCode \u7684\u5BC6\u94A5\uFF1A\u7528 --service opencode \u8BBE\u7F6E\u5B83\uFF0C\u6216\u5148\u8BBE\u7F6E OPENCODE_API_KEY",
|
|
1821
|
+
en: "--judge opencode needs an OpenCode key: set one up with --service opencode, or set OPENCODE_API_KEY first"
|
|
1822
|
+
},
|
|
1823
|
+
SETUP_EXIT.usage
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1826
|
+
return { kind: "opencode" };
|
|
1827
|
+
case "free":
|
|
1828
|
+
return { kind: "free" };
|
|
1705
1829
|
case "jev": {
|
|
1706
1830
|
const key = this.jevFromStdin;
|
|
1707
1831
|
if (!key) {
|
|
@@ -1709,14 +1833,14 @@ var Setup = class {
|
|
|
1709
1833
|
throw this.fail(
|
|
1710
1834
|
{
|
|
1711
1835
|
zh: "--judge jev \u9700\u8981 Jev \u5BC6\u94A5\uFF1A\u5199\u5728\u6807\u51C6\u8F93\u5165\u7684\u7B2C\u4E8C\u884C\uFF0C\u6216\u5148\u8BBE\u7F6E TYPESAFE_API_KEY",
|
|
1712
|
-
en: "--judge jev needs a Jev key: the second line of stdin, or TYPESAFE_API_KEY
|
|
1836
|
+
en: "--judge jev needs a Jev key: put it on the second line of stdin, or set TYPESAFE_API_KEY first"
|
|
1713
1837
|
},
|
|
1714
1838
|
SETUP_EXIT.usage
|
|
1715
1839
|
);
|
|
1716
1840
|
}
|
|
1717
1841
|
if (key === this.modelKey) {
|
|
1718
1842
|
throw this.fail(
|
|
1719
|
-
{ zh: "Jev \u5BC6\u94A5\u548C\u6A21\u578B\u7684\u5BC6\u94A5\u662F\u540C\u4E00\u4E2A", en: "the Jev key is the same as the model
|
|
1843
|
+
{ zh: "Jev \u5BC6\u94A5\u548C\u6A21\u578B\u7684\u5BC6\u94A5\u662F\u540C\u4E00\u4E2A", en: "the Jev key is the same as the model key" },
|
|
1720
1844
|
SETUP_EXIT.usage
|
|
1721
1845
|
);
|
|
1722
1846
|
}
|
|
@@ -1724,7 +1848,7 @@ var Setup = class {
|
|
|
1724
1848
|
if (current && current !== key && !this.args.yes) {
|
|
1725
1849
|
throw this.fail({
|
|
1726
1850
|
zh: `${this.path(this.deps.paths.envFile)} \u91CC\u5DF2\u7ECF\u6709 TYPESAFE_API_KEY\u3002\u8981\u66FF\u6362\u5B83\uFF0C\u52A0\u4E0A --yes`,
|
|
1727
|
-
en: `${this.path(this.deps.paths.envFile)} has a TYPESAFE_API_KEY
|
|
1851
|
+
en: `${this.path(this.deps.paths.envFile)} already has a TYPESAFE_API_KEY. To replace it, add --yes`
|
|
1728
1852
|
});
|
|
1729
1853
|
}
|
|
1730
1854
|
return { kind: "jev", key };
|
|
@@ -1740,14 +1864,14 @@ var Setup = class {
|
|
|
1740
1864
|
const key = await this.secret(
|
|
1741
1865
|
this.t({
|
|
1742
1866
|
zh: "\u7C98\u8D34 Jev \u5BC6\u94A5\uFF08TYPESAFE_API_KEY\uFF0C\u4E0D\u4F1A\u663E\u793A\uFF09\uFF1A",
|
|
1743
|
-
en: "Paste the Jev key (TYPESAFE_API_KEY
|
|
1867
|
+
en: "Paste the Jev key (TYPESAFE_API_KEY; it won't be shown): "
|
|
1744
1868
|
})
|
|
1745
1869
|
);
|
|
1746
1870
|
if (key === this.modelKey) {
|
|
1747
1871
|
this.io.say(
|
|
1748
1872
|
this.t({
|
|
1749
1873
|
zh: `\u8FD9\u662F\u521A\u624D\u7ED9\u6A21\u578B\u7684\u5BC6\u94A5\u3002Jev \u7684\u5BC6\u94A5\u5728 TypeSafe \u7533\u8BF7\uFF1A${JEV_PAGE}`,
|
|
1750
|
-
en: `That
|
|
1874
|
+
en: `That's the key you gave for the model. Get a Jev key from TypeSafe: ${JEV_PAGE}`
|
|
1751
1875
|
})
|
|
1752
1876
|
);
|
|
1753
1877
|
continue;
|
|
@@ -1815,7 +1939,7 @@ var Setup = class {
|
|
|
1815
1939
|
saved.push(
|
|
1816
1940
|
this.savedLine(
|
|
1817
1941
|
modelsPath,
|
|
1818
|
-
custom || moved ? this.t({ zh: `${provider}\uFF1A${reach.baseUrl}`, en: `${provider} at ${reach.baseUrl}` }) : this.t({ zh: `\u7ED9 ${provider} \u52A0\u4E0A ${model}`, en:
|
|
1942
|
+
custom || moved ? this.t({ zh: `${provider}\uFF1A${reach.baseUrl}`, en: `${provider} at ${reach.baseUrl}` }) : this.t({ zh: `\u7ED9 ${provider} \u52A0\u4E0A ${model}`, en: `added ${model} to ${provider}` })
|
|
1819
1943
|
)
|
|
1820
1944
|
);
|
|
1821
1945
|
}
|
|
@@ -1835,14 +1959,14 @@ var Setup = class {
|
|
|
1835
1959
|
saved.push(
|
|
1836
1960
|
this.savedLine(
|
|
1837
1961
|
settingsPath,
|
|
1838
|
-
this.t({ zh: `\u9ED8\u8BA4\u6A21\u578B ${provider}/${model}`, en: `
|
|
1962
|
+
this.t({ zh: `\u9ED8\u8BA4\u6A21\u578B ${provider}/${model}`, en: `default model ${provider}/${model}` })
|
|
1839
1963
|
)
|
|
1840
1964
|
);
|
|
1841
1965
|
} catch {
|
|
1842
1966
|
notes.push(
|
|
1843
1967
|
this.t({
|
|
1844
1968
|
zh: `${this.path(settingsPath)} \u8BFB\u4E0D\u4E86\uFF0C\u9ED8\u8BA4\u6A21\u578B\u6CA1\u6709\u4FDD\u5B58\u3002\u5728 mu \u91CC\u7528 /model \u9009\u5B83\u3002`,
|
|
1845
|
-
en:
|
|
1969
|
+
en: `Couldn't read ${this.path(settingsPath)}, so the default model wasn't saved. Choose it inside mu with /model.`
|
|
1846
1970
|
})
|
|
1847
1971
|
);
|
|
1848
1972
|
}
|
|
@@ -1856,14 +1980,14 @@ var Setup = class {
|
|
|
1856
1980
|
}
|
|
1857
1981
|
this.io.warn(this.t({ zh: `mu setup\uFF1A\u4FDD\u5B58\u65F6\u51FA\u9519\uFF1A${reason}`, en: `mu setup: saving failed: ${reason}` }));
|
|
1858
1982
|
if (saved.length > 0) {
|
|
1859
|
-
this.io.warn(this.t({ zh: "\u51FA\u9519\u524D\u5DF2\u7ECF\u4FDD\u5B58\u7684\uFF1A", en: "Saved before
|
|
1983
|
+
this.io.warn(this.t({ zh: "\u51FA\u9519\u524D\u5DF2\u7ECF\u4FDD\u5B58\u7684\uFF1A", en: "Saved before the error:" }));
|
|
1860
1984
|
for (const entry of saved) this.io.warn(entry);
|
|
1861
1985
|
}
|
|
1862
1986
|
if (backups.path) {
|
|
1863
1987
|
this.io.warn(
|
|
1864
1988
|
this.t({
|
|
1865
1989
|
zh: `\u539F\u6765\u7684\u6587\u4EF6\u5728 ${this.path(backups.path)}`,
|
|
1866
|
-
en: `The
|
|
1990
|
+
en: `The previous versions are in ${this.path(backups.path)}`
|
|
1867
1991
|
})
|
|
1868
1992
|
);
|
|
1869
1993
|
}
|
|
@@ -1877,7 +2001,7 @@ var Setup = class {
|
|
|
1877
2001
|
this.io.say(
|
|
1878
2002
|
this.t({
|
|
1879
2003
|
zh: `\u6539\u52A8\u524D\u7684\u6587\u4EF6\u5DF2\u590D\u5236\u5230 ${this.path(backups.path)}`,
|
|
1880
|
-
en: `
|
|
2004
|
+
en: `Backed up the previous files to ${this.path(backups.path)}`
|
|
1881
2005
|
})
|
|
1882
2006
|
);
|
|
1883
2007
|
}
|
|
@@ -1896,12 +2020,15 @@ var Setup = class {
|
|
|
1896
2020
|
let tiers;
|
|
1897
2021
|
if (judge.kind === "model") {
|
|
1898
2022
|
if (target && model) tiers = [`llm:${target.reach.provider}/${model}`];
|
|
2023
|
+
} else if (judge.kind === "opencode") tiers = ["jev-opencode"];
|
|
2024
|
+
else if (judge.kind === "free") {
|
|
2025
|
+
if (!tiersOf(current).some((tier) => tier === "jev" || tier === "jev-opencode-free")) tiers = ["jev"];
|
|
1899
2026
|
} else if (!tiersOf(current).some((tier) => JEV_TIERS.has(tier))) tiers = ["jev"];
|
|
1900
2027
|
if (tiers && config.state === "unreadable") {
|
|
1901
2028
|
notes.push(
|
|
1902
2029
|
this.t({
|
|
1903
2030
|
zh: `${this.path(configPath)} \u4E0D\u662F\u7EAF JSON\uFF0C\u6CA1\u6709\u6539\u5B83\u3002\u8BF7\u624B\u52A8\u52A0\u4E0A "tiers": ${JSON.stringify(tiers)}`,
|
|
1904
|
-
en: `${this.path(configPath)}
|
|
2031
|
+
en: `${this.path(configPath)} isn't plain JSON, so it was left unchanged. Add "tiers": ${JSON.stringify(tiers)} by hand.`
|
|
1905
2032
|
})
|
|
1906
2033
|
);
|
|
1907
2034
|
} else if (tiers) {
|
|
@@ -1924,7 +2051,7 @@ var Setup = class {
|
|
|
1924
2051
|
notes.push(
|
|
1925
2052
|
this.t({
|
|
1926
2053
|
zh: `\u6CE8\u610F\uFF1A\u73AF\u5883\u53D8\u91CF\u91CC\u4E5F\u6709 TYPESAFE_API_KEY\uFF0C\u5B83\u6BD4 ${this.path(paths.envFile)} \u4F18\u5148\u3002\u5230\u8BBE\u7F6E\u5B83\u7684\u5730\u65B9\uFF08\u4F8B\u5982 ~/.zshrc\uFF09\u6539\u6389\u6216\u5220\u6389\u3002`,
|
|
1927
|
-
en: `Note: TYPESAFE_API_KEY is also set in your environment
|
|
2054
|
+
en: `Note: TYPESAFE_API_KEY is also set in your environment and takes precedence over ${this.path(paths.envFile)}. Change or remove it where it's set (~/.zshrc, for example).`
|
|
1928
2055
|
})
|
|
1929
2056
|
);
|
|
1930
2057
|
}
|
|
@@ -1934,7 +2061,7 @@ var Setup = class {
|
|
|
1934
2061
|
notes.push(
|
|
1935
2062
|
this.t({
|
|
1936
2063
|
zh: `\u6CE8\u610F\uFF1A\u73AF\u5883\u53D8\u91CF MU_JUDGE=${override} \u6BD4 mu.json \u4F18\u5148\uFF0C\u7531\u5B83\u51B3\u5B9A\u5224\u5B9A\u5668\u3002`,
|
|
1937
|
-
en: `Note: MU_JUDGE=${override} is set in your environment
|
|
2064
|
+
en: `Note: MU_JUDGE=${override} is set in your environment and takes precedence over mu.json for the judge.`
|
|
1938
2065
|
})
|
|
1939
2066
|
);
|
|
1940
2067
|
}
|
|
@@ -1942,15 +2069,18 @@ var Setup = class {
|
|
|
1942
2069
|
summary(target, model, judge) {
|
|
1943
2070
|
const done = target && model ? this.t({
|
|
1944
2071
|
zh: `\u5B8C\u6210\u3002mu \u4F1A\u7528 ${this.name(target.service)} \xB7 ${model} \u5F00\u59CB\u5DE5\u4F5C\u3002`,
|
|
1945
|
-
en: `Done. mu
|
|
2072
|
+
en: `Done. mu will start on ${this.name(target.service)} \xB7 ${model}.`
|
|
1946
2073
|
}) : this.t({ zh: "\u5B8C\u6210\u3002", en: "Done." });
|
|
1947
|
-
const judged = judge === void 0 ? "" : judge.kind === "model" ? this.t({ zh: "\u5224\u5B9A\u5668\uFF1A\u540C\u4E00\u4E2A\u6A21\u578B\u3002", en: " Judge: the same model." }) : judge.kind === "none" ? this.t({ zh: "\u5224\u5B9A\u5668\uFF1A\u6682\u65F6\u6CA1\u6709\u3002", en: " Judge: none for now." }) : this.t({ zh: "\u5224\u5B9A\u5668\
|
|
2074
|
+
const judged = judge === void 0 ? "" : judge.kind === "model" ? this.t({ zh: "\u5224\u5B9A\u5668\uFF1A\u540C\u4E00\u4E2A\u6A21\u578B\u3002", en: " Judge: the same model." }) : judge.kind === "none" ? this.t({ zh: "\u5224\u5B9A\u5668\uFF1A\u6682\u65F6\u6CA1\u6709\u3002", en: " Judge: none for now." }) : judge.kind === "opencode" ? this.t({ zh: "\u5224\u5B9A\u5668\uFF1AOpenCode Zen \u4E0A\u7684 Jev\u3002", en: " Judge: Jev on OpenCode Zen." }) : judge.kind === "free" ? this.t({
|
|
2075
|
+
zh: "\u5224\u5B9A\u5668\uFF1AJev\uFF0C\u52A0\u5BC6\u94A5\u4E4B\u524D\u7528 OpenCode Zen \u4E0A\u9650\u65F6\u514D\u8D39\u7684\u7248\u672C\u3002",
|
|
2076
|
+
en: " Judge: Jev, using the free version on OpenCode Zen until you add a key."
|
|
2077
|
+
}) : this.t({ zh: "\u5224\u5B9A\u5668\uFF1AJev\u3002", en: " Judge: Jev." });
|
|
1948
2078
|
this.io.say("");
|
|
1949
2079
|
this.io.say(`${done}${judged}`);
|
|
1950
2080
|
this.io.say(
|
|
1951
2081
|
target ? this.t({
|
|
1952
2082
|
zh: "\u5728 mu \u91CC\u7528 /model \u6362\u6A21\u578B\uFF1B\u968F\u65F6\u53EF\u4EE5\u518D\u8FD0\u884C mu setup\u3002",
|
|
1953
|
-
en: "Switch models inside mu with /model
|
|
2083
|
+
en: "Switch models inside mu with /model, and run mu setup again any time."
|
|
1954
2084
|
}) : this.t({ zh: "\u542F\u52A8 mu \u540E\u8F93\u5165 /login \u767B\u5F55\u3002", en: "Start mu and type /login to sign in." })
|
|
1955
2085
|
);
|
|
1956
2086
|
}
|