@mytegroupinc/myte-core 0.0.34 → 0.0.36
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/lib/mytecody-splash.js +251 -0
- package/mytecody-cli.js +105 -16
- package/package.json +1 -1
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const FRAME_MS = 48;
|
|
4
|
+
const MIN_MS = 850;
|
|
5
|
+
const FRAMES = 32;
|
|
6
|
+
const WIDTH = 84;
|
|
7
|
+
const HEIGHT = 64;
|
|
8
|
+
const RX = 32.5;
|
|
9
|
+
const RY = 27.5;
|
|
10
|
+
const CYAN = [93, 226, 255];
|
|
11
|
+
const BLUE = [45, 150, 255];
|
|
12
|
+
const DIM = [45, 72, 102];
|
|
13
|
+
const WHITE = [229, 244, 255];
|
|
14
|
+
const SOFT = [92, 132, 172];
|
|
15
|
+
|
|
16
|
+
const NODES = [
|
|
17
|
+
[-68, 0], [-55, -110], [-55, -35], [-55, 35], [-55, 110],
|
|
18
|
+
[-35, -150], [-35, -90], [-35, -30], [-35, 30], [-35, 90], [-35, 150],
|
|
19
|
+
[-15, -165], [-15, -110], [-15, -55], [-15, 0], [-15, 55], [-15, 110], [-15, 165],
|
|
20
|
+
[15, -165], [15, -110], [15, -55], [15, 0], [15, 55], [15, 110], [15, 165],
|
|
21
|
+
[35, -150], [35, -90], [35, -30], [35, 30], [35, 90], [35, 150],
|
|
22
|
+
[55, -110], [55, -35], [55, 35], [55, 110], [68, 0],
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const LINKS = [
|
|
26
|
+
[0, 1], [0, 2], [0, 3], [0, 4], [1, 5], [2, 6], [2, 7], [3, 8], [3, 9], [4, 10],
|
|
27
|
+
[5, 11], [6, 12], [7, 13], [8, 15], [9, 16], [10, 17], [11, 18], [12, 19],
|
|
28
|
+
[13, 20], [14, 21], [15, 22], [16, 23], [17, 24], [18, 25], [19, 26], [20, 27],
|
|
29
|
+
[21, 28], [22, 29], [23, 30], [24, 30], [25, 31], [26, 31], [27, 32], [28, 33],
|
|
30
|
+
[29, 34], [30, 35], [31, 35], [32, 35], [33, 35], [34, 35],
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const BRAILLE = [[0x01, 0x08], [0x02, 0x10], [0x04, 0x20], [0x40, 0x80]];
|
|
34
|
+
|
|
35
|
+
function envTruthy(name, fallback = false) {
|
|
36
|
+
const value = process.env[name];
|
|
37
|
+
if (value == null || value === "") return fallback;
|
|
38
|
+
return !["0", "false", "no", "off"].includes(String(value).toLowerCase());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function ansi(rgb, text, opts = {}) {
|
|
42
|
+
if (process.env.NO_COLOR || process.env.MYTE_CODY_SPLASH_ASCII === "1") return text;
|
|
43
|
+
const flags = [opts.bold ? "1" : null, opts.dim ? "2" : null, `38;2;${rgb[0]};${rgb[1]};${rgb[2]}`]
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.join(";");
|
|
46
|
+
return `\x1b[${flags}m${text}\x1b[0m`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function mix(a, b, t) {
|
|
50
|
+
return a.map((v, i) => Math.round(v + (b[i] - v) * t));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function grid() {
|
|
54
|
+
return Array.from({ length: HEIGHT }, () =>
|
|
55
|
+
Array.from({ length: WIDTH }, () => ({ v: 0, n: false })),
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function put(g, x, y, value, node = false) {
|
|
60
|
+
const px = Math.round(x);
|
|
61
|
+
const py = Math.round(y);
|
|
62
|
+
if (py < 0 || py >= HEIGHT || px < 0 || px >= WIDTH) return;
|
|
63
|
+
if (value > g[py][px].v) g[py][px] = { v: value, n: g[py][px].n || node };
|
|
64
|
+
else if (node) g[py][px].n = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function dot(g, x, y, value, radius = 0.85, node = false) {
|
|
68
|
+
const r = Math.ceil(radius);
|
|
69
|
+
for (let dy = -r; dy <= r; dy += 1) {
|
|
70
|
+
for (let dx = -r; dx <= r; dx += 1) {
|
|
71
|
+
const d = Math.sqrt(dx * dx + dy * dy);
|
|
72
|
+
if (d <= radius) put(g, x + dx, y + dy, value * (1 - d / (radius + 0.8)), node);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function project(latDeg, lonDeg, phase) {
|
|
78
|
+
const lat = (latDeg * Math.PI) / 180;
|
|
79
|
+
const lon = (lonDeg * Math.PI) / 180;
|
|
80
|
+
const cosLat = Math.cos(lat);
|
|
81
|
+
const x = cosLat * Math.sin(lon);
|
|
82
|
+
const y = Math.sin(lat);
|
|
83
|
+
const z = cosLat * Math.cos(lon);
|
|
84
|
+
const rp = { x: x * Math.cos(phase) + z * Math.sin(phase), z: -x * Math.sin(phase) + z * Math.cos(phase) };
|
|
85
|
+
return { x: WIDTH / 2 - 0.5 + rp.x * RX, y: HEIGHT / 2 - 0.5 - y * RY, z: rp.z };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function drawCurve(g, points, base = 0.08, radius = 0.75) {
|
|
89
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
90
|
+
const a = points[i - 1];
|
|
91
|
+
const b = points[i];
|
|
92
|
+
const steps = Math.max(2, Math.ceil(Math.hypot(b.x - a.x, b.y - a.y) * 1.7));
|
|
93
|
+
for (let s = 0; s <= steps; s += 1) {
|
|
94
|
+
const t = s / steps;
|
|
95
|
+
const z = a.z + (b.z - a.z) * t;
|
|
96
|
+
const front = Math.max(0, (z + 1) / 2);
|
|
97
|
+
const fade = Math.max(0, (z + 0.38) / 1.38);
|
|
98
|
+
dot(g, a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, base * fade + front * 0.21, radius);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function lonBetween(a, b, t) {
|
|
104
|
+
let delta = b - a;
|
|
105
|
+
if (delta > 180) delta -= 360;
|
|
106
|
+
if (delta < -180) delta += 360;
|
|
107
|
+
let value = a + delta * t;
|
|
108
|
+
if (value > 180) value -= 360;
|
|
109
|
+
if (value < -180) value += 360;
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function drawFrame(index) {
|
|
114
|
+
const phase = (index / FRAMES) * Math.PI * 2;
|
|
115
|
+
const g = grid();
|
|
116
|
+
const cx = WIDTH / 2 - 0.5;
|
|
117
|
+
const cy = HEIGHT / 2 - 0.5;
|
|
118
|
+
|
|
119
|
+
for (let deg = 0; deg < 360; deg += 1) {
|
|
120
|
+
const a = (deg * Math.PI) / 180;
|
|
121
|
+
const pulse = 0.22 + 0.18 * Math.max(0, 1 - Math.abs((((a - phase + Math.PI) % (Math.PI * 2)) - Math.PI)) / 1.1);
|
|
122
|
+
dot(g, cx + Math.cos(a) * RX, cy + Math.sin(a) * RY, pulse + 0.27, 1.0);
|
|
123
|
+
}
|
|
124
|
+
for (const lat of [-60, -42, -24, -8, 8, 24, 42, 60]) {
|
|
125
|
+
const pts = [];
|
|
126
|
+
for (let lon = -180; lon <= 180; lon += 3) pts.push(project(lat, lon, phase));
|
|
127
|
+
drawCurve(g, pts, 0.07, 0.55);
|
|
128
|
+
}
|
|
129
|
+
for (const lon of [-150, -105, -60, -20, 20, 60, 105, 150]) {
|
|
130
|
+
const pts = [];
|
|
131
|
+
for (let lat = -76; lat <= 76; lat += 3) pts.push(project(lat, lon, phase));
|
|
132
|
+
drawCurve(g, pts, 0.055, 0.48);
|
|
133
|
+
}
|
|
134
|
+
for (const [a, b] of LINKS) {
|
|
135
|
+
const start = NODES[a];
|
|
136
|
+
const end = NODES[b];
|
|
137
|
+
const pts = [];
|
|
138
|
+
for (let s = 0; s <= 14; s += 1) {
|
|
139
|
+
const t = s / 14;
|
|
140
|
+
pts.push(project(start[0] + (end[0] - start[0]) * t, lonBetween(start[1], end[1], t), phase));
|
|
141
|
+
}
|
|
142
|
+
drawCurve(g, pts, 0.035, 0.45);
|
|
143
|
+
}
|
|
144
|
+
NODES.forEach(([lat, lon], i) => {
|
|
145
|
+
const p = project(lat, lon, phase);
|
|
146
|
+
const front = Math.max(0, (p.z + 1) / 2);
|
|
147
|
+
const pulse = 0.5 + 0.5 * Math.sin(phase * 2.2 + i * 0.75);
|
|
148
|
+
dot(g, p.x, p.y, 0.28 + front * 0.42 + pulse * 0.24, (front > 0.48 ? 1.55 : 0.9) + pulse * 0.45, true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const rows = Math.floor(HEIGHT / 4);
|
|
152
|
+
const cols = Math.floor(WIDTH / 2);
|
|
153
|
+
const lines = [];
|
|
154
|
+
for (let y = 0; y < rows; y += 1) {
|
|
155
|
+
let line = "";
|
|
156
|
+
for (let x = 0; x < cols; x += 1) {
|
|
157
|
+
let mask = 0;
|
|
158
|
+
let value = 0;
|
|
159
|
+
let node = false;
|
|
160
|
+
for (let dy = 0; dy < 4; dy += 1) {
|
|
161
|
+
for (let dx = 0; dx < 2; dx += 1) {
|
|
162
|
+
const px = g[y * 4 + dy][x * 2 + dx];
|
|
163
|
+
if (px.v <= 0.11) continue;
|
|
164
|
+
mask |= BRAILLE[dy][dx];
|
|
165
|
+
value = Math.max(value, px.v);
|
|
166
|
+
node = node || px.n;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (!mask) line += " ";
|
|
170
|
+
else line += ansi(node ? mix(CYAN, WHITE, Math.min(0.35, value * 0.28)) : mix(DIM, BLUE, Math.min(0.8, value)), String.fromCharCode(0x2800 + mask), { bold: node && value > 0.62, dim: value < 0.25 });
|
|
171
|
+
}
|
|
172
|
+
lines.push(line.replace(/\s+$/u, ""));
|
|
173
|
+
}
|
|
174
|
+
return lines;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function shouldShowSplash() {
|
|
178
|
+
if (!envTruthy("MYTE_CODY_SPLASH", true)) return false;
|
|
179
|
+
if (process.env.CI && process.env.MYTE_CODY_SPLASH_FORCE !== "1") return false;
|
|
180
|
+
return Boolean(process.stdout.isTTY || process.env.MYTE_CODY_SPLASH_FORCE === "1");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildLines(frame, status) {
|
|
184
|
+
return [
|
|
185
|
+
"",
|
|
186
|
+
...drawFrame(frame),
|
|
187
|
+
"",
|
|
188
|
+
` ${ansi(WHITE, "MYTE CODY", { bold: true })}${ansi(SOFT, " - Your Tech Your Way")}`,
|
|
189
|
+
` ${ansi(BLUE, "sovereign coding gateway", { bold: true })}`,
|
|
190
|
+
` ${ansi(CYAN, "◆", { bold: true })} ${ansi(SOFT, status || "opening workspace")}`,
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function createMyteSplash() {
|
|
195
|
+
const enabled = shouldShowSplash();
|
|
196
|
+
let frame = 0;
|
|
197
|
+
let lineCount = 0;
|
|
198
|
+
let rendered = false;
|
|
199
|
+
let timer = null;
|
|
200
|
+
let started = 0;
|
|
201
|
+
let status = "opening workspace";
|
|
202
|
+
|
|
203
|
+
function render() {
|
|
204
|
+
if (!enabled) return;
|
|
205
|
+
const lines = buildLines(frame, status);
|
|
206
|
+
if (rendered) process.stdout.write(`\x1b[${lineCount}F\x1b[J`);
|
|
207
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
208
|
+
lineCount = lines.length;
|
|
209
|
+
rendered = true;
|
|
210
|
+
frame = (frame + 1) % FRAMES;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function start(initialStatus) {
|
|
214
|
+
if (!enabled || timer) return;
|
|
215
|
+
status = initialStatus || status;
|
|
216
|
+
started = Date.now();
|
|
217
|
+
process.stdout.write("\x1b[?25l");
|
|
218
|
+
render();
|
|
219
|
+
timer = setInterval(render, FRAME_MS);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function setStatus(nextStatus) {
|
|
223
|
+
if (nextStatus) status = String(nextStatus);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function stop() {
|
|
227
|
+
if (!enabled) return;
|
|
228
|
+
if (timer) {
|
|
229
|
+
clearInterval(timer);
|
|
230
|
+
timer = null;
|
|
231
|
+
}
|
|
232
|
+
const remaining = Math.max(0, MIN_MS - (Date.now() - started));
|
|
233
|
+
if (remaining) await new Promise((resolve) => setTimeout(resolve, remaining));
|
|
234
|
+
if (rendered) process.stdout.write(`\x1b[${lineCount}F\x1b[J`);
|
|
235
|
+
process.stdout.write("\x1b[?25h");
|
|
236
|
+
rendered = false;
|
|
237
|
+
lineCount = 0;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return { enabled, start, setStatus, stop };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function previewPlain() {
|
|
244
|
+
const strip = (text) => text.replace(/\x1b\[[0-9;]*m/g, "");
|
|
245
|
+
return [0, 8, 16, 24].map((frame) => buildLines(frame, "checking signed release manifest").map(strip).join("\n")).join("\n\n");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
module.exports = {
|
|
249
|
+
createMyteSplash,
|
|
250
|
+
previewPlain,
|
|
251
|
+
};
|
package/mytecody-cli.js
CHANGED
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
DEFAULT_MYTEAI_BASE,
|
|
12
12
|
normalizeMyteAiBase,
|
|
13
13
|
} = require("./lib/ai-gateway");
|
|
14
|
+
const { createMyteSplash } = require("./lib/mytecody-splash");
|
|
14
15
|
|
|
15
16
|
const PACKAGE_VERSION = require("./package.json").version;
|
|
16
17
|
const DEFAULT_CHANNEL = "alpha";
|
|
@@ -262,12 +263,41 @@ function isUrl(value) {
|
|
|
262
263
|
return /^https?:\/\//i.test(String(value || ""));
|
|
263
264
|
}
|
|
264
265
|
|
|
265
|
-
|
|
266
|
+
function statusLine(message) {
|
|
267
|
+
if (process.env.MYTE_CODY_QUIET_SETUP === "1") return;
|
|
268
|
+
console.error(`[MYTE CODY] ${message}`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function setupProgress(splash) {
|
|
272
|
+
return (message) => {
|
|
273
|
+
if (splash && splash.enabled) {
|
|
274
|
+
splash.setStatus(message);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
statusLine(message);
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function formatBytes(bytes) {
|
|
282
|
+
const value = Number(bytes || 0);
|
|
283
|
+
if (!Number.isFinite(value) || value <= 0) return "unknown size";
|
|
284
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
285
|
+
let size = value;
|
|
286
|
+
let unit = 0;
|
|
287
|
+
while (size >= 1024 && unit < units.length - 1) {
|
|
288
|
+
size /= 1024;
|
|
289
|
+
unit += 1;
|
|
290
|
+
}
|
|
291
|
+
return `${size.toFixed(unit === 0 ? 0 : 1)} ${units[unit]}`;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function readManifest(source, { fetchManifest, progress } = {}) {
|
|
266
295
|
if (!source) return { status: "missing", manifest: null };
|
|
267
296
|
if (isUrl(source)) {
|
|
268
297
|
if (!fetchManifest) {
|
|
269
298
|
return { status: "skipped", manifest: null };
|
|
270
299
|
}
|
|
300
|
+
if (progress) progress("checking signed release manifest");
|
|
271
301
|
const response = await fetch(source);
|
|
272
302
|
const text = await response.text();
|
|
273
303
|
if (!response.ok) {
|
|
@@ -367,20 +397,52 @@ function localPathFromArtifactUrl(urlValue) {
|
|
|
367
397
|
return null;
|
|
368
398
|
}
|
|
369
399
|
|
|
370
|
-
async function readArtifactBytes(artifact) {
|
|
400
|
+
async function readArtifactBytes(artifact, { progress } = {}) {
|
|
371
401
|
const urlValue = artifact && artifact.url ? String(artifact.url) : "";
|
|
372
402
|
const localPath = localPathFromArtifactUrl(urlValue);
|
|
373
403
|
if (localPath) {
|
|
404
|
+
if (progress) progress("reading local MyteCody engine artifact");
|
|
374
405
|
return fs.readFileSync(localPath);
|
|
375
406
|
}
|
|
376
407
|
const headers = {};
|
|
377
408
|
const token = getAuthToken();
|
|
378
409
|
if (token) headers.Authorization = `Bearer ${token}`;
|
|
410
|
+
if (progress) {
|
|
411
|
+
const expectedSize = Number(artifact && artifact.size_bytes ? artifact.size_bytes : 0);
|
|
412
|
+
progress(`downloading MyteCody engine (${formatBytes(expectedSize)})`);
|
|
413
|
+
}
|
|
379
414
|
const response = await fetch(urlValue, { method: "GET", headers });
|
|
380
|
-
const bytes = Buffer.from(await response.arrayBuffer());
|
|
381
415
|
if (!response.ok) {
|
|
416
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
382
417
|
throw new Error(`Artifact fetch failed (${response.status}): ${bytes.toString("utf8", 0, Math.min(bytes.length, 300))}`);
|
|
383
418
|
}
|
|
419
|
+
if (!response.body || typeof response.body.getReader !== "function") {
|
|
420
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
421
|
+
if (progress) progress(`downloaded MyteCody engine (${formatBytes(bytes.length)})`);
|
|
422
|
+
return bytes;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const total = Number(response.headers.get("content-length") || artifact?.size_bytes || 0);
|
|
426
|
+
const reader = response.body.getReader();
|
|
427
|
+
const chunks = [];
|
|
428
|
+
let received = 0;
|
|
429
|
+
let lastPct = -1;
|
|
430
|
+
while (true) {
|
|
431
|
+
const { done, value } = await reader.read();
|
|
432
|
+
if (done) break;
|
|
433
|
+
const chunk = Buffer.from(value);
|
|
434
|
+
chunks.push(chunk);
|
|
435
|
+
received += chunk.length;
|
|
436
|
+
if (progress && total > 0) {
|
|
437
|
+
const pct = Math.min(100, Math.floor((received / total) * 100));
|
|
438
|
+
if (pct >= lastPct + 10 || pct === 100) {
|
|
439
|
+
progress(`downloading MyteCody engine ${pct}% (${formatBytes(received)} / ${formatBytes(total)})`);
|
|
440
|
+
lastPct = pct;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const bytes = Buffer.concat(chunks);
|
|
445
|
+
if (progress) progress(`downloaded MyteCody engine (${formatBytes(bytes.length)})`);
|
|
384
446
|
return bytes;
|
|
385
447
|
}
|
|
386
448
|
|
|
@@ -525,8 +587,16 @@ function tomlString(value) {
|
|
|
525
587
|
return JSON.stringify(String(value || ""));
|
|
526
588
|
}
|
|
527
589
|
|
|
590
|
+
function tomlLiteralString(value) {
|
|
591
|
+
const text = String(value || "");
|
|
592
|
+
if (!text.includes("'") && !text.includes("\n") && !text.includes("\r")) {
|
|
593
|
+
return `'${text}'`;
|
|
594
|
+
}
|
|
595
|
+
return tomlString(text);
|
|
596
|
+
}
|
|
597
|
+
|
|
528
598
|
function pathForToml(value) {
|
|
529
|
-
return String(value || "")
|
|
599
|
+
return String(value || "");
|
|
530
600
|
}
|
|
531
601
|
|
|
532
602
|
function writeCodexModelCatalog() {
|
|
@@ -597,7 +667,7 @@ function writeCodexConfig(args = {}) {
|
|
|
597
667
|
const catalogPath = writeCodexModelCatalog();
|
|
598
668
|
const config = `model = ${tomlString(DEFAULT_MODEL_ALIAS)}
|
|
599
669
|
model_provider = "myte_ai"
|
|
600
|
-
model_catalog_json = ${tomlString(
|
|
670
|
+
model_catalog_json = ${tomlString(catalogPath)}
|
|
601
671
|
model_context_window = ${DEFAULT_CONTEXT_WINDOW}
|
|
602
672
|
model_auto_compact_token_limit = ${DEFAULT_AUTO_COMPACT_TOKENS}
|
|
603
673
|
tool_output_token_limit = ${DEFAULT_TOOL_OUTPUT_TOKENS}
|
|
@@ -636,7 +706,7 @@ include_instructions = true
|
|
|
636
706
|
[skills.bundled]
|
|
637
707
|
enabled = false
|
|
638
708
|
|
|
639
|
-
[projects.${
|
|
709
|
+
[projects.${tomlLiteralString(process.cwd())}]
|
|
640
710
|
trust_level = "trusted"
|
|
641
711
|
|
|
642
712
|
[windows]
|
|
@@ -666,7 +736,7 @@ function codexProviderArgs(args = {}) {
|
|
|
666
736
|
"-c",
|
|
667
737
|
'model_providers.myte_ai.wire_api="responses"',
|
|
668
738
|
"-c",
|
|
669
|
-
`model_catalog_json
|
|
739
|
+
`model_catalog_json=${tomlString(codexModelCatalogPath())}`,
|
|
670
740
|
"-c",
|
|
671
741
|
`model_context_window=${DEFAULT_CONTEXT_WINDOW}`,
|
|
672
742
|
"-c",
|
|
@@ -703,23 +773,32 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
703
773
|
console.error("MyteCody requires MYTEAI_API_KEY for coding.");
|
|
704
774
|
return 1;
|
|
705
775
|
}
|
|
776
|
+
const splash = createMyteSplash();
|
|
777
|
+
const progress = setupProgress(splash);
|
|
778
|
+
splash.start("preparing trusted workspace");
|
|
779
|
+
progress("preparing trusted workspace");
|
|
706
780
|
writeCodexConfig(args);
|
|
707
781
|
try {
|
|
708
|
-
const install = await ensureBrandedEngineInstalled(args, envPath);
|
|
782
|
+
const install = await ensureBrandedEngineInstalled(args, envPath, { progress });
|
|
709
783
|
if (install.ok && install.installed) {
|
|
710
|
-
|
|
784
|
+
progress(`engine installed: ${install.payload.installed.version}`);
|
|
785
|
+
} else if (install.ok) {
|
|
786
|
+
progress("engine ready");
|
|
711
787
|
} else if (!install.ok) {
|
|
788
|
+
await splash.stop();
|
|
712
789
|
console.error(`MyteCody branded engine could not be verified: ${install.reason || "unknown"}.`);
|
|
713
790
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
714
791
|
return 1;
|
|
715
792
|
}
|
|
716
793
|
} catch (error) {
|
|
794
|
+
await splash.stop();
|
|
717
795
|
console.error(`MyteCody engine verification failed: ${error && error.message ? error.message : error}`);
|
|
718
796
|
return 1;
|
|
719
797
|
}
|
|
720
798
|
|
|
721
799
|
const command = resolveCodexCommand();
|
|
722
800
|
if (!command) {
|
|
801
|
+
await splash.stop();
|
|
723
802
|
console.error("MyteCody branded engine is not installed.");
|
|
724
803
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
725
804
|
return 1;
|
|
@@ -729,7 +808,10 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
729
808
|
...process.env,
|
|
730
809
|
CODEX_HOME: codexHome(),
|
|
731
810
|
MYTE_CODY_AUTH_TOKEN: token,
|
|
811
|
+
MYTE_CODY_BRAND: "1",
|
|
732
812
|
};
|
|
813
|
+
progress("opening MyteCody workspace");
|
|
814
|
+
await splash.stop();
|
|
733
815
|
return new Promise((resolve) => {
|
|
734
816
|
const child = spawn(command.cmd, launchArgs, {
|
|
735
817
|
cwd: process.cwd(),
|
|
@@ -778,10 +860,13 @@ async function runDoctor(args, envPath) {
|
|
|
778
860
|
return 0;
|
|
779
861
|
}
|
|
780
862
|
|
|
781
|
-
async function buildUpdatePayload(args, envPath, { dryRun = false } = {}) {
|
|
863
|
+
async function buildUpdatePayload(args, envPath, { dryRun = false, progress = null } = {}) {
|
|
782
864
|
const isDryRun = Boolean(dryRun);
|
|
783
865
|
const source = manifestUrl(args);
|
|
784
|
-
const manifestResult = await readManifest(source, {
|
|
866
|
+
const manifestResult = await readManifest(source, {
|
|
867
|
+
fetchManifest: Boolean(args["fetch-manifest"]) || !isDryRun,
|
|
868
|
+
progress,
|
|
869
|
+
});
|
|
785
870
|
const manifest = manifestResult.manifest;
|
|
786
871
|
const artifact = manifest ? artifactForPlatform(manifest) : null;
|
|
787
872
|
const signature = manifest ? signatureAccepted(manifest, args) : { ok: false, signature: { status: "not-checked", verified: false } };
|
|
@@ -811,7 +896,7 @@ async function buildUpdatePayload(args, envPath, { dryRun = false } = {}) {
|
|
|
811
896
|
if (!artifactMetadata.ok) {
|
|
812
897
|
throw new Error(`MyteCody release artifact metadata is ${artifactMetadata.status}.`);
|
|
813
898
|
}
|
|
814
|
-
const bytes = await readArtifactBytes(artifact);
|
|
899
|
+
const bytes = await readArtifactBytes(artifact, { progress });
|
|
815
900
|
const digest = sha256Hex(bytes);
|
|
816
901
|
if (digest.toLowerCase() !== String(artifact.sha256 || "").toLowerCase()) {
|
|
817
902
|
throw new Error(`Artifact SHA-256 mismatch: expected ${artifact.sha256}, got ${digest}`);
|
|
@@ -844,7 +929,7 @@ function autoInstallEnabled(args = {}) {
|
|
|
844
929
|
return true;
|
|
845
930
|
}
|
|
846
931
|
|
|
847
|
-
async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
|
|
932
|
+
async function ensureBrandedEngineInstalled(args = {}, envPath = null, { progress = null } = {}) {
|
|
848
933
|
const updateArgs = {
|
|
849
934
|
...args,
|
|
850
935
|
"fetch-manifest": true,
|
|
@@ -853,7 +938,7 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
|
|
|
853
938
|
delete updateArgs.json;
|
|
854
939
|
|
|
855
940
|
const source = manifestUrl(updateArgs);
|
|
856
|
-
const manifestResult = await readManifest(source, { fetchManifest: true });
|
|
941
|
+
const manifestResult = await readManifest(source, { fetchManifest: true, progress });
|
|
857
942
|
const manifest = manifestResult.manifest;
|
|
858
943
|
if (!manifest) {
|
|
859
944
|
return { ok: false, installed: false, reason: "manifest-unavailable", manifest_status: manifestResult.status };
|
|
@@ -875,7 +960,7 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
|
|
|
875
960
|
return { ok: false, installed: false, reason: "update-required-auto-install-disabled" };
|
|
876
961
|
}
|
|
877
962
|
|
|
878
|
-
const payload = await buildUpdatePayload(updateArgs, envPath, { dryRun: false });
|
|
963
|
+
const payload = await buildUpdatePayload(updateArgs, envPath, { dryRun: false, progress });
|
|
879
964
|
return {
|
|
880
965
|
ok: Boolean(payload.installed && payload.installed.ok),
|
|
881
966
|
installed: Boolean(payload.installed && payload.installed.ok),
|
|
@@ -886,7 +971,10 @@ async function ensureBrandedEngineInstalled(args = {}, envPath = null) {
|
|
|
886
971
|
|
|
887
972
|
async function runUpdate(args, envPath) {
|
|
888
973
|
const dryRun = Boolean(args["dry-run"]);
|
|
889
|
-
const payload = await buildUpdatePayload(args, envPath, {
|
|
974
|
+
const payload = await buildUpdatePayload(args, envPath, {
|
|
975
|
+
dryRun,
|
|
976
|
+
progress: args.json ? null : statusLine,
|
|
977
|
+
});
|
|
890
978
|
|
|
891
979
|
if (args.json) {
|
|
892
980
|
printJson(payload);
|
|
@@ -959,6 +1047,7 @@ module.exports = {
|
|
|
959
1047
|
run,
|
|
960
1048
|
sha256Hex,
|
|
961
1049
|
stableJson,
|
|
1050
|
+
tomlLiteralString,
|
|
962
1051
|
verifyManifestSignature,
|
|
963
1052
|
writeCodexConfig,
|
|
964
1053
|
};
|