fluxflow-cli 3.12.2 → 3.13.1

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/dist/fluxflow.js CHANGED
@@ -3731,7 +3731,7 @@ var init_MultilineInput = __esm({
3731
3731
  });
3732
3732
 
3733
3733
  // src/utils/theme.js
3734
- var CHAOS_PRESETS, THEMES, getThemeColors;
3734
+ var CHAOS_PRESETS, THEMES, cachedChaosPreset, getThemeColors;
3735
3735
  var init_theme = __esm({
3736
3736
  "src/utils/theme.js"() {
3737
3737
  CHAOS_PRESETS = [
@@ -3979,6 +3979,153 @@ var init_theme = __esm({
3979
3979
  logoBodyAnsi: "\x1B[35m",
3980
3980
  logoMutedAnsi: "\x1B[90m",
3981
3981
  logoGradient: ["#ffb3d9", "#ff3399"]
3982
+ },
3983
+ {
3984
+ name: "Radioactive Slime",
3985
+ text: "#ccff00",
3986
+ textMuted: "#99cc00",
3987
+ textDim: "#669900",
3988
+ textInverted: "#0a0f00",
3989
+ border: "#ccff00",
3990
+ borderMuted: "#99cc00",
3991
+ borderDim: "#669900",
3992
+ bg: void 0,
3993
+ cardBg: "#0f1400",
3994
+ highlightBg: "#1a2400",
3995
+ activeBg: "#2a3b00",
3996
+ inputBg: "#1a2400",
3997
+ inputBorder: "#1a2400",
3998
+ inputText: "#ccff00",
3999
+ inputPlaceholder: "#669900",
4000
+ inputPrompt: "#cc00ff",
4001
+ codeBg: "#050a00",
4002
+ codeBorder: "#99cc00",
4003
+ userMsgBg: "#1a2400",
4004
+ userMsgBorder: "#1a2400",
4005
+ userMsgText: "#ccff00",
4006
+ diffRemovalBg: "#2a0033",
4007
+ diffAdditionBg: "#0f3300",
4008
+ diffRemovalText: "#ff00cc",
4009
+ diffAdditionText: "#00ff33",
4010
+ diffRemovalHighlightColor: "#ff33cc",
4011
+ diffRemovalHighlightBg: "#4d0066",
4012
+ diffAdditionHighlightColor: "#33ff66",
4013
+ diffAdditionHighlightBg: "#1a6600",
4014
+ diffRemovalNum: "#ff00cc",
4015
+ diffAdditionNum: "#00ff33",
4016
+ diffRemovalPrefix: "#ff33cc",
4017
+ diffAdditionPrefix: "#33ff66",
4018
+ primary: "#ccff00",
4019
+ secondary: "#cc00ff",
4020
+ accent: "#ff00cc",
4021
+ success: "#00ff33",
4022
+ warning: "#ffcc00",
4023
+ danger: "#ff0033",
4024
+ info: "#00ccff",
4025
+ statusOn: "#ccff00",
4026
+ statusOff: "#669900",
4027
+ logoTextAnsi: "\x1B[1;38;5;190m",
4028
+ logoBodyAnsi: "\x1B[38;5;190m",
4029
+ logoMutedAnsi: "\x1B[90m",
4030
+ logoGradient: ["#ccff00", "#cc00ff"]
4031
+ },
4032
+ {
4033
+ name: "Cosmic Void",
4034
+ text: "#f0f8ff",
4035
+ textMuted: "#a6aeb5",
4036
+ textDim: "#5e656e",
4037
+ textInverted: "#010103",
4038
+ border: "#f0f8ff",
4039
+ borderMuted: "#a6aeb5",
4040
+ borderDim: "#5e656e",
4041
+ bg: void 0,
4042
+ cardBg: "#05030d",
4043
+ highlightBg: "#0b081a",
4044
+ activeBg: "#171133",
4045
+ inputBg: "#0b081a",
4046
+ inputBorder: "#0b081a",
4047
+ inputText: "#f0f8ff",
4048
+ inputPlaceholder: "#5e656e",
4049
+ inputPrompt: "#ff007f",
4050
+ codeBg: "#020108",
4051
+ codeBorder: "#a6aeb5",
4052
+ userMsgBg: "#0b081a",
4053
+ userMsgBorder: "#0b081a",
4054
+ userMsgText: "#f0f8ff",
4055
+ diffRemovalBg: "#2e0a29",
4056
+ diffAdditionBg: "#091c33",
4057
+ diffRemovalText: "#ff33a6",
4058
+ diffAdditionText: "#33d6ff",
4059
+ diffRemovalHighlightColor: "#ff66c2",
4060
+ diffRemovalHighlightBg: "#5c1452",
4061
+ diffAdditionHighlightColor: "#66e0ff",
4062
+ diffAdditionHighlightBg: "#123866",
4063
+ diffRemovalNum: "#ff33a6",
4064
+ diffAdditionNum: "#33d6ff",
4065
+ diffRemovalPrefix: "#ff66c2",
4066
+ diffAdditionPrefix: "#66e0ff",
4067
+ primary: "#f0f8ff",
4068
+ secondary: "#ff007f",
4069
+ accent: "#9d00ff",
4070
+ success: "#33d6ff",
4071
+ warning: "#ffcc00",
4072
+ danger: "#ff0040",
4073
+ info: "#9d00ff",
4074
+ statusOn: "#f0f8ff",
4075
+ statusOff: "#5e656e",
4076
+ logoTextAnsi: "\x1B[1;38;5;231m",
4077
+ logoBodyAnsi: "\x1B[38;5;231m",
4078
+ logoMutedAnsi: "\x1B[38;5;240m",
4079
+ logoGradient: ["#ffffff", "#9d00ff"]
4080
+ },
4081
+ {
4082
+ name: "Magma Eruption",
4083
+ text: "#ff4d00",
4084
+ textMuted: "#cc3d00",
4085
+ textDim: "#802600",
4086
+ textInverted: "#0d0300",
4087
+ border: "#ff4d00",
4088
+ borderMuted: "#cc3d00",
4089
+ borderDim: "#802600",
4090
+ bg: void 0,
4091
+ cardBg: "#1a0600",
4092
+ highlightBg: "#260a00",
4093
+ activeBg: "#401100",
4094
+ inputBg: "#260a00",
4095
+ inputBorder: "#260a00",
4096
+ inputText: "#ff4d00",
4097
+ inputPlaceholder: "#802600",
4098
+ inputPrompt: "#ffcc00",
4099
+ codeBg: "#080200",
4100
+ codeBorder: "#cc3d00",
4101
+ userMsgBg: "#260a00",
4102
+ userMsgBorder: "#260a00",
4103
+ userMsgText: "#ff4d00",
4104
+ diffRemovalBg: "#2e0a0a",
4105
+ diffAdditionBg: "#1f1400",
4106
+ diffRemovalText: "#ff3333",
4107
+ diffAdditionText: "#ffaa00",
4108
+ diffRemovalHighlightColor: "#ff6666",
4109
+ diffRemovalHighlightBg: "#5c1414",
4110
+ diffAdditionHighlightColor: "#ffcc33",
4111
+ diffAdditionHighlightBg: "#3d2900",
4112
+ diffRemovalNum: "#ff3333",
4113
+ diffAdditionNum: "#ffaa00",
4114
+ diffRemovalPrefix: "#ff6666",
4115
+ diffAdditionPrefix: "#ffcc33",
4116
+ primary: "#ff4d00",
4117
+ secondary: "#ffcc00",
4118
+ accent: "#ff0040",
4119
+ success: "#ffaa00",
4120
+ warning: "#ffff00",
4121
+ danger: "#ff0000",
4122
+ info: "#ff8800",
4123
+ statusOn: "#ff4d00",
4124
+ statusOff: "#802600",
4125
+ logoTextAnsi: "\x1B[1;38;5;202m",
4126
+ logoBodyAnsi: "\x1B[38;5;202m",
4127
+ logoMutedAnsi: "\x1B[38;5;236m",
4128
+ logoGradient: ["#ff4d00", "#ff0000"]
3982
4129
  }
3983
4130
  ];
3984
4131
  THEMES = {
@@ -4337,17 +4484,129 @@ var init_theme = __esm({
4337
4484
  logoBodyAnsi: "\x1B[30m",
4338
4485
  logoMutedAnsi: "\x1B[38;5;244m",
4339
4486
  logoGradient: ["#0077ff", "#ff00ff"]
4487
+ },
4488
+ "Synthwave 84": {
4489
+ id: "Synthwave 84",
4490
+ name: "Synthwave 84",
4491
+ text: "#fdfdfd",
4492
+ textMuted: "#a08eb7",
4493
+ textDim: "#705c8a",
4494
+ textInverted: "#1a1025",
4495
+ textExclusive: "#e3dcf0",
4496
+ textMutedExclusive: "#b9abc9",
4497
+ border: "#fc28a8",
4498
+ borderMuted: "#a21568",
4499
+ borderDim: "#5c0a3a",
4500
+ bg: void 0,
4501
+ cardBg: "#261b38",
4502
+ highlightBg: "#35254d",
4503
+ activeBg: "#4c3570",
4504
+ inputBg: "#35254d",
4505
+ inputBorder: "#35254d",
4506
+ inputText: "#fdfdfd",
4507
+ inputPlaceholder: "#a08eb7",
4508
+ inputPrompt: "#03e8fc",
4509
+ codeBg: "#1e142b",
4510
+ codeBorder: "#a21568",
4511
+ userMsgBg: "#35254d",
4512
+ userMsgBorder: "#35254d",
4513
+ userMsgText: "#fdfdfd",
4514
+ diffRemovalBg: "#471434",
4515
+ diffAdditionBg: "#144743",
4516
+ diffRemovalText: "#ff4081",
4517
+ diffAdditionText: "#00e5ff",
4518
+ diffRemovalHighlightColor: "#ff79a1",
4519
+ diffRemovalHighlightBg: "#6b1e4e",
4520
+ diffAdditionHighlightColor: "#66f5ff",
4521
+ diffAdditionHighlightBg: "#1e6b65",
4522
+ diffRemovalNum: "#ff4081",
4523
+ diffAdditionNum: "#00e5ff",
4524
+ diffRemovalPrefix: "#ff79a1",
4525
+ diffAdditionPrefix: "#66f5ff",
4526
+ primary: "#fdfdfd",
4527
+ secondary: "#03e8fc",
4528
+ accent: "#fc28a8",
4529
+ success: "#00e5ff",
4530
+ warning: "#ffc107",
4531
+ danger: "#ff4081",
4532
+ info: "#b388ff",
4533
+ statusOn: "#03e8fc",
4534
+ statusOff: "#a08eb7",
4535
+ logoTextAnsi: "\x1B[1;35m",
4536
+ logoBodyAnsi: "\x1B[35m",
4537
+ logoMutedAnsi: "\x1B[90m",
4538
+ logoGradient: ["#fc28a8", "#03e8fc"]
4539
+ },
4540
+ "Forest Sprite": {
4541
+ id: "Forest Sprite",
4542
+ name: "Forest Sprite",
4543
+ text: "#d6e6d1",
4544
+ textMuted: "#95b38d",
4545
+ textDim: "#628059",
4546
+ textInverted: "#161c14",
4547
+ textExclusive: "#eaf2e8",
4548
+ textMutedExclusive: "#a9c7a2",
4549
+ border: "#74a862",
4550
+ borderMuted: "#477038",
4551
+ borderDim: "#2b4720",
4552
+ bg: void 0,
4553
+ cardBg: "#1f291c",
4554
+ highlightBg: "#2a3826",
4555
+ activeBg: "#3a4d35",
4556
+ inputBg: "#2a3826",
4557
+ inputBorder: "#2a3826",
4558
+ inputText: "#d6e6d1",
4559
+ inputPlaceholder: "#95b38d",
4560
+ inputPrompt: "#8feb73",
4561
+ codeBg: "#161e14",
4562
+ codeBorder: "#477038",
4563
+ userMsgBg: "#2a3826",
4564
+ userMsgBorder: "#2a3826",
4565
+ userMsgText: "#d6e6d1",
4566
+ diffRemovalBg: "#3b231c",
4567
+ diffAdditionBg: "#203b1c",
4568
+ diffRemovalText: "#db6242",
4569
+ diffAdditionText: "#59cc3f",
4570
+ diffRemovalHighlightColor: "#f0896c",
4571
+ diffRemovalHighlightBg: "#5c362a",
4572
+ diffAdditionHighlightColor: "#80e368",
4573
+ diffAdditionHighlightBg: "#305929",
4574
+ diffRemovalNum: "#db6242",
4575
+ diffAdditionNum: "#59cc3f",
4576
+ diffRemovalPrefix: "#f0896c",
4577
+ diffAdditionPrefix: "#80e368",
4578
+ primary: "#d6e6d1",
4579
+ secondary: "#8feb73",
4580
+ accent: "#e69835",
4581
+ success: "#59cc3f",
4582
+ warning: "#e69835",
4583
+ danger: "#db6242",
4584
+ info: "#73b4eb",
4585
+ statusOn: "#8feb73",
4586
+ statusOff: "#95b38d",
4587
+ logoTextAnsi: "\x1B[1;32m",
4588
+ logoBodyAnsi: "\x1B[32m",
4589
+ logoMutedAnsi: "\x1B[90m",
4590
+ logoGradient: ["#8feb73", "#e69835"]
4340
4591
  }
4341
4592
  };
4593
+ cachedChaosPreset = null;
4342
4594
  getThemeColors = (themeName = "Dark") => {
4343
- if (themeName === "Chaos" || themeName === "Mystery") {
4344
- const randomPreset = CHAOS_PRESETS[Math.floor(Math.random() * CHAOS_PRESETS.length)];
4345
- return { ...randomPreset, id: "Chaos" };
4346
- }
4347
- if (THEMES[themeName]) return THEMES[themeName];
4348
- if (themeName === "GitHub") return THEMES["GitHub Dark"];
4349
- if (themeName === "Transparent") return THEMES["Transparent Dark"];
4350
- return THEMES.Dark;
4595
+ let colors;
4596
+ if (themeName === "Mystery" || themeName === "Chaos") {
4597
+ if (!cachedChaosPreset) {
4598
+ cachedChaosPreset = CHAOS_PRESETS[Math.floor(Math.random() * CHAOS_PRESETS.length)];
4599
+ }
4600
+ colors = { ...cachedChaosPreset, id: "Mystery" };
4601
+ } else {
4602
+ cachedChaosPreset = null;
4603
+ if (THEMES[themeName]) colors = THEMES[themeName];
4604
+ else if (themeName === "GitHub") colors = THEMES["GitHub Dark"];
4605
+ else if (themeName === "Transparent") colors = THEMES["Transparent Dark"];
4606
+ else colors = THEMES.Dark;
4607
+ }
4608
+ const codeColor = colors.codeText || colors.secondary || colors.info || colors.logoGradient && colors.logoGradient[0] || "cyan";
4609
+ return { ...colors, codeText: codeColor };
4351
4610
  };
4352
4611
  }
4353
4612
  });
@@ -4788,7 +5047,7 @@ var init_terminal = __esm({
4788
5047
  return `${coloredArt[0]}
4789
5048
  ${coloredArt[1]} ${textColor}Selected Provider: ${provider}${reset}
4790
5049
  ${coloredArt[2]}
4791
- ${coloredArt[3]} ${textColor}FLUX FLOW ${grey("v" + version)}${reset}
5050
+ ${coloredArt[3]} ${textColor}FluxFlow ${grey("v" + version)}${reset}
4792
5051
  ${coloredArt[4]}
4793
5052
  ${coloredArt[5]} ${bodyColor}See /help for additional commands.${reset}
4794
5053
  ${coloredArt[6]} ${grey(quote)}
@@ -4970,12 +5229,13 @@ var init_ChatLayout = __esm({
4970
5229
  if (!text) return null;
4971
5230
  const colors = getThemeColors(theme);
4972
5231
  const textColor = color || colors.text;
5232
+ const highlightColor = colors.codeText || colors.logoGradient && colors.logoGradient[0] || colors.info || colors.secondary || "cyan";
4973
5233
  const parts = text.split(REGEX_MD_TOKENS);
4974
5234
  return /* @__PURE__ */ React4.createElement(Text4, { color: textColor, wrap: "anywhere", italic }, parts.map((part, j) => {
4975
5235
  if (!part) return null;
4976
5236
  if (part.startsWith("```") && part.endsWith("```")) {
4977
5237
  const content = part.slice(3, -3);
4978
- return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: "cyan" }, content);
5238
+ return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor }, content);
4979
5239
  }
4980
5240
  if (part.startsWith("**") && part.endsWith("**")) {
4981
5241
  return /* @__PURE__ */ React4.createElement(Text4, { key: j, bold: true, color: textColor }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: part.slice(2, -2), color: textColor, theme }));
@@ -4989,12 +5249,12 @@ var init_ChatLayout = __esm({
4989
5249
  return p1.split("/").pop().split("\\").pop().replace(REGEX_COLON_L, "#L");
4990
5250
  });
4991
5251
  const hasFileRef = content.includes("@[");
4992
- return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: "cyan", bold: hasFileRef }, formatted);
5252
+ return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor, bold: hasFileRef }, formatted);
4993
5253
  }
4994
5254
  if (part.startsWith("@[") && part.endsWith("]")) {
4995
5255
  const filePath = part.slice(2, -1);
4996
5256
  const basename = filePath.split("/").pop().split("\\").pop().replace(REGEX_COLON_L, "#L");
4997
- return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: "cyan", bold: true }, basename);
5257
+ return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor, bold: true }, basename);
4998
5258
  }
4999
5259
  if (part.startsWith("\\(") && part.endsWith("\\)") || part.startsWith("\\[") && part.endsWith("\\]")) {
5000
5260
  const content = part.slice(2, -2);
@@ -5006,14 +5266,14 @@ var init_ChatLayout = __esm({
5006
5266
  }
5007
5267
  if (part.startsWith("[") && (part.includes("](") || part.includes("] ("))) {
5008
5268
  const match = part.match(REGEX_MD_LINK_PAREN);
5009
- if (match) return /* @__PURE__ */ React4.createElement(Text4, { key: j }, /* @__PURE__ */ React4.createElement(Text4, { color: "cyan", underline: true, bold: true }, match[1]), /* @__PURE__ */ React4.createElement(Text4, { color: "gray", italic: true }, " (", match[2], ")"));
5269
+ if (match) return /* @__PURE__ */ React4.createElement(Text4, { key: j }, /* @__PURE__ */ React4.createElement(Text4, { color: highlightColor, underline: true, bold: true }, match[1]), /* @__PURE__ */ React4.createElement(Text4, { color: "gray", italic: true }, " (", match[2], ")"));
5010
5270
  }
5011
5271
  if (part.startsWith("[") && (part.includes("][") || part.includes("] ["))) {
5012
5272
  const match = part.match(REGEX_MD_LINK_BRACKET);
5013
- if (match) return /* @__PURE__ */ React4.createElement(Text4, { key: j }, /* @__PURE__ */ React4.createElement(Text4, { color: "cyan", underline: true, bold: true }, match[1]), /* @__PURE__ */ React4.createElement(Text4, { color: "gray", italic: true }, " [", match[2], "]"));
5273
+ if (match) return /* @__PURE__ */ React4.createElement(Text4, { key: j }, /* @__PURE__ */ React4.createElement(Text4, { color: highlightColor, underline: true, bold: true }, match[1]), /* @__PURE__ */ React4.createElement(Text4, { color: "gray", italic: true }, " [", match[2], "]"));
5014
5274
  }
5015
5275
  if (part.startsWith("http")) {
5016
- return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: "cyan", underline: true, italic: true }, part);
5276
+ return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor, underline: true, italic: true }, part);
5017
5277
  }
5018
5278
  return renderLatexText(part, j);
5019
5279
  }));
@@ -5021,6 +5281,7 @@ var init_ChatLayout = __esm({
5021
5281
  TableRenderer = React4.memo(({ buffer, terminalWidth = 80, theme = "Dark" }) => {
5022
5282
  if (buffer.length < 2) return null;
5023
5283
  const colors = getThemeColors(theme);
5284
+ const headerColor = colors.codeText || colors.secondary || colors.info || "cyan";
5024
5285
  const rows = buffer.map((line) => {
5025
5286
  const parts = line.split("|");
5026
5287
  if (parts[0] !== void 0 && parts[0].trim() === "") parts.shift();
@@ -5034,7 +5295,7 @@ var init_ChatLayout = __esm({
5034
5295
  const colChars = Math.floor(availableWidth / header.length) - 2;
5035
5296
  return (
5036
5297
  // Table MarginY here
5037
- /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, paddingX: 1, marginY: 0, width: terminalWidth - 2 }, /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: colors.borderMuted, marginBottom: 1, paddingBottom: 0, width: "100%" }, header.map((cell, i) => /* @__PURE__ */ React4.createElement(Box3, { key: i, flexBasis: `${colPercentage}%`, flexGrow: 1, flexShrink: 0, paddingRight: 2 }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: wrapText(cell, colChars), color: "cyan", theme })))), data.map((row, ri) => /* @__PURE__ */ React4.createElement(Box3, { key: ri, flexDirection: "row", marginBottom: ri === data.length - 1 ? 0 : 1, width: "100%" }, row.map((cell, ci) => /* @__PURE__ */ React4.createElement(Box3, { key: ci, flexBasis: `${colPercentage}%`, flexGrow: 1, flexShrink: 0, paddingRight: 2, flexDirection: "column" }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: wrapText(cell, colChars), color: colors.text, theme }))))))
5298
+ /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, paddingX: 1, marginY: 0, width: terminalWidth - 2 }, /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: colors.borderMuted, marginBottom: 1, paddingBottom: 0, width: "100%" }, header.map((cell, i) => /* @__PURE__ */ React4.createElement(Box3, { key: i, flexBasis: `${colPercentage}%`, flexGrow: 1, flexShrink: 0, paddingRight: 2 }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: wrapText(cell, colChars), color: headerColor, theme })))), data.map((row, ri) => /* @__PURE__ */ React4.createElement(Box3, { key: ri, flexDirection: "row", marginBottom: ri === data.length - 1 ? 0 : 1, width: "100%" }, row.map((cell, ci) => /* @__PURE__ */ React4.createElement(Box3, { key: ci, flexBasis: `${colPercentage}%`, flexGrow: 1, flexShrink: 0, paddingRight: 2, flexDirection: "column" }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: wrapText(cell, colChars), color: colors.text, theme }))))))
5038
5299
  );
5039
5300
  });
5040
5301
  MarkdownText = React4.memo(({ text, color, columns = 80, italic = false, theme = "Dark" }) => {
@@ -5412,7 +5673,9 @@ var init_ChatLayout = __esm({
5412
5673
  { cmd: "/mode", desc: "Toggle Flux/Flow modes" },
5413
5674
  { cmd: "/thinking", desc: "Set AI reasoning depth" },
5414
5675
  { cmd: "/model", desc: "Switch AI model" },
5676
+ { cmd: "/provider", desc: "Select AI Provider" },
5415
5677
  { cmd: "/settings", desc: "Configure system prefs" },
5678
+ { cmd: "/theme", desc: "Customize UI color theme" },
5416
5679
  { cmd: "/key", desc: "Manage API keys" },
5417
5680
  { cmd: "/profile", desc: "Edit developer persona" },
5418
5681
  { cmd: "/memory", desc: "Manage agent memory" },
@@ -6068,7 +6331,7 @@ var init_arg_parser = __esm({
6068
6331
 
6069
6332
  // src/data/main_tools.js
6070
6333
  import { execSync } from "child_process";
6071
- var _isPsAvailable, isPsAvailable, TOOL_PROTOCOL;
6334
+ var _isPsAvailable, isPsAvailable, _cachedAdvanceRollback, TOOL_PROTOCOL;
6072
6335
  var init_main_tools = __esm({
6073
6336
  async "src/data/main_tools.js"() {
6074
6337
  await init_exec_command();
@@ -6084,7 +6347,12 @@ var init_main_tools = __esm({
6084
6347
  }
6085
6348
  return _isPsAvailable;
6086
6349
  };
6087
- TOOL_PROTOCOL = (mode, osDetected, isMultiModal, aiProvider, advanceRollback = false, enableSubAgents = true) => `
6350
+ _cachedAdvanceRollback = null;
6351
+ TOOL_PROTOCOL = (mode, osDetected, isMultiModal, aiProvider, advanceRollback = false, enableSubAgents = true) => {
6352
+ if (_cachedAdvanceRollback === null) {
6353
+ _cachedAdvanceRollback = advanceRollback;
6354
+ }
6355
+ return `
6088
6356
  -- TOOL DEFINITIONS --
6089
6357
  Tool calls: ONLY use [tool:functions.ToolName(args)]
6090
6358
  **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
@@ -6108,7 +6376,7 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative; FIRST ARGUMENT, path se
6108
6376
  6. [tool:functions.SearchKeyword(keyword="...", path="optional, target directory or filename", subString="true optional", regex="false for keyword, optional")]. Project-wide search. path limits scope to a file/dir. Find definitions/logic without full reads. Locate relevant code. Defaults: subString=false, regex=true
6109
6377
  7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
6110
6378
  8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task list, no Markdown in arrays. Analyze request: if multi-task, break it down & create Todos BEFORE starting. \`tasks\` & \`markDone\` optional with \`get\`. Use \`get + markDone\` to complete tasks, or \`create + markDone\` to create completed tasks. **UPDATE EVERY TURN**${enableSubAgents ? '\n9. [tool:functions.Await(time="seconds")]. For waiting without exiting agent loop, 15s - 180s' : ""}
6111
- ${advanceRollback ? `
6379
+ ${_cachedAdvanceRollback ? `
6112
6380
  - EMERGENCY SAFETY TOOLS -
6113
6381
  Info: \`initial\` = user prompt for current task. Revert \`id\` = turn BEFORE the disaster tool (e.g. disaster:\`turn_3\` \u2192 revert:\`turn_2\`). Reason explicitly if needed.
6114
6382
  1. [tool:functions.EmergencyRollback(method="getCheckpoint/forceRevert", id="...")]. Rollback workspace to a checkpoint in THIS agent loop.
@@ -6130,6 +6398,7 @@ Invocations:
6130
6398
  - **Escape quotes: \\" for code strings**
6131
6399
  - **Literal escapes: Double-escape sequences (e.g., \\\\n)**
6132
6400
  - **File structure: Real newlines for code formatting**`.trim();
6401
+ };
6133
6402
  }
6134
6403
  });
6135
6404
 
@@ -6822,13 +7091,21 @@ function SettingsMenu({
6822
7091
  saveSettings: saveSettings2,
6823
7092
  quotas,
6824
7093
  setMessages,
6825
- aiProvider
7094
+ aiProvider,
7095
+ initialSelectingTheme = false,
7096
+ onCloseTheme = null,
7097
+ setProviderReturnView = null
6826
7098
  }) {
7099
+ const activeTheme = systemSettings.theme === "Chaos" || systemSettings.theme === "Mystery" ? "Mystery" : systemSettings.theme || "Dark";
7100
+ const defaultIdx = themeOptions.indexOf(activeTheme);
6827
7101
  const [activeColumn, setActiveColumn] = useState6("categories");
6828
7102
  const [selectedCategoryIndex, setSelectedCategoryIndex] = useState6(0);
6829
7103
  const [selectedItemIndex, setSelectedItemIndex] = useState6(0);
6830
7104
  const [editingItem, setEditingItem] = useState6(null);
6831
7105
  const [editValue, setEditValue] = useState6("");
7106
+ const [isSelectingTheme, setIsSelectingTheme] = useState6(initialSelectingTheme);
7107
+ const [themeIndex, setThemeIndex] = useState6(defaultIdx >= 0 ? defaultIdx : 0);
7108
+ const [initialTheme, setInitialTheme] = useState6(systemSettings.theme || "Dark");
6832
7109
  const [currentMemory, setCurrentMemory] = useState6(0);
6833
7110
  const [maxMemory, setMaxMemory] = useState6(0);
6834
7111
  const [memoryUnit, setMemoryUnit] = useState6("MB");
@@ -6903,6 +7180,28 @@ function SettingsMenu({
6903
7180
  const currentCatId = CATEGORIES[selectedCategoryIndex].id;
6904
7181
  const currentItems = getCategoryItems(currentCatId);
6905
7182
  useInput3((input, key) => {
7183
+ if (isSelectingTheme) {
7184
+ if (key.upArrow) {
7185
+ const nextIdx = (themeIndex - 1 + themeOptions.length) % themeOptions.length;
7186
+ setThemeIndex(nextIdx);
7187
+ } else if (key.downArrow) {
7188
+ const nextIdx = (themeIndex + 1) % themeOptions.length;
7189
+ setThemeIndex(nextIdx);
7190
+ } else if (key.return) {
7191
+ const selectedTheme = themeOptions[themeIndex];
7192
+ setSystemSettings((s) => {
7193
+ const newSysSettings = { ...s, theme: selectedTheme };
7194
+ saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
7195
+ return newSysSettings;
7196
+ });
7197
+ if (onCloseTheme) onCloseTheme();
7198
+ else setIsSelectingTheme(false);
7199
+ } else if (key.escape) {
7200
+ if (onCloseTheme) onCloseTheme();
7201
+ else setIsSelectingTheme(false);
7202
+ }
7203
+ return;
7204
+ }
6906
7205
  if (editingItem) {
6907
7206
  if (key.escape) {
6908
7207
  setEditingItem(null);
@@ -7012,6 +7311,7 @@ function SettingsMenu({
7012
7311
  } else if (item.value === "apiTier") {
7013
7312
  setActiveView("apiTier");
7014
7313
  } else if (item.value === "aiProvider") {
7314
+ if (setProviderReturnView) setProviderReturnView("settings");
7015
7315
  setActiveView("selectProvider");
7016
7316
  } else if (item.value === "advanceRollback") {
7017
7317
  if (!systemSettings.advanceRollback) {
@@ -7081,18 +7381,24 @@ function SettingsMenu({
7081
7381
  return newSysSettings;
7082
7382
  });
7083
7383
  } else if (item.value === "theme") {
7084
- const options = ["Dark", "Light", "GitHub Dark", "GitHub Light", "Transparent Dark", "Transparent Light", "Chaos"];
7085
- const activeTheme = systemSettings.theme === "Mystery" ? "Chaos" : systemSettings.theme || "Dark";
7086
- const currentIndex = options.indexOf(activeTheme);
7087
- const nextIndex = (currentIndex + 1) % options.length;
7088
- setSystemSettings((s) => {
7089
- const newSysSettings = { ...s, theme: options[nextIndex] };
7090
- saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
7091
- return newSysSettings;
7092
- });
7384
+ const activeTheme2 = systemSettings.theme === "Chaos" || systemSettings.theme === "Mystery" ? "Mystery" : systemSettings.theme || "Dark";
7385
+ const idx = themeOptions.indexOf(activeTheme2);
7386
+ setThemeIndex(idx >= 0 ? idx : 0);
7387
+ setInitialTheme(systemSettings.theme || "Dark");
7388
+ setIsSelectingTheme(true);
7093
7389
  }
7094
7390
  };
7095
7391
  const colors = getThemeColors(systemSettings.theme);
7392
+ if (isSelectingTheme) {
7393
+ const previewThemeName = themeOptions[themeIndex];
7394
+ const previewColors = getThemeColors(previewThemeName);
7395
+ return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: previewColors.border, padding: 1, width: "100%", minHeight: 32 }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text, bold: true }, "Choose your color scheme:")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "row", width: "100%", flexGrow: 1 }, /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", width: "30%", paddingRight: 1 }, themeOptions.map((tName, index) => {
7396
+ const isSelected = themeIndex === index;
7397
+ const isSaved = (systemSettings.theme || "Dark") === tName;
7398
+ const isForest = tName === "Forest Sprite";
7399
+ return /* @__PURE__ */ React7.createElement(Box6, { key: tName, paddingX: 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? previewColors.text : previewColors.textDim, bold: isSelected }, isSelected ? "> " : " ", tName, isForest && /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? previewColors.success || "#52b788" : "green", bold: true }, " \u2605"), isSaved ? /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.primary || "cyan", italic: true }, " (saved)") : ""));
7400
+ })), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: previewColors.borderMuted, paddingX: 2, paddingY: 1, backgroundColor: previewColors.cardBg }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.secondary || "cyan", bold: true }, "> ", "you: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text }, "add a greeting function")), /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.success || "green" }, " Here's the change:")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", marginLeft: 2, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textDim }, "3 "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textDim }, ' import "fmt"')), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textDim }, "4"), /* @__PURE__ */ React7.createElement(Box6, { backgroundColor: previewColors.diffRemovalBg }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffRemovalNum || previewColors.diffRemovalText }, "5 "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffRemovalPrefix || previewColors.diffRemovalText }, "- "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffRemovalText }, "func "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffRemovalHighlightColor || previewColors.diffRemovalText, backgroundColor: previewColors.diffRemovalHighlightBg, bold: true }, "main()"), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffRemovalText }, " {"))), /* @__PURE__ */ React7.createElement(Box6, { backgroundColor: previewColors.diffAdditionBg }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionNum || previewColors.diffAdditionText }, "5 "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionPrefix || previewColors.diffAdditionText }, "+ "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionText }, "func "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionHighlightColor || previewColors.diffAdditionText, backgroundColor: previewColors.diffAdditionHighlightBg, bold: true }, "greet(name string)"), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionText }, " {"))), /* @__PURE__ */ React7.createElement(Box6, { backgroundColor: previewColors.diffAdditionBg }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionNum || previewColors.diffAdditionText }, "6 "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionPrefix || previewColors.diffAdditionText }, "+ "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionText }, " "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.diffAdditionHighlightColor || previewColors.diffAdditionText, backgroundColor: previewColors.diffAdditionHighlightBg }, 'fmt.Printf("Hello, %s!\\n", name)'))), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textDim }, "7 }")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textDim }, "\u25BE Thought Process"), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textMuted }, " I need to add a greeting function. I'll use fmt.Printf.")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.warning || "yellow" }, "\u2699 tool: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text }, "write_file main.go")), /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.accent || "magenta" }, "\u29BF task: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text }, "Implementing greeting")), /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.danger || "red" }, "X error: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text }, "compilation failed")), /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.warning || "yellow" }, "\u26A0 warning: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text }, "deprecation warning")), /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.info || "blue" }, "\u2192 link: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.info || "blue", underline: true }, "file:///path/to/main.go")), /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.accent || "magenta" }, "\u2605 accent: "), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.text }, "highlighted text")), /* @__PURE__ */ React7.createElement(Text7, { color: previewColors.textDim }, "\xB7 dim: press Enter to continue")))), /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, marginTop: 1, flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", italic: true }, "\u25B2\u25BC Navigate \u2022 ENTER to Select \u2022 ESC to Cancel"), /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Previewing: ", themeOptions[themeIndex], themeOptions[themeIndex] === "Forest Sprite" ? " \u2605" : "")));
7401
+ }
7096
7402
  return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: colors.border, padding: 0, width: "100%", minHeight: 32 }, /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, paddingY: 0, marginBottom: 0, borderStyle: "single", borderColor: colors.borderMuted, width: "100%" }, /* @__PURE__ */ React7.createElement(Text7, { color: colors.text, bold: true }, "SYSTEM CONFIGURATION")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "row", width: "100%", minHeight: 26 }, /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", width: "30%", maxWidth: 40, borderStyle: "round", borderColor: activeColumn === "categories" ? colors.border : colors.borderMuted, padding: 1, paddingY: 0 }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: activeColumn === "categories" ? colors.text : colors.textDim, bold: true, underline: true }, "CATEGORIES")), CATEGORIES.map((cat, index) => {
