dsh-code 1.0.7 → 1.3.0

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 (89) hide show
  1. package/README.en.md +70 -24
  2. package/README.md +71 -25
  3. package/bin/deepseek.mjs +202 -39
  4. package/cordis.patch.yml +13 -4
  5. package/lib/index.mjs +5002 -1061
  6. package/lib/session-query.mjs +3 -2
  7. package/lib/startup.mjs +4 -4
  8. package/lib/{theme-DCT8Y2xf.mjs → theme-B3orFUYz.mjs} +665 -20
  9. package/lib/types/app.d.ts +120 -63
  10. package/lib/types/attachments.d.ts +16 -7
  11. package/lib/types/authorization-panel.d.ts +3 -3
  12. package/lib/types/git-workflow.d.ts +91 -2
  13. package/lib/types/history.d.ts +10 -0
  14. package/lib/types/i18n.d.ts +39 -0
  15. package/lib/types/index.d.ts +74 -2
  16. package/lib/types/input-split.d.ts +1 -1
  17. package/lib/types/kernel-panels.d.ts +89 -32
  18. package/lib/types/language-panel.d.ts +12 -0
  19. package/lib/types/locales/en.d.ts +498 -0
  20. package/lib/types/locales/zh.d.ts +9 -0
  21. package/lib/types/mentions.d.ts +7 -3
  22. package/lib/types/models.d.ts +14 -0
  23. package/lib/types/panel-accent.d.ts +28 -0
  24. package/lib/types/rainbow.d.ts +69 -0
  25. package/lib/types/render/animations.d.ts +42 -0
  26. package/lib/types/render/inspector.d.ts +26 -0
  27. package/lib/types/render/lines.d.ts +21 -1
  28. package/lib/types/render/markdown.d.ts +1 -1
  29. package/lib/types/render/projection.d.ts +95 -4
  30. package/lib/types/render/status.d.ts +12 -9
  31. package/lib/types/render/text.d.ts +6 -0
  32. package/lib/types/render/usage.d.ts +113 -0
  33. package/lib/types/session-directory.d.ts +42 -1
  34. package/lib/types/session-switch.d.ts +8 -0
  35. package/lib/types/startup.d.ts +1 -1
  36. package/lib/types/terminal-title.d.ts +8 -0
  37. package/lib/types/theme-panel.d.ts +2 -2
  38. package/lib/types/theme.d.ts +271 -52
  39. package/lib/types/update-panel.d.ts +27 -6
  40. package/lib/types/update.d.ts +10 -1
  41. package/lib/types/version.d.ts +6 -3
  42. package/package.json +26 -7
  43. package/src/app.ts +1426 -627
  44. package/src/approval.ts +166 -166
  45. package/src/attachments.ts +65 -19
  46. package/src/authorization-panel.ts +24 -18
  47. package/src/editor-keys.ts +371 -371
  48. package/src/fork.ts +11 -7
  49. package/src/git-workflow.ts +229 -3
  50. package/src/history.ts +14 -0
  51. package/src/i18n.ts +68 -0
  52. package/src/index.ts +503 -128
  53. package/src/input-split.ts +27 -7
  54. package/src/kernel-panels.ts +528 -113
  55. package/src/keyboard.ts +5 -4
  56. package/src/language-panel.ts +53 -0
  57. package/src/locales/en.ts +538 -0
  58. package/src/locales/zh.ts +537 -0
  59. package/src/mentions.ts +8 -4
  60. package/src/models.ts +264 -212
  61. package/src/panel-accent.ts +41 -0
  62. package/src/presets.ts +1 -1
  63. package/src/provider-settings.ts +1 -1
  64. package/src/rainbow.ts +218 -0
  65. package/src/render/animations.ts +104 -6
  66. package/src/render/editor.ts +20 -20
  67. package/src/render/export.ts +116 -95
  68. package/src/render/inspector.ts +42 -0
  69. package/src/render/lines.ts +628 -415
  70. package/src/render/markdown.ts +15 -3
  71. package/src/render/projection.ts +429 -19
  72. package/src/render/status.ts +119 -62
  73. package/src/render/text.ts +15 -0
  74. package/src/render/tool-preview.ts +77 -77
  75. package/src/render/usage.ts +430 -0
  76. package/src/render/width.ts +2 -2
  77. package/src/session-directory.ts +90 -9
  78. package/src/session-query.ts +8 -4
  79. package/src/session-switch.ts +14 -0
  80. package/src/startup.ts +3 -3
  81. package/src/store.ts +19 -1
  82. package/src/subagents.ts +229 -229
  83. package/src/terminal-title.ts +22 -5
  84. package/src/theme-panel.ts +17 -21
  85. package/src/theme.ts +281 -33
  86. package/src/update-panel.ts +148 -31
  87. package/src/update.ts +19 -3
  88. package/src/version.ts +63 -20
  89. package/src/whale-glyph.ts +23 -23
