@mytegroupinc/myte-core 0.0.39 → 0.0.41
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 +7 -6
- package/THIRD_PARTY_NOTICES.md +3 -3
- package/mytecody-cli.js +248 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,16 +28,17 @@ This package exists so the public wrapper can stay small and versioned cleanly.
|
|
|
28
28
|
- Public package documentation is intentionally minimal. Internal rollout and design notes are not part of the npm package contract.
|
|
29
29
|
- `mytecody` is a model-agnostic MyteCody team launcher. It supports `doctor`,
|
|
30
30
|
`doctor --probe-gateway`, `update --dry-run`, and `update`. On first coding
|
|
31
|
-
run, it installs the branded MyteCody engine
|
|
32
|
-
into a user-local Myte cache after signature/hash
|
|
33
|
-
requires
|
|
31
|
+
run, it installs the branded MyteCody engine and signed client assets from
|
|
32
|
+
the Myte release manifest into a user-local Myte cache after signature/hash
|
|
33
|
+
checks. Coding execution requires those assets, a reachable Myte AI Cody
|
|
34
|
+
gateway, and `MYTEAI_API_KEY`.
|
|
34
35
|
- `mytecody doctor` reports both the signed MyteCody engine state and this npm
|
|
35
36
|
package version. `mytecody update` updates the engine only. Use
|
|
36
37
|
`npm install -g myte@latest` to update the launcher and the Myte API CLI
|
|
37
38
|
commands shipped by npm.
|
|
38
|
-
- The package does not bundle the large MyteCody engine binary
|
|
39
|
-
|
|
40
|
-
notices.
|
|
39
|
+
- The package does not bundle the large MyteCody engine binary or the async
|
|
40
|
+
Responses bridge implementation. See `THIRD_PARTY_NOTICES.md` and
|
|
41
|
+
`TRADEMARKS.md` for Codex lineage and Myte brand notices.
|
|
41
42
|
|
|
42
43
|
## Agent Usage Contract
|
|
43
44
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -13,9 +13,9 @@ Source lineage tracked for this slice:
|
|
|
13
13
|
- License: Apache-2.0
|
|
14
14
|
- Upstream: https://github.com/openai/codex
|
|
15
15
|
|
|
16
|
-
The MyteCody engine
|
|
17
|
-
through a Myte release manifest. This package verifies
|
|
18
|
-
before installing
|
|
16
|
+
The MyteCody engine and signed client assets are distributed separately from
|
|
17
|
+
this npm package through a Myte release manifest. This package verifies release
|
|
18
|
+
artifacts before installing them into the user's Myte-owned local cache.
|
|
19
19
|
|
|
20
20
|
Myte names, marks, logos, terminal branding, and product design are not part of
|
|
21
21
|
the OpenAI Codex project and remain Myte-owned brand assets.
|
package/mytecody-cli.js
CHANGED
|
@@ -168,6 +168,10 @@ function currentBridgePath() {
|
|
|
168
168
|
return path.join(currentInstallRoot(), "lib", "mytecody-async-responses-bridge.js");
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
function currentControllerPath() {
|
|
172
|
+
return path.join(currentInstallRoot(), "lib", "mytecody-controller.js");
|
|
173
|
+
}
|
|
174
|
+
|
|
171
175
|
function codexHome() {
|
|
172
176
|
return path.join(installRoot(), "engine-home");
|
|
173
177
|
}
|
|
@@ -192,6 +196,15 @@ function installedClientCommand() {
|
|
|
192
196
|
return { cmd: enginePath, args: [], source: "myte-installed-engine" };
|
|
193
197
|
}
|
|
194
198
|
|
|
199
|
+
function installedClientUsable() {
|
|
200
|
+
return Boolean(
|
|
201
|
+
installedClientCommand() &&
|
|
202
|
+
fs.existsSync(currentBridgePath()) &&
|
|
203
|
+
fs.existsSync(currentControllerPath()) &&
|
|
204
|
+
readCurrentClientManifest(),
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
195
208
|
function loadSignedBridge() {
|
|
196
209
|
const bridgePath = currentBridgePath();
|
|
197
210
|
if (!fs.existsSync(bridgePath)) {
|
|
@@ -204,6 +217,18 @@ function loadSignedBridge() {
|
|
|
204
217
|
return bridge;
|
|
205
218
|
}
|
|
206
219
|
|
|
220
|
+
function loadSignedController() {
|
|
221
|
+
const controllerPath = currentControllerPath();
|
|
222
|
+
if (!fs.existsSync(controllerPath)) {
|
|
223
|
+
throw new Error("signed MyteCody controller asset is missing; run `mytecody update`.");
|
|
224
|
+
}
|
|
225
|
+
const controller = require(controllerPath);
|
|
226
|
+
if (!controller || typeof controller.runMyteCodyController !== "function") {
|
|
227
|
+
throw new Error("signed MyteCody controller asset is invalid.");
|
|
228
|
+
}
|
|
229
|
+
return controller;
|
|
230
|
+
}
|
|
231
|
+
|
|
207
232
|
function releaseAssetsForPlatform(manifest, artifact) {
|
|
208
233
|
const assets = [];
|
|
209
234
|
const collect = (value, source) => {
|
|
@@ -369,9 +394,11 @@ function commonStatus(args, envPath) {
|
|
|
369
394
|
install_root: installRoot(),
|
|
370
395
|
engine_path: currentEnginePath(),
|
|
371
396
|
bridge_path: currentBridgePath(),
|
|
397
|
+
controller_path: currentControllerPath(),
|
|
372
398
|
client_manifest: currentClientManifestPath(),
|
|
373
399
|
client_installed: Boolean(current && installedClientCommand()),
|
|
374
400
|
bridge_installed: fs.existsSync(currentBridgePath()),
|
|
401
|
+
controller_installed: fs.existsSync(currentControllerPath()),
|
|
375
402
|
client_version: current && current.version ? current.version : null,
|
|
376
403
|
},
|
|
377
404
|
};
|
|
@@ -1001,6 +1028,157 @@ function codexLaunchArgs(rawArgs, args = {}, providerBaseUrl = codyInferenceBase
|
|
|
1001
1028
|
return [...providerArgs, ...rawArgs];
|
|
1002
1029
|
}
|
|
1003
1030
|
|
|
1031
|
+
function execArgsAndStdin(rawArgs) {
|
|
1032
|
+
if (!rawArgs.length) return { args: [], stdin: null };
|
|
1033
|
+
const valueOptions = new Set([
|
|
1034
|
+
"-a",
|
|
1035
|
+
"--ask-for-approval",
|
|
1036
|
+
"-C",
|
|
1037
|
+
"--cd",
|
|
1038
|
+
"-c",
|
|
1039
|
+
"--config",
|
|
1040
|
+
"-i",
|
|
1041
|
+
"--image",
|
|
1042
|
+
"-m",
|
|
1043
|
+
"--model",
|
|
1044
|
+
"-o",
|
|
1045
|
+
"--output-last-message",
|
|
1046
|
+
"-p",
|
|
1047
|
+
"--profile",
|
|
1048
|
+
"-s",
|
|
1049
|
+
"--sandbox",
|
|
1050
|
+
"--color",
|
|
1051
|
+
"--local-provider",
|
|
1052
|
+
"--output-schema",
|
|
1053
|
+
]);
|
|
1054
|
+
const forwarded = [];
|
|
1055
|
+
let index = 0;
|
|
1056
|
+
while (index < rawArgs.length) {
|
|
1057
|
+
const arg = rawArgs[index];
|
|
1058
|
+
if (arg === "--") {
|
|
1059
|
+
index += 1;
|
|
1060
|
+
break;
|
|
1061
|
+
}
|
|
1062
|
+
if (arg === "-") break;
|
|
1063
|
+
if (!arg.startsWith("-")) break;
|
|
1064
|
+
forwarded.push(arg);
|
|
1065
|
+
index += 1;
|
|
1066
|
+
if (valueOptions.has(arg) && index < rawArgs.length) {
|
|
1067
|
+
forwarded.push(rawArgs[index]);
|
|
1068
|
+
index += 1;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
const promptParts = rawArgs.slice(index);
|
|
1072
|
+
if (!promptParts.length) return { args: forwarded, stdin: null };
|
|
1073
|
+
if (promptParts.length === 1 && promptParts[0] === "-") {
|
|
1074
|
+
return { args: [...forwarded, "-"], stdin: fs.readFileSync(0, "utf8") };
|
|
1075
|
+
}
|
|
1076
|
+
const prompt = promptParts.join(" ");
|
|
1077
|
+
if (prompt.includes("\n") || prompt.includes("\r") || promptParts.length > 1) {
|
|
1078
|
+
return { args: [...forwarded, "-"], stdin: prompt };
|
|
1079
|
+
}
|
|
1080
|
+
return { args: [...forwarded, prompt], stdin: null };
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
function stripControllerArgs(rawArgs) {
|
|
1084
|
+
const kept = [];
|
|
1085
|
+
let enabled = process.env.MYTE_CODY_CONTROLLER !== "0";
|
|
1086
|
+
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
1087
|
+
const arg = rawArgs[i];
|
|
1088
|
+
if (arg === "--controller") {
|
|
1089
|
+
const next = rawArgs[i + 1];
|
|
1090
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
1091
|
+
enabled = !["0", "false", "off", "raw"].includes(String(next).toLowerCase());
|
|
1092
|
+
i += 1;
|
|
1093
|
+
} else {
|
|
1094
|
+
enabled = true;
|
|
1095
|
+
}
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
if (arg.startsWith("--controller=")) {
|
|
1099
|
+
const value = arg.slice("--controller=".length);
|
|
1100
|
+
enabled = !["0", "false", "off", "raw"].includes(String(value).toLowerCase());
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
if (arg === "--no-controller") {
|
|
1104
|
+
enabled = false;
|
|
1105
|
+
continue;
|
|
1106
|
+
}
|
|
1107
|
+
kept.push(arg);
|
|
1108
|
+
}
|
|
1109
|
+
return { enabled, args: kept };
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
function controllerPromptFromExecArgs(rawArgs) {
|
|
1113
|
+
const execInput = execArgsAndStdin(rawArgs);
|
|
1114
|
+
if (execInput.stdin != null) return { prompt: execInput.stdin, forwardedArgs: [] };
|
|
1115
|
+
const prompt = execInput.args.length ? execInput.args[execInput.args.length - 1] : "";
|
|
1116
|
+
if (!prompt || prompt.startsWith("-")) {
|
|
1117
|
+
return { prompt: "", forwardedArgs: execInput.args };
|
|
1118
|
+
}
|
|
1119
|
+
return { prompt, forwardedArgs: execInput.args.slice(0, -1) };
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
function runEngineExecWorker({ command, args, providerBaseUrl, token, prompt, timeoutMs }) {
|
|
1123
|
+
return new Promise((resolve) => {
|
|
1124
|
+
const started = Date.now();
|
|
1125
|
+
const env = {
|
|
1126
|
+
...process.env,
|
|
1127
|
+
CODEX_HOME: codexHome(),
|
|
1128
|
+
MYTE_CODY_AUTH_TOKEN: token,
|
|
1129
|
+
MYTE_CODY_BRAND: "1",
|
|
1130
|
+
MYTE_CODY_CONTROLLER: "0",
|
|
1131
|
+
MYTE_CODY_BRIDGE_BASE_URL: providerBaseUrl,
|
|
1132
|
+
};
|
|
1133
|
+
const launchArgs = [...command.args, ...codexLaunchArgs(["exec", "--json", "-"], args, providerBaseUrl)];
|
|
1134
|
+
const child = spawn(command.cmd, launchArgs, {
|
|
1135
|
+
cwd: process.cwd(),
|
|
1136
|
+
env,
|
|
1137
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1138
|
+
shell: process.platform === "win32" && command.cmd === "codex",
|
|
1139
|
+
});
|
|
1140
|
+
let stdout = "";
|
|
1141
|
+
let stderr = "";
|
|
1142
|
+
let settled = false;
|
|
1143
|
+
const timer = setTimeout(() => {
|
|
1144
|
+
if (settled) return;
|
|
1145
|
+
try {
|
|
1146
|
+
child.kill();
|
|
1147
|
+
} catch {}
|
|
1148
|
+
}, timeoutMs || 180000);
|
|
1149
|
+
child.stdout.on("data", (chunk) => {
|
|
1150
|
+
stdout += chunk.toString();
|
|
1151
|
+
});
|
|
1152
|
+
child.stderr.on("data", (chunk) => {
|
|
1153
|
+
stderr += chunk.toString();
|
|
1154
|
+
});
|
|
1155
|
+
child.on("error", (error) => {
|
|
1156
|
+
settled = true;
|
|
1157
|
+
clearTimeout(timer);
|
|
1158
|
+
resolve({
|
|
1159
|
+
status: 1,
|
|
1160
|
+
stdout,
|
|
1161
|
+
stderr,
|
|
1162
|
+
error: error.message || String(error),
|
|
1163
|
+
durationMs: Date.now() - started,
|
|
1164
|
+
});
|
|
1165
|
+
});
|
|
1166
|
+
child.on("exit", (code, signal) => {
|
|
1167
|
+
settled = true;
|
|
1168
|
+
clearTimeout(timer);
|
|
1169
|
+
resolve({
|
|
1170
|
+
status: code == null ? 1 : code,
|
|
1171
|
+
signal: signal || null,
|
|
1172
|
+
stdout,
|
|
1173
|
+
stderr,
|
|
1174
|
+
error: null,
|
|
1175
|
+
durationMs: Date.now() - started,
|
|
1176
|
+
});
|
|
1177
|
+
});
|
|
1178
|
+
child.stdin.end(prompt);
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1004
1182
|
async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
1005
1183
|
const token = getAuthToken();
|
|
1006
1184
|
if (!token) {
|
|
@@ -1059,7 +1237,48 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
1059
1237
|
return 1;
|
|
1060
1238
|
}
|
|
1061
1239
|
|
|
1062
|
-
const
|
|
1240
|
+
const normalizedRawArgs = rawArgs[0] === "exec" ? ["exec", ...stripControllerArgs(rawArgs.slice(1)).args] : rawArgs;
|
|
1241
|
+
const controllerState = rawArgs[0] === "exec" ? stripControllerArgs(rawArgs.slice(1)) : { enabled: false, args: [] };
|
|
1242
|
+
if (rawArgs[0] === "exec" && controllerState.enabled) {
|
|
1243
|
+
try {
|
|
1244
|
+
progress("opening MyteCody controller");
|
|
1245
|
+
const signedController = loadSignedController();
|
|
1246
|
+
const promptInfo = controllerPromptFromExecArgs(controllerState.args);
|
|
1247
|
+
if (!promptInfo.prompt.trim()) {
|
|
1248
|
+
await splash.stop();
|
|
1249
|
+
await bridge.close();
|
|
1250
|
+
console.error("MyteCody controller exec requires a prompt or stdin via exec -.");
|
|
1251
|
+
return 1;
|
|
1252
|
+
}
|
|
1253
|
+
await splash.stop();
|
|
1254
|
+
if (packageNotice) statusLine(packageNotice);
|
|
1255
|
+
const summary = await signedController.runMyteCodyController({
|
|
1256
|
+
prompt: promptInfo.prompt,
|
|
1257
|
+
workspace: process.cwd(),
|
|
1258
|
+
artifactRoot: path.join(installRoot(), "controller-runs"),
|
|
1259
|
+
runWorker: (workerPrompt, workerOptions = {}) =>
|
|
1260
|
+
runEngineExecWorker({
|
|
1261
|
+
command,
|
|
1262
|
+
args,
|
|
1263
|
+
providerBaseUrl: bridge.baseUrl,
|
|
1264
|
+
token,
|
|
1265
|
+
prompt: workerPrompt,
|
|
1266
|
+
timeoutMs: workerOptions.timeoutMs || 180000,
|
|
1267
|
+
}),
|
|
1268
|
+
});
|
|
1269
|
+
console.error(`[MYTE CODY] controller run: ${summary.artifact_dir}`);
|
|
1270
|
+
console.error(`[MYTE CODY] controller status: ${summary.status}`);
|
|
1271
|
+
await bridge.close();
|
|
1272
|
+
return summary.status === "pass" ? 0 : 1;
|
|
1273
|
+
} catch (error) {
|
|
1274
|
+
await splash.stop();
|
|
1275
|
+
await bridge.close();
|
|
1276
|
+
console.error(`MyteCody controller failed: ${error && error.message ? error.message : error}`);
|
|
1277
|
+
return 1;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
const launchArgs = [...command.args, ...codexLaunchArgs(normalizedRawArgs, args, bridge.baseUrl)];
|
|
1063
1282
|
const env = {
|
|
1064
1283
|
...process.env,
|
|
1065
1284
|
CODEX_HOME: codexHome(),
|
|
@@ -1098,7 +1317,10 @@ async function runDoctor(args, envPath) {
|
|
|
1098
1317
|
payload.gateway.probe = await probeGateway(args);
|
|
1099
1318
|
}
|
|
1100
1319
|
payload.ready_for_coding =
|
|
1101
|
-
payload.auth.present &&
|
|
1320
|
+
payload.auth.present &&
|
|
1321
|
+
payload.release.client_installed &&
|
|
1322
|
+
payload.release.bridge_installed &&
|
|
1323
|
+
payload.release.controller_installed;
|
|
1102
1324
|
if (payload.gateway.probe) {
|
|
1103
1325
|
payload.ready_for_coding = Boolean(payload.ready_for_coding && payload.gateway.probe.ok);
|
|
1104
1326
|
}
|
|
@@ -1226,9 +1448,31 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null, { progres
|
|
|
1226
1448
|
delete updateArgs.json;
|
|
1227
1449
|
|
|
1228
1450
|
const source = manifestUrl(updateArgs);
|
|
1229
|
-
|
|
1451
|
+
let manifestResult;
|
|
1452
|
+
try {
|
|
1453
|
+
manifestResult = await readManifest(source, { fetchManifest: true, progress });
|
|
1454
|
+
} catch (error) {
|
|
1455
|
+
if (isUrl(source) && installedClientUsable()) {
|
|
1456
|
+
return {
|
|
1457
|
+
ok: true,
|
|
1458
|
+
installed: false,
|
|
1459
|
+
reason: "cached-engine-manifest-unavailable",
|
|
1460
|
+
manifest_status: "fetch-failed",
|
|
1461
|
+
error: error && error.message ? error.message : String(error),
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
throw error;
|
|
1465
|
+
}
|
|
1230
1466
|
const manifest = manifestResult.manifest;
|
|
1231
1467
|
if (!manifest) {
|
|
1468
|
+
if (isUrl(source) && installedClientUsable()) {
|
|
1469
|
+
return {
|
|
1470
|
+
ok: true,
|
|
1471
|
+
installed: false,
|
|
1472
|
+
reason: "cached-engine-manifest-unavailable",
|
|
1473
|
+
manifest_status: manifestResult.status,
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1232
1476
|
return { ok: false, installed: false, reason: "manifest-unavailable", manifest_status: manifestResult.status };
|
|
1233
1477
|
}
|
|
1234
1478
|
const signature = signatureAccepted(manifest, updateArgs);
|
|
@@ -1330,6 +1574,7 @@ module.exports = {
|
|
|
1330
1574
|
codyInferenceBase,
|
|
1331
1575
|
codyGatewayUrl,
|
|
1332
1576
|
currentBridgePath,
|
|
1577
|
+
currentControllerPath,
|
|
1333
1578
|
currentClientManifestPath,
|
|
1334
1579
|
currentEnginePath,
|
|
1335
1580
|
ensureBrandedEngineInstalled,
|