7097
7403
  const isSelected = selectedCategoryIndex === index;
7098
7404
  const isExit = cat.id === "exit";
@@ -7181,11 +7487,12 @@ function SettingsMenu({
7181
7487
  return elements;
7182
7488
  })() : /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, flexDirection: "column", width: "100%" }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", italic: true }, CATEGORIES[selectedCategoryIndex].desc), currentCatId === "exit" && /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 19, paddingX: 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: colors.text }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited")), /* @__PURE__ */ React7.createElement(Box6, { key: "memory-load-2026", paddingX: 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Memory Load: ", currentMemory, "/", maxMemory, " ", memoryUnit)))))), /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, marginTop: 0, flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", italic: true }, activeColumn === "categories" ? "\u25B2\u25BC Select Category \u2022 Enter/\u25BA to configure" : "\u25B2\u25BC Select Option \u2022 Enter to Toggle \u2022 \u25C4/ESC to go back"), activeColumn === "categories" && /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, CATEGORIES[selectedCategoryIndex].desc)));
7183
7489
  }
7184
- var CATEGORIES, getActivePreset, truncateCSV;
7490
+ var themeOptions, CATEGORIES, getActivePreset, truncateCSV;
7185
7491
  var init_SettingsMenu = __esm({
7186
7492
  async "src/components/SettingsMenu.jsx"() {
7187
7493
  await init_exec_command();
7188
7494
  init_theme();
7495
+ themeOptions = [...Object.keys(THEMES), "Mystery"];
7189
7496
  CATEGORIES = [
7190
7497
  { id: "appearance", label: "Appearance", desc: "Customize UI theme & rendering options" },
7191
7498
  { id: "memory", label: "Memory", desc: "Manage system context & agent's memory" },
@@ -11947,6 +12254,7 @@ __export(ai_exports, {
11947
12254
  runSubagent: () => runSubagent,
11948
12255
  signalTermination: () => signalTermination
11949
12256
  });
12257
+ import dotenv from "dotenv";
11950
12258
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
11951
12259
  import path24, { normalize } from "path";
11952
12260
  import fs25 from "fs";
@@ -11970,6 +12278,7 @@ var init_ai = __esm({
11970
12278
  init_revert();
11971
12279
  init_advanceRevert();
11972
12280
  init_editor();
12281
+ dotenv.config();
11973
12282
  RE_STUTTER_CODE_BLOCK_CLOSED = /```[\s\S]*?```/g;
11974
12283
  RE_STUTTER_CODE_BLOCK_OPEN = /```[\s\S]*$/g;
11975
12284
  RE_STUTTER_INLINE_CODE = /`[^`]+`/g;
@@ -12535,18 +12844,19 @@ var init_ai = __esm({
12535
12844
  let attempts = 0;
12536
12845
  const maxAttempts = 6;
12537
12846
  let hasYielded = false;
12538
- let baseUrl = process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1/chat/completions";
12539
- if (!baseUrl.endsWith("/chat/completions")) {
12540
- baseUrl = baseUrl.replace(/\/+$/, "") + "/chat/completions";
12847
+ let _baseUrl = process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1/chat/completions";
12848
+ let _apiKey = process.env.NVIDIA_API_KEY && process.env.NVIDIA_BASE_URL ? process.env.NVIDIA_API_KEY : apiKey;
12849
+ if (!_baseUrl.endsWith("/chat/completions")) {
12850
+ _baseUrl = _baseUrl.replace(/\/+$/, "") + "/chat/completions";
12541
12851
  }
12542
12852
  while (attempts < maxAttempts) {
12543
12853
  attempts++;
12544
12854
  try {
12545
- const response = await fetchWithBackoff(baseUrl, {
12855
+ const response = await fetchWithBackoff(_baseUrl, {
12546
12856
  method: "POST",
12547
12857
  headers: {
12548
12858
  "Content-Type": "application/json",
12549
- "Authorization": `Bearer ${apiKey}`
12859
+ "Authorization": `Bearer ${_apiKey}`
12550
12860
  },
12551
12861
  body: JSON.stringify(body),
12552
12862
  signal
@@ -17616,7 +17926,8 @@ var init_witty_phrases = __esm({
17616
17926
  // src/components/RevertModal.jsx
17617
17927
  import React14, { useState as useState13 } from "react";
17618
17928
  import { Box as Box13, Text as Text14, useInput as useInput8 } from "ink";
17619
- function RevertModal({ prompts, onSelect, onClose }) {
17929
+ function RevertModal({ prompts, onSelect, onClose, theme = "Dark" }) {
17930
+ const colors = getThemeColors(theme);
17620
17931
  const [selectedIndex, setSelectedIndex] = useState13(0);
17621
17932
  useInput8((input, key) => {
17622
17933
  if (key.escape) onClose();
@@ -17637,7 +17948,7 @@ function RevertModal({ prompts, onSelect, onClose }) {
17637
17948
  }
17638
17949
  }
17639
17950
  const visiblePrompts = prompts.slice(startIndex, startIndex + MAX_VISIBLE);
17640
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "grey", padding: 0, width: "100%" }, /* @__PURE__ */ React14.createElement(Box13, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true }, "CODEBASE TIME TRAVEL: SELECT UNDO POINT")), /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, null, "Select a prompt to revert the codebase back to the state ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "cyan" }, "immediately before"), " it was executed:")), prompts.length === 0 ? /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React14.createElement(Text14, { italic: true, color: "gray" }, "No prompt checkpoints found for this session.")) : /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", width: "100%" }, startIndex > 0 && /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, "\u25B2 (+", startIndex, " more prompts above)")), visiblePrompts.map((p, index) => {
17951
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, padding: 0, width: "100%" }, /* @__PURE__ */ React14.createElement(Box13, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: colors.text, bold: true }, "CODEBASE TIME TRAVEL: SELECT UNDO POINT")), /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: colors.text }, "Select a prompt to revert the codebase back to the state ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: colors.secondary || "cyan" }, "immediately before"), " it was executed:")), prompts.length === 0 ? /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React14.createElement(Text14, { italic: true, color: colors.textMuted }, "No prompt checkpoints found for this session.")) : /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", width: "100%" }, startIndex > 0 && /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: colors.textMuted }, "\u25B2 (+", startIndex, " more prompts above)")), visiblePrompts.map((p, index) => {
17641
17952
  const actualIndex = startIndex + index;
17642
17953
  const isSelected = actualIndex === selectedIndex;
17643
17954
  const dateStr = formatDate2(p.timestamp);
@@ -17647,12 +17958,12 @@ function RevertModal({ prompts, onSelect, onClose }) {
17647
17958
  {
17648
17959
  key: p.id,
17649
17960
  paddingX: 1,
17650
- backgroundColor: isSelected ? "#444444" : void 0,
17961
+ backgroundColor: isSelected ? colors.highlightBg : void 0,
17651
17962
  width: "100%"
17652
17963
  },
17653
- /* @__PURE__ */ React14.createElement(Box13, { flexGrow: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: isSelected ? "white" : "grey", bold: isSelected }, isSelected ? "\u276F " : " ", '"', formatPromptPreview(p.prompt), '"', /* @__PURE__ */ React14.createElement(Text14, { color: `${isSelected ? "white" : "grey"}`, dimColor: true }, " [", dateStr, " \u2022 ", fileCount, " file(s) changed]")))
17964
+ /* @__PURE__ */ React14.createElement(Box13, { flexGrow: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: isSelected ? colors.text : colors.textMuted, bold: isSelected }, isSelected ? "\u276F " : " ", '"', formatPromptPreview(p.prompt), '"', /* @__PURE__ */ React14.createElement(Text14, { color: colors.textMuted }, " [", dateStr, " \u2022 ", fileCount, " file(s) changed]")))
17654
17965
  );
17655
- }), startIndex + MAX_VISIBLE < prompts.length && /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, "\u25BC (+", prompts.length - (startIndex + MAX_VISIBLE), " more prompts below)"))), /* @__PURE__ */ React14.createElement(
17966
+ }), startIndex + MAX_VISIBLE < prompts.length && /* @__PURE__ */ React14.createElement(Box13, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: colors.textMuted }, "\u25BC (+", prompts.length - (startIndex + MAX_VISIBLE), " more prompts below)"))), /* @__PURE__ */ React14.createElement(
17656
17967
  Box13,
17657
17968
  {
17658
17969
  marginTop: 1,
@@ -17661,9 +17972,9 @@ function RevertModal({ prompts, onSelect, onClose }) {
17661
17972
  borderLeft: false,
17662
17973
  borderRight: false,
17663
17974
  borderBottom: false,
17664
- borderColor: "grey"
17975
+ borderColor: colors.borderMuted
17665
17976
  },
17666
- /* @__PURE__ */ React14.createElement(Text14, { color: "grey", italic: true }, "\u2191\u2193 navigate \u2022 Enter select undo point \u2022 Esc close")
17977
+ /* @__PURE__ */ React14.createElement(Text14, { color: colors.textMuted, italic: true }, "\u2191\u2193 navigate \u2022 Enter select undo point \u2022 Esc close")
17667
17978
  ));
