@mytegroupinc/myte-core 0.0.34 → 0.0.35

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 +86 -16
  2. package/package.json +1 -1
package/mytecody-cli.js CHANGED
@@ -262,12 +262,31 @@ function isUrl(value) {
262
262
  return /^https?:\/\//i.test(String(value || ""));
263
263
  }
264
264
 
265
- async function readManifest(source, { fetchManifest }) {
265
+ function statusLine(message) {
266
+ if (process.env.MYTE_CODY_QUIET_SETUP === "1") return;
267
+ console.error(`[MYTE CODY] ${message}`);
268
+ }
269
+
270
+ function formatBytes(bytes) {
271
+ const value = Number(bytes || 0);
272
+ if (!Number.isFinite(value) || value <= 0) return "unknown size";
273
+ const units = ["B", "KB", "MB", "GB"];
274
+ let size = value;
275
+ let unit = 0;
276
+ while (size >= 1024 && unit < units.length - 1) {
277
+ size /= 1024;
278
+ unit += 1;
279
+ }
280
+ return `${size.toFixed(unit === 0 ? 0 : 1)} ${units[unit]}`;
281
+ }
282
+
283
+ async function readManifest(source, { fetchManifest, progress } = {}) {
266
284
  if (!source) return { status: "missing", manifest: null };
267
285
  if (isUrl(source)) {
268
286
  if (!fetchManifest) {
269
287
  return { status: "skipped", manifest: null };
270
288
  }
289
+ if (progress) progress("checking signed release manifest");
271
290
  const response = await fetch(source);
272
291
  const text = await response.text();
273
292
  if (!response.ok) {
@@ -367,20 +386,52 @@ function localPathFromArtifactUrl(urlValue) {
367
386
  return null;
368
387
  }
369
388
 
370
- async function readArtifactBytes(artifact) {
389
+ async function readArtifactBytes(artifact, { progress } = {}) {
371
390
  const urlValue = artifact && artifact.url ? String(artifact.url) : "";
372
391
  const localPath = localPathFromArtifactUrl(urlValue);
373
392
  if (localPath) {
393
+ if (progress) progress("reading local MyteCody engine artifact");
374
394
  return fs.readFileSync(localPath);
375
395
  }
376
396
  const headers = {};
377
397
  const token = getAuthToken();
378
398
  if (token) headers.Authorization = `Bearer ${token}`;
399
+ if (progress) {
400
+ const expectedSize = Number(artifact && artifact.size_bytes ? artifact.size_bytes : 0);
401
+ progress(`downloading MyteCody engine (${formatBytes(expectedSize)})`);
402
+ }
379
403
  const response = await fetch(urlValue, { method: "GET", headers });
380
- const bytes = Buffer.from(await response.arrayBuffer());
381
404
  if (!response.ok) {
405
+ const bytes = Buffer.from(await response.arrayBuffer());
382
406
  throw new Error(`Artifact fetch failed (${response.status}): ${bytes.toString("utf8", 0, Math.min(bytes.length, 300))}`);
383
407
  }
408
+ if (!response.body || typeof response.body.getReader !== "function") {
409
+ const bytes = Buffer.from(await response.arrayBuffer());
410
+ if (progress) progress(`downloaded MyteCody engine (${formatBytes(bytes.length)})`);
411
+ return bytes;
412
+ }
413
+
414
+ const total = Number(response.headers.get("content-length") || artifact?.size_bytes || 0);
415
+ const reader = response.body.getReader();
416
+ const chunks = [];
417
+ let received = 0;
418
+ let lastPct = -1;
419
+ while (true) {
420
+ const { done, value } = await reader.read();
421
+ if (done) break;
422
+ const chunk = Buffer.from(value);
423
+ chunks.push(chunk);
424
+ received += chunk.length;
425
+ if (progress && total > 0) {
426
+ const pct = Math.min(100, Math.floor((received / total) * 100));
427
+ if (pct >= lastPct + 10 || pct === 100) {
428
+ progress(`downloading MyteCody engine ${pct}% (${formatBytes(received)} / ${formatBytes(total)})`);
429
+ lastPct = pct;
430
+ }
431
+ }
432
+ }
433
+ const bytes = Buffer.concat(chunks);
434
+ if (progress) progress(`downloaded MyteCody engine (${formatBytes(bytes.length)})`);
384
435
  return bytes;
385
436
  }
386
437
 
@@ -525,8 +576,16 @@ function tomlString(value) {
525
576
  return JSON.stringify(String(value || ""));
526
577
  }
527
578
 
579
+ function tomlLiteralString(value) {
580
+ const text = String(value || "");
581
+ if (!text.includes("'") && !text.includes("\n") && !text.includes("\r")) {
582
+ return `'${text}'`;
583
+ }
584
+ return tomlString(text);
585
+ }
586
+
528
587
  function pathForToml(value) {
529
- return String(value || "").replace(/\\/g, "\\\\");
588
+ return String(value || "");
530
589
  }
531
590
 
532
591
  function writeCodexModelCatalog() {
@@ -597,7 +656,7 @@ function writeCodexConfig(args = {}) {
597
656
  const catalogPath = writeCodexModelCatalog();
598
657
  const config = `model = ${tomlString(DEFAULT_MODEL_ALIAS)}
599
658
  model_provider = "myte_ai"
600
- model_catalog_json = ${tomlString(pathForToml(catalogPath))}
659
+ model_catalog_json = ${tomlString(catalogPath)}
601
660
  model_context_window = ${DEFAULT_CONTEXT_WINDOW}
602
661
  model_auto_compact_token_limit = ${DEFAULT_AUTO_COMPACT_TOKENS}
603
662
  tool_output_token_limit = ${DEFAULT_TOOL_OUTPUT_TOKENS}
@@ -636,7 +695,7 @@ include_instructions = true
636
695
  [skills.bundled]
637
696
  enabled = false
638
697
 
639
- [projects.${tomlString(pathForToml(process.cwd()))}]
698
+ [projects.${tomlLiteralString(process.cwd())}]
640
699
  trust_level = "trusted"
641
700
 
642
701
  [windows]
@@ -666,7 +725,7 @@ function codexProviderArgs(args = {}) {
666
725
  "-c",
667
726
  'model_providers.myte_ai.wire_api="responses"',
668
727
  "-c",
669
- `model_catalog_json="${pathForToml(codexModelCatalogPath())}"`,
728
+ `model_catalog_json=${tomlString(codexModelCatalogPath())}`,
670
729
  "-c",
671
730
  `model_context_window=${DEFAULT_CONTEXT_WINDOW}`,
672
731
  "-c",
@@ -703,11 +762,14 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
703
762
  console.error("MyteCody requires MYTEAI_API_KEY for coding.");
704
763
  return 1;
705
764
  }
765
+ statusLine("preparing trusted workspace");
706
766
  writeCodexConfig(args);
707
767
  try {
708
- const install = await ensureBrandedEngineInstalled(args, envPath);
768
+ const install = await ensureBrandedEngineInstalled(args, envPath, { progress: statusLine });
709
769
  if (install.ok && install.installed) {
710
- console.error(`MyteCody engine installed: ${install.payload.installed.version}`);
770
+ statusLine(`engine installed: ${install.payload.installed.version}`);
771
+ } else if (install.ok) {
772
+ statusLine("engine ready");
711
773
  } else if (!install.ok) {
712
774
  console.error(`MyteCody branded engine could not be verified: ${install.reason || "unknown"}.`);
713
775
  console.error("Run `mytecody update` with access to the Myte release manifest.");
@@ -729,6 +791,7 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
729
791
  ...process.env,
730
792
  CODEX_HOME: codexHome(),
731
793
  MYTE_CODY_AUTH_TOKEN: token,
794
+ MYTE_CODY_BRAND: "1",
732
795
  };
733
796
  return new Promise((resolve) => {
734
797
  const child = spawn(command.cmd, launchArgs, {
@@ -778,10 +841,13 @@ async function runDoctor(args, envPath) {
778
841
  return 0;
779
842
  }
780
843
 
781
- async function buildUpdatePayload(args, envPath, { dryRun = false } = {}) {
844
+ async function buildUpdatePayload(args, envPath, { dryRun = false, progress = null } = {}) {
782
845
  const isDryRun = Boolean(dryRun);
783
846
  const source = manifestUrl(args);
784
- const manifestResult = await readManifest(source, { fetchManifest: Boolean(args["fetch-manifest"]) || !isDryRun });
847
+ const manifestResult = await readManifest(source, {
848
+ fetchManifest: Boolean(args["fetch-manifest"]) || !isDryRun,
849
+ progress,
850
+ });
785
851
  const manifest = manifestResult.manifest;
786
852
  const artifact = manifest ? artifactForPlatform(manifest) : null;
787
853
  const signature = manifest ? signatureAccepted(manifest, args) : { ok: false, signature: { status: "not-checked", verified: false } };
@@ -811,7 +877,7 @@ async function buildUpdatePayload(args, envPath, { dryRun = false } = {}) {
811
877
  if (!artifactMetadata.ok) {
812
878
  throw new Error(`MyteCody release artifact metadata is ${artifactMetadata.status}.`);
813
879
  }
814
- const bytes = await readArtifactBytes(artifact);
880
+ const bytes = await readArtifactBytes(artifact, { progress });
815
881
  const digest = sha256Hex(bytes);
816
882
  if (digest.toLowerCase() !== String(artifact.sha256 || "").toLowerCase()) {
817
883
  throw new Error(`Artifact SHA-256 mismatch: expected ${artifact.sha256}, got ${digest}`);
@@ -844,7 +910,7 @@ function autoInstallEnabled(args = {}) {
844
910
  return true;
845
911
  }
846
912
 
847
- async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
913
+ async function ensureBrandedEngineInstalled(args = {}, envPath = null, { progress = null } = {}) {
848
914
  const updateArgs = {
849
915
  ...args,
850
916
  "fetch-manifest": true,
@@ -853,7 +919,7 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
853
919
  delete updateArgs.json;
854
920
 
855
921
  const source = manifestUrl(updateArgs);
856
- const manifestResult = await readManifest(source, { fetchManifest: true });
922
+ const manifestResult = await readManifest(source, { fetchManifest: true, progress });
857
923
  const manifest = manifestResult.manifest;
858
924
  if (!manifest) {
859
925
  return { ok: false, installed: false, reason: "manifest-unavailable", manifest_status: manifestResult.status };
@@ -875,7 +941,7 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
875
941
  return { ok: false, installed: false, reason: "update-required-auto-install-disabled" };
876
942
  }
877
943
 
878
- const payload = await buildUpdatePayload(updateArgs, envPath, { dryRun: false });
944
+ const payload = await buildUpdatePayload(updateArgs, envPath, { dryRun: false, progress });
879
945
  return {
880
946
  ok: Boolean(payload.installed && payload.installed.ok),
881
947
  installed: Boolean(payload.installed && payload.installed.ok),
@@ -886,7 +952,10 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
886
952
 
887
953
  async function runUpdate(args, envPath) {
888
954
  const dryRun = Boolean(args["dry-run"]);
889
- const payload = await buildUpdatePayload(args, envPath, { dryRun });
955
+ const payload = await buildUpdatePayload(args, envPath, {
956
+ dryRun,
957
+ progress: args.json ? null : statusLine,
958
+ });
890
959
 
891
960
  if (args.json) {
892
961
  printJson(payload);
@@ -959,6 +1028,7 @@ module.exports = {
959
1028
  run,
960
1029
  sha256Hex,
961
1030
  stableJson,
1031
+ tomlLiteralString,
962
1032
  verifyManifestSignature,
963
1033
  writeCodexConfig,
964
1034
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mytegroupinc/myte-core",
3
- "version": "0.0.34",
3
+ "version": "0.0.35",
4
4
  "description": "Myte CLI core implementation.",
5
5
  "type": "commonjs",
6
6
  "main": "cli.js",