mu-agent 0.1.14 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +3 -1
- package/judge/dist/mude.js +1436 -0
- package/judge/dist/setup.js +1409 -160
- package/judge/manifest.json +26 -26
- package/judge/mu/index.js +16 -1
- package/kyrn/bin/kyrn-doctor +27 -1
- package/kyrn/bin/mu.mjs +125 -3
- package/kyrn/local-judge/mude-requirements.lock.txt +746 -0
- package/package.json +2 -2
package/judge/manifest.json
CHANGED
|
@@ -1226,19 +1226,19 @@
|
|
|
1226
1226
|
"group": "turn",
|
|
1227
1227
|
"feature": "ttsr",
|
|
1228
1228
|
"title": {
|
|
1229
|
-
"zh": "
|
|
1230
|
-
"en": "Mid-stream correction
|
|
1231
|
-
"zh-TW": "
|
|
1232
|
-
"ja-JP": "
|
|
1233
|
-
"ko-KR": "출력 중 교정
|
|
1234
|
-
"de-DE": "Korrektur während der Ausgabe
|
|
1235
|
-
"fr-FR": "Correction en cours d’écriture
|
|
1236
|
-
"es-ES": "Corrección sobre la marcha
|
|
1237
|
-
"pt-BR": "Correção durante a escrita
|
|
1238
|
-
"ru-RU": "Исправление на лету
|
|
1239
|
-
"uk-UA": "Виправлення на льоту
|
|
1240
|
-
"tr-TR": "Akış içinde düzeltme
|
|
1241
|
-
"fa-IR": "اصلاح در میانهٔ خروجی
|
|
1229
|
+
"zh": "写偏即停",
|
|
1230
|
+
"en": "Mid-stream correction",
|
|
1231
|
+
"zh-TW": "寫偏即停",
|
|
1232
|
+
"ja-JP": "出力中の軌道修正",
|
|
1233
|
+
"ko-KR": "출력 중 교정",
|
|
1234
|
+
"de-DE": "Korrektur während der Ausgabe",
|
|
1235
|
+
"fr-FR": "Correction en cours d’écriture",
|
|
1236
|
+
"es-ES": "Corrección sobre la marcha",
|
|
1237
|
+
"pt-BR": "Correção durante a escrita",
|
|
1238
|
+
"ru-RU": "Исправление на лету",
|
|
1239
|
+
"uk-UA": "Виправлення на льоту",
|
|
1240
|
+
"tr-TR": "Akış içinde düzeltme",
|
|
1241
|
+
"fa-IR": "اصلاح در میانهٔ خروجی"
|
|
1242
1242
|
},
|
|
1243
1243
|
"summary": {
|
|
1244
1244
|
"zh": "模型边输出,判定器边每隔几百字对照一次你的硬约束和下面配置的规则;确信写偏了就立刻掐断输出,告诉模型是哪一条,让它从断点接着写。只有开启了「写偏即停」功能才会运行。",
|
|
@@ -5619,19 +5619,19 @@
|
|
|
5619
5619
|
{
|
|
5620
5620
|
"name": "ttsr",
|
|
5621
5621
|
"title": {
|
|
5622
|
-
"zh": "
|
|
5623
|
-
"en": "Mid-stream correction
|
|
5624
|
-
"zh-TW": "
|
|
5625
|
-
"ja-JP": "
|
|
5626
|
-
"ko-KR": "출력 중 교정
|
|
5627
|
-
"de-DE": "Korrektur während der Ausgabe
|
|
5628
|
-
"fr-FR": "Correction en cours d’écriture
|
|
5629
|
-
"es-ES": "Corrección sobre la marcha
|
|
5630
|
-
"pt-BR": "Correção durante a escrita
|
|
5631
|
-
"ru-RU": "Исправление на лету
|
|
5632
|
-
"uk-UA": "Виправлення на льоту
|
|
5633
|
-
"tr-TR": "Akış içinde düzeltme
|
|
5634
|
-
"fa-IR": "اصلاح در میانهٔ خروجی
|
|
5622
|
+
"zh": "写偏即停",
|
|
5623
|
+
"en": "Mid-stream correction",
|
|
5624
|
+
"zh-TW": "寫偏即停",
|
|
5625
|
+
"ja-JP": "出力中の軌道修正",
|
|
5626
|
+
"ko-KR": "출력 중 교정",
|
|
5627
|
+
"de-DE": "Korrektur während der Ausgabe",
|
|
5628
|
+
"fr-FR": "Correction en cours d’écriture",
|
|
5629
|
+
"es-ES": "Corrección sobre la marcha",
|
|
5630
|
+
"pt-BR": "Correção durante a escrita",
|
|
5631
|
+
"ru-RU": "Исправление на лету",
|
|
5632
|
+
"uk-UA": "Виправлення на льоту",
|
|
5633
|
+
"tr-TR": "Akış içinde düzeltme",
|
|
5634
|
+
"fa-IR": "اصلاح در میانهٔ خروجی"
|
|
5635
5635
|
},
|
|
5636
5636
|
"summary": {
|
|
5637
5637
|
"zh": "语义版 TTSR:不用正则,而由判定器发现模型写偏,中断输出、摆出规则、从原处继续。默认关闭;开启后每隔一段输出就会多一次判定调用。",
|
package/judge/mu/index.js
CHANGED
|
@@ -27471,6 +27471,20 @@ var BUILT_IN_JUDGES = {
|
|
|
27471
27471
|
type: "local",
|
|
27472
27472
|
profile: { capabilities: { relate: false, rate: false, meta: false, screen: false, intent: false } }
|
|
27473
27473
|
},
|
|
27474
|
+
// mude, the decision model trained for mu's judgment layer, on this Mac (`mu judge mude install`, Apple silicon):
|
|
27475
|
+
// the System One server that comes in its package, on 127.0.0.1:8790, with the key the install wrote to the .env.
|
|
27476
|
+
// Trusted on every capability: on mu's own dev scenarios (an internal benchmark, not public yet) it did as well as Jev
|
|
27477
|
+
// or better on relate, rate, meta, screening tool output (`tool.admission`) and promises (`turn.continue`), and on
|
|
27478
|
+
// classify but for one check: a tool's description screened for injected instructions (`tool.description`), where
|
|
27479
|
+
// Jev did better. Nothing measured it on injections in fetched content (`tool.injection`). So with a judge behind it,
|
|
27480
|
+
// `mu judge mude` routes those two checks to that judge (`routes` in mu.json). It answers in about 0.1 s here.
|
|
27481
|
+
mude: {
|
|
27482
|
+
type: "typesafe",
|
|
27483
|
+
baseUrl: "http://127.0.0.1:8790/v1/systemone",
|
|
27484
|
+
model: "mude",
|
|
27485
|
+
apiKeyEnv: "MU_JUDGE_MUDE_KEY",
|
|
27486
|
+
timeoutMs: 4e3
|
|
27487
|
+
},
|
|
27474
27488
|
mock: { type: "mock" }
|
|
27475
27489
|
};
|
|
27476
27490
|
var DEFAULT_CONFIG = {
|
|
@@ -29713,7 +29727,8 @@ var DEFAULT_TIMEOUT_MS2 = {
|
|
|
29713
29727
|
var KEYS_FOR_ELSEWHERE = /* @__PURE__ */ new Set([
|
|
29714
29728
|
"MU_JUDGE_OPENROUTER_API_KEY",
|
|
29715
29729
|
"MU_JUDGE_CUSTOM_API_KEY",
|
|
29716
|
-
"MU_JUDGE_CLM_API_KEY"
|
|
29730
|
+
"MU_JUDGE_CLM_API_KEY",
|
|
29731
|
+
"MU_JUDGE_MUDE_KEY"
|
|
29717
29732
|
]);
|
|
29718
29733
|
function resolveJudgeConfig(name, config) {
|
|
29719
29734
|
if (name.startsWith("llm:")) return { type: "llm", model: name.slice("llm:".length) };
|
package/kyrn/bin/kyrn-doctor
CHANGED
|
@@ -196,7 +196,10 @@ const CLASSIFIER_KEYS = {
|
|
|
196
196
|
const fromFile = existsSync(envFile) ? parseEnvFile(readFileSync(envFile, "utf8")).entries : [];
|
|
197
197
|
const has = (name) => Boolean(process.env[name]) || fromFile.some(([key, value]) => key === name && value !== "");
|
|
198
198
|
const where = `to ${tilde(envFile)} or to your environment`;
|
|
199
|
-
|
|
199
|
+
// mude speaks System One too, but on this machine and with a key of its own (its rows are below).
|
|
200
|
+
const jevTier = tiers.find(
|
|
201
|
+
(tier) => tier !== "mude" && ["jev", "typesafe", "gateway"].includes((config?.judges?.[tier] ?? JEV_ROUTES[tier])?.type),
|
|
202
|
+
);
|
|
200
203
|
if (jevTier && asksJudge) {
|
|
201
204
|
const judge = config?.judges?.[jevTier] ?? JEV_ROUTES[jevTier];
|
|
202
205
|
if (judge.type === "jev") {
|
|
@@ -237,6 +240,29 @@ if (jevTier && asksJudge) {
|
|
|
237
240
|
}
|
|
238
241
|
}
|
|
239
242
|
|
|
243
|
+
// mude on this Mac (mu judge mude): its server's /health, and the key mu sends it.
|
|
244
|
+
if (asksJudge && tiers.includes("mude")) {
|
|
245
|
+
const fallback = tiers.filter((tier) => tier !== "mude");
|
|
246
|
+
const behind = fallback.length > 0 ? `until it answers, ${fallback.join(" > ")} decide${fallback.length === 1 ? "s" : ""} (what they read leaves this machine)` : "until it answers, decisions take their fallbacks";
|
|
247
|
+
if (process.platform !== "darwin") {
|
|
248
|
+
row("--", "mude 1.0", `not available on ${platformName({ platform: process.platform, wsl })}: mude 1.0 runs on a Mac with Apple silicon`);
|
|
249
|
+
} else {
|
|
250
|
+
const entry = config?.judges?.mude;
|
|
251
|
+
const address = (typeof entry?.baseUrl === "string" ? entry.baseUrl : "http://127.0.0.1:8790/v1/systemone").replace(/\/v1\/systemone\/?$/, "");
|
|
252
|
+
const startedAt = performance.now();
|
|
253
|
+
try {
|
|
254
|
+
const response = await fetch(`${address}/health`, { signal: AbortSignal.timeout(2000) });
|
|
255
|
+
const health = await response.json();
|
|
256
|
+
const ms = Math.round(performance.now() - startedAt);
|
|
257
|
+
row(health.status === "ready" ? "ok" : "--", "mude 1.0", `${address} · ${health.status} · ${ms} ms`);
|
|
258
|
+
} catch {
|
|
259
|
+
row("fix", "mude 1.0", `${address} isn't answering: run mu judge mude start (first time: mu judge mude install)`);
|
|
260
|
+
row("--", "", behind);
|
|
261
|
+
}
|
|
262
|
+
if (!has("MU_JUDGE_MUDE_KEY")) row("fix", "mude 1.0 key", "MU_JUDGE_MUDE_KEY is not set, so mu can't ask mude 1.0: run mu judge mude enable");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
240
266
|
// Classifier models of pi's catalog (Jev on OpenCode Zen or Cloudflare, Clef, …), for the tiers and routes that use them.
|
|
241
267
|
const classifierOf = (tier) =>
|
|
242
268
|
tier.startsWith("classifier:")
|
package/kyrn/bin/mu.mjs
CHANGED
|
@@ -102,6 +102,8 @@ export function usage(platform) {
|
|
|
102
102
|
" mu -c | -r continue the last session | pick a session to resume",
|
|
103
103
|
" mu setup connect a model (paste an API key or pick a service) and choose a judge",
|
|
104
104
|
" (see mu setup --help for scripting, reading a key from stdin and the supported services)",
|
|
105
|
+
" mu judge mude install run mude 1.0, mu's decision model optimized for coding, on this Mac as the judge (Apple silicon, 1.8 GB)",
|
|
106
|
+
" enable | disable | start | stop | status | uninstall (mu judge mude help)",
|
|
105
107
|
" mu judge <cmd> manage the local judge, Laya (macOS on Apple silicon): setup | start | stop | status | run",
|
|
106
108
|
" mu ledger [n] [--json] print the judge's verdicts from the last n sessions",
|
|
107
109
|
" mu import <file>... import Claude Code, Codex and ZCode conversations; --list shows them (mu import --help)",
|
|
@@ -321,8 +323,8 @@ export function layoutOf({ root, platform, exists }) {
|
|
|
321
323
|
}
|
|
322
324
|
|
|
323
325
|
/**
|
|
324
|
-
* The files the npm package runs: pi, the judgment layer, the sign-in of `mu auth`, the importer of `mu import
|
|
325
|
-
* wizard of `mu setup`.
|
|
326
|
+
* The files the npm package runs: pi, the judgment layer, the sign-in of `mu auth`, the importer of `mu import`, the
|
|
327
|
+
* wizard of `mu setup` and `mu judge mude`.
|
|
326
328
|
*/
|
|
327
329
|
export function packageEntries({ root, platform }) {
|
|
328
330
|
const path = pathFor(platform);
|
|
@@ -332,6 +334,7 @@ export function packageEntries({ root, platform }) {
|
|
|
332
334
|
auth: path.join(root, "judge", "dist", "auth.js"),
|
|
333
335
|
import: path.join(root, "judge", "dist", "import.js"),
|
|
334
336
|
setup: path.join(root, "judge", "dist", "setup.js"),
|
|
337
|
+
mude: path.join(root, "judge", "dist", "mude.js"),
|
|
335
338
|
};
|
|
336
339
|
}
|
|
337
340
|
|
|
@@ -440,6 +443,28 @@ export function wantsLaya({ env, agentDir, platform, readFile }) {
|
|
|
440
443
|
}
|
|
441
444
|
|
|
442
445
|
/** The Core ML sidecar exists for macOS only. Anything else needs a server of its own behind MU_LOCAL_JUDGE_URL. */
|
|
446
|
+
/**
|
|
447
|
+
* Whether the configuration asks for mude (mu judge mude): MU_JUDGE naming it, else `tiers` or a route in mu.json (or
|
|
448
|
+
* kyrn.json when there is no mu.json). Its server is then started when a session starts, as Laya's is.
|
|
449
|
+
*/
|
|
450
|
+
export function wantsMude({ env, agentDir, platform, readFile }) {
|
|
451
|
+
const judges = muEnv("JUDGE", env);
|
|
452
|
+
if (judges) return judges.split(",").some((judge) => judge.trim() === "mude");
|
|
453
|
+
const path = pathFor(platform);
|
|
454
|
+
for (const name of ["mu.json", "kyrn.json"]) {
|
|
455
|
+
let config;
|
|
456
|
+
try {
|
|
457
|
+
config = JSON.parse(readFile(path.join(agentDir, name)));
|
|
458
|
+
} catch (error) {
|
|
459
|
+
if (error instanceof SyntaxError) return false;
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
const named = (tiers) => Array.isArray(tiers) && tiers.includes("mude");
|
|
463
|
+
return named(config?.tiers) || Object.values(config?.routes ?? {}).some(named);
|
|
464
|
+
}
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
|
|
443
468
|
export function localJudgeSupport({ platform, env, wsl = false }) {
|
|
444
469
|
if (platform === "darwin") return { runs: true };
|
|
445
470
|
const url = muEnv("LOCAL_JUDGE_URL", env);
|
|
@@ -580,6 +605,14 @@ export function planLaunch({
|
|
|
580
605
|
}
|
|
581
606
|
}
|
|
582
607
|
|
|
608
|
+
// mude's server, when the configuration asks for it: started without waiting, so a session never waits for the
|
|
609
|
+
// model to load (what mude cannot answer yet goes to the judges behind it). Only a Mac runs it.
|
|
610
|
+
let startMude;
|
|
611
|
+
if (execPath && platform === "darwin" && wantsMude({ env: childEnv, agentDir, platform, readFile: fs.readFile })) {
|
|
612
|
+
const mude = planMude({ platform, env: childEnv, argv: ["start", "--no-wait"], root, home, execPath, fs, stripsTypes });
|
|
613
|
+
if (!mude.error) startMude = { command: mude.command, args: mude.args, env: mude.env };
|
|
614
|
+
}
|
|
615
|
+
|
|
583
616
|
return {
|
|
584
617
|
command: execPath,
|
|
585
618
|
args: [...entry, ...judgeArgs({ argv, layout, root, platform, agentDir, readFile: fs.readFile }), ...argv],
|
|
@@ -590,6 +623,7 @@ export function planLaunch({
|
|
|
590
623
|
appDir,
|
|
591
624
|
agentDir,
|
|
592
625
|
startJudge,
|
|
626
|
+
startMude,
|
|
593
627
|
notes,
|
|
594
628
|
preface: argv[0] === "-h" || argv[0] === "--help" ? `${usage(platform)}\n\npi's help (mu passes all of this through):\n` : undefined,
|
|
595
629
|
};
|
|
@@ -606,10 +640,17 @@ export function planLaunch({
|
|
|
606
640
|
*
|
|
607
641
|
* A checkout runs there as it runs on the command line (sourceRuntime). Returns { error } when pi cannot run.
|
|
608
642
|
*/
|
|
609
|
-
export function planHost({ platform, env, argv, root, home, fs, wsl = false, stripsTypes = true }) {
|
|
643
|
+
export function planHost({ platform, env, argv, root, home, fs, wsl = false, stripsTypes = true, nodePath, nodeEnv = {} }) {
|
|
610
644
|
const path = pathFor(platform);
|
|
611
645
|
const launch = planLaunch({ platform, env, argv, root, home, execPath: "", fs, wsl, stripsTypes });
|
|
612
646
|
if (launch.error !== undefined) return { error: launch.error };
|
|
647
|
+
// mude's server is started by a Node of the host's: `nodePath` with `nodeEnv` (Electron's own binary with
|
|
648
|
+
// ELECTRON_RUN_AS_NODE=1 in the desktop app). Without one, the host leaves it to the app.
|
|
649
|
+
let startMude;
|
|
650
|
+
if (nodePath && platform === "darwin" && wantsMude({ env: launch.env, agentDir: launch.agentDir, platform, readFile: fs.readFile })) {
|
|
651
|
+
const mude = planMude({ platform, env: { ...launch.env, ...nodeEnv }, argv: ["start", "--no-wait"], root, home, execPath: nodePath, fs, stripsTypes });
|
|
652
|
+
if (!mude.error) startMude = { command: mude.command, args: mude.args, env: mude.env };
|
|
653
|
+
}
|
|
613
654
|
const common = {
|
|
614
655
|
env: launch.env,
|
|
615
656
|
layout: launch.layout,
|
|
@@ -617,6 +658,7 @@ export function planHost({ platform, env, argv, root, home, fs, wsl = false, str
|
|
|
617
658
|
appDir: launch.appDir,
|
|
618
659
|
agentDir: launch.agentDir,
|
|
619
660
|
startJudge: launch.startJudge,
|
|
661
|
+
startMude,
|
|
620
662
|
notes: launch.notes,
|
|
621
663
|
};
|
|
622
664
|
if (launch.layout === "package") {
|
|
@@ -661,6 +703,7 @@ function prepareFiles({ plan, platform, root, err }) {
|
|
|
661
703
|
*/
|
|
662
704
|
export function prepareLaunch({ plan, platform, root, bin, err }) {
|
|
663
705
|
prepareFiles({ plan, platform, root, err });
|
|
706
|
+
startMudeServer(plan);
|
|
664
707
|
if (plan.startJudge) {
|
|
665
708
|
const started = spawnSync(pathFor(platform).join(bin, "kyrn-judge-local"), ["start"], {
|
|
666
709
|
stdio: "ignore",
|
|
@@ -670,12 +713,32 @@ export function prepareLaunch({ plan, platform, root, bin, err }) {
|
|
|
670
713
|
}
|
|
671
714
|
}
|
|
672
715
|
|
|
716
|
+
/**
|
|
717
|
+
* mude's server, started in the background (`mu judge mude start --no-wait`): nothing waits for it, and it outlives this
|
|
718
|
+
* process, shared by every mu session like Laya. When mude is not installed it does nothing (the doctor says so).
|
|
719
|
+
*/
|
|
720
|
+
function startMudeServer(plan) {
|
|
721
|
+
if (!plan.startMude) return;
|
|
722
|
+
try {
|
|
723
|
+
const child = spawn(plan.startMude.command, plan.startMude.args, {
|
|
724
|
+
env: plan.startMude.env,
|
|
725
|
+
stdio: "ignore",
|
|
726
|
+
detached: true,
|
|
727
|
+
});
|
|
728
|
+
child.once("error", () => {});
|
|
729
|
+
child.unref();
|
|
730
|
+
} catch {
|
|
731
|
+
// mu works without it: the judges behind mude answer.
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
673
735
|
/**
|
|
674
736
|
* prepareLaunch for a program that must not stop while the local judge starts, such as the desktop app's main process:
|
|
675
737
|
* the same steps and notes, with the local judge started through a child process it waits for without blocking.
|
|
676
738
|
*/
|
|
677
739
|
export async function prepareLaunchAsync({ plan, platform, root, bin, err }) {
|
|
678
740
|
prepareFiles({ plan, platform, root, err });
|
|
741
|
+
startMudeServer(plan);
|
|
679
742
|
if (!plan.startJudge) return;
|
|
680
743
|
const status = await new Promise((resolve) => {
|
|
681
744
|
const child = spawn(pathFor(platform).join(bin, "kyrn-judge-local"), ["start"], {
|
|
@@ -793,6 +856,42 @@ export function planImport({ platform, env, argv, root, home, execPath, fs, stri
|
|
|
793
856
|
return { command: execPath, args: [...entry, ...argv], env: childEnv, agentDir };
|
|
794
857
|
}
|
|
795
858
|
|
|
859
|
+
// ---------------------------------------------------------------------------------------------------------
|
|
860
|
+
// mu judge mude
|
|
861
|
+
// ---------------------------------------------------------------------------------------------------------
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* `mu judge mude <command>` (packages/kyrn-judge/src/mude): mude on this Mac, from the checkout's TypeScript or the
|
|
865
|
+
* package's built judge/dist/mude.js. It is told where mu keeps things: the agent folder (mu.json), mu's home (the
|
|
866
|
+
* model and its environment go under local-judge/mude), the .env (its key) and the lock of its Python packages.
|
|
867
|
+
*/
|
|
868
|
+
export function planMude({ platform, env, argv, root, home, execPath, fs, stripsTypes = true }) {
|
|
869
|
+
const path = pathFor(platform);
|
|
870
|
+
const layout = layoutOf({ root, platform, exists: fs.exists });
|
|
871
|
+
let entry;
|
|
872
|
+
if (layout === "package") {
|
|
873
|
+
const built = packageEntries({ root, platform }).mude;
|
|
874
|
+
if (!fs.exists(built)) {
|
|
875
|
+
return { error: `This mu-agent package has no mu judge mude (${built} is missing). Update it: npm i -g mu-agent` };
|
|
876
|
+
}
|
|
877
|
+
entry = [built];
|
|
878
|
+
} else {
|
|
879
|
+
const source = path.join(root, "packages", "kyrn-judge", "src", "mude", "cli.ts");
|
|
880
|
+
if (!fs.exists(source)) return { error: `mu judge mude is missing from this checkout (${source})` };
|
|
881
|
+
if (!stripsTypes) return { error: NO_TYPE_STRIPPING };
|
|
882
|
+
entry = ["--disable-warning=ExperimentalWarning", source];
|
|
883
|
+
}
|
|
884
|
+
const muDir = muHome({ home, platform, isDir: fs.isDir });
|
|
885
|
+
const agentDir = agentDirFor({ env, muDir, platform });
|
|
886
|
+
const childEnv = {};
|
|
887
|
+
for (const [key, value] of Object.entries(env)) if (typeof value === "string") childEnv[key] = value;
|
|
888
|
+
childEnv.MU_AGENT_DIR = agentDir;
|
|
889
|
+
childEnv.MU_MUDE_HOME = muDir;
|
|
890
|
+
childEnv.MU_MUDE_ENV_FILE = envFilePath({ layout, root, muDir, platform });
|
|
891
|
+
childEnv.MU_MUDE_LOCK = path.join(root, "kyrn", "local-judge", "mude-requirements.lock.txt");
|
|
892
|
+
return { command: execPath, args: [...entry, ...argv], env: childEnv, agentDir };
|
|
893
|
+
}
|
|
894
|
+
|
|
796
895
|
// ---------------------------------------------------------------------------------------------------------
|
|
797
896
|
// mu setup
|
|
798
897
|
// ---------------------------------------------------------------------------------------------------------
|
|
@@ -913,6 +1012,12 @@ export function planSetup({ platform, env, argv, root, home, execPath, fs, strip
|
|
|
913
1012
|
childEnv.MU_SETUP_HOME = muDir;
|
|
914
1013
|
// The .env a session gets: the wizard writes the Jev key there, and reads a proxy from it.
|
|
915
1014
|
childEnv.MU_SETUP_ENV_FILE = envFilePath({ layout, root, muDir, platform });
|
|
1015
|
+
// mude 1.0, which the judge step installs on a Mac that can run it: where `mu judge mude` keeps it (planMude).
|
|
1016
|
+
if (platform === "darwin") {
|
|
1017
|
+
childEnv.MU_MUDE_HOME = muDir;
|
|
1018
|
+
childEnv.MU_MUDE_ENV_FILE = childEnv.MU_SETUP_ENV_FILE;
|
|
1019
|
+
childEnv.MU_MUDE_LOCK = path.join(root, "kyrn", "local-judge", "mude-requirements.lock.txt");
|
|
1020
|
+
}
|
|
916
1021
|
return { command: execPath, args: [...entry, ...args], env: childEnv, strategy: "spawn", agentDir, keyGiven: key !== undefined };
|
|
917
1022
|
}
|
|
918
1023
|
|
|
@@ -1504,6 +1609,23 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1504
1609
|
},
|
|
1505
1610
|
});
|
|
1506
1611
|
}
|
|
1612
|
+
if (command === "judge" && rest[0] === "mude") {
|
|
1613
|
+
const plan = planMude({
|
|
1614
|
+
platform,
|
|
1615
|
+
env,
|
|
1616
|
+
argv: rest.slice(1),
|
|
1617
|
+
root,
|
|
1618
|
+
home,
|
|
1619
|
+
execPath: process.execPath,
|
|
1620
|
+
stripsTypes: Boolean(process.features.typescript),
|
|
1621
|
+
fs: { exists: existsSync, isDir, readFile: readText },
|
|
1622
|
+
});
|
|
1623
|
+
if (plan.error) {
|
|
1624
|
+
err(plan.error);
|
|
1625
|
+
return 1;
|
|
1626
|
+
}
|
|
1627
|
+
return handOver({ command: plan.command, args: plan.args, env: plan.env, strategy: "spawn" });
|
|
1628
|
+
}
|
|
1507
1629
|
if (command === "judge") {
|
|
1508
1630
|
const plan = planJudge({ platform, env, argv: rest, bin, wsl });
|
|
1509
1631
|
if (plan.kind === "script") return handOver({ command: plan.command, args: plan.args, env, strategy });
|