17668
17979
  }
17669
17980
  function formatPromptPreview(prompt) {
@@ -17694,6 +18005,7 @@ function formatDate2(timestamp) {
17694
18005
  var init_RevertModal = __esm({
17695
18006
  "src/components/RevertModal.jsx"() {
17696
18007
  init_terminal();
18008
+ init_theme();
17697
18009
  }
17698
18010
  });
17699
18011
 
@@ -18180,6 +18492,7 @@ function App({ args = [] }) {
18180
18492
  const [quotas, setQuotas] = useState15({ limitMode: "Daily", agentLimit: 99999999, tokenLimit: 99999999999999, backgroundLimit: 999999, searchLimit: 100, customModelId: "", customLimit: 0, providerBudgets: {} });
18181
18493
  const [inputConfig, setInputConfig] = useState15(null);
18182
18494
  const [budgetReturnView, setBudgetReturnView] = useState15("chat");
18495
+ const [providerReturnView, setProviderReturnView] = useState15("settings");
18183
18496
  const [providerBudgetQueue, setProviderBudgetQueue] = useState15([]);
18184
18497
  const [providerBudgetCursor, setProviderBudgetCursor] = useState15(0);
18185
18498
  const [pbsCursor, setPbsCursor] = useState15(0);
@@ -19255,6 +19568,10 @@ function App({ args = [] }) {
19255
19568
  desc: "Select Agent Model",
19256
19569
  subs: getModels(aiProvider, apiTier)
19257
19570
  },
19571
+ {
19572
+ cmd: "/provider",
19573
+ desc: "Select AI Provider"
19574
+ },
19258
19575
  {
19259
19576
  cmd: "/mode",
19260
19577
  desc: "Toggle Flux/Flow modes",
@@ -19264,6 +19581,7 @@ function App({ args = [] }) {
19264
19581
  ]
19265
19582
  },
19266
19583
  { cmd: "/settings", desc: "Configure system prefs" },
19584
+ { cmd: "/theme", desc: "Customize UI color theme" },
19267
19585
  { cmd: "/key", desc: "Manage API keys" },
19268
19586
  { cmd: "/profile", desc: "Edit developer persona" },
19269
19587
  { cmd: "/memory", desc: "Manage agent memory" },
@@ -19771,6 +20089,16 @@ ${cleanText}`, color: "magenta" }];
19771
20089
  setActiveView("settings");
19772
20090
  break;
19773
20091
  }
20092
+ case "/provider":
20093
+ case "/providers": {
20094
+ setProviderReturnView("chat");
20095
+ setActiveView("selectProvider");
20096
+ break;
20097
+ }
20098
+ case "/theme": {
20099
+ setActiveView("theme");
20100
+ break;
20101
+ }
19774
20102
  case "/key": {
19775
20103
  setActiveView("key");
19776
20104
  break;
@@ -21105,7 +21433,26 @@ Selection: ${val}`,
21105
21433
  saveSettings,
21106
21434
  quotas,
21107
21435
  setMessages,
21108
- aiProvider
21436
+ aiProvider,
21437
+ setProviderReturnView
21438
+ }
21439
+ );
21440
+ case "theme":
21441
+ return /* @__PURE__ */ React16.createElement(
21442
+ SettingsMenu,
21443
+ {
21444
+ systemSettings,
21445
+ setSystemSettings,
21446
+ apiTier,
21447
+ setActiveView,
21448
+ setInputConfig,
21449
+ saveSettings,
21450
+ quotas,
21451
+ setMessages,
21452
+ aiProvider,
21453
+ initialSelectingTheme: true,
21454
+ onCloseTheme: () => setActiveView("chat"),
21455
+ setProviderReturnView
21109
21456
  }
21110
21457
  );
21111
21458
  case "selectProvider":
@@ -21119,12 +21466,12 @@ Selection: ${val}`,
21119
21466
  { label: "DeepSeek (Paid)", value: "DeepSeek" },
21120
21467
  { label: "Mistral (Free/Paid) [EXPERIMENTAL]", value: "Mistral" },
21121
21468
  { label: "OpenRouter (Free/Paid) [EXPERIMENTAL]", value: "OpenRouter" },
21122
- { label: "Back", value: "settings" }
21469
+ { label: "Back", value: providerReturnView }
21123
21470
  ],
21124
21471
  theme: systemSettings.theme,
21125
21472
  onSelect: async (item) => {
21126
- if (item.value === "settings" || item.value === "Back") {
21127
- setActiveView("settings");
21473
+ if (item.value === providerReturnView || item.value === "settings" || item.value === "Back") {
21474
+ setActiveView(providerReturnView);
21128
21475
  return;
21129
21476
  }
21130
21477
  const selectedProvider = item.value;
@@ -21151,19 +21498,19 @@ Selection: ${val}`,
21151
21498
  isMeta: true
21152
21499
  }
