@mytegroupinc/myte-core 0.0.33 → 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.
- package/mytecody-cli.js +147 -33
- package/package.json +1 -1
package/mytecody-cli.js
CHANGED
|
@@ -179,6 +179,29 @@ function installedClientCommand() {
|
|
|
179
179
|
return { cmd: enginePath, args: [], source: "myte-installed-engine" };
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
function installedClientMatchesManifest(manifest, artifact) {
|
|
183
|
+
const current = readCurrentClientManifest();
|
|
184
|
+
if (!current || !installedClientCommand()) return false;
|
|
185
|
+
if (manifest && manifest.version && current.version !== manifest.version) return false;
|
|
186
|
+
|
|
187
|
+
const currentArtifact = current.artifact || {};
|
|
188
|
+
if (artifact && artifact.sha256) {
|
|
189
|
+
if (String(currentArtifact.sha256 || "").toLowerCase() !== String(artifact.sha256 || "").toLowerCase()) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const expectedInstalledSha =
|
|
195
|
+
artifact && (artifact.installed_sha256 || artifact.executable_sha256 || artifact.uncompressed_sha256);
|
|
196
|
+
if (expectedInstalledSha) {
|
|
197
|
+
if (String(currentArtifact.installed_sha256 || "").toLowerCase() !== String(expectedInstalledSha).toLowerCase()) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
182
205
|
function printHelp() {
|
|
183
206
|
console.log(`MYTE CODY - Your Tech Your Way
|
|
184
207
|
|
|
@@ -239,12 +262,31 @@ function isUrl(value) {
|
|
|
239
262
|
return /^https?:\/\//i.test(String(value || ""));
|
|
240
263
|
}
|
|
241
264
|
|
|
242
|
-
|
|
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 } = {}) {
|
|
243
284
|
if (!source) return { status: "missing", manifest: null };
|
|
244
285
|
if (isUrl(source)) {
|
|
245
286
|
if (!fetchManifest) {
|
|
246
287
|
return { status: "skipped", manifest: null };
|
|
247
288
|
}
|
|
289
|
+
if (progress) progress("checking signed release manifest");
|
|
248
290
|
const response = await fetch(source);
|
|
249
291
|
const text = await response.text();
|
|
250
292
|
if (!response.ok) {
|
|
@@ -344,20 +386,52 @@ function localPathFromArtifactUrl(urlValue) {
|
|
|
344
386
|
return null;
|
|
345
387
|
}
|
|
346
388
|
|
|
347
|
-
async function readArtifactBytes(artifact) {
|
|
389
|
+
async function readArtifactBytes(artifact, { progress } = {}) {
|
|
348
390
|
const urlValue = artifact && artifact.url ? String(artifact.url) : "";
|
|
349
391
|
const localPath = localPathFromArtifactUrl(urlValue);
|
|
350
392
|
if (localPath) {
|
|
393
|
+
if (progress) progress("reading local MyteCody engine artifact");
|
|
351
394
|
return fs.readFileSync(localPath);
|
|
352
395
|
}
|
|
353
396
|
const headers = {};
|
|
354
397
|
const token = getAuthToken();
|
|
355
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
|
+
}
|
|
356
403
|
const response = await fetch(urlValue, { method: "GET", headers });
|
|
357
|
-
const bytes = Buffer.from(await response.arrayBuffer());
|
|
358
404
|
if (!response.ok) {
|
|
405
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
359
406
|
throw new Error(`Artifact fetch failed (${response.status}): ${bytes.toString("utf8", 0, Math.min(bytes.length, 300))}`);
|
|
360
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)})`);
|
|
361
435
|
return bytes;
|
|
362
436
|
}
|
|
363
437
|
|
|
@@ -502,8 +576,16 @@ function tomlString(value) {
|
|
|
502
576
|
return JSON.stringify(String(value || ""));
|
|
503
577
|
}
|
|
504
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
|
+
|
|
505
587
|
function pathForToml(value) {
|
|
506
|
-
return String(value || "")
|
|
588
|
+
return String(value || "");
|
|
507
589
|
}
|
|
508
590
|
|
|
509
591
|
function writeCodexModelCatalog() {
|
|
@@ -574,7 +656,7 @@ function writeCodexConfig(args = {}) {
|
|
|
574
656
|
const catalogPath = writeCodexModelCatalog();
|
|
575
657
|
const config = `model = ${tomlString(DEFAULT_MODEL_ALIAS)}
|
|
576
658
|
model_provider = "myte_ai"
|
|
577
|
-
model_catalog_json = ${tomlString(
|
|
659
|
+
model_catalog_json = ${tomlString(catalogPath)}
|
|
578
660
|
model_context_window = ${DEFAULT_CONTEXT_WINDOW}
|
|
579
661
|
model_auto_compact_token_limit = ${DEFAULT_AUTO_COMPACT_TOKENS}
|
|
580
662
|
tool_output_token_limit = ${DEFAULT_TOOL_OUTPUT_TOKENS}
|
|
@@ -613,7 +695,7 @@ include_instructions = true
|
|
|
613
695
|
[skills.bundled]
|
|
614
696
|
enabled = false
|
|
615
697
|
|
|
616
|
-
[projects.${
|
|
698
|
+
[projects.${tomlLiteralString(process.cwd())}]
|
|
617
699
|
trust_level = "trusted"
|
|
618
700
|
|
|
619
701
|
[windows]
|
|
@@ -643,7 +725,7 @@ function codexProviderArgs(args = {}) {
|
|
|
643
725
|
"-c",
|
|
644
726
|
'model_providers.myte_ai.wire_api="responses"',
|
|
645
727
|
"-c",
|
|
646
|
-
`model_catalog_json
|
|
728
|
+
`model_catalog_json=${tomlString(codexModelCatalogPath())}`,
|
|
647
729
|
"-c",
|
|
648
730
|
`model_context_window=${DEFAULT_CONTEXT_WINDOW}`,
|
|
649
731
|
"-c",
|
|
@@ -680,30 +762,36 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
680
762
|
console.error("MyteCody requires MYTEAI_API_KEY for coding.");
|
|
681
763
|
return 1;
|
|
682
764
|
}
|
|
765
|
+
statusLine("preparing trusted workspace");
|
|
683
766
|
writeCodexConfig(args);
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
} catch (error) {
|
|
693
|
-
console.error(`MyteCody engine auto-install failed: ${error && error.message ? error.message : error}`);
|
|
694
|
-
}
|
|
695
|
-
command = resolveCodexCommand();
|
|
696
|
-
if (!command) {
|
|
697
|
-
console.error("MyteCody branded engine is not installed.");
|
|
767
|
+
try {
|
|
768
|
+
const install = await ensureBrandedEngineInstalled(args, envPath, { progress: statusLine });
|
|
769
|
+
if (install.ok && install.installed) {
|
|
770
|
+
statusLine(`engine installed: ${install.payload.installed.version}`);
|
|
771
|
+
} else if (install.ok) {
|
|
772
|
+
statusLine("engine ready");
|
|
773
|
+
} else if (!install.ok) {
|
|
774
|
+
console.error(`MyteCody branded engine could not be verified: ${install.reason || "unknown"}.`);
|
|
698
775
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
699
776
|
return 1;
|
|
700
777
|
}
|
|
778
|
+
} catch (error) {
|
|
779
|
+
console.error(`MyteCody engine verification failed: ${error && error.message ? error.message : error}`);
|
|
780
|
+
return 1;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
const command = resolveCodexCommand();
|
|
784
|
+
if (!command) {
|
|
785
|
+
console.error("MyteCody branded engine is not installed.");
|
|
786
|
+
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
787
|
+
return 1;
|
|
701
788
|
}
|
|
702
789
|
const launchArgs = [...command.args, ...codexLaunchArgs(rawArgs, args)];
|
|
703
790
|
const env = {
|
|
704
791
|
...process.env,
|
|
705
792
|
CODEX_HOME: codexHome(),
|
|
706
793
|
MYTE_CODY_AUTH_TOKEN: token,
|
|
794
|
+
MYTE_CODY_BRAND: "1",
|
|
707
795
|
};
|
|
708
796
|
return new Promise((resolve) => {
|
|
709
797
|
const child = spawn(command.cmd, launchArgs, {
|
|
@@ -753,10 +841,13 @@ async function runDoctor(args, envPath) {
|
|
|
753
841
|
return 0;
|
|
754
842
|
}
|
|
755
843
|
|
|
756
|
-
async function buildUpdatePayload(args, envPath, { dryRun = false } = {}) {
|
|
844
|
+
async function buildUpdatePayload(args, envPath, { dryRun = false, progress = null } = {}) {
|
|
757
845
|
const isDryRun = Boolean(dryRun);
|
|
758
846
|
const source = manifestUrl(args);
|
|
759
|
-
const manifestResult = await readManifest(source, {
|
|
847
|
+
const manifestResult = await readManifest(source, {
|
|
848
|
+
fetchManifest: Boolean(args["fetch-manifest"]) || !isDryRun,
|
|
849
|
+
progress,
|
|
850
|
+
});
|
|
760
851
|
const manifest = manifestResult.manifest;
|
|
761
852
|
const artifact = manifest ? artifactForPlatform(manifest) : null;
|
|
762
853
|
const signature = manifest ? signatureAccepted(manifest, args) : { ok: false, signature: { status: "not-checked", verified: false } };
|
|
@@ -786,7 +877,7 @@ async function buildUpdatePayload(args, envPath, { dryRun = false } = {}) {
|
|
|
786
877
|
if (!artifactMetadata.ok) {
|
|
787
878
|
throw new Error(`MyteCody release artifact metadata is ${artifactMetadata.status}.`);
|
|
788
879
|
}
|
|
789
|
-
const bytes = await readArtifactBytes(artifact);
|
|
880
|
+
const bytes = await readArtifactBytes(artifact, { progress });
|
|
790
881
|
const digest = sha256Hex(bytes);
|
|
791
882
|
if (digest.toLowerCase() !== String(artifact.sha256 || "").toLowerCase()) {
|
|
792
883
|
throw new Error(`Artifact SHA-256 mismatch: expected ${artifact.sha256}, got ${digest}`);
|
|
@@ -819,20 +910,38 @@ function autoInstallEnabled(args = {}) {
|
|
|
819
910
|
return true;
|
|
820
911
|
}
|
|
821
912
|
|
|
822
|
-
async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
|
|
823
|
-
if (installedClientCommand()) {
|
|
824
|
-
return { ok: true, installed: false, reason: "already-installed" };
|
|
825
|
-
}
|
|
826
|
-
if (!autoInstallEnabled(args)) {
|
|
827
|
-
return { ok: false, installed: false, reason: "auto-install-disabled" };
|
|
828
|
-
}
|
|
913
|
+
async function ensureBrandedEngineInstalled(args = {}, envPath = null, { progress = null } = {}) {
|
|
829
914
|
const updateArgs = {
|
|
830
915
|
...args,
|
|
831
916
|
"fetch-manifest": true,
|
|
832
917
|
};
|
|
833
918
|
delete updateArgs["dry-run"];
|
|
834
919
|
delete updateArgs.json;
|
|
835
|
-
|
|
920
|
+
|
|
921
|
+
const source = manifestUrl(updateArgs);
|
|
922
|
+
const manifestResult = await readManifest(source, { fetchManifest: true, progress });
|
|
923
|
+
const manifest = manifestResult.manifest;
|
|
924
|
+
if (!manifest) {
|
|
925
|
+
return { ok: false, installed: false, reason: "manifest-unavailable", manifest_status: manifestResult.status };
|
|
926
|
+
}
|
|
927
|
+
const signature = signatureAccepted(manifest, updateArgs);
|
|
928
|
+
if (!signature.ok) {
|
|
929
|
+
return { ok: false, installed: false, reason: "manifest-untrusted", signature: signature.signature };
|
|
930
|
+
}
|
|
931
|
+
const artifact = artifactForPlatform(manifest);
|
|
932
|
+
const artifactMetadata = validateArtifactMetadata(artifact);
|
|
933
|
+
if (!artifactMetadata.ok) {
|
|
934
|
+
return { ok: false, installed: false, reason: "artifact-metadata-invalid", artifact: artifactMetadata };
|
|
935
|
+
}
|
|
936
|
+
if (installedClientMatchesManifest(manifest, artifact)) {
|
|
937
|
+
return { ok: true, installed: false, reason: "already-current" };
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
if (!autoInstallEnabled(args)) {
|
|
941
|
+
return { ok: false, installed: false, reason: "update-required-auto-install-disabled" };
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
const payload = await buildUpdatePayload(updateArgs, envPath, { dryRun: false, progress });
|
|
836
945
|
return {
|
|
837
946
|
ok: Boolean(payload.installed && payload.installed.ok),
|
|
838
947
|
installed: Boolean(payload.installed && payload.installed.ok),
|
|
@@ -843,7 +952,10 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
|
|
|
843
952
|
|
|
844
953
|
async function runUpdate(args, envPath) {
|
|
845
954
|
const dryRun = Boolean(args["dry-run"]);
|
|
846
|
-
const payload = await buildUpdatePayload(args, envPath, {
|
|
955
|
+
const payload = await buildUpdatePayload(args, envPath, {
|
|
956
|
+
dryRun,
|
|
957
|
+
progress: args.json ? null : statusLine,
|
|
958
|
+
});
|
|
847
959
|
|
|
848
960
|
if (args.json) {
|
|
849
961
|
printJson(payload);
|
|
@@ -907,6 +1019,7 @@ module.exports = {
|
|
|
907
1019
|
codexProviderArgs,
|
|
908
1020
|
codyInferenceBase,
|
|
909
1021
|
codyGatewayUrl,
|
|
1022
|
+
currentClientManifestPath,
|
|
910
1023
|
currentEnginePath,
|
|
911
1024
|
ensureBrandedEngineInstalled,
|
|
912
1025
|
gatewayRoot,
|
|
@@ -915,6 +1028,7 @@ module.exports = {
|
|
|
915
1028
|
run,
|
|
916
1029
|
sha256Hex,
|
|
917
1030
|
stableJson,
|
|
1031
|
+
tomlLiteralString,
|
|
918
1032
|
verifyManifestSignature,
|
|
919
1033
|
writeCodexConfig,
|
|
920
1034
|
};
|