mu-agent 0.1.7 → 0.1.8

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.
Files changed (143) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +5 -4
  3. package/dist/bundle/chunks/anthropic-messages-MI4QHRXW.js +6 -0
  4. package/dist/bundle/chunks/anthropic.js +2 -2
  5. package/dist/bundle/chunks/azure-openai-responses-E3QGN4VN.js +2 -0
  6. package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
  7. package/dist/bundle/chunks/chunk-33KL6IIQ.js +20 -0
  8. package/dist/bundle/chunks/chunk-4OBXYPH4.js +4 -0
  9. package/dist/bundle/chunks/chunk-C47CLQZK.js +2 -0
  10. package/dist/bundle/chunks/chunk-F5ZABL6Z.js +20 -0
  11. package/dist/bundle/chunks/chunk-H3QXYIF7.js +31 -0
  12. package/dist/bundle/chunks/chunk-HQHD6PZI.js +2 -0
  13. package/dist/bundle/chunks/chunk-KJUDFE6Y.js +11 -0
  14. package/dist/bundle/chunks/chunk-LD2P6SFZ.js +2 -0
  15. package/dist/bundle/chunks/chunk-NG4PO5FP.js +1204 -0
  16. package/dist/bundle/chunks/chunk-NTSWBG4X.js +2 -0
  17. package/dist/bundle/chunks/chunk-RLZVFGW4.js +127 -0
  18. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-S3GGRYIO.js} +2 -2
  19. package/dist/bundle/chunks/{chunk-4O2SCVYF.js → chunk-TAOL3JFA.js} +1 -1
  20. package/dist/bundle/chunks/chunk-TE3GUV6H.js +9 -0
  21. package/dist/bundle/chunks/chunk-VIV3CWXG.js +2 -0
  22. package/dist/bundle/chunks/{chunk-V7IXECST.js → chunk-WE4MXUQS.js} +3 -3
  23. package/dist/bundle/chunks/chunk-Y2PP32XV.js +2 -0
  24. package/dist/bundle/chunks/chunk-YLY6CKPK.js +132 -0
  25. package/dist/bundle/chunks/chunk-ZE5FMF3V.js +99 -0
  26. package/dist/bundle/chunks/cli-AOVD3SSZ.js +51 -0
  27. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NM3JRRWQ.js +2 -0
  28. package/dist/bundle/chunks/codemode-worker.js +374 -0
  29. package/dist/bundle/chunks/easter-egg-3d-G2LUBEMZ.js +2 -0
  30. package/dist/bundle/chunks/execute-MZVUC6BB.js +388 -0
  31. package/dist/bundle/chunks/github-copilot.js +1 -1
  32. package/dist/bundle/chunks/{google-generative-ai-C44KRRZ4.js → google-generative-ai-XMFHGQC5.js} +1 -1
  33. package/dist/bundle/chunks/{google-vertex-25DUXPTJ.js → google-vertex-4XRRNP74.js} +1 -1
  34. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-TEDK3E5I.js} +2 -2
  35. package/dist/bundle/chunks/llama-cpp-classify-XT44PI3C.js +22 -0
  36. package/dist/bundle/chunks/mistral-conversations-Q22M3IBG.js +5 -0
  37. package/dist/bundle/chunks/node-N5BSDOA5.js +16 -0
  38. package/dist/bundle/chunks/openai-chatgpt.js +86 -0
  39. package/dist/bundle/chunks/{openai-codex-responses-3UAYOSSR.js → openai-codex-responses-4MYQSO5E.js} +1 -1
  40. package/dist/bundle/chunks/openai-codex.js +2 -2
  41. package/dist/bundle/chunks/openai-completions-OSRCWAAA.js +7 -0
  42. package/dist/bundle/chunks/openai-responses-UHF3DHNG.js +3 -0
  43. package/dist/bundle/chunks/{openrouter-images-JVEJN44Q.js → openrouter-images-ZVXWCSIM.js} +1 -1
  44. package/dist/bundle/chunks/openrouter.js +2 -2
  45. package/dist/bundle/chunks/radius.js +2 -2
  46. package/dist/bundle/chunks/runtime-VJMMDLVH.js +2 -0
  47. package/dist/bundle/chunks/typesafe-system-one-PRR5K6CI.js +2 -0
  48. package/dist/bundle/chunks/virtual-modules-RJXJGCPI.js +2 -0
  49. package/dist/bundle/cli-runtime.js +1 -1
  50. package/dist/bundle/index.js +1 -1
  51. package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
  52. package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
  53. package/dist/bundle/rpc-entry.js +1 -1
  54. package/dist/core/export-html/template.js +16 -0
  55. package/dist/modes/interactive/theme/dark.json +59 -72
  56. package/dist/modes/interactive/theme/light.json +57 -69
  57. package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
  58. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  59. package/dist/modes/interactive/theme/system-theme.js +546 -0
  60. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  61. package/dist/modes/interactive/theme/theme-controller.d.ts +43 -9
  62. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  63. package/dist/modes/interactive/theme/theme-controller.js +121 -79
  64. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  65. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  66. package/dist/modes/interactive/theme/theme-json.js +1 -1
  67. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  68. package/dist/modes/interactive/theme/theme-schema.json +2 -2
  69. package/dist/modes/interactive/theme/theme.d.ts +34 -40
  70. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  71. package/dist/modes/interactive/theme/theme.js +139 -126
  72. package/dist/modes/interactive/theme/theme.js.map +1 -1
  73. package/dist/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
  74. package/dist/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
  75. package/docs/cli.md +60 -7
  76. package/docs/codemode.md +207 -0
  77. package/docs/configuration.md +2 -0
  78. package/docs/docs.json +13 -1
  79. package/docs/environment-variables.md +2 -2
  80. package/docs/extensions.md +53 -0
  81. package/docs/index.md +1 -1
  82. package/docs/keybindings.md +2 -2
  83. package/docs/llama-cpp.md +13 -0
  84. package/docs/mcp.md +270 -0
  85. package/docs/models.md +83 -1
  86. package/docs/packages.md +1 -1
  87. package/docs/providers.md +19 -6
  88. package/docs/quickstart.md +16 -2
  89. package/docs/rpc-commands.md +9 -3
  90. package/docs/rpc.md +3 -1
  91. package/docs/sdk.md +8 -3
  92. package/docs/security.md +2 -0
  93. package/docs/session-format.md +5 -1
  94. package/docs/settings.md +24 -5
  95. package/docs/themes.md +28 -6
  96. package/docs/usage.md +1 -1
  97. package/docs/virtual-models.md +114 -0
  98. package/docs/windows.md +2 -0
  99. package/examples/README.md +1 -1
  100. package/examples/extensions/README.md +1 -0
  101. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  102. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  103. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  104. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  105. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  106. package/examples/extensions/gondolin/package-lock.json +2 -2
  107. package/examples/extensions/gondolin/package.json +1 -1
  108. package/examples/extensions/jev-router.ts +113 -0
  109. package/examples/extensions/minimal-mode.ts +24 -96
  110. package/examples/extensions/sandbox/package-lock.json +2 -2
  111. package/examples/extensions/sandbox/package.json +1 -1
  112. package/examples/extensions/with-deps/package-lock.json +2 -2
  113. package/examples/extensions/with-deps/package.json +1 -1
  114. package/examples/rpc-client.ts +1 -1
  115. package/examples/rpc-extension-ui.ts +1 -1
  116. package/examples/sdk/14-codemode-mcp.ts +61 -0
  117. package/examples/sdk/README.md +2 -1
  118. package/judge/THIRD_PARTY_NOTICES.md +63 -0
  119. package/judge/dist/auth.js +128 -113
  120. package/judge/dist/import.js +10 -9
  121. package/judge/dist/kyrn-judge.js +5444 -5354
  122. package/judge/dist/setup.js +138 -12
  123. package/judge/manifest.json +414 -102
  124. package/kyrn/bin/kyrn-doctor +61 -11
  125. package/kyrn/bin/mu.mjs +84 -69
  126. package/package.json +4 -4
  127. package/dist/bundle/chunks/anthropic-messages-VMESUHQ7.js +0 -6
  128. package/dist/bundle/chunks/azure-openai-responses-K232MQFF.js +0 -2
  129. package/dist/bundle/chunks/chunk-AYFRR3OD.js +0 -2
  130. package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +0 -42
  131. package/dist/bundle/chunks/chunk-FU4XQUSL.js +0 -11
  132. package/dist/bundle/chunks/chunk-GNYZK6XN.js +0 -2
  133. package/dist/bundle/chunks/chunk-HEMXN7VJ.js +0 -1653
  134. package/dist/bundle/chunks/chunk-MVPXOVOJ.js +0 -2
  135. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  136. package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
  137. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NR2TDCXU.js +0 -2
  138. package/dist/bundle/chunks/mistral-conversations-6IHQOR4R.js +0 -5
  139. package/dist/bundle/chunks/node-O3RIBJRH.js +0 -16
  140. package/dist/bundle/chunks/openai-completions-FIEQGWAH.js +0 -7
  141. package/dist/bundle/chunks/openai-responses-OZJXLHFC.js +0 -2
  142. package/dist/bundle/chunks/typesafe-system-one-VKYX4OGY.js +0 -2
  143. package/dist/bundle/chunks/virtual-modules-V7SXVVLP.js +0 -2