@@ -1,5 +1,5 @@
1
1
  import os from "node:os";
2
- import process from "node:process";
2
+ import process$1 from "node:process";
3
3
  import tty from "node:tty";
4
4
  //#region node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
5
5
  const ANSI_BACKGROUND_OFFSET = 10;
@@ -166,13 +166,13 @@ function assembleStyles() {
166
166
  const ansiStyles = assembleStyles();
167
167
  //#endregion
168
168
  //#region node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
169
- function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {
169
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process$1.argv) {
170
170
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
171
171
  const position = argv.indexOf(prefix + flag);
172
172
  const terminatorPosition = argv.indexOf("--");
173
173
  return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
174
174
  }
175
- const { env: env$1 } = process;
175
+ const { env: env$1 } = process$1;
176
176
  let flagForceColor;
177
177
  if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) flagForceColor = 0;
178
178
  else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) flagForceColor = 1;
@@ -205,7 +205,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
205
205
  if (haveStream && !streamIsTTY && forceColor === void 0) return 0;
206
206
  const min = forceColor || 0;
207
207
  if (env$1.TERM === "dumb") return min;
208
- if (process.platform === "win32") {
208
+ if (process$1.platform === "win32") {
209
209
  const osRelease = os.release().split(".");
210
210
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
211
211
  return 1;
@@ -403,6 +403,252 @@ Object.defineProperties(createChalk.prototype, styles);
403
403
  const chalk = createChalk();
404
404
  createChalk({ level: stderrColor ? stderrColor.level : 0 });
405
405
  //#endregion
406
+ //#region src/rainbow.ts
407
+ /**
408
+ * The bright-tier spectrum: twelve Tailwind *-300 hues covering red through
409
+ * fuchsia, every one ≥11:1 on black. The roll samples this pool by shuffle;
410
+ * nothing outside it is ever painted.
411
+ */
412
+ const RAINBOW_POOL = [
413
+ [
414
+ 252,
415
+ 165,
416
+ 165
417
+ ],
418
+ [
419
+ 253,
420
+ 186,
421
+ 116
422
+ ],
423
+ [
424
+ 253,
425
+ 230,
426
+ 138
427
+ ],
428
+ [
429
+ 253,
430
+ 224,
431
+ 71
432
+ ],
433
+ [
434
+ 190,
435
+ 242,
436
+ 100
437
+ ],
438
+ [
439
+ 134,
440
+ 239,
441
+ 172
442
+ ],
443
+ [
444
+ 94,
445
+ 234,
446
+ 212
447
+ ],
448
+ [
449
+ 103,
450
+ 232,
451
+ 249
452
+ ],
453
+ [
454
+ 125,
455
+ 211,
456
+ 252
457
+ ],
458
+ [
459
+ 147,
460
+ 197,
461
+ 253
462
+ ],
463
+ [
464
+ 196,
465
+ 181,
466
+ 253
467
+ ],
468
+ [
469
+ 240,
470
+ 171,
471
+ 252
472
+ ]
473
+ ];
474
+ /**
475
+ * Status tones in canonical on-screen order (row one left-to-right, then row
476
+ * two): consecutive entries here are the pairs the "adjacent spans differ"
477
+ * guarantee covers, including the accent→value step across the row boundary.
478
+ */
479
+ const TONE_ORDER = [
480
+ "live",
481
+ "model",
482
+ "path",
483
+ "branch",
484
+ "accent",
485
+ "value",
486
+ "label",
487
+ "meta",
488
+ "ctxFill",
489
+ "success",
490
+ "plan",
491
+ "warn",
492
+ "error"
493
+ ];
494
+ /** Parse a RAINBOW_SEED value: a non-negative decimal uint32, else nothing. */
495
+ function parseRainbowSeed(value) {
496
+ if (value === void 0 || !/^\d{1,10}$/.test(value.trim())) return void 0;
497
+ const parsed = Number(value.trim());
498
+ return Number.isSafeInteger(parsed) ? parsed >>> 0 : void 0;
499
+ }
500
+ /**
501
+ * One parsed `/rainbow` argument: empty means a fresh random roll; a
502
+ * decimal uint32 pins that seed; anything else is a usage error.
503
+ * @param argument - the raw text after `/rainbow`.
504
+ * @returns `{ seed }`, `'random'`, or `'usage'`.
505
+ */
506
+ function parseRainbowArgument(argument) {
507
+ const trimmed = argument.trim();
508
+ if (trimmed === "") return "random";
509
+ const parsed = parseRainbowSeed(trimmed);
510
+ return parsed === void 0 ? "usage" : { seed: parsed };
511
+ }
512
+ /** Deterministic 32-bit RNG (mulberry32) — one roll, one stream. */
513
+ function mulberry32(seed) {
514
+ let state = seed >>> 0;
515
+ return () => {
516
+ state = state + 1831565813 | 0;
517
+ let t = Math.imul(state ^ state >>> 15, 1 | state);
518
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
519
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
520
+ };
521
+ }
522
+ /** Fisher–Yates shuffle over a copy, driven by the roll's RNG. */
523
+ function shuffle(items, rng) {
524
+ const out = [...items];
525
+ for (let i = out.length - 1; i > 0; i -= 1) {
526
+ const j = Math.floor(rng() * (i + 1));
527
+ [out[i], out[j]] = [out[j], out[i]];
528
+ }
529
+ return out;
530
+ }
531
+ /** Approximate HSL hue of one RGB triple, degrees in [0, 360). */
532
+ function hueOf([r, g, b]) {
533
+ const max = Math.max(r, g, b);
534
+ const min = Math.min(r, g, b);
535
+ if (max === min) return 0;
536
+ const span = max - min;
537
+ if (max === r) return (60 * (g - b) / span + 360) % 360;
538
+ if (max === g) return (60 * (b - r) / span + 120) % 360;
539
+ return (60 * (r - g) / span + 240) % 360;
540
+ }
541
+ /** Strict RGB equality for the wrap-collision repair. */
542
+ function sameRgb(left, right) {
543
+ return left[0] === right[0] && left[1] === right[1] && left[2] === right[2];
544
+ }
545
+ /** A dark row tint for diff backgrounds: the hue at 22% strength over black. */
546
+ function darkTint(hue) {
547
+ return [
548
+ Math.round(hue[0] * .22),
549
+ Math.round(hue[1] * .22),
550
+ Math.round(hue[2] * .22)
551
+ ];
552
+ }
553
+ /** Readability anchors shared by every roll: captions, text, band stay calm. */
554
+ const DIM = [
555
+ 166,
556
+ 163,
557
+ 184
558
+ ];
559
+ const TEXT = [
560
+ 240,
561
+ 238,
562
+ 249
563
+ ];
564
+ const BAND = [
565
+ 46,
566
+ 46,
567
+ 52
568
+ ];
569
+ /**
570
+ * Build the roll for one seed: pure and deterministic, so tests pin exact
571
+ * outcomes and RAINBOW_SEED reproduces a lucky launch exactly.
572
+ * @param seed - the uint32 seed to roll from.
573
+ * @returns the complete carnival roll.
574
+ */
575
+ function rollRainbow(seed) {
576
+ const rng = mulberry32(seed);
577
+ const pool = shuffle(RAINBOW_POOL, rng);
578
+ const [brand, brandBright, brandMid, brandDeep, code, success, error, warn, addHue, delHue] = pool;
579
+ const palette = {
580
+ brand,
581
+ brandBright,
582
+ brandMid,
583
+ brandDeep,
584
+ dim: DIM,
585
+ success,
586
+ error,
587
+ warn,
588
+ text: TEXT,
589
+ code,
590
+ composerBand: BAND,
591
+ diffAdd: darkTint(addHue),
592
+ diffDel: darkTint(delHue),
593
+ diffAddFg: addHue,
594
+ diffDelFg: delHue,
595
+ surface: [
596
+ 0,
597
+ 0,
598
+ 0
599
+ ],
600
+ prompt: brandBright,
601
+ queued: warn,
602
+ steered: code
603
+ };
604
+ const ring = shuffle(RAINBOW_POOL, rng).slice(0, 4);
605
+ const offset = Math.floor(rng() * RAINBOW_POOL.length);
606
+ const toneColors = {};
607
+ TONE_ORDER.forEach((tone, index) => {
608
+ toneColors[tone] = pool[(offset + index) % pool.length];
609
+ });
610
+ if (sameRgb(toneColors.live, toneColors.error)) {
611
+ const replacement = pool.find((hue) => !sameRgb(hue, toneColors.live) && !sameRgb(hue, toneColors.warn));
612
+ if (replacement !== void 0) toneColors.error = replacement;
613
+ }
614
+ return {
615
+ seed,
616
+ palette,
617
+ ring,
618
+ toneColors,
619
+ flowAnchors: [...RAINBOW_POOL].sort((a, b) => hueOf(a) - hueOf(b)),
620
+ flowPhaseMs: Math.floor(rng() * 2400)
621
+ };
622
+ }
623
+ /** The launch seed: RAINBOW_SEED when parseable, else a fresh random roll. */
624
+ function launchSeed() {
625
+ const pinned = parseRainbowSeed(process.env.RAINBOW_SEED);
626
+ if (pinned !== void 0) return pinned;
627
+ return (Date.now() ^ Math.floor(Math.random() * 4294967296)) >>> 0;
628
+ }
629
+ let rolled;
630
+ /** The memoized per-launch roll; computed once, stable for the whole run. */
631
+ function rainbowRoll() {
632
+ if (rolled === void 0) rolled = rollRainbow(launchSeed());
633
+ return rolled;
634
+ }
635
+ /**
636
+ * Replace the memoized roll: omit the seed for a fresh random one, or pass
637
+ * a uint32 to pin it. `/rainbow` uses this so a mid-session reroll actually
638
+ * recolors; {@link setTheme}(`'rainbow'`) must run afterwards so the
639
+ * palette accessor picks the new values up.
640
+ * @param seed - the seed to pin, or undefined for a new random roll.
641
+ * @returns the roll now in force.
642
+ */
643
+ function rerollRainbow(seed) {
644
+ rolled = rollRainbow(seed ?? (Date.now() ^ Math.floor(Math.random() * 4294967296)) >>> 0);
645
+ return rolled;
646
+ }
647
+ /** The current roll's seed as display copy (also the RAINBOW_SEED value). */
648
+ function rainbowSeedLabel() {
649
+ return String(rainbowRoll().seed);
650
+ }
651
+ //#endregion
406
652
  //#region src/theme.ts
407
653
  /**
408
654
  * Terminal color tokens for the dsh TUI, mapped from the product design
@@ -410,13 +656,12 @@ createChalk({ level: stderrColor ? stderrColor.level : 0 });
410
656
  * (`packages/client/ui-theme/src/styles/design-platform.css`). Truecolor RGB
411
657
  * rides chalk, which degrades automatically on terminals without truecolor.
412
658
  *
413
- * Two palettes — `dark` (the default) and `light` — share the same token keys
414
- * with different values. Painters and the palette accessor read the ACTIVE
659
+ * Three palettes — `dark` (the default), `light`, and `prismatic` (the
660
+ * neon synthwave skin) share the same token keys with different values.
661
+ * Painters and the palette accessor read the ACTIVE
415
662
  * palette selected through {@link setTheme}, so a theme switch recolors every
416
- * painted surface on the next render without touching call sites. Raw token
417
- * consumers keep reading {@link TUI_RGB} (the dark values) until the
418
- * theme-aware integration replaces those call sites with
419
- * `inkColor(getPalette().token)`.
663
+ * painted surface on the next render without touching call sites; consumers
664
+ * read colors through {@link getPalette} or the painters below only.
420
665
  *
421
666
  * @module @deepseek-ai/dsh-tui/theme
422
667
  */
@@ -424,9 +669,43 @@ createChalk({ level: stderrColor ? stderrColor.level : 0 });
424
669
  const THEME_NAMES = [
425
670
  "dark",
426
671
  "light",
672
+ "prismatic",
673
+ "rainbow",
427
674
  "auto"
428
675
  ];
429
676
  /**
677
+ * Every theme's picker metadata in canonical order — the single source the
678
+ * /theme panel rows derive from; {@link THEME_NAMES} stays the validation
679
+ * list. Adding a theme means adding its palette plus one row here.
680
+ */
681
+ const THEMES = [
682
+ {
683
+ id: "dark",
684
+ label: "dark",
685
+ description: "DeepSeek dark palette (default)"
686
+ },
687
+ {
688
+ id: "light",
689
+ label: "light",
690
+ description: "light palette for bright terminals"
691
+ },
692
+ {
693
+ id: "prismatic",
694
+ label: "prismatic",
695
+ description: "neon synthwave palette (violet/magenta/cyan)"
696
+ },
697
+ {
698
+ id: "rainbow",
699
+ label: "rainbow",
700
+ description: "randomized carnival palette (/rainbow to reroll)"
701
+ },
702
+ {
703
+ id: "auto",
704
+ label: "auto",
705
+ description: "follow the terminal; dark until detection lands"
706
+ }
707
+ ];
708
+ /**
430
709
  * DeepSeek dark palette: the original TUI colors, one entry per
431
710
  * design-platform token in use. Keep names and values in sync with the CSS
432
711
  * custom properties cited inline.
@@ -497,13 +776,67 @@ const DARK_PALETTE = {
497
776
  46,
498
777
  48,
499
778
  52
779
+ ],
780
+ /** Diff added-line background — Codex's muted dark green tint (#213A2B). */
781
+ diffAdd: [
782
+ 33,
783
+ 58,
784
+ 43
785
+ ],
786
+ /** Diff removed-line background — Codex's muted dark red tint (#4A221D). */
787
+ diffDel: [
788
+ 74,
789
+ 34,
790
+ 29
791
+ ],
792
+ /** Diff added-line foreground — green-500, 5.4:1 on the diffAdd tint. */
793
+ diffAddFg: [
794
+ 34,
795
+ 197,
796
+ 94
797
+ ],
798
+ /** Diff removed-line foreground — red-400, 4.9:1 on the diffDel tint (error's red-500 sinks to 3.6:1 on it). */
799
+ diffDelFg: [
800
+ 248,
801
+ 113,
802
+ 113
803
+ ],
804
+ /** Terminal background this palette is designed against; row tints blend toward it. */
805
+ surface: [
806
+ 0,
807
+ 0,
808
+ 0
809
+ ],
810
+ /**
811
+ * The three prompt-row colors, one per delivery kind. They are the palette's
812
+ * own accents (bright brand, warning amber, violet) rather than fixed RGBs,
813
+ * and every row's bar is these colors laid over {@link surface}.
814
+ */
815
+ prompt: [
816
+ 103,
817
+ 158,
818
+ 254
819
+ ],
820
+ queued: [
821
+ 245,
822
+ 158,
823
+ 11
824
+ ],
825
+ steered: [
826
+ 167,
827
+ 139,
828
+ 250
500
829
  ]
501
830
  };
502
- /** Every palette by theme name; auto resolves through {@link resolveTheme}. */
831
+ /**
832
+ * Every STATIC palette by theme name; auto resolves through {@link resolveTheme}
833
+ * and rainbow is rolled per launch ({@link rainbowRoll}), so neither lives
834
+ * here — {@link setTheme} resolves both through the same key space.
835
+ */
503
836
  const PALETTES = {
504
837
  dark: DARK_PALETTE,
505
838
  light: {
506
- /** Primary brand blue — unchanged, ≈4.9:1 AA on white. */
839
+ /** Primary brand blue — unchanged design-platform value; ≈4.2:1 on white, so bold/accent spans only (body-size brand text uses brandBright). */
507
840
  brand: [
508
841
  65,
509
842
  118,
@@ -568,6 +901,170 @@ const PALETTES = {
568
901
  229,
569
902
  231,
570
903
  235
904
+ ],
905
+ /** Diff added-line background — GitHub's pastel green (#dafbe1), Codex's light pick. */
906
+ diffAdd: [
907
+ 218,
908
+ 251,
909
+ 225
910
+ ],
911
+ /** Diff removed-line background — GitHub's pastel red (#ffebe9), Codex's light pick. */
912
+ diffDel: [
913
+ 255,
914
+ 235,
915
+ 233
916
+ ],
917
+ /** Diff added-line foreground — green-800, 6.4:1 on the pastel tint (green-700 clears 4.5:1 by a hair). */
918
+ diffAddFg: [
919
+ 22,
920
+ 101,
921
+ 52
922
+ ],
923
+ /** Diff removed-line foreground — red-700, 5.6:1 on the pastel tint (error's red-600 is 3.9:1). */
924
+ diffDelFg: [
925
+ 185,
926
+ 28,
927
+ 28
928
+ ],
929
+ /** Terminal background this palette is designed against; row tints blend toward it. */
930
+ surface: [
931
+ 255,
932
+ 255,
933
+ 255
934
+ ],
935
+ /**
936
+ * Prompt-row colors deepened for white: the amber and violet the dark theme
937
+ * uses sit at the AA edge on their own pastel bars, so each kind carries a
938
+ * value that clears 4.5:1 both on the bar and on plain white.
939
+ */
940
+ prompt: [
941
+ 47,
942
+ 76,
943
+ 143
944
+ ],
945
+ queued: [
946
+ 124,
947
+ 53,
948
+ 10
949
+ ],
950
+ steered: [
951
+ 109,
952
+ 40,
953
+ 217
954
+ ]
955
+ },
956
+ prismatic: {
957
+ /** Primary electric purple — violet-500 (#8B5CF6), 5.0:1 on black. */
958
+ brand: [
959
+ 139,
960
+ 92,
961
+ 246
962
+ ],
963
+ /** Live/streaming emphasis — neon fuchsia-300 (#F0ABFC), 11.9:1 on black. */
964
+ brandBright: [
965
+ 240,
966
+ 171,
967
+ 252
968
+ ],
969
+ /** Intermediate violet — violet-400 (#A78BFA), 7.7:1 on black. */
970
+ brandMid: [
971
+ 167,
972
+ 139,
973
+ 250
974
+ ],
975
+ /** Deep secondary chrome — violet-600 (#7C3AED), 3.7:1 on black (violet-700 misses 3:1). */
976
+ brandDeep: [
977
+ 124,
978
+ 58,
979
+ 237
980
+ ],
981
+ /** Muted captions — lavender gray (#A6A3B8), 8.6:1 on black. */
982
+ dim: [
983
+ 166,
984
+ 163,
985
+ 184
986
+ ],
987
+ /** Success green — unchanged from dark. */
988
+ success: [
989
+ 34,
990
+ 197,
991
+ 94
992
+ ],
993
+ /** Error red — unchanged from dark. */
994
+ error: [
995
+ 239,
996
+ 68,
997
+ 68
998
+ ],
999
+ /** Warning amber — unchanged from dark. */
1000
+ warn: [
1001
+ 245,
1002
+ 158,
1003
+ 11
1004
+ ],
1005
+ /** Default foreground text — white with a lavender cast (#F0EEF9). */
1006
+ text: [
1007
+ 240,
1008
+ 238,
1009
+ 249
1010
+ ],
1011
+ /** Inline/fenced code — neon cyan-300 (#67E8F9), 14.5:1 on black. */
1012
+ code: [
1013
+ 103,
1014
+ 232,
1015
+ 249
1016
+ ],
1017
+ /** Composer three-row band base — neutral dark gray, hue-free so wave tints read on it. */
1018
+ composerBand: [
1019
+ 46,
1020
+ 46,
1021
+ 52
1022
+ ],
1023
+ /** Diff added-line background — unchanged from dark. */
1024
+ diffAdd: [
1025
+ 33,
1026
+ 58,
1027
+ 43
1028
+ ],
1029
+ /** Diff removed-line background — unchanged from dark. */
1030
+ diffDel: [
1031
+ 74,
1032
+ 34,
1033
+ 29
1034
+ ],
1035
+ /** Diff added-line foreground — unchanged from dark. */
1036
+ diffAddFg: [
1037
+ 34,
1038
+ 197,
1039
+ 94
1040
+ ],
1041
+ /** Diff removed-line foreground — unchanged from dark. */
1042
+ diffDelFg: [
1043
+ 248,
1044
+ 113,
1045
+ 113
1046
+ ],
1047
+ /** Terminal background this palette is designed against; row tints blend toward it. */
1048
+ surface: [
1049
+ 0,
1050
+ 0,
1051
+ 0
1052
+ ],
1053
+ /** Prompt rows in the skin's own neon: fuchsia, amber, cyan. */
1054
+ prompt: [
1055
+ 240,
1056
+ 171,
1057
+ 252
1058
+ ],
1059
+ queued: [
1060
+ 245,
1061
+ 158,
1062
+ 11
1063
+ ],
1064
+ steered: [
1065
+ 103,
1066
+ 232,
1067
+ 249
571
1068
  ]
572
1069
  }
573
1070
  };
@@ -578,12 +1075,13 @@ let activePalette = DARK_PALETTE;
578
1075
  /**
579
1076
  * Resolve a theme name to the palette actually in use. `auto` detection
580
1077
  * (OSC 11 terminal background query) is a later enhancement; until it lands,
581
- * auto falls back to the dark palette.
1078
+ * auto falls back to the dark palette (prismatic and rainbow are always
1079
+ * explicit choices, never auto-resolved).
582
1080
  * @param name - the requested theme name.
583
- * @returns 'dark' or 'light' — the palette key to paint with.
1081
+ * @returns 'dark', 'light', 'prismatic', or 'rainbow' — the palette key.
584
1082
  */
585
1083
  function resolveTheme(name) {
586
- return name === "light" ? "light" : "dark";
1084
+ return name === "light" ? "light" : name === "prismatic" ? "prismatic" : name === "rainbow" ? "rainbow" : "dark";
587
1085
  }
588
1086
  /**
589
1087
  * Switch the active theme: painters and {@link getPalette} reflect the new
@@ -593,7 +1091,8 @@ function resolveTheme(name) {
593
1091
  */
594
1092
  function setTheme(name) {
595
1093
  activeName = name;
596
- activePalette = PALETTES[resolveTheme(name)];
1094
+ const resolved = resolveTheme(name);
1095
+ activePalette = resolved === "rainbow" ? rainbowRoll().palette : PALETTES[resolved];
597
1096
  }
598
1097
  /**
599
1098
  * The theme name in force. Returns the requested name ('auto' included) so
@@ -608,21 +1107,167 @@ function getPalette() {
608
1107
  return activePalette;
609
1108
  }
610
1109
  /**
611
- * Parse a persisted theme name: only 'light' and 'auto' survive; anything
612
- * else (missing, corrupt, or unknown) falls back to the dark default.
1110
+ * Parse a persisted theme name: only names in {@link THEME_NAMES} survive;
1111
+ * anything else (missing, corrupt, or unknown) falls back to the dark default.
613
1112
  * @param value - the raw parsed JSON value (expected string).
614
1113
  * @returns a valid theme name.
615
1114
  */
616
1115
  function parseThemeName(value) {
617
- return value === "light" || value === "auto" ? value : "dark";
1116
+ return typeof value === "string" && THEME_NAMES.includes(value) ? value : "dark";
618
1117
  }
619
1118
  /** Ink `color` string for one RGB triple. */
620
1119
  function inkColor(triple) {
621
1120
  return `rgb(${triple[0]}, ${triple[1]}, ${triple[2]})`;
622
1121
  }
1122
+ /**
1123
+ * Diff-line background as an Ink `backgroundColor` string, theme-aware and
1124
+ * depth-gated (the Codex diff renderer's rule): 16-color terminals paint
1125
+ * backgrounds from the saturated system palette, which drowns the text, so
1126
+ * they keep the foreground-only look; 256-color and truecolor terminals get
1127
+ * the palette's tint (chalk quantizes the RGB form down automatically).
1128
+ * @param token - which diff background, added or removed lines.
1129
+ * @returns the Ink background color, or undefined to paint foreground-only.
1130
+ */
1131
+ function diffBackground(token) {
1132
+ if (chalk.level < 2) return void 0;
1133
+ return inkColor(activePalette[token]);
1134
+ }
1135
+ /** How far one prompt-row tint leans toward its color, over the surface. */
1136
+ const PROMPT_ROW_TINT = .22;
1137
+ /**
1138
+ * The color family one prompt row wears, chosen by how it was delivered: the
1139
+ * ordinary brand accent, the warning amber for a queued prompt, and the
1140
+ * palette's own third accent for a steered one. The bar behind it is derived
1141
+ * from that same color, so every theme — including a freshly rolled rainbow —
1142
+ * carries its own look instead of a fixed triple.
1143
+ * @param delivery - how the prompt was delivered; undefined is an ordinary one.
1144
+ * @returns the palette token whose color paints the row.
1145
+ */
1146
+ function promptRowTokens(delivery) {
1147
+ if (delivery === "queued") return { fg: "queued" };
1148
+ if (delivery === "steered") return { fg: "steered" };
1149
+ return { fg: "prompt" };
1150
+ }
1151
+ /**
1152
+ * Blended prompt-row background for one row color: the palette color laid
1153
+ * over the surface the palette is designed for (dark themes over black, light
1154
+ * over white), depth-gated exactly like {@link diffBackground} — a 16-color
1155
+ * terminal keeps the foreground-only look rather than painting a saturated
1156
+ * system background behind the text.
1157
+ * @param color - the row's palette token.
1158
+ * @returns the Ink background color, or undefined to paint foreground-only.
1159
+ */
1160
+ function rowBackground(color) {
1161
+ if (chalk.level < 2) return void 0;
1162
+ const surface = activePalette.surface;
1163
+ const tint = activePalette[color];
1164
+ const blend = (index) => Math.round(surface[index] + (tint[index] - surface[index]) * PROMPT_ROW_TINT);
1165
+ return inkColor([
1166
+ blend(0),
1167
+ blend(1),
1168
+ blend(2)
1169
+ ]);
1170
+ }
1171
+ /**
1172
+ * The prismatic surface ring: four neon accents panels cycle through by
1173
+ * mount order (cyan → fuchsia → violet → lime), all ≥3:1 on black. Dark and
1174
+ * light ignore the ring — {@link surfaceAccent} falls back to the passed-in
1175
+ * base color so those themes stay pixel-identical.
1176
+ */
1177
+ const ACCENT_RING = [
1178
+ [
1179
+ 34,
1180
+ 211,
1181
+ 238
1182
+ ],
1183
+ [
1184
+ 232,
1185
+ 121,
1186
+ 249
1187
+ ],
1188
+ [
1189
+ 167,
1190
+ 139,
1191
+ 250
1192
+ ],
1193
+ [
1194
+ 163,
1195
+ 230,
1196
+ 53
1197
+ ]
1198
+ ];
1199
+ /**
1200
+ * The prismatic flow anchors: brand violet → neon fuchsia → neon cyan. All
1201
+ * three clear 4.5:1 on black, so a flowing foreground stays AA throughout
1202
+ * the oscillation (render/animations.ts walks the triangle).
1203
+ */
1204
+ const FLOW_ANCHORS = [
1205
+ [
1206
+ 139,
1207
+ 92,
1208
+ 246
1209
+ ],
1210
+ [
1211
+ 232,
1212
+ 121,
1213
+ 249
1214
+ ],
1215
+ [
1216
+ 34,
1217
+ 211,
1218
+ 238
1219
+ ]
1220
+ ];
1221
+ /**
1222
+ * Whether the active theme is prismatic (the neon skin with surface rings
1223
+ * and flowing accents).
1224
+ */
1225
+ function isPrismatic() {
1226
+ return activeName === "prismatic";
1227
+ }
1228
+ /** Whether the active theme is rainbow (the per-launch carnival roll). */
1229
+ function isRainbow() {
1230
+ return activeName === "rainbow";
1231
+ }
1232
+ /**
1233
+ * The flowing theme's anchor walk: prismatic rides the fixed violet→fuchsia→
1234
+ * cyan triangle; rainbow rides its rolled full-spectrum anchors with a random
1235
+ * phase; dark and light have no flow (undefined) and keep static accents.
1236
+ */
1237
+ function themeFlow() {
1238
+ if (isPrismatic()) return {
1239
+ anchors: FLOW_ANCHORS,
1240
+ phaseMs: 0
1241
+ };
1242
+ if (isRainbow()) {
1243
+ const roll = rainbowRoll();
1244
+ return {
1245
+ anchors: roll.flowAnchors,
1246
+ phaseMs: roll.flowPhaseMs
1247
+ };
1248
+ }
1249
+ }
1250
+ /**
1251
+ * The accent for one surface slot: prismatic rotates the {@link ACCENT_RING}
1252
+ * by slot index; every other theme gets the caller's base color back.
1253
+ * @param index - the slot's position in the mount-order sequence.
1254
+ * @param base - the color to use outside prismatic (the surface's usual one).
1255
+ * @returns the accent to paint the surface's border/title with.
1256
+ */
1257
+ function surfaceAccent(index, base) {
1258
+ if (isPrismatic()) {
1259
+ const ring = ACCENT_RING;
1260
+ return ring[(index % ring.length + ring.length) % ring.length];
1261
+ }
1262
+ if (isRainbow()) {
1263
+ const ring = rainbowRoll().ring;
1264
+ return ring[(index % ring.length + ring.length) % ring.length];
1265
+ }
1266
+ return base;
1267
+ }
623
1268
  /** Paint muted captions, hints, and meta lines. */
624
1269
  function dim(text) {
625
1270
  return chalk.rgb(...activePalette.dim)(text);
626
1271
  }
627
1272
  //#endregion
628
- export { inkColor as a, chalk as c, getTheme as i, dim as n, parseThemeName as o, getPalette as r, setTheme as s, THEME_NAMES as t };
1273
+ export { parseRainbowArgument as _, dim as a, rerollRainbow as b, inkColor as c, parseThemeName as d, promptRowTokens as f, themeFlow as g, surfaceAccent as h, diffBackground as i, isPrismatic as l, setTheme as m, THEMES as n, getPalette as o, rowBackground as p, THEME_NAMES as r, getTheme as s, FLOW_ANCHORS as t, isRainbow as u, rainbowRoll as v, chalk as x, rainbowSeedLabel as y };