@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 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: baseInstructions,
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
- statusLine("preparing trusted workspace");
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: statusLine });
885
+ const install = await ensureBrandedEngineInstalled(args, envPath, { progress });
769
886
  if (install.ok && install.installed) {
770
- statusLine(`engine installed: ${install.payload.installed.version}`);
887
+ progress(`engine installed: ${install.payload.installed.version}`);
771
888
  } else if (install.ok) {
772
- statusLine("engine ready");
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mytegroupinc/myte-core",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "Myte CLI core implementation.",
5
5
  "type": "commonjs",
6
6
  "main": "cli.js",