@mytegroupinc/myte-core 0.0.40 → 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.
Files changed (2) hide show
  1. package/mytecody-cli.js +222 -3
  2. package/package.json +1 -1
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
  }
@@ -193,7 +197,12 @@ function installedClientCommand() {
193
197
  }
194
198
 
195
199
  function installedClientUsable() {
196
- return Boolean(installedClientCommand() && fs.existsSync(currentBridgePath()) && readCurrentClientManifest());
200
+ return Boolean(
201
+ installedClientCommand() &&
202
+ fs.existsSync(currentBridgePath()) &&
203
+ fs.existsSync(currentControllerPath()) &&
204
+ readCurrentClientManifest(),
205
+ );
197
206
  }
198
207
 
199
208
  function loadSignedBridge() {
@@ -208,6 +217,18 @@ function loadSignedBridge() {
208
217
  return bridge;
209
218
  }
210
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
+
211
232
  function releaseAssetsForPlatform(manifest, artifact) {
212
233
  const assets = [];
213
234
  const collect = (value, source) => {
@@ -373,9 +394,11 @@ function commonStatus(args, envPath) {
373
394
  install_root: installRoot(),
374
395
  engine_path: currentEnginePath(),
375
396
  bridge_path: currentBridgePath(),
397
+ controller_path: currentControllerPath(),
376
398
  client_manifest: currentClientManifestPath(),
377
399
  client_installed: Boolean(current && installedClientCommand()),
378
400
  bridge_installed: fs.existsSync(currentBridgePath()),
401
+ controller_installed: fs.existsSync(currentControllerPath()),
379
402
  client_version: current && current.version ? current.version : null,
380
403
  },
381
404
  };
@@ -1005,6 +1028,157 @@ function codexLaunchArgs(rawArgs, args = {}, providerBaseUrl = codyInferenceBase
1005
1028
  return [...providerArgs, ...rawArgs];
1006
1029
  }
1007
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
+
1008
1182
  async function runCodex(rawArgs, args = {}, envPath = null) {
1009
1183
  const token = getAuthToken();
1010
1184
  if (!token) {
@@ -1063,7 +1237,48 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
1063
1237
  return 1;
1064
1238
  }
1065
1239
 
1066
- const launchArgs = [...command.args, ...codexLaunchArgs(rawArgs, args, bridge.baseUrl)];
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)];
1067
1282
  const env = {
1068
1283
  ...process.env,
1069
1284
  CODEX_HOME: codexHome(),
@@ -1102,7 +1317,10 @@ async function runDoctor(args, envPath) {
1102
1317
  payload.gateway.probe = await probeGateway(args);
1103
1318
  }
1104
1319
  payload.ready_for_coding =
1105
- payload.auth.present && payload.release.client_installed && payload.release.bridge_installed;
1320
+ payload.auth.present &&
1321
+ payload.release.client_installed &&
1322
+ payload.release.bridge_installed &&
1323
+ payload.release.controller_installed;
1106
1324
  if (payload.gateway.probe) {
1107
1325
  payload.ready_for_coding = Boolean(payload.ready_for_coding && payload.gateway.probe.ok);
1108
1326
  }
@@ -1356,6 +1574,7 @@ module.exports = {
1356
1574
  codyInferenceBase,
1357
1575
  codyGatewayUrl,
1358
1576
  currentBridgePath,
1577
+ currentControllerPath,
1359
1578
  currentClientManifestPath,
1360
1579
  currentEnginePath,
1361
1580
  ensureBrandedEngineInstalled,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mytegroupinc/myte-core",
3
- "version": "0.0.40",
3
+ "version": "0.0.41",
4
4
  "description": "Myte CLI core implementation.",
5
5
  "type": "commonjs",
6
6
  "main": "cli.js",