@@ -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;
@@ -671,6 +678,32 @@ function explainProblem(problem, context, language) {
671
678
  return zh ? `${service} \u62D2\u7EDD\u4E86\u8FD9\u6B21\u68C0\u67E5\uFF08HTTP ${problem.status ?? "?"}\uFF09\u3002${said}` : `${service} refused the check (HTTP ${problem.status ?? "?"}).${said}`;
672
679
  }
673
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 };
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
+ };
706
+ }
674
707
 
675
708
  // packages/kyrn-judge/src/setup/services.ts
676
709
  var SK_HEX32 = /^sk-[0-9a-f]{32}$/;
@@ -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/zen/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(["jev", "jev-direct", "jev-openrouter", "jev-gateway"]);
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 = {
@@ -950,8 +1003,13 @@ function parseSetupArgs(argv) {
950
1003
  return { error: { zh: "--api \u53EA\u80FD\u662F openai \u6216 anthropic", en: "--api is openai or anthropic" } };
951
1004
  }
952
1005
  const judge = values.get("--judge");
953
- if (judge !== void 0 && judge !== "jev" && judge !== "model" && judge !== "none") {
954
- return { error: { zh: "--judge \u53EA\u80FD\u662F jev\u3001model \u6216 none", en: "--judge is jev, model or none" } };
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 is 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)) {
@@ -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 jev|model|none] [--yes]",
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",
@@ -1007,7 +1067,7 @@ function setupUsage(language) {
1007
1067
  "",
1008
1068
  " mu setup asks step by step, in a terminal",
1009
1069
  " mu setup <key> starts from an API key: mu tells by its shape which service it belongs to",
1010
- " mu setup --service <id> --key-stdin [--model <id>] [--base-url <url>] [--judge jev|model|none] [--yes]",
1070
+ " mu setup --service <id> --key-stdin [--model <id>] [--base-url <url>] [--judge <judge>] [--yes]",
1011
1071
  " for scripts: the key is read from stdin",
1012
1072
  " mu setup --list the services mu knows, with their ids",
1013
1073
  "",
@@ -1016,6 +1076,8 @@ function setupUsage(language) {
1016
1076
  "prompt when you can.",
1017
1077
  "",
1018
1078
  " --judge jev the Jev key (TypeSafe) is the second line of stdin, unless TYPESAFE_API_KEY is set already",
1079
+ " --judge opencode Jev on OpenCode Zen, with OpenCode's key (--service opencode, or OPENCODE_API_KEY)",
1080
+ " --judge free Jev on OpenCode Zen, free for a limited time, with no key (what jev uses while no key is set)",
1019
1081
  " --judge model the model just set up answers as the judge (slower, and every decision costs tokens)",
1020
1082
  " --judge none leaves the judge as it is, as leaving out --judge does",
1021
1083
  " --api, --name for the service `other`: its API (openai or anthropic) and its name in mu",
@@ -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;
@@ -1652,12 +1727,32 @@ var Setup = class {
1652
1727
  const { env, paths } = this.deps;
1653
1728
  const envText = readTextFile(paths.envFile);
1654
1729
  const existing = jevKeyAt(env, envText);
1655
- if (this.scripted) return this.scriptedJudge(model, envText, existing !== void 0);
1730
+ 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;
1731
+ if (this.scripted) return this.scriptedJudge(model, envText, existing !== void 0, opencode);
1656
1732
  const where = existing ? existing.where === "env" ? this.t({ zh: `\u73AF\u5883\u53D8\u91CF ${existing.name}`, en: `${existing.name} in your environment` }) : this.t({
1657
1733
  zh: `${this.path(paths.envFile)} \u91CC\u7684 ${existing.name}`,
1658
1734
  en: `${existing.name} in ${this.path(paths.envFile)}`
1659
1735
  }) : void 0;
1660
1736
  const choices = [];
1737
+ const keyless = !opencode && !where;
1738
+ if (keyless) {
1739
+ choices.push({
1740
+ label: this.t({
1741
+ 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",
1742
+ en: "Jev for free (recommended) on OpenCode Zen: no key, free for a limited time; a key added later takes over"
1743
+ }),
1744
+ value: "free"
1745
+ });
1746
+ }
1747
+ if (opencode && !where) {
1748
+ choices.push({
1749
+ label: this.t({
1750
+ zh: "Jev\uFF08\u63A8\u8350\uFF09\uFF0C\u5728 OpenCode Zen \u4E0A\uFF0C\u7528\u4F60\u7684 OpenCode \u5BC6\u94A5\uFF0C\u6309\u6B21\u8BA1\u8D39",
1751
+ en: "Jev (recommended) on OpenCode Zen, with your OpenCode key, billed per call"
1752
+ }),
1753
+ value: "opencode"
1754
+ });
1755
+ }
1661
1756
  if (where) {
1662
1757
  choices.push({
1663
1758
  label: this.t({
@@ -1668,12 +1763,24 @@ var Setup = class {
1668
1763
  });
1669
1764
  }
1670
1765
  choices.push({
1671
- label: where ? this.t({ zh: "Jev\uFF0C\u6362\u4E00\u4E2A\u65B0\u5BC6\u94A5", en: "Jev, with a new key" }) : this.t({
1672
- zh: `Jev\uFF08\u63A8\u8350\uFF09\uFF1A\u53C8\u5FEB\u53C8\u51C6\uFF0C\u6309\u6B21\u8BA1\u8D39\u3002\u5BC6\u94A5\u5728 TypeSafe \u7533\u8BF7\uFF1A${JEV_PAGE}`,
1673
- en: `Jev (recommended): fast and accurate, billed per call. Get a key from TypeSafe: ${JEV_PAGE}`
1766
+ label: where ? this.t({ zh: "Jev\uFF0C\u6362\u4E00\u4E2A\u65B0\u5BC6\u94A5", en: "Jev, with a new key" }) : opencode ? this.t({
1767
+ zh: `Jev\uFF0C\u7528 TypeSafe \u7684\u5BC6\u94A5\uFF1A${JEV_PAGE}`,
1768
+ en: `Jev with a TypeSafe key: ${JEV_PAGE}`
1769
+ }) : this.t({
1770
+ zh: `Jev\uFF0C\u7528\u81EA\u5DF1\u7684\u5BC6\u94A5\uFF1A\u53C8\u5FEB\u53C8\u51C6\uFF0C\u6309\u6B21\u8BA1\u8D39\u3002\u5BC6\u94A5\u5728 TypeSafe \u7533\u8BF7\uFF1A${JEV_PAGE}`,
1771
+ en: `Jev with a key of your own: fast and accurate, billed per call. Get a key from TypeSafe: ${JEV_PAGE}`
1674
1772
  }),
1675
1773
  value: "jev"
1676
1774
  });
1775
+ if (!keyless) {
1776
+ choices.push({
1777
+ label: this.t({
1778
+ zh: "Jev \u514D\u8D39\u7248\uFF0C\u5728 OpenCode Zen \u4E0A\uFF1A\u4E0D\u7528\u5BC6\u94A5\uFF0C\u9650\u65F6\u514D\u8D39",
1779
+ en: "Jev for free on OpenCode Zen: no key, free for a limited time"
1780
+ }),
1781
+ value: "free"
1782
+ });
1783
+ }
1677
1784
  if (model) {
1678
1785
  choices.push({
1679
1786
  label: this.t({
@@ -1700,8 +1807,21 @@ var Setup = class {
1700
1807
  if (picked === "jev") return { kind: "jev", key: await this.jevKey() };
1701
1808
  return { kind: picked };
1702
1809
  }
1703
- scriptedJudge(model, envText, keySet) {
1810
+ scriptedJudge(model, envText, keySet, opencode) {
1704
1811
  switch (this.args.judge) {
1812
+ case "opencode":
1813
+ if (!opencode) {
1814
+ throw this.fail(
1815
+ {
1816
+ zh: "--judge opencode \u9700\u8981 OpenCode \u7684\u5BC6\u94A5\uFF1A\u7528 --service opencode \u8BBE\u7F6E\u5B83\uFF0C\u6216\u5148\u8BBE\u7F6E OPENCODE_API_KEY",
1817
+ en: "--judge opencode needs an OpenCode key: set it up with --service opencode, or set OPENCODE_API_KEY first"
1818
+ },
1819
+ SETUP_EXIT.usage
1820
+ );
1821
+ }
1822
+ return { kind: "opencode" };
1823
+ case "free":
1824
+ return { kind: "free" };
1705
1825
  case "jev": {
1706
1826
  const key = this.jevFromStdin;
1707
1827
  if (!key) {
@@ -1896,6 +2016,9 @@ var Setup = class {
1896
2016
  let tiers;
1897
2017
  if (judge.kind === "model") {
1898
2018
  if (target && model) tiers = [`llm:${target.reach.provider}/${model}`];
2019
+ } else if (judge.kind === "opencode") tiers = ["jev-opencode"];
2020
+ else if (judge.kind === "free") {
2021
+ if (!tiersOf(current).some((tier) => tier === "jev" || tier === "jev-opencode-free")) tiers = ["jev"];
1899
2022
  } else if (!tiersOf(current).some((tier) => JEV_TIERS.has(tier))) tiers = ["jev"];
1900
2023
  if (tiers && config.state === "unreadable") {
1901
2024
  notes.push(
@@ -1944,7 +2067,10 @@ var Setup = class {
1944
2067
  zh: `\u5B8C\u6210\u3002mu \u4F1A\u7528 ${this.name(target.service)} \xB7 ${model} \u5F00\u59CB\u5DE5\u4F5C\u3002`,
1945
2068
  en: `Done. mu starts on ${this.name(target.service)} \xB7 ${model}.`
1946
2069
  }) : 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\uFF1AJev\u3002", en: " Judge: Jev." });
2070
+ 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({
2071
+ zh: "\u5224\u5B9A\u5668\uFF1AJev\uFF0C\u52A0\u5BC6\u94A5\u4E4B\u524D\u7528 OpenCode Zen \u4E0A\u9650\u65F6\u514D\u8D39\u7684\u7248\u672C\u3002",
2072
+ en: " Judge: Jev, free on OpenCode Zen for a limited time until you add a key."
2073
+ }) : this.t({ zh: "\u5224\u5B9A\u5668\uFF1AJev\u3002", en: " Judge: Jev." });
1948
2074
  this.io.say("");
1949
2075
  this.io.say(`${done}${judged}`);
1950
2076
  this.io.say(