@mytegroupinc/myte-core 0.0.35 → 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 +23 -4
- 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";
|
|
@@ -267,6 +268,16 @@ function statusLine(message) {
|
|
|
267
268
|
console.error(`[MYTE CODY] ${message}`);
|
|
268
269
|
}
|
|
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
|
+
|
|
270
281
|
function formatBytes(bytes) {
|
|
271
282
|
const value = Number(bytes || 0);
|
|
272
283
|
if (!Number.isFinite(value) || value <= 0) return "unknown size";
|
|
@@ -762,26 +773,32 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
762
773
|
console.error("MyteCody requires MYTEAI_API_KEY for coding.");
|
|
763
774
|
return 1;
|
|
764
775
|
}
|
|
765
|
-
|
|
776
|
+
const splash = createMyteSplash();
|
|
777
|
+
const progress = setupProgress(splash);
|
|
778
|
+
splash.start("preparing trusted workspace");
|
|
779
|
+
progress("preparing trusted workspace");
|
|
766
780
|
writeCodexConfig(args);
|
|
767
781
|
try {
|
|
768
|
-
const install = await ensureBrandedEngineInstalled(args, envPath, { progress
|
|
782
|
+
const install = await ensureBrandedEngineInstalled(args, envPath, { progress });
|
|
769
783
|
if (install.ok && install.installed) {
|
|
770
|
-
|
|
784
|
+
progress(`engine installed: ${install.payload.installed.version}`);
|
|
771
785
|
} else if (install.ok) {
|
|
772
|
-
|
|
786
|
+
progress("engine ready");
|
|
773
787
|
} else if (!install.ok) {
|
|
788
|
+
await splash.stop();
|
|
774
789
|
console.error(`MyteCody branded engine could not be verified: ${install.reason || "unknown"}.`);
|
|
775
790
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
776
791
|
return 1;
|
|
777
792
|
}
|
|
778
793
|
} catch (error) {
|
|
794
|
+
await splash.stop();
|
|
779
795
|
console.error(`MyteCody engine verification failed: ${error && error.message ? error.message : error}`);
|
|
780
796
|
return 1;
|
|
781
797
|
}
|
|
782
798
|
|
|
783
799
|
const command = resolveCodexCommand();
|
|
784
800
|
if (!command) {
|
|
801
|
+
await splash.stop();
|
|
785
802
|
console.error("MyteCody branded engine is not installed.");
|
|
786
803
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
787
804
|
return 1;
|
|
@@ -793,6 +810,8 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
793
810
|
MYTE_CODY_AUTH_TOKEN: token,
|
|
794
811
|
MYTE_CODY_BRAND: "1",
|
|
795
812
|
};
|
|
813
|
+
progress("opening MyteCody workspace");
|
|
814
|
+
await splash.stop();
|
|
796
815
|
return new Promise((resolve) => {
|
|
797
816
|
const child = spawn(command.cmd, launchArgs, {
|
|
798
817
|
cwd: process.cwd(),
|