21153
21500
  ]);
21154
- setActiveView("settings");
21501
+ setActiveView(providerReturnView);
21155
21502
  } else {
21156
21503
  setInputConfig({
21157
21504
  label: `Enter ${selectedProvider} API Key:`,
21158
21505
  key: "providerKey",
21159
21506
  provider: selectedProvider,
21160
21507
  value: "",
21161
- returnView: "settings"
21508
+ returnView: providerReturnView
21162
21509
  });
21163
21510
  setActiveView("input");
21164
21511
  }
21165
21512
  },
21166
- onClose: () => setActiveView("settings")
21513
+ onClose: () => setActiveView(providerReturnView)
21167
21514
  }
21168
21515
  );
21169
21516
  case "apiTier": {
@@ -21522,7 +21869,7 @@ Selection: ${val}`,
21522
21869
  }
21523
21870
  )));
21524
21871
  case "advanceRollbackDanger":
21525
- return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, paddingTop: 0, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, "\u26A0 Emergency Rollback Notice"), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "When enabled, full repo snapshots exist only during active AI turns."), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "If catastrophic changes occur during a turn, avoid abruptly stopping the agent unless absolutely necessary (external damages out of codebase)."), /* @__PURE__ */ React16.createElement(Text16, null, "The agent may be able to automatically restore the repo to a safe state."), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "Once the turn ends, emergency snapshots are deleted and standard /revert takes over which may not retain full repo content."), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
21872
+ return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, paddingTop: 0, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, "\u26A0 Emergency Rollback Notice"), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "When enabled, full repo snapshots exist only during active AI turns."), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "If catastrophic changes occur during a turn, avoid abruptly stopping the agent unless absolutely necessary (external damages out of codebase)."), /* @__PURE__ */ React16.createElement(Text16, null, "The agent may be able to automatically restore the repo to a safe state."), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "Once the turn ends, emergency snapshots are deleted and standard /revert takes over which may not retain full repo content."), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1 }, "(Requires Restart to take effect)"), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
21526
21873
  CommandMenu,
21527
21874
  {
21528
21875
  title: "Confirm",
@@ -21708,7 +22055,8 @@ Selection: ${val}`,
21708
22055
  setActiveView("chat");
21709
22056
  }
