cartethyia 2.4.0 → 2.4.2

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.
Files changed (20) hide show
  1. package/dist/dashboard/assets/{BannedPage-CvnNj-tj.js → BannedPage-KprmzKo8.js} +1 -1
  2. package/dist/dashboard/assets/{CliToolDetailPage-DdYuTZKs.js → CliToolDetailPage-BL_oNmmg.js} +1 -1
  3. package/dist/dashboard/assets/{CliToolsPage-Ba55GO-L.js → CliToolsPage-XjDkuNCh.js} +1 -1
  4. package/dist/dashboard/assets/{ConsoleLogPage-D-OQwsYE.js → ConsoleLogPage-COtZ6SqU.js} +1 -1
  5. package/dist/dashboard/assets/{CustomizationPage-BMqN7mc4.js → CustomizationPage-0K0ySe8K.js} +1 -1
  6. package/dist/dashboard/assets/{HealthEventsModal-C5cygmiy.js → HealthEventsModal-O05igcJY.js} +1 -1
  7. package/dist/dashboard/assets/{LoginPage-lI7CDb07.js → LoginPage-a_voqncN.js} +1 -1
  8. package/dist/dashboard/assets/{OverviewPage-HaMJcZaC.js → OverviewPage-hl2ua1qC.js} +1 -1
  9. package/dist/dashboard/assets/{ProviderDetailPage-Pb-0zXVA.js → ProviderDetailPage-CjpQIFMI.js} +1 -1
  10. package/dist/dashboard/assets/{ProvidersPage-KifbSUkV.js → ProvidersPage-xsrxYHsk.js} +1 -1
  11. package/dist/dashboard/assets/{ProxyPage-DKLnIcne.js → ProxyPage-Bm8Eu21x.js} +1 -1
  12. package/dist/dashboard/assets/{QuotaPage-BzG3XTSg.js → QuotaPage-BKU9VtlD.js} +1 -1
  13. package/dist/dashboard/assets/{SetupPage-Cu42oonZ.js → SetupPage-CdjhQfnC.js} +1 -1
  14. package/dist/dashboard/assets/{StudioPage-DIglSNvf.js → StudioPage-DMGEaI3G.js} +1 -1
  15. package/dist/dashboard/assets/{UsagePage-DQh2rUsY.js → UsagePage-B6D-eJDG.js} +1 -1
  16. package/dist/dashboard/assets/{entry-6PSJYbzI.js → entry-B92UGcyr.js} +3 -3
  17. package/dist/dashboard/assets/{index-Bysq3XgY.js → index-BGSJSZeV.js} +2 -2
  18. package/dist/dashboard/index.html +1 -1
  19. package/package.json +1 -1
  20. package/scripts/cli/cli.ts +40 -35
@@ -303,6 +303,31 @@ async function stopTray(tray: SysTray, ready: boolean, exited: boolean): Promise
303
303
  * and is never seen. `carte --tray` opts into the icon instead.
304
304
  */
