@mytegroupinc/myte-core 0.0.35 → 0.0.37
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/README.md +4 -0
- package/lib/mytecody-splash.js +251 -0
- package/mytecody-cli.js +166 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,10 @@ This package exists so the public wrapper can stay small and versioned cleanly.
|
|
|
31
31
|
run, it installs the branded MyteCody engine from the Myte release manifest
|
|
32
32
|
into a user-local Myte cache after signature/hash checks. Coding execution
|
|
33
33
|
requires that engine, a reachable Myte AI Cody gateway, and `MYTEAI_API_KEY`.
|
|
34
|
+
- `mytecody doctor` reports both the signed MyteCody engine state and this npm
|
|
35
|
+
package version. `mytecody update` updates the engine only. Use
|
|
36
|
+
`npm install -g myte@latest` to update the launcher and the Myte API CLI
|
|
37
|
+
commands shipped by npm.
|
|
34
38
|
- The package does not bundle the large MyteCody engine binary. See
|
|
35
39
|
`THIRD_PARTY_NOTICES.md` and `TRADEMARKS.md` for Codex lineage and Myte brand
|
|
36
40
|
notices.
|
|
@@ -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,14 +11,19 @@ const {
|
|
|
11
11
|
DEFAULT_MYTEAI_BASE,
|
|
12
12
|
normalizeMyteAiBase,
|
|
13
13
|
} = require("./lib/ai-gateway");
|
|
14
|
+
const { createMyteSplash } = require("./lib/mytecody-splash");
|
|
14
15
|
|
|
16
|
+
const PACKAGE_NAME = "myte";
|
|
15
17
|
const PACKAGE_VERSION = require("./package.json").version;
|
|
18
|
+
const DEFAULT_PACKAGE_LATEST_URL = "https://registry.npmjs.org/myte/latest";
|
|
16
19
|
const DEFAULT_CHANNEL = "alpha";
|
|
17
20
|
const DEFAULT_MODEL_ALIAS = "myte";
|
|
18
21
|
const DEFAULT_CONTEXT_WINDOW = Number(process.env.MYTE_CODY_CONTEXT_WINDOW || 49152);
|
|
19
22
|
const DEFAULT_AUTO_COMPACT_TOKENS = Number(process.env.MYTE_CODY_AUTO_COMPACT_TOKENS || 40960);
|
|
20
23
|
const DEFAULT_TOOL_OUTPUT_TOKENS = Number(process.env.MYTE_CODY_TOOL_OUTPUT_TOKENS || 10000);
|
|
21
24
|
const DEFAULT_AGENT_THREADS = Number(process.env.MYTE_CODY_AGENT_THREADS || 4);
|
|
25
|
+
const CLIENT_BASE_INSTRUCTIONS =
|
|
26
|
+
"You are MyteCody, a coding agent running through the Myte coding gateway.";
|
|
22
27
|
|
|
23
28
|
function findEnvPath(startDir) {
|
|
24
29
|
let cur = startDir;
|
|
@@ -213,6 +218,10 @@ Usage:
|
|
|
213
218
|
mytecody update [--json] [--manifest <url-or-file>]
|
|
214
219
|
mytecody help
|
|
215
220
|
|
|
221
|
+
Updates:
|
|
222
|
+
mytecody update updates the signed MyteCody engine only
|
|
223
|
+
npm install -g myte@latest updates this npm launcher and Myte API tools
|
|
224
|
+
|
|
216
225
|
Network:
|
|
217
226
|
The distributed MyteCody client uses the Myte AI gateway for coding
|
|
218
227
|
inference. It can inspect local config without network, but coding requires
|
|
@@ -232,6 +241,7 @@ function commonStatus(args, envPath) {
|
|
|
232
241
|
product: "MyteCody",
|
|
233
242
|
command: "mytecody",
|
|
234
243
|
package_version: PACKAGE_VERSION,
|
|
244
|
+
package: packageStatusBase(args),
|
|
235
245
|
mode: "team-gateway",
|
|
236
246
|
workspace: process.cwd(),
|
|
237
247
|
env_file: envPath,
|
|
@@ -241,6 +251,16 @@ function commonStatus(args, envPath) {
|
|
|
241
251
|
inference_base_url: codyInferenceBase(args),
|
|
242
252
|
network_required_for_coding: true,
|
|
243
253
|
},
|
|
254
|
+
instruction_pack: {
|
|
255
|
+
owner: "myte-cody-gateway",
|
|
256
|
+
client_embedded: false,
|
|
257
|
+
},
|
|
258
|
+
runtime: {
|
|
259
|
+
context_window: DEFAULT_CONTEXT_WINDOW,
|
|
260
|
+
auto_compact_tokens: DEFAULT_AUTO_COMPACT_TOKENS,
|
|
261
|
+
tool_output_tokens: DEFAULT_TOOL_OUTPUT_TOKENS,
|
|
262
|
+
max_concurrent_agent_threads: DEFAULT_AGENT_THREADS,
|
|
263
|
+
},
|
|
244
264
|
release: {
|
|
245
265
|
channel: String(args.channel || process.env.MYTE_CODY_RELEASE_CHANNEL || DEFAULT_CHANNEL),
|
|
246
266
|
manifest_url: manifestUrl(args),
|
|
@@ -254,6 +274,103 @@ function commonStatus(args, envPath) {
|
|
|
254
274
|
};
|
|
255
275
|
}
|
|
256
276
|
|
|
277
|
+
function packageLatestUrl(args = {}) {
|
|
278
|
+
return String(
|
|
279
|
+
args["package-latest-url"] ||
|
|
280
|
+
process.env.MYTE_CODY_PACKAGE_LATEST_URL ||
|
|
281
|
+
process.env.MYTE_PACKAGE_LATEST_URL ||
|
|
282
|
+
DEFAULT_PACKAGE_LATEST_URL,
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function packageUpdateCheckEnabled(args = {}) {
|
|
287
|
+
if (args["package-update-check"] === false) return false;
|
|
288
|
+
return process.env.MYTE_CODY_PACKAGE_UPDATE_CHECK !== "0";
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function packageStatusBase(args = {}) {
|
|
292
|
+
return {
|
|
293
|
+
name: PACKAGE_NAME,
|
|
294
|
+
installed_version: PACKAGE_VERSION,
|
|
295
|
+
latest_version: null,
|
|
296
|
+
update_available: null,
|
|
297
|
+
check_status: "not-checked",
|
|
298
|
+
latest_url: packageLatestUrl(args),
|
|
299
|
+
update_command: `npm install -g ${PACKAGE_NAME}@latest`,
|
|
300
|
+
engine_update_command: "mytecody update",
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function parseSemverish(version) {
|
|
305
|
+
const main = String(version || "")
|
|
306
|
+
.trim()
|
|
307
|
+
.replace(/^v/i, "")
|
|
308
|
+
.split(/[+-]/)[0];
|
|
309
|
+
const match = main.match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
310
|
+
if (!match) return null;
|
|
311
|
+
return [match[1], match[2] || "0", match[3] || "0"].map((part) => Number(part));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function compareSemverish(left, right) {
|
|
315
|
+
const leftParts = parseSemverish(left);
|
|
316
|
+
const rightParts = parseSemverish(right);
|
|
317
|
+
if (!leftParts || !rightParts) return String(left || "").localeCompare(String(right || ""));
|
|
318
|
+
for (let i = 0; i < 3; i += 1) {
|
|
319
|
+
if (leftParts[i] > rightParts[i]) return 1;
|
|
320
|
+
if (leftParts[i] < rightParts[i]) return -1;
|
|
321
|
+
}
|
|
322
|
+
return 0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function isVersionNewer(latest, installed = PACKAGE_VERSION) {
|
|
326
|
+
return compareSemverish(latest, installed) > 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function packageUpdateTimeoutMs() {
|
|
330
|
+
const value = Number(process.env.MYTE_CODY_PACKAGE_UPDATE_TIMEOUT_MS || 1500);
|
|
331
|
+
return Number.isFinite(value) && value > 0 ? value : 1500;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async function checkPackageUpdate(args = {}) {
|
|
335
|
+
const status = packageStatusBase(args);
|
|
336
|
+
if (!packageUpdateCheckEnabled(args)) {
|
|
337
|
+
return { ...status, check_status: "skipped" };
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const response = await fetchJson(status.latest_url, {
|
|
341
|
+
timeoutMs: packageUpdateTimeoutMs(),
|
|
342
|
+
});
|
|
343
|
+
if (!response.ok) {
|
|
344
|
+
return {
|
|
345
|
+
...status,
|
|
346
|
+
check_status: "unavailable",
|
|
347
|
+
registry_status: response.status,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
const latestVersion = response.body && response.body.version ? String(response.body.version) : "";
|
|
351
|
+
if (!latestVersion) {
|
|
352
|
+
return { ...status, check_status: "invalid-response" };
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
...status,
|
|
356
|
+
latest_version: latestVersion,
|
|
357
|
+
update_available: isVersionNewer(latestVersion, PACKAGE_VERSION),
|
|
358
|
+
check_status: "ok",
|
|
359
|
+
};
|
|
360
|
+
} catch (error) {
|
|
361
|
+
return {
|
|
362
|
+
...status,
|
|
363
|
+
check_status: "unavailable",
|
|
364
|
+
error: error && error.message ? error.message : String(error),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function packageUpdateNotice(packageStatus) {
|
|
370
|
+
if (!packageStatus || packageStatus.update_available !== true) return "";
|
|
371
|
+
return `myte package update available: ${packageStatus.latest_version} (installed ${packageStatus.installed_version}). Run ${packageStatus.update_command}`;
|
|
372
|
+
}
|
|
373
|
+
|
|
257
374
|
function printJson(payload) {
|
|
258
375
|
console.log(JSON.stringify(payload, null, 2));
|
|
259
376
|
}
|
|
@@ -267,6 +384,16 @@ function statusLine(message) {
|
|
|
267
384
|
console.error(`[MYTE CODY] ${message}`);
|
|
268
385
|
}
|
|
269
386
|
|
|
387
|
+
function setupProgress(splash) {
|
|
388
|
+
return (message) => {
|
|
389
|
+
if (splash && splash.enabled) {
|
|
390
|
+
splash.setStatus(message);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
statusLine(message);
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
270
397
|
function formatBytes(bytes) {
|
|
271
398
|
const value = Number(bytes || 0);
|
|
272
399
|
if (!Number.isFinite(value) || value <= 0) return "unknown size";
|
|
@@ -590,26 +717,13 @@ function pathForToml(value) {
|
|
|
590
717
|
|
|
591
718
|
function writeCodexModelCatalog() {
|
|
592
719
|
fs.mkdirSync(codexHome(), { recursive: true });
|
|
593
|
-
const baseInstructions = [
|
|
594
|
-
"You are MyteCody, a coding agent running in the Myte terminal harness.",
|
|
595
|
-
"",
|
|
596
|
-
"You and the user share one local workspace. Start in the current repository and operate there by default. Inspect outside the current repository only when explicitly asked.",
|
|
597
|
-
"",
|
|
598
|
-
"Your job is to understand the user's intent, inspect the relevant files, run local commands when useful, edit files with the available patch tool, run focused verification, and stop when the task is actually handled.",
|
|
599
|
-
"",
|
|
600
|
-
"For documentation, architecture, and repo-summary work, verify each material claim independently before presenting it as implemented fact. Separate current implementation from planned direction and unknowns. Treat planning docs as intent unless source code, config, command output, or logs prove the behavior exists.",
|
|
601
|
-
"",
|
|
602
|
-
"For edits, prefer apply_patch. If a patch fails, read the error, inspect the target file again, and retry with a corrected patch. Do not claim completion until after inspecting the resulting file or relevant diff.",
|
|
603
|
-
"",
|
|
604
|
-
"Keep responses concise and factual. Do not invent commands, flags, telemetry names, tool behavior, context-window defaults, retrieval behavior, or implemented features.",
|
|
605
|
-
].join("\n");
|
|
606
720
|
const catalog = {
|
|
607
721
|
models: [
|
|
608
722
|
{
|
|
609
723
|
slug: DEFAULT_MODEL_ALIAS,
|
|
610
724
|
display_name: "Myte",
|
|
611
725
|
description: "Myte AI coding model.",
|
|
612
|
-
base_instructions:
|
|
726
|
+
base_instructions: CLIENT_BASE_INSTRUCTIONS,
|
|
613
727
|
default_reasoning_level: "medium",
|
|
614
728
|
supported_reasoning_levels: [
|
|
615
729
|
{ effort: "low", description: "Fast local coding pass." },
|
|
@@ -762,26 +876,40 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
762
876
|
console.error("MyteCody requires MYTEAI_API_KEY for coding.");
|
|
763
877
|
return 1;
|
|
764
878
|
}
|
|
765
|
-
|
|
879
|
+
const splash = createMyteSplash();
|
|
880
|
+
const progress = setupProgress(splash);
|
|
881
|
+
splash.start("preparing trusted workspace");
|
|
882
|
+
progress("preparing trusted workspace");
|
|
766
883
|
writeCodexConfig(args);
|
|
767
884
|
try {
|
|
768
|
-
const install = await ensureBrandedEngineInstalled(args, envPath, { progress
|
|
885
|
+
const install = await ensureBrandedEngineInstalled(args, envPath, { progress });
|
|
769
886
|
if (install.ok && install.installed) {
|
|
770
|
-
|
|
887
|
+
progress(`engine installed: ${install.payload.installed.version}`);
|
|
771
888
|
} else if (install.ok) {
|
|
772
|
-
|
|
889
|
+
progress("engine ready");
|
|
773
890
|
} else if (!install.ok) {
|
|
891
|
+
await splash.stop();
|
|
774
892
|
console.error(`MyteCody branded engine could not be verified: ${install.reason || "unknown"}.`);
|
|
775
893
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
776
894
|
return 1;
|
|
777
895
|
}
|
|
778
896
|
} catch (error) {
|
|
897
|
+
await splash.stop();
|
|
779
898
|
console.error(`MyteCody engine verification failed: ${error && error.message ? error.message : error}`);
|
|
780
899
|
return 1;
|
|
781
900
|
}
|
|
782
901
|
|
|
902
|
+
let packageNotice = "";
|
|
903
|
+
try {
|
|
904
|
+
progress("checking myte package version");
|
|
905
|
+
packageNotice = packageUpdateNotice(await checkPackageUpdate(args));
|
|
906
|
+
} catch {
|
|
907
|
+
packageNotice = "";
|
|
908
|
+
}
|
|
909
|
+
|
|
783
910
|
const command = resolveCodexCommand();
|
|
784
911
|
if (!command) {
|
|
912
|
+
await splash.stop();
|
|
785
913
|
console.error("MyteCody branded engine is not installed.");
|
|
786
914
|
console.error("Run `mytecody update` with access to the Myte release manifest.");
|
|
787
915
|
return 1;
|
|
@@ -793,6 +921,9 @@ async function runCodex(rawArgs, args = {}, envPath = null) {
|
|
|
793
921
|
MYTE_CODY_AUTH_TOKEN: token,
|
|
794
922
|
MYTE_CODY_BRAND: "1",
|
|
795
923
|
};
|
|
924
|
+
progress("opening MyteCody workspace");
|
|
925
|
+
await splash.stop();
|
|
926
|
+
if (packageNotice) statusLine(packageNotice);
|
|
796
927
|
return new Promise((resolve) => {
|
|
797
928
|
const child = spawn(command.cmd, launchArgs, {
|
|
798
929
|
cwd: process.cwd(),
|
|
@@ -814,6 +945,7 @@ async function runDoctor(args, envPath) {
|
|
|
814
945
|
ready_for_coding: false,
|
|
815
946
|
...commonStatus(args, envPath),
|
|
816
947
|
};
|
|
948
|
+
payload.package = await checkPackageUpdate(args);
|
|
817
949
|
if (args["probe-gateway"]) {
|
|
818
950
|
payload.gateway.probe = await probeGateway(args);
|
|
819
951
|
}
|
|
@@ -834,6 +966,17 @@ async function runDoctor(args, envPath) {
|
|
|
834
966
|
if (payload.gateway.probe) {
|
|
835
967
|
console.log(`gateway probe: ${payload.gateway.probe.ok ? "ok" : "failed"}`);
|
|
836
968
|
}
|
|
969
|
+
console.log(`package: ${payload.package.installed_version}`);
|
|
970
|
+
if (payload.package.check_status === "ok" && payload.package.update_available) {
|
|
971
|
+
console.log(`package update: ${payload.package.latest_version} available`);
|
|
972
|
+
console.log(`package command: ${payload.package.update_command}`);
|
|
973
|
+
} else if (payload.package.check_status === "ok") {
|
|
974
|
+
console.log("package update: current");
|
|
975
|
+
} else if (payload.package.check_status === "skipped") {
|
|
976
|
+
console.log("package update: skipped");
|
|
977
|
+
} else {
|
|
978
|
+
console.log(`package update: ${payload.package.check_status}`);
|
|
979
|
+
}
|
|
837
980
|
console.log(`client: ${payload.release.client_installed ? payload.release.client_version : "not installed"}`);
|
|
838
981
|
console.log(`install: ${payload.release.install_root}`);
|
|
839
982
|
console.log("");
|
|
@@ -962,6 +1105,7 @@ async function runUpdate(args, envPath) {
|
|
|
962
1105
|
return 0;
|
|
963
1106
|
}
|
|
964
1107
|
console.log(dryRun ? "MYTE CODY update dry-run" : "MYTE CODY update");
|
|
1108
|
+
console.log("scope: MyteCody engine only");
|
|
965
1109
|
console.log(`manifest: ${payload.manifest.source}`);
|
|
966
1110
|
console.log(`manifest read: ${payload.manifest.read_status}`);
|
|
967
1111
|
console.log(`platform: ${payload.release.platform}`);
|
|
@@ -977,6 +1121,7 @@ async function runUpdate(args, envPath) {
|
|
|
977
1121
|
if (payload.installed) {
|
|
978
1122
|
console.log(`installed: ${payload.installed.executable}`);
|
|
979
1123
|
}
|
|
1124
|
+
console.log(`npm launcher/API tools: ${payload.package.update_command}`);
|
|
980
1125
|
return 0;
|
|
981
1126
|
}
|
|
982
1127
|
|
|
@@ -1015,6 +1160,7 @@ if (require.main === module) {
|
|
|
1015
1160
|
}
|
|
1016
1161
|
|
|
1017
1162
|
module.exports = {
|
|
1163
|
+
checkPackageUpdate,
|
|
1018
1164
|
codexLaunchArgs,
|
|
1019
1165
|
codexProviderArgs,
|
|
1020
1166
|
codyInferenceBase,
|
|
@@ -1024,6 +1170,8 @@ module.exports = {
|
|
|
1024
1170
|
ensureBrandedEngineInstalled,
|
|
1025
1171
|
gatewayRoot,
|
|
1026
1172
|
installedClientCommand,
|
|
1173
|
+
isVersionNewer,
|
|
1174
|
+
packageUpdateNotice,
|
|
1027
1175
|
resolveCodexCommand,
|
|
1028
1176
|
run,
|
|
1029
1177
|
sha256Hex,
|