21710
22057
  },
21711
- onClose: () => setActiveView("chat")
22058
+ onClose: () => setActiveView("chat"),
22059
+ theme: systemSettings.theme
21712
22060
  }
21713
22061
  ));
21714
22062
  case "resume":
@@ -22589,6 +22937,8 @@ var init_app = __esm({
22589
22937
  import { spawn as spawn3 } from "child_process";
22590
22938
  import { fileURLToPath as fileURLToPath4 } from "url";
22591
22939
  import os6 from "os";
22940
+ import dotenv2 from "dotenv";
22941
+ dotenv2.config();
22592
22942
  var totalSystemRamBytes = os6.totalmem();
22593
22943
  var totalSystemRamMB = totalSystemRamBytes / (1024 * 1024);
22594
22944
  var SAFETY_MARGIN = 0.5;
@@ -22674,12 +23024,12 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
22674
23024
  /btw <question> Send raw inquiry to the agent mid-turn
22675
23025
  /image setup key <default|custom> Configure image API key strategy
22676
23026
  /budget Set or View budget limits
22677
- /image setup quality <low...premium> Configure default image generation quality
22678
- /image stats Show image quota stats
22679
23027
  /mode <flux|flow> Toggle Flux/Flow modes
22680
23028
  /thinking <Fast|Low|Medium|High|xHigh> Set AI reasoning depth
22681
23029
  /model <model_name> Switch Model for Agent
23030
+ /provider Select AI Provider
22682
23031
  /settings Configure system preferences
23032
+ /theme Customize UI color theme
22683
23033
  /key Manage API keys
22684
23034
  /profile Edit developer persona
22685
23035
  /memory Manage agent memory
package/model_config.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 0,
3
- "release": 20260728,
3
+ "release": 20260729,
4
4
  "fallbacks": {
5
5
  "janitor_default": "gemini-3.1-flash-lite",
6
6
  "janitor_attempts_fallback": "gemma-4-26b-a4b-it",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.12.2",
4
- "date": "2026-07-28",
3
+ "version": "3.13.1",
4
+ "date": "2026-07-29",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",
@@ -41,12 +41,13 @@
41
41
  },
42
42
  "scripts": {
43
43
  "start": "tsx ./src/cli.jsx",
44
- "build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:@google/genai --external:zod --external:nanoid --external:puppeteer --external:pdf-lib --external:node-pty --external:html-to-docx --external:typescript --external:ws --external:web-tree-sitter --external:diff"
44
+ "build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:@google/genai --external:zod --external:nanoid --external:puppeteer --external:pdf-lib --external:node-pty --external:html-to-docx --external:typescript --external:ws --external:web-tree-sitter --external:diff --external:dotenv"
45
45
  },
46
46
  "dependencies": {
47
47
  "@google/genai": "^1.52.0",
48
48
  "chalk": "^5.6.2",
49
49
  "diff": "^9.0.0",
50
+ "dotenv": "^17.4.2",
50
51
  "fs-extra": "^11.3.4",
51
52
  "gradient-string": "^3.0.0",
52
53
  "html-to-docx": "^1.8.0",