305
305
  async function startMenu(): Promise<void> {
306
+ // A fresh install has no config file yet, and the gateway refuses to boot
307
+ // without CARTETHYIA_DB_MODE — which surfaced as a stack trace about a
308
+ // missing database mode rather than "you have not set this up". Run setup
309
+ // first, the way `carte` is expected to behave on a new install.
310
+ const { ENV_PATH, readEnvFile } = await import("../shared/env");
311
+ const configured = existsSync(ENV_PATH) && (await readEnvFile(ENV_PATH)).CARTETHYIA_DB_MODE;
312
+ if (!configured) {
313
+ console.log(
314
+ existsSync(ENV_PATH)
315
+ ? "Cartethyia is missing its database mode. Starting setup.\n"
316
+ : "Cartethyia is not set up yet. Starting setup.\n",
317
+ );
318
+ const { setup } = await import("./setup");
319
+ await setup();
320
+ const after = existsSync(ENV_PATH) ? (await readEnvFile(ENV_PATH)).CARTETHYIA_DB_MODE : undefined;
321
+ if (!after) {
322
+ console.error(
323
+ `Setup did not record CARTETHYIA_DB_MODE in ${ENV_PATH}; run \`cartethyia setup\` and try again.`,
324
+ );
325
+ process.exitCode = 1;
326
+ return;
327
+ }
328
+ process.env.CARTETHYIA_DB_MODE = after;
329
+ }
330
+
306
331
  const port = resolvePort();
307
332
  const drainToken = ensureDrainToken();
308
333
  const dashboardUrl = `http://127.0.0.1:${port}/console`;
@@ -412,18 +437,13 @@ async function startMenu(): Promise<void> {
412
437
  latestVersion = await readLatestPublishedVersion();
413
438
  },
414
439
  async () => {
415
- // Hand the gateway to a tray. This process's gateway is attached, so it
416
- // would die with the menu; the handoff therefore drains it and starts a
417
- // detached one that the tray adopts. The port is briefly empty between
418
- // the two, which is the cost of having Ctrl-C reliably stop a gateway
419
- // while a hidden one still outlives the terminal.
420
- running = false;
421
- stopping = true;
422
- handedOff = true;
423
- console.log("Handing the gateway to the tray…");
424
- await shutDown();
425
- const replacement = await startGateway(port, drainToken, { detached: true });
426
- replacement.unref();
440
+ // Start a detached `tray` process that owns the gateway from scratch,
441
+ // then drain this one so the new process can claim the port. This is
442
+ // the pattern 9router uses and it is simpler than handing a live
443
+ // gateway between processes: the tray is a normal first-class run, not
444
+ // an adopted orphan, so Exit and update behave the same whether the
445
+ // gateway was started here or from `carte --tray`.
446
+ console.log("Starting the tray in the background…");
427
447
  const tray = spawn(
428
448
  process.execPath,
429
449
  ["run", resolvePackagePath("scripts", "cli", "cli.ts"), "tray"],
@@ -432,12 +452,16 @@ async function startMenu(): Promise<void> {
432
452
  detached: true,
433
453
  stdio: "ignore",
434
454
  windowsHide: true,
435
- env: { ...process.env, CARTETHYIA_TRAY_ADOPT_RUNNING: "1" },
455
+ env: process.env,
436
456
  },
437
457
  );
438
458
  tray.unref();
439
- console.log(`Cartethyia keeps running at ${dashboardUrl}.`);
440
- console.log("The tray icon now owns it. Stop it with: cartethyia stop");
459
+ running = false;
460
+ stopping = true;
461
+ handedOff = true;
462
+ await shutDown();
463
+ console.log(`Cartethyia is running in the background at ${dashboardUrl}.`);
464
+ console.log("The tray icon owns it. Stop it with: cartethyia stop");
441
465
  },
442
466
  async () => {
443
467
  running = false;
@@ -660,7 +684,6 @@ async function startTray(): Promise<void> {
660
684
  let closing = false;
661
685
  let busy = false;
662
686
  let resetArmed = false;
663
- const adopted = process.env.CARTETHYIA_TRAY_ADOPT_RUNNING === "1";
664
687
  let latestVersion: string | null = null;
665
688
  let closePromise: Promise<void> | undefined;
666
689
 
@@ -670,15 +693,7 @@ async function startTray(): Promise<void> {
670
693
  closePromise = (async () => {
671
694
  const current: ReturnType<typeof Bun.spawn> | null = gateway;
672
695
  gateway = null;
673
- if (current) {
674
- await stopGateway(current, port, drainToken);
675
- } else if (adopted) {
676
- // An adopted tray never held the gateway as a child, so there is no
677
- // process to signal. Draining through the loopback endpoint is the only
678
- // way Exit stops it — without this, Exit closed the icon and left the
679
- // gateway listening, which looked like a phantom process.
680
- await drainThroughEndpoint(port, drainToken);
681
- }
696
+ if (current) await stopGateway(current, port, drainToken);
682
697
  await stopTray(tray, trayReady, trayExited);
683
698
  process.exitCode = exitCode;
684
699
  })();
@@ -835,16 +850,6 @@ async function startTray(): Promise<void> {
835
850
  try {
836
851
  await waitForTray(tray);
837
852
  trayReady = true;
838
- // "Hide to tray" hands over a gateway that is already listening. Spawning a
839
- // second one would fail on the port, so an adopted tray only watches the
840
- // existing process and stops owning it when the menu process exits.
841
- if (process.env.CARTETHYIA_TRAY_ADOPT_RUNNING === "1") {
842
- reportTrayStartup({ status: "ready", url: dashboardUrl });
843
- console.log(`Cartethyia is running at ${dashboardUrl}`);
844
- void refreshVersion();
845
- while (!closing) await Bun.sleep(500);
846
- return;
847
- }
848
853
  gateway = await startGateway(port, drainToken);
849
854
  reportTrayStartup({ status: "ready", url: dashboardUrl });
850
855
  console.log(`Cartethyia is running at ${dashboardUrl}`);