@mytegroupinc/myte-core 0.0.42 → 0.0.43
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/README.md +3 -1
- package/lib/mytecody-splash.js +3 -3
- package/mytecody-cli.js +393 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,7 +31,9 @@ This package exists so the public wrapper can stay small and versioned cleanly.
|
|
|
31
31
|
run, it installs the branded MyteCody engine and signed client assets from
|
|
32
32
|
the Myte release manifest into a user-local Myte cache after signature/hash
|
|
33
33
|
checks. Coding execution requires those assets, a reachable Myte AI Cody
|
|
34
|
-
gateway, and `MYTEAI_API_KEY`.
|
|
34
|
+
gateway, and `MYTEAI_API_KEY`. Normal coding runs use the branded Codex
|
|
35
|
+
harness with Myte context hardening; the experimental controller is not the
|
|
36
|
+
default product path.
|
|
35
37
|
- `mytecody doctor` reports both the signed MyteCody engine state and this npm
|
|
36
38
|
package version. `mytecody update` updates the engine only. Use
|
|
37
39
|
`npm install -g myte@latest` to update the launcher and the Myte API CLI
|
package/lib/mytecody-splash.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const FRAME_MS = 48;
|
|
4
|
-
const MIN_MS =
|
|
4
|
+
const MIN_MS = 3000;
|
|
5
5
|
const FRAMES = 32;
|
|
6
6
|
const WIDTH = 84;
|
|
7
7
|
const HEIGHT = 64;
|
|
@@ -225,12 +225,12 @@ function createMyteSplash() {
|
|
|
225
225
|
|
|
226
226
|
async function stop() {
|
|
227
227
|
if (!enabled) return;
|
|
228
|
+
const remaining = Math.max(0, MIN_MS - (Date.now() - started));
|
|
229
|
+
if (remaining) await new Promise((resolve) => setTimeout(resolve, remaining));
|
|
228
230
|
if (timer) {
|
|
229
231
|
clearInterval(timer);
|
|
230
232
|
timer = null;
|
|
231
233
|
}
|
|
232
|
-
const remaining = Math.max(0, MIN_MS - (Date.now() - started));
|
|
233
|
-
if (remaining) await new Promise((resolve) => setTimeout(resolve, remaining));
|
|
234
234
|
if (rendered) process.stdout.write(`\x1b[${lineCount}F\x1b[J`);
|
|
235
235
|
process.stdout.write("\x1b[?25h");
|
|
236
236
|
rendered = false;
|
package/mytecody-cli.js
CHANGED
|
@@ -7,6 +7,7 @@ const path = require("path");
|
|
|
7
7
|
const crypto = require("crypto");
|
|
8
8
|
const zlib = require("zlib");
|
|
9
9
|
const { spawn } = require("child_process");
|
|
10
|
+
const readline = require("readline");
|
|
10
11
|
const {
|
|
11
12
|
DEFAULT_MYTEAI_BASE,
|
|
12
13
|
normalizeMyteAiBase,
|
|
@@ -229,6 +230,55 @@ function loadSignedController() {
|
|
|
229
230
|
return controller;
|
|
230
231
|
}
|
|
231
232
|
|
|
233
|
+
function controllerRunsRoot() {
|
|
234
|
+
return path.join(installRoot(), "controller-runs");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function readJsonFileIfPresent(filePath) {
|
|
238
|
+
try {
|
|
239
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
240
|
+
} catch {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function listControllerRunRecords() {
|
|
246
|
+
const root = controllerRunsRoot();
|
|
247
|
+
if (!fs.existsSync(root)) return [];
|
|
248
|
+
const records = [];
|
|
249
|
+
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
250
|
+
if (!entry.isDirectory()) continue;
|
|
251
|
+
const runPath = path.join(root, entry.name, "run.json");
|
|
252
|
+
const run = readJsonFileIfPresent(runPath);
|
|
253
|
+
if (!run || !run.run_id) continue;
|
|
254
|
+
let mtimeMs = 0;
|
|
255
|
+
try {
|
|
256
|
+
mtimeMs = fs.statSync(runPath).mtimeMs;
|
|
257
|
+
} catch {}
|
|
258
|
+
records.push({
|
|
259
|
+
run_id: run.run_id,
|
|
260
|
+
workspace_root: run.workspace_root || process.cwd(),
|
|
261
|
+
status: run.status || "unknown",
|
|
262
|
+
path: runPath,
|
|
263
|
+
mtimeMs,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return records.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function resolveControllerRunTarget(target = "latest") {
|
|
270
|
+
const records = listControllerRunRecords();
|
|
271
|
+
if (!records.length) return null;
|
|
272
|
+
const wanted = String(target || "latest");
|
|
273
|
+
if (wanted === "latest") return records[0];
|
|
274
|
+
const exact = records.find((record) => record.run_id === wanted);
|
|
275
|
+
if (exact) return exact;
|
|
276
|
+
const prefixed = records.filter((record) => record.run_id.startsWith(wanted));
|
|
277
|
+
if (prefixed.length === 1) return prefixed[0];
|
|
278
|
+
if (prefixed.length > 1) throw new Error(`CodyRun prefix is ambiguous: ${wanted}`);
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
|
|
232
282
|
function releaseAssetsForPlatform(manifest, artifact) {
|
|
233
283
|
const assets = [];
|
|
234
284
|
const collect = (value, source) => {
|
|
@@ -337,12 +387,23 @@ function printHelp() {
|
|
|
337
387
|
|
|
338
388
|
Usage:
|
|
339
389
|
mytecody
|
|
390
|
+
mytecody [prompt...]
|
|
340
391
|
mytecody doctor [--json] [--base-url <url>] [--probe-gateway]
|
|
341
392
|
mytecody exec [prompt or agent exec args...]
|
|
393
|
+
mytecody resume [codex-session-id|latest]
|
|
394
|
+
mytecody controller-resume [controller-run-id|latest]
|
|
395
|
+
mytecody codex [raw engine args...]
|
|
342
396
|
mytecody update --dry-run [--json] [--manifest <url-or-file>] [--fetch-manifest]
|
|
343
397
|
mytecody update [--json] [--manifest <url-or-file>]
|
|
344
398
|
mytecody help
|
|
345
399
|
|
|
400
|
+
Defaults:
|
|
401
|
+
mytecody opens the branded Codex harness with Myte context hardening.
|
|
402
|
+
Non-command prompt args are forwarded to the branded engine, not the experimental controller.
|
|
403
|
+
Use --controller on exec or controller-shell for temporary controller diagnostics.
|
|
404
|
+
Use mytecody controller-shell only for temporary controller-shell diagnostics.
|
|
405
|
+
Use mytecody codex only for raw engine diagnostics.
|
|
406
|
+
|
|
346
407
|
Updates:
|
|
347
408
|
mytecody update updates the signed MyteCody engine only
|
|
348
409
|
npm install -g myte@latest updates this npm launcher and Myte API tools
|
|
@@ -1139,12 +1200,13 @@ function execArgsAndStdin(rawArgs) {
|
|
|
1139
1200
|
|
|
1140
1201
|
function stripControllerArgs(rawArgs) {
|
|
1141
1202
|
const kept = [];
|
|
1142
|
-
let enabled = process.env.MYTE_CODY_CONTROLLER
|
|
1203
|
+
let enabled = process.env.MYTE_CODY_CONTROLLER === "1";
|
|
1143
1204
|
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
1144
1205
|
const arg = rawArgs[i];
|
|
1145
1206
|
if (arg === "--controller") {
|
|
1146
1207
|
const next = rawArgs[i + 1];
|
|
1147
|
-
|
|
1208
|
+
const normalizedNext = String(next || "").toLowerCase();
|
|
1209
|
+
if (next !== undefined && !next.startsWith("-") && ["0", "1", "false", "true", "off", "on", "raw"].includes(normalizedNext)) {
|
|
1148
1210
|
enabled = !["0", "false", "off", "raw"].includes(String(next).toLowerCase());
|
|
1149
1211
|
i += 1;
|
|
1150
1212
|
} else {
|
|
@@ -1176,6 +1238,24 @@ function controllerPromptFromExecArgs(rawArgs) {
|
|
|
1176
1238
|
return { prompt, forwardedArgs: execInput.args.slice(0, -1) };
|
|
1177
1239
|
}
|
|
1178
1240
|
|
|
1241
|
+
function classifyMyteCodyInvocation(rawArgs = []) {
|
|
1242
|
+
const args = Array.isArray(rawArgs) ? rawArgs : [];
|
|
1243
|
+
if (!args.length) return { mode: "raw-codex", args: [], controller: false };
|
|
1244
|
+
|
|
1245
|
+
const command = args[0];
|
|
1246
|
+
if (command === "codex") return { mode: "raw-codex", args: args.slice(1), controller: false };
|
|
1247
|
+
if (command === "controller-shell") return { mode: "controller-shell", args: args.slice(1) };
|
|
1248
|
+
if (command === "controller-resume") return { mode: "controller-resume", args: args.slice(1) };
|
|
1249
|
+
if (command === "resume") return { mode: "raw-codex", args, controller: false };
|
|
1250
|
+
if (command === "exec") {
|
|
1251
|
+
const controller = stripControllerArgs(args.slice(1));
|
|
1252
|
+
if (controller.enabled) return { mode: "controller-exec", args: controller.args };
|
|
1253
|
+
return { mode: "raw-codex", args: ["exec", ...controller.args] };
|
|
1254
|
+
}
|
|
1255
|
+
if (String(command || "").startsWith("-")) return { mode: "raw-codex", args };
|
|
1256
|
+
return { mode: "raw-codex", args, controller: false };
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1179
1259
|
function runEngineExecWorker({ command, args, providerBaseUrl, token, prompt, timeoutMs }) {
|
|
1180
1260
|
return new Promise((resolve) => {
|
|
1181
1261
|
const started = Date.now();
|
|
@@ -1236,6 +1316,242 @@ function runEngineExecWorker({ command, args, providerBaseUrl, token, prompt, ti
|
|
|
1236
1316
|
});
|
|
1237
1317
|
}
|
|
1238
1318
|
|
|
1319
|
+
async function runSignedControllerPrompt({ signedController, command, args, bridge, token, promptInfo }) {
|
|
1320
|
+
if (!promptInfo.prompt.trim()) {
|
|
1321
|
+
console.error("MyteCody controller requires a prompt.");
|
|
1322
|
+
return 1;
|
|
1323
|
+
}
|
|
1324
|
+
const summary = await signedController.runMyteCodyController({
|
|
1325
|
+
prompt: promptInfo.prompt,
|
|
1326
|
+
workspace: process.cwd(),
|
|
1327
|
+
artifactRoot: path.join(installRoot(), "controller-runs"),
|
|
1328
|
+
runWorker: (workerPrompt, workerOptions = {}) =>
|
|
1329
|
+
runEngineExecWorker({
|
|
1330
|
+
command,
|
|
1331
|
+
args,
|
|
1332
|
+
providerBaseUrl: bridge.baseUrl,
|
|
1333
|
+
token,
|
|
1334
|
+
prompt: workerPrompt,
|
|
1335
|
+
timeoutMs: workerOptions.timeoutMs || 180000,
|
|
1336
|
+
}),
|
|
1337
|
+
});
|
|
1338
|
+
console.error(`[MYTE CODY] controller run: ${summary.artifact_dir}`);
|
|
1339
|
+
console.error(`[MYTE CODY] controller status: ${summary.status}`);
|
|
1340
|
+
if (summary.status === "paused") {
|
|
1341
|
+
console.error(`[MYTE CODY] resume: mytecody resume ${summary.run_id}`);
|
|
1342
|
+
}
|
|
1343
|
+
return ["pass", "paused", "completed"].includes(summary.status) ? 0 : 1;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
async function runSignedControllerResume({ signedController, command, args, bridge, token, target }) {
|
|
1347
|
+
if (!signedController || typeof signedController.resumeMyteCodyControllerRun !== "function") {
|
|
1348
|
+
console.error("Installed MyteCody controller does not support resume; run `mytecody update`.");
|
|
1349
|
+
return 1;
|
|
1350
|
+
}
|
|
1351
|
+
let record;
|
|
1352
|
+
try {
|
|
1353
|
+
record = resolveControllerRunTarget(target || "latest");
|
|
1354
|
+
} catch (error) {
|
|
1355
|
+
console.error(`[MYTE CODY] ${error && error.message ? error.message : error}`);
|
|
1356
|
+
return 1;
|
|
1357
|
+
}
|
|
1358
|
+
if (!record) {
|
|
1359
|
+
console.error(`[MYTE CODY] CodyRun not found: ${target || "latest"}`);
|
|
1360
|
+
return 1;
|
|
1361
|
+
}
|
|
1362
|
+
const summary = await signedController.resumeMyteCodyControllerRun({
|
|
1363
|
+
runId: record.run_id,
|
|
1364
|
+
workspace: record.workspace_root || process.cwd(),
|
|
1365
|
+
artifactRoot: controllerRunsRoot(),
|
|
1366
|
+
runWorker: (workerPrompt, workerOptions = {}) =>
|
|
1367
|
+
runEngineExecWorker({
|
|
1368
|
+
command,
|
|
1369
|
+
args,
|
|
1370
|
+
providerBaseUrl: bridge.baseUrl,
|
|
1371
|
+
token,
|
|
1372
|
+
prompt: workerPrompt,
|
|
1373
|
+
timeoutMs: workerOptions.timeoutMs || 180000,
|
|
1374
|
+
}),
|
|
1375
|
+
});
|
|
1376
|
+
console.error(`[MYTE CODY] resumed CodyRun: ${summary.run_id}`);
|
|
1377
|
+
console.error(`[MYTE CODY] controller status: ${summary.status}`);
|
|
1378
|
+
if (summary.status === "paused") {
|
|
1379
|
+
console.error(`[MYTE CODY] resume: mytecody resume ${summary.run_id}`);
|
|
1380
|
+
}
|
|
1381
|
+
return ["pass", "paused", "completed"].includes(summary.status) ? 0 : 1;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
function isControllerShellExit(value) {
|
|
1385
|
+
return ["/exit", "/quit", "exit", "quit"].includes(String(value || "").trim().toLowerCase());
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
function compactWorkspacePath(workspace = process.cwd()) {
|
|
1389
|
+
const home = os.homedir();
|
|
1390
|
+
const resolved = path.resolve(workspace);
|
|
1391
|
+
if (resolved.toLowerCase().startsWith(home.toLowerCase())) {
|
|
1392
|
+
return `~${resolved.slice(home.length)}`;
|
|
1393
|
+
}
|
|
1394
|
+
return resolved;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
function fitCell(value, width) {
|
|
1398
|
+
const text = String(value || "");
|
|
1399
|
+
if (text.length <= width) return `${text}${" ".repeat(width - text.length)}`;
|
|
1400
|
+
return `${text.slice(0, Math.max(0, width - 1))}…`;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
function printControllerShellBanner() {
|
|
1404
|
+
const width = 70;
|
|
1405
|
+
const lines = [
|
|
1406
|
+
"MYTE CODY - Your Tech Your Way",
|
|
1407
|
+
`workspace: ${compactWorkspacePath()}`,
|
|
1408
|
+
"mode: sovereign coding agent - Myte AI gateway",
|
|
1409
|
+
"enter a prompt, /resume latest, /diagnostics, /help, or /exit",
|
|
1410
|
+
];
|
|
1411
|
+
console.log(`╭${"─".repeat(width)}╮`);
|
|
1412
|
+
for (const line of lines) console.log(`│ ${fitCell(line, width - 2)} │`);
|
|
1413
|
+
console.log(`╰${"─".repeat(width)}╯`);
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
function printControllerShellHelp() {
|
|
1417
|
+
console.log("");
|
|
1418
|
+
console.log("MYTE CODY commands");
|
|
1419
|
+
console.log("/resume [run_id|latest] Continue a paused CodyRun.");
|
|
1420
|
+
console.log("/diagnostics Open the raw engine diagnostics view.");
|
|
1421
|
+
console.log("/exit Quit.");
|
|
1422
|
+
console.log("");
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
async function runControllerShell({ signedController, command, args, bridge, token }) {
|
|
1426
|
+
printControllerShellBanner();
|
|
1427
|
+
const rl = readline.createInterface({
|
|
1428
|
+
input: process.stdin,
|
|
1429
|
+
output: process.stdout,
|
|
1430
|
+
prompt: "\n› ",
|
|
1431
|
+
});
|
|
1432
|
+
rl.prompt();
|
|
1433
|
+
for await (const line of rl) {
|
|
1434
|
+
const prompt = String(line || "").trim();
|
|
1435
|
+
if (!prompt) {
|
|
1436
|
+
rl.prompt();
|
|
1437
|
+
continue;
|
|
1438
|
+
}
|
|
1439
|
+
if (isControllerShellExit(prompt)) break;
|
|
1440
|
+
if (prompt === "/help") {
|
|
1441
|
+
printControllerShellHelp();
|
|
1442
|
+
rl.prompt();
|
|
1443
|
+
continue;
|
|
1444
|
+
}
|
|
1445
|
+
if (prompt === "/diagnostics" || prompt === "/codex") {
|
|
1446
|
+
rl.close();
|
|
1447
|
+
return { rawCodexRequested: true };
|
|
1448
|
+
}
|
|
1449
|
+
if (prompt.startsWith("/resume")) {
|
|
1450
|
+
const target = prompt.split(/\s+/).slice(1)[0] || "latest";
|
|
1451
|
+
await runSignedControllerResume({
|
|
1452
|
+
signedController,
|
|
1453
|
+
command,
|
|
1454
|
+
args,
|
|
1455
|
+
bridge,
|
|
1456
|
+
token,
|
|
1457
|
+
target,
|
|
1458
|
+
});
|
|
1459
|
+
rl.prompt();
|
|
1460
|
+
continue;
|
|
1461
|
+
}
|
|
1462
|
+
await runSignedControllerPrompt({
|
|
1463
|
+
signedController,
|
|
1464
|
+
command,
|
|
1465
|
+
args,
|
|
1466
|
+
bridge,
|
|
1467
|
+
token,
|
|
1468
|
+
promptInfo: { prompt, forwardedArgs: [] },
|
|
1469
|
+
});
|
|
1470
|
+
rl.prompt();
|
|
1471
|
+
}
|
|
1472
|
+
return { rawCodexRequested: false };
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
function emitSidecarEvent(event) {
|
|
1476
|
+
process.stdout.write(`${JSON.stringify(event)}\n`);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
async function runControllerSidecar() {
|
|
1480
|
+
let request;
|
|
1481
|
+
try {
|
|
1482
|
+
const raw = fs.readFileSync(0, "utf8");
|
|
1483
|
+
request = raw.trim() ? JSON.parse(raw) : {};
|
|
1484
|
+
} catch (error) {
|
|
1485
|
+
emitSidecarEvent({
|
|
1486
|
+
type: "failed",
|
|
1487
|
+
message: `Invalid MyteCody sidecar request: ${error && error.message ? error.message : error}`,
|
|
1488
|
+
});
|
|
1489
|
+
return 1;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
const prompt = String(request.prompt || "").trim();
|
|
1493
|
+
const workspace = path.resolve(request.workspace || process.cwd());
|
|
1494
|
+
if (!prompt) {
|
|
1495
|
+
emitSidecarEvent({ type: "failed", message: "MyteCody sidecar request did not include a prompt." });
|
|
1496
|
+
return 1;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
const token = process.env.MYTE_CODY_AUTH_TOKEN || getAuthToken();
|
|
1500
|
+
const providerBaseUrl = process.env.MYTE_CODY_BRIDGE_BASE_URL;
|
|
1501
|
+
const command = resolveCodexCommand();
|
|
1502
|
+
if (!token || !providerBaseUrl || !command) {
|
|
1503
|
+
emitSidecarEvent({
|
|
1504
|
+
type: "failed",
|
|
1505
|
+
message: "MyteCody sidecar is missing auth, bridge URL, or installed engine command.",
|
|
1506
|
+
});
|
|
1507
|
+
return 1;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
emitSidecarEvent({
|
|
1511
|
+
type: "started",
|
|
1512
|
+
message: "MyteCody controller started.",
|
|
1513
|
+
workspace,
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
try {
|
|
1517
|
+
const signedController = loadSignedController();
|
|
1518
|
+
const summary = await signedController.runMyteCodyController({
|
|
1519
|
+
prompt,
|
|
1520
|
+
workspace,
|
|
1521
|
+
artifactRoot: process.env.MYTE_CODY_CONTROLLER_RUNS_DIR || controllerRunsRoot(),
|
|
1522
|
+
mode: process.env.MYTE_CODY_CONTROLLER_MODE || "gateway",
|
|
1523
|
+
runWorker: (workerPrompt, workerOptions = {}) =>
|
|
1524
|
+
runEngineExecWorker({
|
|
1525
|
+
command,
|
|
1526
|
+
args: {},
|
|
1527
|
+
providerBaseUrl,
|
|
1528
|
+
token,
|
|
1529
|
+
prompt: workerPrompt,
|
|
1530
|
+
timeoutMs: workerOptions.timeoutMs || 180000,
|
|
1531
|
+
}),
|
|
1532
|
+
});
|
|
1533
|
+
const resumeCommand = `mytecody resume ${summary.run_id}`;
|
|
1534
|
+
emitSidecarEvent({
|
|
1535
|
+
type: summary.status === "paused" ? "paused" : "completed",
|
|
1536
|
+
run_id: summary.run_id,
|
|
1537
|
+
status: summary.status,
|
|
1538
|
+
artifact_dir: summary.artifact_dir,
|
|
1539
|
+
resume: summary.status === "paused" ? resumeCommand : null,
|
|
1540
|
+
message:
|
|
1541
|
+
summary.status === "paused"
|
|
1542
|
+
? `MyteCody paused with a durable run state. Resume with: ${resumeCommand}`
|
|
1543
|
+
: `MyteCody controller completed with status: ${summary.status}`,
|
|
1544
|
+
});
|
|
1545
|
+
return ["pass", "paused", "completed"].includes(summary.status) ? 0 : 1;
|
|
1546
|
+
} catch (error) {
|
|
1547
|
+
emitSidecarEvent({
|
|
1548
|
+
type: "failed",
|
|
1549
|
+
message: error && error.stack ? error.stack : error && error.message ? error.message : String(error),
|
|
1550
|
+
});
|
|
1551
|
+
return 1;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1239
1555
|
async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
1240
1556
|
const token = getAuthToken();
|
|
1241
1557
|
if (!token) {
|
|
@@ -1294,39 +1610,82 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
1294
1610
|
return 1;
|
|
1295
1611
|
}
|
|
1296
1612
|
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
if (rawArgs[0] === "exec" && controllerState.enabled) {
|
|
1613
|
+
const invocation = classifyMyteCodyInvocation(rawArgs);
|
|
1614
|
+
if (["controller-exec", "controller-prompt", "controller-shell", "controller-resume"].includes(invocation.mode)) {
|
|
1300
1615
|
try {
|
|
1301
1616
|
progress("opening MyteCody controller");
|
|
1302
1617
|
const signedController = loadSignedController();
|
|
1303
|
-
|
|
1618
|
+
await splash.stop();
|
|
1619
|
+
if (packageNotice) statusLine(packageNotice);
|
|
1620
|
+
|
|
1621
|
+
if (invocation.mode === "controller-resume") {
|
|
1622
|
+
const code = await runSignedControllerResume({
|
|
1623
|
+
signedController,
|
|
1624
|
+
command,
|
|
1625
|
+
args,
|
|
1626
|
+
bridge,
|
|
1627
|
+
token,
|
|
1628
|
+
target: invocation.args[0] || "latest",
|
|
1629
|
+
});
|
|
1630
|
+
await bridge.close();
|
|
1631
|
+
return code;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
if (invocation.mode === "controller-shell") {
|
|
1635
|
+
const shellResult = await runControllerShell({
|
|
1636
|
+
signedController,
|
|
1637
|
+
command,
|
|
1638
|
+
args,
|
|
1639
|
+
bridge,
|
|
1640
|
+
token,
|
|
1641
|
+
});
|
|
1642
|
+
if (shellResult.rawCodexRequested) {
|
|
1643
|
+
const rawArgs = [...command.args, ...codexLaunchArgs([], args, bridge.baseUrl)];
|
|
1644
|
+
const env = {
|
|
1645
|
+
...process.env,
|
|
1646
|
+
CODEX_HOME: codexHome(),
|
|
1647
|
+
MYTE_CODY_AUTH_TOKEN: token,
|
|
1648
|
+
MYTE_CODY_BRAND: "1",
|
|
1649
|
+
MYTE_CODY_CONTROLLER: "0",
|
|
1650
|
+
MYTE_CODY_BRIDGE_BASE_URL: bridge.baseUrl,
|
|
1651
|
+
};
|
|
1652
|
+
return await new Promise((resolve) => {
|
|
1653
|
+
const child = spawn(command.cmd, rawArgs, {
|
|
1654
|
+
cwd: process.cwd(),
|
|
1655
|
+
env,
|
|
1656
|
+
stdio: "inherit",
|
|
1657
|
+
shell: process.platform === "win32" && command.cmd === "codex",
|
|
1658
|
+
});
|
|
1659
|
+
child.on("error", (error) => {
|
|
1660
|
+
console.error(`Unable to launch MyteCody engine: ${error.message || error}`);
|
|
1661
|
+
bridge.close().finally(() => resolve(1));
|
|
1662
|
+
});
|
|
1663
|
+
child.on("close", (code) => {
|
|
1664
|
+
bridge.close().finally(() => resolve(Number.isInteger(code) ? code : 1));
|
|
1665
|
+
});
|
|
1666
|
+
});
|
|
1667
|
+
}
|
|
1668
|
+
await bridge.close();
|
|
1669
|
+
return 0;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
const promptInfo = controllerPromptFromExecArgs(invocation.args);
|
|
1304
1673
|
if (!promptInfo.prompt.trim()) {
|
|
1305
1674
|
await splash.stop();
|
|
1306
1675
|
await bridge.close();
|
|
1307
|
-
console.error("MyteCody controller
|
|
1676
|
+
console.error("MyteCody controller requires a prompt.");
|
|
1308
1677
|
return 1;
|
|
1309
1678
|
}
|
|
1310
|
-
await
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
runEngineExecWorker({
|
|
1318
|
-
command,
|
|
1319
|
-
args,
|
|
1320
|
-
providerBaseUrl: bridge.baseUrl,
|
|
1321
|
-
token,
|
|
1322
|
-
prompt: workerPrompt,
|
|
1323
|
-
timeoutMs: workerOptions.timeoutMs || 180000,
|
|
1324
|
-
}),
|
|
1679
|
+
const code = await runSignedControllerPrompt({
|
|
1680
|
+
signedController,
|
|
1681
|
+
command,
|
|
1682
|
+
args,
|
|
1683
|
+
bridge,
|
|
1684
|
+
token,
|
|
1685
|
+
promptInfo,
|
|
1325
1686
|
});
|
|
1326
|
-
console.error(`[MYTE CODY] controller run: ${summary.artifact_dir}`);
|
|
1327
|
-
console.error(`[MYTE CODY] controller status: ${summary.status}`);
|
|
1328
1687
|
await bridge.close();
|
|
1329
|
-
return
|
|
1688
|
+
return code;
|
|
1330
1689
|
} catch (error) {
|
|
1331
1690
|
await splash.stop();
|
|
1332
1691
|
await bridge.close();
|
|
@@ -1335,12 +1694,17 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
1335
1694
|
}
|
|
1336
1695
|
}
|
|
1337
1696
|
|
|
1338
|
-
const launchArgs = [...command.args, ...codexLaunchArgs(
|
|
1697
|
+
const launchArgs = [...command.args, ...codexLaunchArgs(invocation.args, args, bridge.baseUrl)];
|
|
1339
1698
|
const env = {
|
|
1340
1699
|
...process.env,
|
|
1341
1700
|
CODEX_HOME: codexHome(),
|
|
1342
1701
|
MYTE_CODY_AUTH_TOKEN: token,
|
|
1343
1702
|
MYTE_CODY_BRAND: "1",
|
|
1703
|
+
MYTE_CODY_CONTROLLER: invocation.controller === true ? "1" : "0",
|
|
1704
|
+
MYTE_CODY_CONTROLLER_MODE: "gateway",
|
|
1705
|
+
MYTE_CODY_CONTROLLER_NODE: process.execPath,
|
|
1706
|
+
MYTE_CODY_CONTROLLER_ENTRY: __filename,
|
|
1707
|
+
MYTE_CODY_CONTROLLER_RUNS_DIR: controllerRunsRoot(),
|
|
1344
1708
|
MYTE_CODY_BRIDGE_BASE_URL: bridge.baseUrl,
|
|
1345
1709
|
};
|
|
1346
1710
|
progress("opening MyteCody workspace");
|
|
@@ -1376,8 +1740,7 @@ async function runDoctor(args, envPath) {
|
|
|
1376
1740
|
payload.ready_for_coding =
|
|
1377
1741
|
payload.auth.present &&
|
|
1378
1742
|
payload.release.client_installed &&
|
|
1379
|
-
payload.release.bridge_installed
|
|
1380
|
-
payload.release.controller_installed;
|
|
1743
|
+
payload.release.bridge_installed;
|
|
1381
1744
|
if (payload.gateway.probe) {
|
|
1382
1745
|
payload.ready_for_coding = Boolean(payload.ready_for_coding && payload.gateway.probe.ok);
|
|
1383
1746
|
}
|
|
@@ -1613,6 +1976,7 @@ async function run(argv = process.argv.slice(2)) {
|
|
|
1613
1976
|
}
|
|
1614
1977
|
if (command === "doctor") return runDoctor(restArgs, envPath);
|
|
1615
1978
|
if (command === "update") return runUpdate(restArgs, envPath);
|
|
1979
|
+
if (command === "controller-sidecar") return runControllerSidecar();
|
|
1616
1980
|
if (command === "version" || command === "--version" || command === "-v") {
|
|
1617
1981
|
console.log(PACKAGE_VERSION);
|
|
1618
1982
|
return 0;
|
|
@@ -1637,6 +2001,7 @@ if (require.main === module) {
|
|
|
1637
2001
|
|
|
1638
2002
|
module.exports = {
|
|
1639
2003
|
checkPackageUpdate,
|
|
2004
|
+
classifyMyteCodyInvocation,
|
|
1640
2005
|
codexLaunchArgs,
|
|
1641
2006
|
codexProviderArgs,
|
|
1642
2007
|
codyInferenceBase,
|