@trydecember/cli 0.3.12 → 0.3.14

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/december.js CHANGED
@@ -23143,7 +23143,7 @@ var init_dist = __esm(() => {
23143
23143
  });
23144
23144
 
23145
23145
  // ../../packages/shared/src/env.ts
23146
- var env3;
23146
+ var env3, effectiveJwtSecret;
23147
23147
  var init_env = __esm(() => {
23148
23148
  init_dist();
23149
23149
  init_zod();
@@ -23161,7 +23161,7 @@ var init_env = __esm(() => {
23161
23161
  FIRECRACKER_BINARY: exports_external.string().default("./firecracker"),
23162
23162
  FIRECRACKER_KERNEL_PATH: exports_external.string().default("./vmlinux.bin"),
23163
23163
  FIRECRACKER_ROOTFS_PATH: exports_external.string().default("./ubuntu-rootfs.ext4"),
23164
- JWT_SECRET: exports_external.string().default("default-dev-jwt-secret")
23164
+ JWT_SECRET: exports_external.string().default(process.env.ACCESS_TOKEN_SECRET || "default-dev-jwt-secret")
23165
23165
  },
23166
23166
  clientPrefix: "",
23167
23167
  client: {},
@@ -23172,8 +23172,9 @@ var init_env = __esm(() => {
23172
23172
  throw new Error("Invalid shared environment variables");
23173
23173
  }
23174
23174
  });
23175
- if (env3.NODE_ENV === "production" && env3.JWT_SECRET === "default-dev-jwt-secret") {
23176
- throw new Error("JWT_SECRET must be configured with a secure secret in production.");
23175
+ effectiveJwtSecret = env3.JWT_SECRET || process.env.ACCESS_TOKEN_SECRET;
23176
+ if (env3.NODE_ENV === "production" && (!effectiveJwtSecret || effectiveJwtSecret === "default-dev-jwt-secret")) {
23177
+ throw new Error("JWT_SECRET or ACCESS_TOKEN_SECRET must be configured with a secure secret in production.");
23177
23178
  }
23178
23179
  });
23179
23180
 
@@ -63425,6 +63426,9 @@ function decomposeContext(options) {
63425
63426
  };
63426
63427
  }
63427
63428
 
63429
+ // ../../packages/shared/src/usage-rates.ts
63430
+ var init_usage_rates = () => {};
63431
+
63428
63432
  // ../../packages/shared/src/index.ts
63429
63433
  var init_src = __esm(() => {
63430
63434
  init_env();
@@ -63432,6 +63436,7 @@ var init_src = __esm(() => {
63432
63436
  init_ignore();
63433
63437
  init_custom_commands();
63434
63438
  init_permissions2();
63439
+ init_usage_rates();
63435
63440
  });
63436
63441
 
63437
63442
  // ../../packages/providers/src/providers/anthropic.ts
@@ -104735,7 +104740,8 @@ async function streamAssistantResponse(agent, eventQueue, signal, turnCount = 1)
104735
104740
  eventQueue.push({
104736
104741
  type: "AgentUsage",
104737
104742
  promptTokens: chunk.promptTokens,
104738
- completionTokens: chunk.completionTokens
104743
+ completionTokens: chunk.completionTokens,
104744
+ model: loggedModel
104739
104745
  });
104740
104746
  }
104741
104747
  }
@@ -108818,13 +108824,18 @@ function createLocalBashOperations() {
108818
108824
  cwd,
108819
108825
  detached: process.platform !== "win32",
108820
108826
  env: options.env ?? process.env,
108821
- shell: true
108827
+ shell: true,
108828
+ stdio: ["pipe", "pipe", "pipe"]
108822
108829
  });
108830
+ try {
108831
+ child.stdin?.end?.();
108832
+ } catch {}
108823
108833
  if (child.pid)
108824
108834
  trackDetachedChildPid(child.pid);
108825
108835
  let output = "";
108836
+ let resolved = false;
108826
108837
  const handleData = (data) => {
108827
- const chunk = data.toString();
108838
+ const chunk = typeof data === "string" ? data : data.toString();
108828
108839
  output += chunk;
108829
108840
  options.onData(chunk);
108830
108841
  };
@@ -108849,13 +108860,19 @@ function createLocalBashOperations() {
108849
108860
  else
108850
108861
  options.signal.addEventListener("abort", onAbort, { once: true });
108851
108862
  }
108852
- child.on("close", (code) => {
108863
+ const cleanup = () => {
108853
108864
  if (child.pid)
108854
108865
  untrackDetachedChildPid(child.pid);
108855
108866
  if (timeoutHandle)
108856
108867
  clearTimeout(timeoutHandle);
108857
108868
  if (options.signal)
108858
108869
  options.signal.removeEventListener("abort", onAbort);
108870
+ };
108871
+ const finish = (code) => {
108872
+ if (resolved)
108873
+ return;
108874
+ resolved = true;
108875
+ cleanup();
108859
108876
  if (timedOut) {
108860
108877
  return reject(new Error("timeout"));
108861
108878
  }
@@ -108863,6 +108880,17 @@ function createLocalBashOperations() {
108863
108880
  return reject(new Error("aborted"));
108864
108881
  }
108865
108882
  resolve4({ exitCode: code, output });
108883
+ };
108884
+ child.on("close", finish);
108885
+ child.on("exit", (code) => {
108886
+ setTimeout(() => finish(code), 50);
108887
+ });
108888
+ child.on("error", (err) => {
108889
+ if (resolved)
108890
+ return;
108891
+ resolved = true;
108892
+ cleanup();
108893
+ reject(err);
108866
108894
  });
108867
108895
  });
108868
108896
  }
@@ -213716,7 +213744,6 @@ var init_handoff = __esm(() => {
213716
213744
  });
213717
213745
 
213718
213746
  // ../../packages/tui/src/components/command-menu/commands.tsx
213719
- import { exec as exec5 } from "node:child_process";
213720
213747
  import fs17 from "node:fs";
213721
213748
  import os9 from "node:os";
213722
213749
  import path16 from "node:path";
@@ -214020,28 +214047,7 @@ build/
214020
214047
  name: "update",
214021
214048
  description: "Update to the latest version",
214022
214049
  value: "/update",
214023
- action: (ctx) => {
214024
- ctx.toast.show({ message: "Updating CLI..." });
214025
- exec5("npm install -g @trydecember/cli", async (err) => {
214026
- if (err) {
214027
- ctx.toast.show({
214028
- variant: "error",
214029
- message: "Update failed. Check your npm logs."
214030
- });
214031
- return;
214032
- }
214033
- if (ctx.agent) {
214034
- await ctx.agent.saveContext();
214035
- }
214036
- if (ctx.onUpdateSuccess) {
214037
- await ctx.onUpdateSuccess();
214038
- }
214039
- ctx.toast.show({
214040
- variant: "success",
214041
- message: "December CLI updated successfully! Please restart the CLI in your terminal."
214042
- });
214043
- });
214044
- }
214050
+ action: (ctx) => {}
214045
214051
  },
214046
214052
  {
214047
214053
  name: "usage",
@@ -214683,400 +214689,414 @@ var init_text_area = __esm(async () => {
214683
214689
  });
214684
214690
 
214685
214691
  // ../../packages/tui/src/components/input-bar.tsx
214686
- function InputBar({
214687
- onSubmit,
214688
- disabled = false,
214689
- placeholder = "Ask December to build...",
214690
- activeModel = "unknown",
214691
- authMethod,
214692
- hasBothAuth = false,
214693
- authUI,
214694
- agent: agent2,
214695
- resetChat,
214696
- onUpdateSuccess,
214697
- grillMode = false,
214698
- customInputMode = false,
214699
- onInterrupt,
214700
- onCopy,
214701
- contextTokens,
214702
- showExitConfirm = false,
214703
- toasts,
214704
- queuedPrompts
214705
- }) {
214706
- const [value2, setValue] = import_react42.useState("");
214707
- const toast = useToast();
214708
- const dialog = useDialog();
214709
- const columns = useTerminalColumns();
214710
- const [selectedFileIndex, setSelectedFileIndex] = import_react42.useState(0);
214711
- const [allWorkspaceFiles, setAllWorkspaceFiles] = import_react42.useState([]);
214712
- const activeToast = toasts && toasts.length > 0 ? toasts[toasts.length - 1] : toast.currentToast ? { message: toast.currentToast.message, variant: toast.currentToast.variant } : null;
214713
- const handleContentChangeRef = import_react42.useRef(() => {});
214714
- const handleAutocompleteCommand = import_react42.useCallback((completedText) => {
214715
- setValue(completedText);
214716
- handleContentChangeRef.current(completedText);
214717
- }, []);
214718
- const {
214719
- showCommandMenu,
214720
- commandQuery,
214721
- selectedIndex,
214722
- windowStart,
214723
- handleContentChange,
214724
- resolveCommand,
214725
- setSelectedIndex
214726
- } = useCommandMenu({ onAutocomplete: handleAutocompleteCommand });
214727
- handleContentChangeRef.current = handleContentChange;
214728
- const [showShortcutsMenu, setShowShortcutsMenu] = import_react42.useState(false);
214729
- import_react42.useEffect(() => {
214730
- try {
214731
- const ignores = getWorkspaceIgnores();
214732
- const files = import_fast_glob.default.sync(["**/*"], {
214733
- dot: true,
214734
- ignore: ignores,
214735
- onlyFiles: true,
214736
- suppressErrors: true
214737
- });
214738
- setAllWorkspaceFiles(files);
214739
- } catch {
214740
- setAllWorkspaceFiles([]);
214741
- }
214742
- }, []);
214743
- const fileMatch = value2.match(/@(\S*)$/);
214744
- const showFileMenu = Boolean(fileMatch) && !showCommandMenu && !showShortcutsMenu;
214745
- const fileQuery = fileMatch ? fileMatch[1]?.toLowerCase() || "" : "";
214746
- const matchingFiles = import_react42.useMemo(() => {
214747
- if (!showFileMenu)
214748
- return [];
214749
- return allWorkspaceFiles.filter((f3) => f3.toLowerCase().includes(fileQuery)).slice(0, MAX_FILE_SUGGESTIONS);
214750
- }, [showFileMenu, allWorkspaceFiles, fileQuery]);
214751
- const isCtrlW = import_react42.useRef(false);
214752
- use_input_default((input, key) => {
214753
- if (showFileMenu && matchingFiles.length > 0) {
214754
- if (key.upArrow) {
214755
- setSelectedFileIndex((prev2) => Math.max(0, prev2 - 1));
214756
- return;
214757
- }
214758
- if (key.downArrow) {
214759
- setSelectedFileIndex((prev2) => Math.min(matchingFiles.length - 1, prev2 + 1));
214692
+ var import_fast_glob, import_react42, jsx_runtime8, MAX_FILE_SUGGESTIONS = 5, InputBar;
214693
+ var init_input_bar = __esm(async () => {
214694
+ init_src();
214695
+ init_theme();
214696
+ init_prompt_history();
214697
+ await __promiseAll([
214698
+ init_build2(),
214699
+ init_use_terminal_columns(),
214700
+ init_dialog(),
214701
+ init_toast(),
214702
+ init_command_menu(),
214703
+ init_use_command_menu(),
214704
+ init_shortcuts_menu(),
214705
+ init_text_area()
214706
+ ]);
214707
+ import_fast_glob = __toESM(require_out4(), 1);
214708
+ import_react42 = __toESM(require_react(), 1);
214709
+ jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
214710
+ InputBar = import_react42.default.memo(function InputBar2({
214711
+ onSubmit,
214712
+ disabled = false,
214713
+ placeholder = "Ask December to build...",
214714
+ activeModel = "unknown",
214715
+ authMethod,
214716
+ hasBothAuth = false,
214717
+ authUI,
214718
+ agent: agent2,
214719
+ resetChat,
214720
+ onUpdateSuccess,
214721
+ grillMode = false,
214722
+ customInputMode = false,
214723
+ onInterrupt,
214724
+ onCopy,
214725
+ contextTokens,
214726
+ showExitConfirm = false,
214727
+ toasts,
214728
+ queuedPrompts
214729
+ }) {
214730
+ const [value2, setValue] = import_react42.useState("");
214731
+ const toast = useToast();
214732
+ const dialog = useDialog();
214733
+ const columns = useTerminalColumns();
214734
+ const [selectedFileIndex, setSelectedFileIndex] = import_react42.useState(0);
214735
+ const [allWorkspaceFiles, setAllWorkspaceFiles] = import_react42.useState([]);
214736
+ const activeToast = toasts && toasts.length > 0 ? toasts[toasts.length - 1] : toast.currentToast ? { message: toast.currentToast.message, variant: toast.currentToast.variant } : null;
214737
+ const handleContentChangeRef = import_react42.useRef(() => {});
214738
+ const handleAutocompleteCommand = import_react42.useCallback((completedText) => {
214739
+ setValue(completedText);
214740
+ handleContentChangeRef.current(completedText);
214741
+ }, []);
214742
+ const {
214743
+ showCommandMenu,
214744
+ commandQuery,
214745
+ selectedIndex,
214746
+ windowStart,
214747
+ handleContentChange,
214748
+ resolveCommand,
214749
+ setSelectedIndex
214750
+ } = useCommandMenu({ onAutocomplete: handleAutocompleteCommand });
214751
+ handleContentChangeRef.current = handleContentChange;
214752
+ const [showShortcutsMenu, setShowShortcutsMenu] = import_react42.useState(false);
214753
+ const fileMatch = value2.match(/@(\S*)$/);
214754
+ const showFileMenu = Boolean(fileMatch) && !showCommandMenu && !showShortcutsMenu;
214755
+ const fileQuery = fileMatch ? fileMatch[1]?.toLowerCase() || "" : "";
214756
+ import_react42.useEffect(() => {
214757
+ if (!fileMatch || allWorkspaceFiles.length > 0)
214760
214758
  return;
214759
+ let isMounted = true;
214760
+ try {
214761
+ const ignores = getWorkspaceIgnores();
214762
+ import_fast_glob.default(["**/*"], {
214763
+ dot: true,
214764
+ ignore: ignores,
214765
+ onlyFiles: true,
214766
+ suppressErrors: true
214767
+ }).then((files) => {
214768
+ if (isMounted) {
214769
+ setAllWorkspaceFiles(files);
214770
+ }
214771
+ }).catch(() => {
214772
+ if (isMounted) {
214773
+ setAllWorkspaceFiles([]);
214774
+ }
214775
+ });
214776
+ } catch {
214777
+ setAllWorkspaceFiles([]);
214761
214778
  }
214762
- if (key.tab || key.return) {
214763
- const selectedFile = matchingFiles[selectedFileIndex];
214764
- if (selectedFile) {
214765
- const nextVal = value2.replace(/@\S*$/, `@${selectedFile} `);
214779
+ return () => {
214780
+ isMounted = false;
214781
+ };
214782
+ }, [fileMatch, allWorkspaceFiles.length]);
214783
+ const matchingFiles = import_react42.useMemo(() => {
214784
+ if (!showFileMenu)
214785
+ return [];
214786
+ return allWorkspaceFiles.filter((f3) => f3.toLowerCase().includes(fileQuery)).slice(0, MAX_FILE_SUGGESTIONS);
214787
+ }, [showFileMenu, allWorkspaceFiles, fileQuery]);
214788
+ const isCtrlW = import_react42.useRef(false);
214789
+ use_input_default((input, key) => {
214790
+ if (showFileMenu && matchingFiles.length > 0) {
214791
+ if (key.upArrow) {
214792
+ setSelectedFileIndex((prev2) => Math.max(0, prev2 - 1));
214793
+ return;
214794
+ }
214795
+ if (key.downArrow) {
214796
+ setSelectedFileIndex((prev2) => Math.min(matchingFiles.length - 1, prev2 + 1));
214797
+ return;
214798
+ }
214799
+ if (key.tab || key.return) {
214800
+ const selectedFile = matchingFiles[selectedFileIndex];
214801
+ if (selectedFile) {
214802
+ const nextVal = value2.replace(/@\S*$/, `@${selectedFile} `);
214803
+ setValue(nextVal);
214804
+ handleContentChange(nextVal);
214805
+ setSelectedFileIndex(0);
214806
+ }
214807
+ return;
214808
+ }
214809
+ if (key.escape) {
214810
+ const nextVal = value2.replace(/@\S*$/, "");
214766
214811
  setValue(nextVal);
214767
214812
  handleContentChange(nextVal);
214768
- setSelectedFileIndex(0);
214813
+ return;
214769
214814
  }
214815
+ }
214816
+ if (key.ctrl && input === "w") {
214817
+ isCtrlW.current = true;
214818
+ setValue((prev2) => {
214819
+ const match2 = prev2.match(/(\s*\S+\s*)$/);
214820
+ const next2 = match2 ? prev2.slice(0, -match2[0].length) : prev2;
214821
+ handleContentChange(next2);
214822
+ return next2;
214823
+ });
214824
+ }
214825
+ if ((key.backspace || key.delete) && value2.length === 0 && grillMode) {
214826
+ onSubmit("/grill-me");
214827
+ }
214828
+ if (key.ctrl && input === "c") {
214829
+ if (onInterrupt)
214830
+ onInterrupt();
214770
214831
  return;
214771
214832
  }
214772
- if (key.escape) {
214773
- const nextVal = value2.replace(/@\S*$/, "");
214774
- setValue(nextVal);
214775
- handleContentChange(nextVal);
214833
+ if (key.ctrl && input === "y") {
214834
+ if (onCopy)
214835
+ onCopy();
214776
214836
  return;
214777
214837
  }
214778
- }
214779
- if (key.ctrl && input === "w") {
214780
- isCtrlW.current = true;
214781
- setValue((prev2) => {
214782
- const match2 = prev2.match(/(\s*\S+\s*)$/);
214783
- const next2 = match2 ? prev2.slice(0, -match2[0].length) : prev2;
214838
+ });
214839
+ const handleChange = import_react42.useCallback((newValue) => {
214840
+ if (disabled)
214841
+ return;
214842
+ if (isCtrlW.current) {
214843
+ isCtrlW.current = false;
214844
+ return;
214845
+ }
214846
+ if (newValue === "?") {
214847
+ setShowShortcutsMenu(true);
214848
+ setValue("?");
214849
+ return;
214850
+ } else if (showShortcutsMenu) {
214851
+ setShowShortcutsMenu(false);
214852
+ }
214853
+ setValue(newValue);
214854
+ handleContentChange(newValue);
214855
+ setSelectedFileIndex(0);
214856
+ }, [disabled, handleContentChange, showShortcutsMenu]);
214857
+ const handleHistoryUp = import_react42.useCallback(() => {
214858
+ const prev2 = defaultPromptHistory.getPrevious(value2);
214859
+ if (prev2 !== value2) {
214860
+ setValue(prev2);
214861
+ handleContentChange(prev2);
214862
+ }
214863
+ }, [value2, handleContentChange]);
214864
+ const handleHistoryDown = import_react42.useCallback(() => {
214865
+ const next2 = defaultPromptHistory.getNext();
214866
+ if (next2 !== value2) {
214867
+ setValue(next2);
214784
214868
  handleContentChange(next2);
214785
- return next2;
214786
- });
214787
- }
214788
- if ((key.backspace || key.delete) && value2.length === 0 && grillMode) {
214789
- onSubmit("/grill-me");
214790
- }
214791
- if (key.ctrl && input === "c") {
214792
- if (onInterrupt)
214793
- onInterrupt();
214794
- return;
214795
- }
214796
- if (key.ctrl && input === "y") {
214797
- if (onCopy)
214798
- onCopy();
214799
- return;
214800
- }
214801
- });
214802
- const handleChange = import_react42.useCallback((newValue) => {
214803
- if (disabled)
214804
- return;
214805
- if (isCtrlW.current) {
214806
- isCtrlW.current = false;
214807
- return;
214808
- }
214809
- if (newValue === "?") {
214810
- setShowShortcutsMenu(true);
214811
- setValue("?");
214812
- return;
214813
- } else if (showShortcutsMenu) {
214814
- setShowShortcutsMenu(false);
214815
- }
214816
- setValue(newValue);
214817
- handleContentChange(newValue);
214818
- setSelectedFileIndex(0);
214819
- }, [disabled, handleContentChange, showShortcutsMenu]);
214820
- const handleHistoryUp = import_react42.useCallback(() => {
214821
- const prev2 = defaultPromptHistory.getPrevious(value2);
214822
- if (prev2 !== value2) {
214823
- setValue(prev2);
214824
- handleContentChange(prev2);
214825
- }
214826
- }, [value2, handleContentChange]);
214827
- const handleHistoryDown = import_react42.useCallback(() => {
214828
- const next2 = defaultPromptHistory.getNext();
214829
- if (next2 !== value2) {
214830
- setValue(next2);
214831
- handleContentChange(next2);
214832
- }
214833
- }, [value2, handleContentChange]);
214834
- const handleCommand = import_react42.useCallback((command) => {
214835
- if (!command)
214836
- return;
214837
- const currentValue = value2.trim();
214838
- setValue("");
214839
- handleContentChange("");
214840
- const forwardCommands = [
214841
- "/grill-me",
214842
- "/login",
214843
- "/logout",
214844
- "/exit",
214845
- "/model",
214846
- "/plan",
214847
- "/resume",
214848
- "/settings",
214849
- "/context",
214850
- "/tasks",
214851
- "/usage",
214852
- "/feedback",
214853
- "/mcp"
214854
- ];
214855
- if (forwardCommands.includes(command.value) || !command.action) {
214856
- if (currentValue.length > command.value.length && currentValue.toLowerCase().startsWith(command.value.toLowerCase())) {
214857
- onSubmit(currentValue);
214858
- } else {
214859
- onSubmit(command.value);
214860
214869
  }
214861
- return;
214862
- }
214863
- if (command.action) {
214864
- command.action({
214865
- exit: () => process.exit(0),
214866
- toast,
214867
- dialog,
214868
- agent: agent2,
214869
- resetChat,
214870
- onUpdateSuccess
214871
- });
214872
- }
214873
- }, [toast, dialog, agent2, resetChat, onUpdateSuccess, handleContentChange, onSubmit, value2]);
214874
- const handleSubmit = import_react42.useCallback((text3) => {
214875
- if (disabled)
214876
- return;
214877
- if (showCommandMenu) {
214878
- const command = resolveCommand(selectedIndex);
214879
- handleCommand(command);
214880
- return;
214881
- }
214882
- if (showShortcutsMenu) {
214883
- return;
214884
- }
214885
- const trimmed = text3.trim();
214886
- if (trimmed.length === 0)
214887
- return;
214888
- defaultPromptHistory.append(trimmed);
214889
- defaultPromptHistory.resetCursor();
214890
- onSubmit(trimmed);
214891
- setValue("");
214892
- handleContentChange("");
214893
- }, [
214894
- disabled,
214895
- showCommandMenu,
214896
- showShortcutsMenu,
214897
- resolveCommand,
214898
- selectedIndex,
214899
- handleCommand,
214900
- onSubmit,
214901
- handleContentChange
214902
- ]);
214903
- const sepWidth = Math.max(10, columns - THEME.padding.paddingX * 2);
214904
- const sep4 = "─".repeat(sepWidth);
214905
- return /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214906
- flexDirection: "column",
214907
- paddingX: THEME.padding.paddingX,
214908
- marginTop: 1,
214909
- children: [
214910
- dialog.isOpen && dialog.currentDialog && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214911
- justifyContent: "flex-end",
214912
- children: /* @__PURE__ */ jsx_runtime8.jsx(InlineDialog, {
214913
- config: dialog.currentDialog,
214914
- close: dialog.close
214915
- })
214916
- }),
214917
- queuedPrompts && queuedPrompts.length > 0 && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214918
- width: "100%",
214919
- marginBottom: 0,
214920
- children: /* @__PURE__ */ jsx_runtime8.jsxs(Text3, {
214921
- color: THEME.colors.brand,
214922
- children: [
214923
- `Queued (${queuedPrompts.length}): "${queuedPrompts[0]}"`,
214924
- queuedPrompts.length > 1 ? ` (+${queuedPrompts.length - 1} more)` : ""
214925
- ]
214926
- })
214927
- }),
214928
- showFileMenu && matchingFiles.length > 0 && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214929
- flexDirection: "column",
214930
- paddingLeft: 1,
214931
- marginBottom: 0,
214932
- children: matchingFiles.map((file, idx) => {
214933
- const isSelected = idx === selectedFileIndex;
214934
- return /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214935
- flexDirection: "row",
214936
- gap: 1,
214870
+ }, [value2, handleContentChange]);
214871
+ const handleCommand = import_react42.useCallback((command) => {
214872
+ if (!command)
214873
+ return;
214874
+ const currentValue = value2.trim();
214875
+ setValue("");
214876
+ handleContentChange("");
214877
+ const forwardCommands = [
214878
+ "/grill-me",
214879
+ "/login",
214880
+ "/logout",
214881
+ "/exit",
214882
+ "/model",
214883
+ "/plan",
214884
+ "/resume",
214885
+ "/settings",
214886
+ "/context",
214887
+ "/tasks",
214888
+ "/usage",
214889
+ "/feedback",
214890
+ "/mcp",
214891
+ "/update"
214892
+ ];
214893
+ if (forwardCommands.includes(command.value) || !command.action) {
214894
+ if (currentValue.length > command.value.length && currentValue.toLowerCase().startsWith(command.value.toLowerCase())) {
214895
+ onSubmit(currentValue);
214896
+ } else {
214897
+ onSubmit(command.value);
214898
+ }
214899
+ return;
214900
+ }
214901
+ if (command.action) {
214902
+ command.action({
214903
+ exit: () => process.exit(0),
214904
+ toast,
214905
+ dialog,
214906
+ agent: agent2,
214907
+ resetChat,
214908
+ onUpdateSuccess
214909
+ });
214910
+ }
214911
+ }, [toast, dialog, agent2, resetChat, onUpdateSuccess, handleContentChange, onSubmit, value2]);
214912
+ const handleSubmit = import_react42.useCallback((text3) => {
214913
+ if (disabled)
214914
+ return;
214915
+ if (showCommandMenu) {
214916
+ const command = resolveCommand(selectedIndex);
214917
+ handleCommand(command);
214918
+ return;
214919
+ }
214920
+ if (showShortcutsMenu) {
214921
+ return;
214922
+ }
214923
+ const trimmed = text3.trim();
214924
+ if (trimmed.length === 0)
214925
+ return;
214926
+ defaultPromptHistory.append(trimmed);
214927
+ defaultPromptHistory.resetCursor();
214928
+ onSubmit(trimmed);
214929
+ setValue("");
214930
+ handleContentChange("");
214931
+ }, [
214932
+ disabled,
214933
+ showCommandMenu,
214934
+ showShortcutsMenu,
214935
+ resolveCommand,
214936
+ selectedIndex,
214937
+ handleCommand,
214938
+ onSubmit,
214939
+ handleContentChange
214940
+ ]);
214941
+ const sepWidth = Math.max(10, columns - THEME.padding.paddingX * 2);
214942
+ const sep4 = "─".repeat(sepWidth);
214943
+ return /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214944
+ flexDirection: "column",
214945
+ paddingX: THEME.padding.paddingX,
214946
+ marginTop: 1,
214947
+ children: [
214948
+ dialog.isOpen && dialog.currentDialog && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214949
+ justifyContent: "flex-end",
214950
+ children: /* @__PURE__ */ jsx_runtime8.jsx(InlineDialog, {
214951
+ config: dialog.currentDialog,
214952
+ close: dialog.close
214953
+ })
214954
+ }),
214955
+ queuedPrompts && queuedPrompts.length > 0 && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214956
+ width: "100%",
214957
+ marginBottom: 0,
214958
+ children: /* @__PURE__ */ jsx_runtime8.jsxs(Text3, {
214959
+ color: THEME.colors.brand,
214937
214960
  children: [
214938
- /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214939
- color: isSelected ? THEME.colors.brand : THEME.colors.muted,
214940
- children: isSelected ? `${THEME.glyphs.selector} ` : " "
214941
- }),
214942
- /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214943
- color: isSelected ? THEME.colors.brand : THEME.colors.text,
214944
- children: file
214945
- })
214961
+ `Queued (${queuedPrompts.length}): "${queuedPrompts[0]}"`,
214962
+ queuedPrompts.length > 1 ? ` (+${queuedPrompts.length - 1} more)` : ""
214946
214963
  ]
214947
- }, file);
214948
- })
214949
- }),
214950
- /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214951
- overflow: "hidden",
214952
- height: 1,
214953
- width: "100%",
214954
- children: /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214955
- color: THEME.colors.border,
214956
- wrap: "truncate",
214957
- children: sep4
214958
- })
214959
- }),
214960
- /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214961
- width: "100%",
214962
- paddingRight: 4,
214963
- children: [
214964
- /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214965
- color: disabled ? THEME.colors.muted : THEME.colors.brand,
214966
- children: `${THEME.glyphs.prompt} `
214967
- }),
214968
- grillMode && /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214969
- color: THEME.colors.brand,
214970
- children: "/grill-me "
214971
- }),
214972
- (!authUI || customInputMode) && /* @__PURE__ */ jsx_runtime8.jsx(TextArea, {
214973
- value: value2,
214974
- onChange: handleChange,
214975
- onSubmit: handleSubmit,
214976
- onHistoryUp: handleHistoryUp,
214977
- onHistoryDown: handleHistoryDown,
214978
- placeholder: customInputMode ? "Type your custom answer..." : grillMode ? "" : placeholder,
214979
- focus: !disabled && !dialog.isOpen,
214980
- disableHistoryNav: showCommandMenu || showFileMenu || showShortcutsMenu
214981
214964
  })
214982
- ]
214983
- }),
214984
- /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214985
- overflow: "hidden",
214986
- height: 1,
214987
- width: "100%",
214988
- children: /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214989
- color: THEME.colors.border,
214990
- wrap: "truncate",
214991
- children: sep4
214992
- })
214993
- }),
214994
- !showCommandMenu && !showShortcutsMenu && !authUI && /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214995
- width: "100%",
214996
- justifyContent: "space-between",
214997
- children: [
214998
- /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214999
- gap: 2,
215000
- alignItems: "center",
215001
- flexShrink: 1,
215002
- children: /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214965
+ }),
214966
+ showFileMenu && matchingFiles.length > 0 && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214967
+ flexDirection: "column",
214968
+ paddingLeft: 1,
214969
+ marginBottom: 0,
214970
+ children: matchingFiles.map((file, idx) => {
214971
+ const isSelected = idx === selectedFileIndex;
214972
+ return /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214973
+ flexDirection: "row",
215003
214974
  gap: 1,
215004
- flexShrink: 1,
215005
214975
  children: [
215006
- /* @__PURE__ */ jsx_runtime8.jsxs(Text3, {
215007
- color: THEME.colors.muted,
215008
- children: [
215009
- activeModel,
215010
- hasBothAuth && authMethod ? ` (${authMethod === "december" ? "December Cloud" : "BYOK"})` : ""
215011
- ]
214976
+ /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214977
+ color: isSelected ? THEME.colors.brand : THEME.colors.muted,
214978
+ children: isSelected ? `${THEME.glyphs.selector} ` : " "
215012
214979
  }),
215013
- activeToast ? /* @__PURE__ */ jsx_runtime8.jsxs(Text3, {
215014
- wrap: "truncate",
215015
- color: activeToast.variant === "success" ? THEME.colors.success : activeToast.variant === "error" ? THEME.colors.error : THEME.colors.muted,
215016
- children: [
215017
- "· ",
215018
- activeToast.message.replace(/\s+/g, " ").trim()
215019
- ]
215020
- }) : showExitConfirm ? /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215021
- color: THEME.colors.muted,
215022
- children: "· Press Ctrl+C again to exit"
215023
- }) : null
214980
+ /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214981
+ color: isSelected ? THEME.colors.brand : THEME.colors.text,
214982
+ children: file
214983
+ })
215024
214984
  ]
214985
+ }, file);
214986
+ })
214987
+ }),
214988
+ /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
214989
+ overflow: "hidden",
214990
+ height: 1,
214991
+ width: "100%",
214992
+ children: /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
214993
+ color: THEME.colors.border,
214994
+ wrap: "truncate",
214995
+ children: sep4
214996
+ })
214997
+ }),
214998
+ /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
214999
+ width: "100%",
215000
+ paddingRight: 4,
215001
+ children: [
215002
+ /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215003
+ color: disabled ? THEME.colors.muted : THEME.colors.brand,
215004
+ children: `${THEME.glyphs.prompt} `
215005
+ }),
215006
+ grillMode && /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215007
+ color: THEME.colors.brand,
215008
+ children: "/grill-me "
215009
+ }),
215010
+ (!authUI || customInputMode) && /* @__PURE__ */ jsx_runtime8.jsx(TextArea, {
215011
+ value: value2,
215012
+ onChange: handleChange,
215013
+ onSubmit: handleSubmit,
215014
+ onHistoryUp: handleHistoryUp,
215015
+ onHistoryDown: handleHistoryDown,
215016
+ placeholder: customInputMode ? "Type your custom answer..." : grillMode ? "" : placeholder,
215017
+ focus: !disabled && !dialog.isOpen,
215018
+ disableHistoryNav: showCommandMenu || showFileMenu || showShortcutsMenu
215025
215019
  })
215026
- }),
215027
- /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
215028
- gap: 0,
215029
- flexShrink: 0,
215030
- marginLeft: 2,
215031
- children: /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215032
- color: THEME.colors.muted,
215033
- children: "? for shortcuts"
215034
- })
215020
+ ]
215021
+ }),
215022
+ /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
215023
+ overflow: "hidden",
215024
+ height: 1,
215025
+ width: "100%",
215026
+ children: /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215027
+ color: THEME.colors.border,
215028
+ wrap: "truncate",
215029
+ children: sep4
215035
215030
  })
215036
- ]
215037
- }),
215038
- authUI && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
215039
- paddingBottom: 1,
215040
- children: authUI
215041
- }),
215042
- showCommandMenu && /* @__PURE__ */ jsx_runtime8.jsx(CommandMenu, {
215043
- query: commandQuery,
215044
- selectedIndex,
215045
- windowStart,
215046
- totalFiltered: 0,
215047
- onSelect: setSelectedIndex,
215048
- onExecute: (index2) => {
215049
- const command = resolveCommand(index2);
215050
- handleCommand(command);
215051
- }
215052
- }),
215053
- showShortcutsMenu && /* @__PURE__ */ jsx_runtime8.jsx(ShortcutsMenu, {
215054
- onClose: () => {
215055
- setShowShortcutsMenu(false);
215056
- setValue("");
215057
- }
215058
- })
215059
- ]
215031
+ }),
215032
+ !showCommandMenu && !showShortcutsMenu && !authUI && /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
215033
+ width: "100%",
215034
+ justifyContent: "space-between",
215035
+ children: [
215036
+ /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
215037
+ gap: 2,
215038
+ alignItems: "center",
215039
+ flexShrink: 1,
215040
+ children: /* @__PURE__ */ jsx_runtime8.jsxs(Box_default, {
215041
+ gap: 1,
215042
+ flexShrink: 1,
215043
+ children: [
215044
+ /* @__PURE__ */ jsx_runtime8.jsxs(Text3, {
215045
+ color: THEME.colors.muted,
215046
+ children: [
215047
+ activeModel,
215048
+ hasBothAuth && authMethod ? ` (${authMethod === "december" ? "December Cloud" : "BYOK"})` : ""
215049
+ ]
215050
+ }),
215051
+ activeToast ? /* @__PURE__ */ jsx_runtime8.jsxs(Text3, {
215052
+ wrap: "truncate",
215053
+ color: activeToast.variant === "success" ? THEME.colors.success : activeToast.variant === "error" ? THEME.colors.error : THEME.colors.muted,
215054
+ children: [
215055
+ "· ",
215056
+ activeToast.message.replace(/\s+/g, " ").trim()
215057
+ ]
215058
+ }) : showExitConfirm ? /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215059
+ color: THEME.colors.muted,
215060
+ children: "· Press Ctrl+C again to exit"
215061
+ }) : null
215062
+ ]
215063
+ })
215064
+ }),
215065
+ /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
215066
+ gap: 0,
215067
+ flexShrink: 0,
215068
+ marginLeft: 2,
215069
+ children: /* @__PURE__ */ jsx_runtime8.jsx(Text3, {
215070
+ color: THEME.colors.muted,
215071
+ children: "? for shortcuts"
215072
+ })
215073
+ })
215074
+ ]
215075
+ }),
215076
+ authUI && /* @__PURE__ */ jsx_runtime8.jsx(Box_default, {
215077
+ paddingBottom: 1,
215078
+ children: authUI
215079
+ }),
215080
+ showCommandMenu && /* @__PURE__ */ jsx_runtime8.jsx(CommandMenu, {
215081
+ query: commandQuery,
215082
+ selectedIndex,
215083
+ windowStart,
215084
+ totalFiltered: 0,
215085
+ onSelect: setSelectedIndex,
215086
+ onExecute: (index2) => {
215087
+ const command = resolveCommand(index2);
215088
+ handleCommand(command);
215089
+ }
215090
+ }),
215091
+ showShortcutsMenu && /* @__PURE__ */ jsx_runtime8.jsx(ShortcutsMenu, {
215092
+ onClose: () => {
215093
+ setShowShortcutsMenu(false);
215094
+ setValue("");
215095
+ }
215096
+ })
215097
+ ]
215098
+ });
215060
215099
  });
215061
- }
215062
- var import_fast_glob, import_react42, jsx_runtime8, MAX_FILE_SUGGESTIONS = 5;
215063
- var init_input_bar = __esm(async () => {
215064
- init_src();
215065
- init_theme();
215066
- init_prompt_history();
215067
- await __promiseAll([
215068
- init_build2(),
215069
- init_use_terminal_columns(),
215070
- init_dialog(),
215071
- init_toast(),
215072
- init_command_menu(),
215073
- init_use_command_menu(),
215074
- init_shortcuts_menu(),
215075
- init_text_area()
215076
- ]);
215077
- import_fast_glob = __toESM(require_out4(), 1);
215078
- import_react42 = __toESM(require_react(), 1);
215079
- jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
215080
215100
  });
215081
215101
 
215082
215102
  // ../../node_modules/.bun/cli-spinners@2.9.2/node_modules/cli-spinners/spinners.json
@@ -260441,14 +260461,40 @@ ${r2}`;
260441
260461
  });
260442
260462
 
260443
260463
  // ../../packages/tui/src/components/header.tsx
260444
- import { execSync } from "node:child_process";
260464
+ import fs18 from "node:fs";
260445
260465
  import { homedir } from "node:os";
260446
- function getGitBranch() {
260447
- try {
260448
- return execSync("git rev-parse --abbrev-ref HEAD", { stdio: "pipe" }).toString().trim();
260449
- } catch {
260450
- return null;
260466
+ import path17 from "node:path";
260467
+ function getGitBranch(workspaceRoot = process.cwd()) {
260468
+ if (cachedBranch !== undefined) {
260469
+ return cachedBranch;
260451
260470
  }
260471
+ try {
260472
+ const gitPath = path17.resolve(workspaceRoot, ".git");
260473
+ if (fs18.existsSync(gitPath)) {
260474
+ const stat4 = fs18.statSync(gitPath);
260475
+ let headPath = path17.resolve(gitPath, "HEAD");
260476
+ if (stat4.isFile()) {
260477
+ const content = fs18.readFileSync(gitPath, "utf-8").trim();
260478
+ if (content.startsWith("gitdir:")) {
260479
+ const gitDir = content.slice(7).trim();
260480
+ headPath = path17.resolve(workspaceRoot, gitDir, "HEAD");
260481
+ }
260482
+ }
260483
+ if (fs18.existsSync(headPath)) {
260484
+ const headContent = fs18.readFileSync(headPath, "utf-8").trim();
260485
+ if (headContent.startsWith("ref: refs/heads/")) {
260486
+ cachedBranch = headContent.replace("ref: refs/heads/", "").trim();
260487
+ return cachedBranch;
260488
+ }
260489
+ if (headContent) {
260490
+ cachedBranch = headContent.slice(0, 7);
260491
+ return cachedBranch;
260492
+ }
260493
+ }
260494
+ }
260495
+ } catch {}
260496
+ cachedBranch = null;
260497
+ return null;
260452
260498
  }
260453
260499
  function getCwd() {
260454
260500
  try {
@@ -260459,81 +260505,82 @@ function getCwd() {
260459
260505
  return "~";
260460
260506
  }
260461
260507
  }
260462
- function Header({
260463
- cliVersion = "0.1.0",
260464
- latestVersion,
260465
- userEmail
260466
- }) {
260467
- const cwd2 = getCwd();
260468
- const branch = getGitBranch();
260469
- return /* @__PURE__ */ jsx_runtime14.jsxs(Box_default, {
260470
- flexDirection: "column",
260471
- paddingX: THEME.padding.paddingX,
260472
- paddingTop: 1,
260473
- paddingBottom: 0,
260474
- children: [
260475
- /* @__PURE__ */ jsx_runtime14.jsxs(Text3, {
260476
- bold: true,
260477
- color: THEME.colors.text,
260478
- children: [
260479
- "✱ December CLI ",
260480
- cliVersion.replace(/^v/, "")
260481
- ]
260482
- }),
260483
- userEmail && /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260484
- color: THEME.colors.muted,
260485
- children: userEmail
260486
- }),
260487
- /* @__PURE__ */ jsx_runtime14.jsxs(Box_default, {
260488
- gap: 1,
260489
- children: [
260490
- /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260491
- color: THEME.colors.muted,
260492
- children: cwd2
260493
- }),
260494
- branch && /* @__PURE__ */ jsx_runtime14.jsxs(Text3, {
260495
- color: THEME.colors.muted,
260496
- children: [
260497
- "(",
260498
- branch,
260499
- ")"
260500
- ]
260501
- })
260502
- ]
260503
- }),
260504
- /* @__PURE__ */ jsx_runtime14.jsxs(Box_default, {
260505
- flexDirection: "column",
260506
- marginTop: 1,
260507
- children: [
260508
- /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260509
- color: THEME.colors.brand,
260510
- children: "Tips for getting started"
260511
- }),
260512
- /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260513
- color: THEME.colors.muted,
260514
- children: "Run /init to scaffold .december workspace for custom rules and skills"
260515
- }),
260516
- /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260517
- color: THEME.colors.muted,
260518
- children: "Use /handoff to continue this session in December (trydecember.com)"
260519
- }),
260520
- latestVersion && /* @__PURE__ */ jsx_runtime14.jsxs(Text3, {
260521
- color: THEME.colors.muted,
260522
- children: [
260523
- "Run /update to install December CLI ",
260524
- latestVersion
260525
- ]
260526
- })
260527
- ]
260528
- })
260529
- ]
260530
- });
260531
- }
260532
- var jsx_runtime14;
260508
+ var import_react47, jsx_runtime14, cachedBranch = undefined, Header;
260533
260509
  var init_header = __esm(async () => {
260534
260510
  init_theme();
260535
260511
  await init_build2();
260512
+ import_react47 = __toESM(require_react(), 1);
260536
260513
  jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
260514
+ Header = import_react47.default.memo(function Header2({
260515
+ cliVersion = "0.1.0",
260516
+ latestVersion,
260517
+ userEmail
260518
+ }) {
260519
+ const cwd2 = getCwd();
260520
+ const branch = getGitBranch();
260521
+ return /* @__PURE__ */ jsx_runtime14.jsxs(Box_default, {
260522
+ flexDirection: "column",
260523
+ paddingX: THEME.padding.paddingX,
260524
+ paddingTop: 1,
260525
+ paddingBottom: 0,
260526
+ children: [
260527
+ /* @__PURE__ */ jsx_runtime14.jsxs(Text3, {
260528
+ bold: true,
260529
+ color: THEME.colors.text,
260530
+ children: [
260531
+ "✱ December CLI ",
260532
+ cliVersion.replace(/^v/, "")
260533
+ ]
260534
+ }),
260535
+ userEmail && /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260536
+ color: THEME.colors.muted,
260537
+ children: userEmail
260538
+ }),
260539
+ /* @__PURE__ */ jsx_runtime14.jsxs(Box_default, {
260540
+ gap: 1,
260541
+ children: [
260542
+ /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260543
+ color: THEME.colors.muted,
260544
+ children: cwd2
260545
+ }),
260546
+ branch && /* @__PURE__ */ jsx_runtime14.jsxs(Text3, {
260547
+ color: THEME.colors.muted,
260548
+ children: [
260549
+ "(",
260550
+ branch,
260551
+ ")"
260552
+ ]
260553
+ })
260554
+ ]
260555
+ }),
260556
+ /* @__PURE__ */ jsx_runtime14.jsxs(Box_default, {
260557
+ flexDirection: "column",
260558
+ marginTop: 1,
260559
+ children: [
260560
+ /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260561
+ color: THEME.colors.brand,
260562
+ children: "Tips for getting started"
260563
+ }),
260564
+ /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260565
+ color: THEME.colors.muted,
260566
+ children: "Run /init to scaffold .december workspace for custom rules and skills"
260567
+ }),
260568
+ /* @__PURE__ */ jsx_runtime14.jsx(Text3, {
260569
+ color: THEME.colors.muted,
260570
+ children: "Use /handoff to continue this session in December (trydecember.com)"
260571
+ }),
260572
+ latestVersion && /* @__PURE__ */ jsx_runtime14.jsxs(Text3, {
260573
+ color: THEME.colors.muted,
260574
+ children: [
260575
+ "Run /update to install December CLI ",
260576
+ latestVersion
260577
+ ]
260578
+ })
260579
+ ]
260580
+ })
260581
+ ]
260582
+ });
260583
+ });
260537
260584
  });
260538
260585
 
260539
260586
  // ../../packages/tui/src/components/messages/error-message.tsx
@@ -260561,13 +260608,13 @@ var init_error_message = __esm(async () => {
260561
260608
  });
260562
260609
 
260563
260610
  // ../../packages/tui/src/components/messages/user-message.tsx
260564
- var import_react47, jsx_runtime16, UserMessage;
260611
+ var import_react48, jsx_runtime16, UserMessage;
260565
260612
  var init_user_message = __esm(async () => {
260566
260613
  init_theme();
260567
260614
  await init_build2();
260568
- import_react47 = __toESM(require_react(), 1);
260615
+ import_react48 = __toESM(require_react(), 1);
260569
260616
  jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
260570
- UserMessage = import_react47.default.memo(function UserMessage2({ message }) {
260617
+ UserMessage = import_react48.default.memo(function UserMessage2({ message }) {
260571
260618
  return /* @__PURE__ */ jsx_runtime16.jsxs(Box_default, {
260572
260619
  paddingX: THEME.padding.paddingX,
260573
260620
  paddingY: 0,
@@ -260622,23 +260669,7 @@ function renderSingleMessage(msg, index2, allMessages, cliVersion, latestVersion
260622
260669
  expandCommands
260623
260670
  }, key);
260624
260671
  }
260625
- function MessageList({
260626
- staticKey,
260627
- staticMessages,
260628
- activeMessages,
260629
- isAuthenticated,
260630
- cliVersion,
260631
- latestVersion,
260632
- userEmail,
260633
- expandCommands
260634
- }) {
260635
- const allMessages = [...staticMessages, ...activeMessages];
260636
- return /* @__PURE__ */ jsx_runtime17.jsx(Box_default, {
260637
- flexDirection: "column",
260638
- children: allMessages.map((msg, index2) => renderSingleMessage(msg, index2, allMessages, cliVersion, latestVersion, userEmail, expandCommands))
260639
- });
260640
- }
260641
- var jsx_runtime17;
260672
+ var import_react49, jsx_runtime17, MessageList;
260642
260673
  var init_message_list = __esm(async () => {
260643
260674
  await __promiseAll([
260644
260675
  init_build2(),
@@ -260647,7 +260678,24 @@ var init_message_list = __esm(async () => {
260647
260678
  init_error_message(),
260648
260679
  init_user_message()
260649
260680
  ]);
260681
+ import_react49 = __toESM(require_react(), 1);
260650
260682
  jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
260683
+ MessageList = import_react49.default.memo(function MessageList2({
260684
+ staticKey,
260685
+ staticMessages,
260686
+ activeMessages,
260687
+ isAuthenticated,
260688
+ cliVersion,
260689
+ latestVersion,
260690
+ userEmail,
260691
+ expandCommands
260692
+ }) {
260693
+ const allMessages = [...staticMessages, ...activeMessages];
260694
+ return /* @__PURE__ */ jsx_runtime17.jsx(Box_default, {
260695
+ flexDirection: "column",
260696
+ children: allMessages.map((msg, index2) => renderSingleMessage(msg, index2, allMessages, cliVersion, latestVersion, userEmail, expandCommands))
260697
+ });
260698
+ });
260651
260699
  });
260652
260700
  // ../../packages/tui/src/providers/theme/index.tsx
260653
260701
  function ThemeProvider({ children: children2 }) {
@@ -260656,12 +260704,12 @@ function ThemeProvider({ children: children2 }) {
260656
260704
  children: children2
260657
260705
  });
260658
260706
  }
260659
- var import_react48, jsx_runtime18, ThemeContext;
260707
+ var import_react50, jsx_runtime18, ThemeContext;
260660
260708
  var init_theme2 = __esm(() => {
260661
260709
  init_theme();
260662
- import_react48 = __toESM(require_react(), 1);
260710
+ import_react50 = __toESM(require_react(), 1);
260663
260711
  jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
260664
- ThemeContext = import_react48.createContext({ colors: COLORS });
260712
+ ThemeContext = import_react50.createContext({ colors: COLORS });
260665
260713
  });
260666
260714
 
260667
260715
  // ../../packages/tui/src/layouts/root-layout.tsx
@@ -260708,12 +260756,12 @@ var init_menu_items = __esm(async () => {
260708
260756
 
260709
260757
  // ../../node_modules/.bun/ink-text-input@6.0.0+99d24c251f842efe/node_modules/ink-text-input/build/index.js
260710
260758
  function TextInput({ value: originalValue, placeholder = "", focus = true, mask, highlightPastedText = false, showCursor = true, onChange, onSubmit }) {
260711
- const [state, setState] = import_react49.useState({
260759
+ const [state, setState] = import_react51.useState({
260712
260760
  cursorOffset: (originalValue || "").length,
260713
260761
  cursorWidth: 0
260714
260762
  });
260715
260763
  const { cursorOffset, cursorWidth } = state;
260716
- import_react49.useEffect(() => {
260764
+ import_react51.useEffect(() => {
260717
260765
  setState((previousState) => {
260718
260766
  if (!focus || !showCursor) {
260719
260767
  return previousState;
@@ -260791,13 +260839,13 @@ function TextInput({ value: originalValue, placeholder = "", focus = true, mask,
260791
260839
  onChange(nextValue);
260792
260840
  }
260793
260841
  }, { isActive: focus });
260794
- return import_react49.default.createElement(Text3, null, placeholder ? value2.length > 0 ? renderedValue : renderedPlaceholder : renderedValue);
260842
+ return import_react51.default.createElement(Text3, null, placeholder ? value2.length > 0 ? renderedValue : renderedPlaceholder : renderedValue);
260795
260843
  }
260796
- var import_react49, build_default2;
260844
+ var import_react51, build_default2;
260797
260845
  var init_build4 = __esm(async () => {
260798
260846
  init_source();
260799
260847
  await init_build2();
260800
- import_react49 = __toESM(require_react(), 1);
260848
+ import_react51 = __toESM(require_react(), 1);
260801
260849
  build_default2 = TextInput;
260802
260850
  });
260803
260851
 
@@ -261186,24 +261234,24 @@ var init_figures = __esm(() => {
261186
261234
 
261187
261235
  // ../../node_modules/.bun/ink-select-input@6.2.0+99d24c251f842efe/node_modules/ink-select-input/build/Indicator.js
261188
261236
  function Indicator({ isSelected = false }) {
261189
- return import_react50.default.createElement(Box_default, { marginRight: 1 }, isSelected ? import_react50.default.createElement(Text3, { color: "blue" }, figures_default.pointer) : import_react50.default.createElement(Text3, null, " "));
261237
+ return import_react52.default.createElement(Box_default, { marginRight: 1 }, isSelected ? import_react52.default.createElement(Text3, { color: "blue" }, figures_default.pointer) : import_react52.default.createElement(Text3, null, " "));
261190
261238
  }
261191
- var import_react50, Indicator_default;
261239
+ var import_react52, Indicator_default;
261192
261240
  var init_Indicator = __esm(async () => {
261193
261241
  init_figures();
261194
261242
  await init_build2();
261195
- import_react50 = __toESM(require_react(), 1);
261243
+ import_react52 = __toESM(require_react(), 1);
261196
261244
  Indicator_default = Indicator;
261197
261245
  });
261198
261246
 
261199
261247
  // ../../node_modules/.bun/ink-select-input@6.2.0+99d24c251f842efe/node_modules/ink-select-input/build/Item.js
261200
261248
  function Item({ isSelected = false, label }) {
261201
- return React23.createElement(Text3, { color: isSelected ? "blue" : undefined }, label);
261249
+ return React25.createElement(Text3, { color: isSelected ? "blue" : undefined }, label);
261202
261250
  }
261203
- var React23, Item_default;
261251
+ var React25, Item_default;
261204
261252
  var init_Item = __esm(async () => {
261205
261253
  await init_build2();
261206
- React23 = __toESM(require_react(), 1);
261254
+ React25 = __toESM(require_react(), 1);
261207
261255
  Item_default = Item;
261208
261256
  });
261209
261257
 
@@ -261235,17 +261283,17 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
261235
261283
  const hasLimit = typeof customLimit === "number" && items.length > customLimit;
261236
261284
  const limit3 = hasLimit ? Math.min(customLimit, items.length) : items.length;
261237
261285
  const lastIndex = limit3 - 1;
261238
- const [rotateIndex, setRotateIndex] = import_react51.useState(initialIndex > lastIndex ? lastIndex - initialIndex : 0);
261239
- const [selectedIndex, setSelectedIndex] = import_react51.useState(initialIndex ? initialIndex > lastIndex ? lastIndex : initialIndex : 0);
261240
- const previousItems = import_react51.useRef(items);
261241
- import_react51.useEffect(() => {
261286
+ const [rotateIndex, setRotateIndex] = import_react53.useState(initialIndex > lastIndex ? lastIndex - initialIndex : 0);
261287
+ const [selectedIndex, setSelectedIndex] = import_react53.useState(initialIndex ? initialIndex > lastIndex ? lastIndex : initialIndex : 0);
261288
+ const previousItems = import_react53.useRef(items);
261289
+ import_react53.useEffect(() => {
261242
261290
  if (!isDeepStrictEqual(previousItems.current.map((item) => item.value), items.map((item) => item.value))) {
261243
261291
  setRotateIndex(0);
261244
261292
  setSelectedIndex(0);
261245
261293
  }
261246
261294
  previousItems.current = items;
261247
261295
  }, [items]);
261248
- use_input_default(import_react51.useCallback((input, key) => {
261296
+ use_input_default(import_react53.useCallback((input, key) => {
261249
261297
  if (input === "k" || key.upArrow) {
261250
261298
  const lastIndex2 = (hasLimit ? limit3 : items.length) - 1;
261251
261299
  const atFirstIndex = selectedIndex === 0;
@@ -261297,19 +261345,19 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
261297
261345
  onHighlight
261298
261346
  ]), { isActive: isFocused });
261299
261347
  const slicedItems = hasLimit ? toRotated(items, rotateIndex).slice(0, limit3) : items;
261300
- return import_react51.default.createElement(Box_default, { flexDirection: "column" }, slicedItems.map((item, index2) => {
261348
+ return import_react53.default.createElement(Box_default, { flexDirection: "column" }, slicedItems.map((item, index2) => {
261301
261349
  const isSelected = index2 === selectedIndex;
261302
- return import_react51.default.createElement(Box_default, { key: item.key ?? item.value }, import_react51.default.createElement(indicatorComponent, { isSelected }), import_react51.default.createElement(itemComponent, { ...item, isSelected }));
261350
+ return import_react53.default.createElement(Box_default, { key: item.key ?? item.value }, import_react53.default.createElement(indicatorComponent, { isSelected }), import_react53.default.createElement(itemComponent, { ...item, isSelected }));
261303
261351
  }));
261304
261352
  }
261305
- var import_react51, SelectInput_default;
261353
+ var import_react53, SelectInput_default;
261306
261354
  var init_SelectInput = __esm(async () => {
261307
261355
  await __promiseAll([
261308
261356
  init_build2(),
261309
261357
  init_Indicator(),
261310
261358
  init_Item()
261311
261359
  ]);
261312
- import_react51 = __toESM(require_react(), 1);
261360
+ import_react53 = __toESM(require_react(), 1);
261313
261361
  SelectInput_default = SelectInput;
261314
261362
  });
261315
261363
 
@@ -261854,7 +261902,7 @@ function McpManagerMenu({
261854
261902
  setAuthMode
261855
261903
  }) {
261856
261904
  const serverInfos = propServerInfos || (agent2?.mcpPool ? agent2.mcpPool.getServerInfos() : []);
261857
- const [selectedIndex, setSelectedIndex] = import_react52.useState(0);
261905
+ const [selectedIndex, setSelectedIndex] = import_react54.useState(0);
261858
261906
  use_input_default((input, key) => {
261859
261907
  if (key.escape) {
261860
261908
  setAuthMode("none");
@@ -262025,14 +262073,14 @@ function McpManagerMenu({
262025
262073
  ]
262026
262074
  });
262027
262075
  }
262028
- var import_react52, jsx_runtime26;
262076
+ var import_react54, jsx_runtime26;
262029
262077
  var init_mcp_manager_menu = __esm(async () => {
262030
262078
  init_theme();
262031
262079
  await __promiseAll([
262032
262080
  init_build2(),
262033
262081
  init_menu_footer()
262034
262082
  ]);
262035
- import_react52 = __toESM(require_react(), 1);
262083
+ import_react54 = __toESM(require_react(), 1);
262036
262084
  jsx_runtime26 = __toESM(require_jsx_runtime(), 1);
262037
262085
  });
262038
262086
 
@@ -262132,8 +262180,8 @@ var init_model_select_menu = __esm(async () => {
262132
262180
 
262133
262181
  // ../../packages/tui/src/components/menus/ollama-setup-menu.tsx
262134
262182
  function OllamaSetupMenu({ status, onRetry, onCancel, onProceed }) {
262135
- const [isEditingUrl, setIsEditingUrl] = import_react53.useState(false);
262136
- const [customUrl, setCustomUrl] = import_react53.useState(status?.baseUrl || "http://localhost:11434");
262183
+ const [isEditingUrl, setIsEditingUrl] = import_react55.useState(false);
262184
+ const [customUrl, setCustomUrl] = import_react55.useState(status?.baseUrl || "http://localhost:11434");
262137
262185
  const isRunning = status?.running ?? false;
262138
262186
  const compatibleModels = status?.compatibleModels ?? [];
262139
262187
  const hasCompatibleModel = compatibleModels.length > 0;
@@ -262296,7 +262344,7 @@ function OllamaSetupMenu({ status, onRetry, onCancel, onProceed }) {
262296
262344
  ]
262297
262345
  });
262298
262346
  }
262299
- var import_react53, jsx_runtime29;
262347
+ var import_react55, jsx_runtime29;
262300
262348
  var init_ollama_setup_menu = __esm(async () => {
262301
262349
  init_theme();
262302
262350
  await __promiseAll([
@@ -262306,7 +262354,7 @@ var init_ollama_setup_menu = __esm(async () => {
262306
262354
  init_menu_footer(),
262307
262355
  init_menu_items()
262308
262356
  ]);
262309
- import_react53 = __toESM(require_react(), 1);
262357
+ import_react55 = __toESM(require_react(), 1);
262310
262358
  jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
262311
262359
  });
262312
262360
 
@@ -262410,11 +262458,11 @@ function SessionSelectMenu(props) {
262410
262458
  handleSessionSelect,
262411
262459
  setAuthMode
262412
262460
  } = props;
262413
- const [isSearching, setIsSearching] = import_react54.useState(false);
262414
- const [searchQuery, setSearchQuery] = import_react54.useState("");
262461
+ const [isSearching, setIsSearching] = import_react56.useState(false);
262462
+ const [searchQuery, setSearchQuery] = import_react56.useState("");
262415
262463
  const columns = useTerminalColumns();
262416
262464
  const SESSION_PAGE_SIZE = 10;
262417
- const filteredSessions = import_react54.useMemo(() => {
262465
+ const filteredSessions = import_react56.useMemo(() => {
262418
262466
  if (!searchQuery.trim())
262419
262467
  return sessionsData;
262420
262468
  const q2 = searchQuery.toLowerCase();
@@ -262428,11 +262476,11 @@ function SessionSelectMenu(props) {
262428
262476
  const maxPage = Math.max(0, Math.ceil(totalItems / SESSION_PAGE_SIZE) - 1);
262429
262477
  const startIndex = sessionPage * SESSION_PAGE_SIZE;
262430
262478
  const visibleItems = filteredSessions.slice(startIndex, startIndex + SESSION_PAGE_SIZE);
262431
- const selectedIdxRef = import_react54.useRef(sessionSelectedIndex);
262479
+ const selectedIdxRef = import_react56.useRef(sessionSelectedIndex);
262432
262480
  selectedIdxRef.current = sessionSelectedIndex;
262433
- const pageRef = import_react54.useRef(sessionPage);
262481
+ const pageRef = import_react56.useRef(sessionPage);
262434
262482
  pageRef.current = sessionPage;
262435
- const isSearchingRef = import_react54.useRef(isSearching);
262483
+ const isSearchingRef = import_react56.useRef(isSearching);
262436
262484
  isSearchingRef.current = isSearching;
262437
262485
  const timeAgo = (date7) => {
262438
262486
  if (!date7)
@@ -262726,7 +262774,7 @@ function SessionSelectMenu(props) {
262726
262774
  ]
262727
262775
  });
262728
262776
  }
262729
- var import_react54, jsx_runtime31;
262777
+ var import_react56, jsx_runtime31;
262730
262778
  var init_session_select_menu = __esm(async () => {
262731
262779
  init_theme();
262732
262780
  await __promiseAll([
@@ -262735,7 +262783,7 @@ var init_session_select_menu = __esm(async () => {
262735
262783
  init_use_terminal_columns(),
262736
262784
  init_menu_footer()
262737
262785
  ]);
262738
- import_react54 = __toESM(require_react(), 1);
262786
+ import_react56 = __toESM(require_react(), 1);
262739
262787
  jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
262740
262788
  });
262741
262789
 
@@ -263298,13 +263346,13 @@ var init_auth_menus = __esm(async () => {
263298
263346
 
263299
263347
  // ../../packages/tui/src/components/menus/ask-question-menu.tsx
263300
263348
  function AskQuestionMenu({ questions, onComplete }) {
263301
- const [currentQuestionIdx, setCurrentQuestionIdx] = import_react55.useState(0);
263302
- const [answers, setAnswers] = import_react55.useState([]);
263303
- const [selectedIndex, setSelectedIndex] = import_react55.useState(0);
263304
- const [selectedMultiIndices, setSelectedMultiIndices] = import_react55.useState(new Set);
263305
- const selectedIndexRef = import_react55.useRef(0);
263349
+ const [currentQuestionIdx, setCurrentQuestionIdx] = import_react57.useState(0);
263350
+ const [answers, setAnswers] = import_react57.useState([]);
263351
+ const [selectedIndex, setSelectedIndex] = import_react57.useState(0);
263352
+ const [selectedMultiIndices, setSelectedMultiIndices] = import_react57.useState(new Set);
263353
+ const selectedIndexRef = import_react57.useRef(0);
263306
263354
  selectedIndexRef.current = selectedIndex;
263307
- const selectedMultiRef = import_react55.useRef(new Set);
263355
+ const selectedMultiRef = import_react57.useRef(new Set);
263308
263356
  selectedMultiRef.current = selectedMultiIndices;
263309
263357
  const currentQ = questions[currentQuestionIdx];
263310
263358
  const isMulti = Boolean(currentQ?.is_multi_select);
@@ -263427,14 +263475,14 @@ function AskQuestionMenu({ questions, onComplete }) {
263427
263475
  ]
263428
263476
  });
263429
263477
  }
263430
- var import_react55, jsx_runtime36;
263478
+ var import_react57, jsx_runtime36;
263431
263479
  var init_ask_question_menu = __esm(async () => {
263432
263480
  init_theme();
263433
263481
  await __promiseAll([
263434
263482
  init_build2(),
263435
263483
  init_menu_footer()
263436
263484
  ]);
263437
- import_react55 = __toESM(require_react(), 1);
263485
+ import_react57 = __toESM(require_react(), 1);
263438
263486
  jsx_runtime36 = __toESM(require_jsx_runtime(), 1);
263439
263487
  });
263440
263488
 
@@ -263623,8 +263671,8 @@ function ChatApp({
263623
263671
  onUpdateSuccess,
263624
263672
  session
263625
263673
  }) {
263626
- const [exitConfirm, setExitConfirm] = import_react56.useState(false);
263627
- import_react56.useEffect(() => {
263674
+ const [exitConfirm, setExitConfirm] = import_react58.useState(false);
263675
+ import_react58.useEffect(() => {
263628
263676
  if (exitConfirm) {
263629
263677
  const timer = setTimeout(() => setExitConfirm(false), 3000);
263630
263678
  return () => clearTimeout(timer);
@@ -263663,7 +263711,7 @@ function ChatApp({
263663
263711
  agent: agent2,
263664
263712
  getProviderModels: session.getProviderModels
263665
263713
  }) : null;
263666
- const handleFormSubmit = import_react56.useCallback((text3) => {
263714
+ const handleFormSubmit = import_react58.useCallback((text3) => {
263667
263715
  handleSubmit(text3);
263668
263716
  }, [handleSubmit]);
263669
263717
  const totalTokens = [...staticMessages, ...activeMessages].reduce((acc, msg) => {
@@ -263740,7 +263788,7 @@ function ChatApp({
263740
263788
  ]
263741
263789
  });
263742
263790
  }
263743
- var import_react56, jsx_runtime38;
263791
+ var import_react58, jsx_runtime38;
263744
263792
  var init_app = __esm(async () => {
263745
263793
  await __promiseAll([
263746
263794
  init_build2(),
@@ -263751,7 +263799,7 @@ var init_app = __esm(async () => {
263751
263799
  init_tool_permission_menu(),
263752
263800
  init_message_list()
263753
263801
  ]);
263754
- import_react56 = __toESM(require_react(), 1);
263802
+ import_react58 = __toESM(require_react(), 1);
263755
263803
  jsx_runtime38 = __toESM(require_jsx_runtime(), 1);
263756
263804
  });
263757
263805
 
@@ -263829,25 +263877,25 @@ var exports_file_session_repository = {};
263829
263877
  __export(exports_file_session_repository, {
263830
263878
  FileSessionRepository: () => FileSessionRepository
263831
263879
  });
263832
- import fs18 from "node:fs/promises";
263880
+ import fs19 from "node:fs/promises";
263833
263881
  import os10 from "node:os";
263834
- import path17 from "node:path";
263882
+ import path18 from "node:path";
263835
263883
 
263836
263884
  class FileSessionRepository {
263837
263885
  sessionDir;
263838
263886
  sessionCache = {};
263839
263887
  constructor(sessionDir) {
263840
- this.sessionDir = sessionDir || path17.join(os10.homedir(), ".config", "december", "sessions");
263888
+ this.sessionDir = sessionDir || path18.join(os10.homedir(), ".config", "december", "sessions");
263841
263889
  }
263842
263890
  async saveContext(sessionId, messages) {
263843
- await fs18.mkdir(this.sessionDir, { recursive: true });
263844
- const historyPath = path17.join(this.sessionDir, `${sessionId}.jsonl`);
263891
+ await fs19.mkdir(this.sessionDir, { recursive: true });
263892
+ const historyPath = path18.join(this.sessionDir, `${sessionId}.jsonl`);
263845
263893
  let existing = this.sessionCache[sessionId];
263846
263894
  if (!existing) {
263847
263895
  existing = {};
263848
263896
  this.sessionCache[sessionId] = existing;
263849
263897
  try {
263850
- const data2 = await fs18.readFile(historyPath, "utf-8");
263898
+ const data2 = await fs19.readFile(historyPath, "utf-8");
263851
263899
  const lines = data2.split(`
263852
263900
  `).filter((l3) => l3.trim().length > 0);
263853
263901
  for (const l3 of lines) {
@@ -263871,13 +263919,13 @@ class FileSessionRepository {
263871
263919
  }
263872
263920
  }
263873
263921
  if (appendContent) {
263874
- await fs18.appendFile(historyPath, appendContent, "utf-8");
263922
+ await fs19.appendFile(historyPath, appendContent, "utf-8");
263875
263923
  }
263876
263924
  }
263877
263925
  async loadContext(sessionId) {
263878
- const historyPath = path17.join(this.sessionDir, `${sessionId}.jsonl`);
263926
+ const historyPath = path18.join(this.sessionDir, `${sessionId}.jsonl`);
263879
263927
  try {
263880
- const data2 = await fs18.readFile(historyPath, "utf-8");
263928
+ const data2 = await fs19.readFile(historyPath, "utf-8");
263881
263929
  const lines = data2.split(`
263882
263930
  `).filter((l3) => l3.trim().length > 0);
263883
263931
  const msgMap = new Map;
@@ -263908,7 +263956,7 @@ class FileSessionRepository {
263908
263956
  if (msgs.length < lines.length) {
263909
263957
  const compacted = msgs.map((m3) => JSON.stringify(m3)).join(`
263910
263958
  `);
263911
- await fs18.writeFile(historyPath, compacted, "utf-8").catch(() => {});
263959
+ await fs19.writeFile(historyPath, compacted, "utf-8").catch(() => {});
263912
263960
  }
263913
263961
  const cacheObj = {};
263914
263962
  for (const msg of msgs) {
@@ -263922,17 +263970,17 @@ class FileSessionRepository {
263922
263970
  }
263923
263971
  async listSessions() {
263924
263972
  try {
263925
- await fs18.mkdir(this.sessionDir, { recursive: true });
263926
- const files = await fs18.readdir(this.sessionDir);
263973
+ await fs19.mkdir(this.sessionDir, { recursive: true });
263974
+ const files = await fs19.readdir(this.sessionDir);
263927
263975
  const sessions = [];
263928
263976
  for (const file of files) {
263929
263977
  if (!file.endsWith(".jsonl"))
263930
263978
  continue;
263931
263979
  const id = file.replace(".jsonl", "");
263932
- const filePath = path17.join(this.sessionDir, file);
263980
+ const filePath = path18.join(this.sessionDir, file);
263933
263981
  try {
263934
- const stat4 = await fs18.stat(filePath);
263935
- const data2 = await fs18.readFile(filePath, "utf-8");
263982
+ const stat4 = await fs19.stat(filePath);
263983
+ const data2 = await fs19.readFile(filePath, "utf-8");
263936
263984
  const lines = data2.split(`
263937
263985
  `).filter((l3) => l3.trim().length > 0);
263938
263986
  let preview = "";
@@ -263960,15 +264008,15 @@ class FileSessionRepository {
263960
264008
  }
263961
264009
  }
263962
264010
  async deleteSession(sessionId) {
263963
- const historyPath = path17.join(this.sessionDir, `${sessionId}.jsonl`);
264011
+ const historyPath = path18.join(this.sessionDir, `${sessionId}.jsonl`);
263964
264012
  try {
263965
- await fs18.unlink(historyPath);
264013
+ await fs19.unlink(historyPath);
263966
264014
  } catch (e2) {}
263967
264015
  }
263968
264016
  async renameSession(oldSessionId, newSessionId) {
263969
- const oldPath = path17.join(this.sessionDir, `${oldSessionId}.jsonl`);
263970
- const newPath = path17.join(this.sessionDir, `${newSessionId}.jsonl`);
263971
- await fs18.rename(oldPath, newPath);
264017
+ const oldPath = path18.join(this.sessionDir, `${oldSessionId}.jsonl`);
264018
+ const newPath = path18.join(this.sessionDir, `${newSessionId}.jsonl`);
264019
+ await fs19.rename(oldPath, newPath);
263972
264020
  }
263973
264021
  }
263974
264022
  var init_file_session_repository = () => {};
@@ -264065,11 +264113,11 @@ var init_vanilla = () => {};
264065
264113
 
264066
264114
  // ../../node_modules/.bun/zustand@5.0.14+93dbe784b8baa420/node_modules/zustand/esm/react.mjs
264067
264115
  function useStore(api3, selector = identity2) {
264068
- const slice3 = import_react57.default.useSyncExternalStore(api3.subscribe, import_react57.default.useCallback(() => selector(api3.getState()), [api3, selector]), import_react57.default.useCallback(() => selector(api3.getInitialState()), [api3, selector]));
264069
- import_react57.default.useDebugValue(slice3);
264116
+ const slice3 = import_react59.default.useSyncExternalStore(api3.subscribe, import_react59.default.useCallback(() => selector(api3.getState()), [api3, selector]), import_react59.default.useCallback(() => selector(api3.getInitialState()), [api3, selector]));
264117
+ import_react59.default.useDebugValue(slice3);
264070
264118
  return slice3;
264071
264119
  }
264072
- var import_react57, identity2 = (arg) => arg, createImpl = (createState) => {
264120
+ var import_react59, identity2 = (arg) => arg, createImpl = (createState) => {
264073
264121
  const api3 = createStore(createState);
264074
264122
  const useBoundStore = (selector) => useStore(api3, selector);
264075
264123
  Object.assign(useBoundStore, api3);
@@ -264077,7 +264125,7 @@ var import_react57, identity2 = (arg) => arg, createImpl = (createState) => {
264077
264125
  }, create5 = (createState) => createState ? createImpl(createState) : createImpl;
264078
264126
  var init_react = __esm(() => {
264079
264127
  init_vanilla();
264080
- import_react57 = __toESM(require_react(), 1);
264128
+ import_react59 = __toESM(require_react(), 1);
264081
264129
  });
264082
264130
 
264083
264131
  // ../../node_modules/.bun/zustand@5.0.14+93dbe784b8baa420/node_modules/zustand/esm/index.mjs
@@ -264228,9 +264276,9 @@ var init_store = __esm(async () => {
264228
264276
  });
264229
264277
 
264230
264278
  // src/store/interceptors.ts
264231
- import { execSync as execSync2 } from "node:child_process";
264232
- import fs19 from "node:fs/promises";
264233
- import path18 from "node:path";
264279
+ import { execSync } from "node:child_process";
264280
+ import fs20 from "node:fs/promises";
264281
+ import path19 from "node:path";
264234
264282
  async function computeToolCallDiff(toolCall) {
264235
264283
  if (toolCall.input?.diff) {
264236
264284
  return toolCall.input.diff;
@@ -264239,11 +264287,11 @@ async function computeToolCallDiff(toolCall) {
264239
264287
  if (!targetPath)
264240
264288
  return;
264241
264289
  const cwd2 = process.cwd();
264242
- const resolved = path18.resolve(cwd2, targetPath);
264243
- const relative2 = path18.relative(cwd2, resolved);
264290
+ const resolved = path19.resolve(cwd2, targetPath);
264291
+ const relative2 = path19.relative(cwd2, resolved);
264244
264292
  let oldContent = "";
264245
264293
  try {
264246
- oldContent = await fs19.readFile(resolved, "utf-8");
264294
+ oldContent = await fs20.readFile(resolved, "utf-8");
264247
264295
  } catch {}
264248
264296
  if (toolCall.name === "write_to_file" || toolCall.name === "write") {
264249
264297
  const newContent = toolCall.input?.CodeContent ?? toolCall.input?.content ?? "";
@@ -264307,9 +264355,9 @@ function setupAgentInterceptors(agent2, storeState) {
264307
264355
  ];
264308
264356
  if (fileTools.includes(toolCall.name)) {
264309
264357
  const cwd2 = process.cwd();
264310
- const resolved = path18.resolve(cwd2, targetPath);
264311
- const relative2 = path18.relative(cwd2, resolved);
264312
- const isOutside = relative2.startsWith("..") || path18.isAbsolute(relative2);
264358
+ const resolved = path19.resolve(cwd2, targetPath);
264359
+ const relative2 = path19.relative(cwd2, resolved);
264360
+ const isOutside = relative2.startsWith("..") || path19.isAbsolute(relative2);
264313
264361
  if (!config3.nonWorkspaceAccess && isOutside) {
264314
264362
  return {
264315
264363
  block: true,
@@ -264380,10 +264428,10 @@ function setupAgentInterceptors(agent2, storeState) {
264380
264428
  const targetPath = toolCall.input?.TargetFile || toolCall.input?.AbsolutePath || toolCall.input?.filePath || toolCall.input?.path;
264381
264429
  if (targetPath) {
264382
264430
  const cwd2 = process.cwd();
264383
- const resolved = path18.resolve(cwd2, targetPath);
264384
- const relative2 = path18.relative(cwd2, resolved);
264431
+ const resolved = path19.resolve(cwd2, targetPath);
264432
+ const relative2 = path19.relative(cwd2, resolved);
264385
264433
  try {
264386
- execSync2(`git ls-files --error-unmatch "${relative2}"`, {
264434
+ execSync(`git ls-files --error-unmatch "${relative2}"`, {
264387
264435
  cwd: cwd2,
264388
264436
  stdio: "pipe"
264389
264437
  });
@@ -264515,10 +264563,14 @@ function startDirectCommand(command, options = {}) {
264515
264563
  stdio: ["pipe", "pipe", "pipe"],
264516
264564
  detached: !isWindows3
264517
264565
  });
264566
+ try {
264567
+ child.stdin?.end?.();
264568
+ } catch {}
264518
264569
  let timeoutTimer = null;
264519
264570
  const promise4 = new Promise((resolve4) => {
264571
+ let closed = false;
264520
264572
  child.stdout?.on("data", (data2) => {
264521
- const str2 = data2.toString("utf8");
264573
+ const str2 = typeof data2 === "string" ? data2 : data2.toString("utf8");
264522
264574
  output += str2;
264523
264575
  if (isBackground && bgTaskId) {
264524
264576
  taskManager.appendOutput(bgTaskId, str2);
@@ -264527,7 +264579,7 @@ function startDirectCommand(command, options = {}) {
264527
264579
  }
264528
264580
  });
264529
264581
  child.stderr?.on("data", (data2) => {
264530
- const str2 = data2.toString("utf8");
264582
+ const str2 = typeof data2 === "string" ? data2 : data2.toString("utf8");
264531
264583
  output += str2;
264532
264584
  if (isBackground && bgTaskId) {
264533
264585
  taskManager.appendOutput(bgTaskId, str2);
@@ -264536,6 +264588,9 @@ function startDirectCommand(command, options = {}) {
264536
264588
  }
264537
264589
  });
264538
264590
  child.on("error", (err) => {
264591
+ if (closed)
264592
+ return;
264593
+ closed = true;
264539
264594
  const errStr = `
264540
264595
  Failed to start process: ${err?.message || err}
264541
264596
  `;
@@ -264551,7 +264606,10 @@ Failed to start process: ${err?.message || err}
264551
264606
  taskId: bgTaskId
264552
264607
  });
264553
264608
  });
264554
- child.on("close", (code) => {
264609
+ const finish = (code) => {
264610
+ if (closed)
264611
+ return;
264612
+ closed = true;
264555
264613
  if (timeoutTimer)
264556
264614
  clearTimeout(timeoutTimer);
264557
264615
  const finalCode = isAborted2 ? 130 : code ?? 0;
@@ -264564,6 +264622,10 @@ Failed to start process: ${err?.message || err}
264564
264622
  isBackground: false
264565
264623
  });
264566
264624
  }
264625
+ };
264626
+ child.on("close", finish);
264627
+ child.on("exit", (code) => {
264628
+ setTimeout(() => finish(code), 50);
264567
264629
  });
264568
264630
  if (timeoutMs > 0 && timeoutMs < Infinity) {
264569
264631
  timeoutTimer = setTimeout(() => {
@@ -265156,7 +265218,7 @@ Provider: ${displayName}
265156
265218
  *Prompts go directly to the provider API; December servers do not track, log, or bill this usage. Token consumption, quotas, and billing are managed in your ${displayName} account at [${billingLink}](${billingLink})*`;
265157
265219
  }
265158
265220
  var PROVIDER_BILLING_LINKS, PROVIDER_DISPLAY_NAMES;
265159
- var init_usage_rates = __esm(() => {
265221
+ var init_usage_rates2 = __esm(() => {
265160
265222
  init_messages5();
265161
265223
  PROVIDER_BILLING_LINKS = {
265162
265224
  december: "https://trydecember.com/settings/usage",
@@ -265201,20 +265263,20 @@ function getToolSummary(name, inputStr) {
265201
265263
  switch (name) {
265202
265264
  case "read_file":
265203
265265
  case "view_file": {
265204
- const path19 = args.AbsolutePath || args.TargetFile || args.filePath || args.filepath || args.path || args.file || "";
265205
- return `Read(${path19})`.trim();
265266
+ const path20 = args.AbsolutePath || args.TargetFile || args.filePath || args.filepath || args.path || args.file || "";
265267
+ return `Read(${path20})`.trim();
265206
265268
  }
265207
265269
  case "write_file":
265208
265270
  case "write_to_file": {
265209
- const path19 = args.TargetFile || args.AbsolutePath || args.filePath || args.filepath || args.path || args.file || "";
265210
- return `Create(${path19})`.trim();
265271
+ const path20 = args.TargetFile || args.AbsolutePath || args.filePath || args.filepath || args.path || args.file || "";
265272
+ return `Create(${path20})`.trim();
265211
265273
  }
265212
265274
  case "edit_file":
265213
265275
  case "edit_diff":
265214
265276
  case "replace_file_content":
265215
265277
  case "multi_replace_file_content": {
265216
- const path19 = args.TargetFile || args.AbsolutePath || args.filePath || args.filepath || args.path || args.file || "";
265217
- return `Edit(${path19})`.trim();
265278
+ const path20 = args.TargetFile || args.AbsolutePath || args.filePath || args.filepath || args.path || args.file || "";
265279
+ return `Edit(${path20})`.trim();
265218
265280
  }
265219
265281
  case "list_dir":
265220
265282
  return `ListDir(${args.DirectoryPath || args.dirPath || args.path || ""})`.trim();
@@ -266061,6 +266123,271 @@ var init_use_settings_handlers = __esm(async () => {
266061
266123
  await init_store();
266062
266124
  });
266063
266125
 
266126
+ // src/utils/version-check.ts
266127
+ var exports_version_check = {};
266128
+ __export(exports_version_check, {
266129
+ CHECK_TTL_MS: () => CHECK_TTL_MS,
266130
+ checkForLatestVersion: () => checkForLatestVersion,
266131
+ clearVersionCheckCache: () => clearVersionCheckCache,
266132
+ isNewerVersion: () => isNewerVersion
266133
+ });
266134
+ import https2 from "node:https";
266135
+ function isNewerVersion(current, latest) {
266136
+ const cleanCurrent = current.replace(/^v/, "");
266137
+ const cleanLatest = latest.replace(/^v/, "");
266138
+ const p1 = cleanCurrent.split(".").map((n) => Number(n) || 0);
266139
+ const p2 = cleanLatest.split(".").map((n) => Number(n) || 0);
266140
+ for (let i2 = 0;i2 < Math.max(p1.length, p2.length); i2++) {
266141
+ const v1 = p1[i2] ?? 0;
266142
+ const v2 = p2[i2] ?? 0;
266143
+ if (v2 > v1)
266144
+ return true;
266145
+ if (v1 > v2)
266146
+ return false;
266147
+ }
266148
+ return false;
266149
+ }
266150
+ async function checkForLatestVersion(currentVersion) {
266151
+ try {
266152
+ const config3 = await loadConfig();
266153
+ const now2 = Date.now();
266154
+ if (config3.versionCheckCache) {
266155
+ const { latestVersion, checkedAt } = config3.versionCheckCache;
266156
+ if (now2 - checkedAt < CHECK_TTL_MS) {
266157
+ if (latestVersion && isNewerVersion(currentVersion, latestVersion)) {
266158
+ return latestVersion;
266159
+ }
266160
+ return null;
266161
+ }
266162
+ }
266163
+ const freshLatest = await fetchLatestFromNpm();
266164
+ if (freshLatest) {
266165
+ config3.versionCheckCache = {
266166
+ latestVersion: freshLatest,
266167
+ checkedAt: now2
266168
+ };
266169
+ await saveConfig(config3).catch(() => {});
266170
+ if (isNewerVersion(currentVersion, freshLatest)) {
266171
+ return freshLatest;
266172
+ }
266173
+ }
266174
+ } catch {}
266175
+ return null;
266176
+ }
266177
+ function fetchLatestFromNpm() {
266178
+ return new Promise((resolve4) => {
266179
+ const req = https2.get("https://registry.npmjs.org/@trydecember/cli/latest", { timeout: 1200 }, (res) => {
266180
+ if (res.statusCode !== 200) {
266181
+ resolve4(null);
266182
+ return;
266183
+ }
266184
+ let data2 = "";
266185
+ res.on("data", (chunk2) => {
266186
+ data2 += chunk2;
266187
+ });
266188
+ res.on("end", () => {
266189
+ try {
266190
+ const parsed = JSON.parse(data2);
266191
+ const latest = parsed.version;
266192
+ if (latest && typeof latest === "string") {
266193
+ resolve4(latest);
266194
+ } else {
266195
+ resolve4(null);
266196
+ }
266197
+ } catch {
266198
+ resolve4(null);
266199
+ }
266200
+ });
266201
+ });
266202
+ req.on("error", () => resolve4(null));
266203
+ req.on("timeout", () => {
266204
+ req.destroy();
266205
+ resolve4(null);
266206
+ });
266207
+ });
266208
+ }
266209
+ async function clearVersionCheckCache() {
266210
+ try {
266211
+ const config3 = await loadConfig();
266212
+ if (config3.versionCheckCache) {
266213
+ delete config3.versionCheckCache;
266214
+ await saveConfig(config3);
266215
+ }
266216
+ } catch {}
266217
+ }
266218
+ var CHECK_TTL_MS;
266219
+ var init_version_check = __esm(() => {
266220
+ init_config();
266221
+ CHECK_TTL_MS = 24 * 60 * 60 * 1000;
266222
+ });
266223
+
266224
+ // src/utils/updater.ts
266225
+ var exports_updater = {};
266226
+ __export(exports_updater, {
266227
+ detectInstallMethod: () => detectInstallMethod,
266228
+ getUpdateCommand: () => getUpdateCommand,
266229
+ performCliUpdate: () => performCliUpdate
266230
+ });
266231
+ import { exec as exec5 } from "node:child_process";
266232
+ function detectInstallMethod(options) {
266233
+ const configMethod = options?.configInstallMethod;
266234
+ const validMethods = ["curl", "npm", "bun", "pnpm", "yarn", "brew", "source"];
266235
+ if (configMethod && validMethods.includes(configMethod)) {
266236
+ return configMethod;
266237
+ }
266238
+ const execPath = (options?.execPath ?? process.execPath ?? "").replace(/\\/g, "/");
266239
+ const argv1 = (options?.argv1 ?? (process.argv.length > 1 ? process.argv[1] : "") ?? "").replace(/\\/g, "/");
266240
+ const env8 = options?.env ?? process.env;
266241
+ if (argv1.includes("/apps/cli/src") || argv1.includes("/apps/cli/dist") || argv1.includes("december/apps/cli")) {
266242
+ return "source";
266243
+ }
266244
+ if (execPath.includes("/Cellar/december") || execPath.includes("/opt/homebrew/Cellar/december") || argv1.includes("/Cellar/december") || argv1.includes("/opt/homebrew/bin/december")) {
266245
+ return "brew";
266246
+ }
266247
+ if (execPath.includes(".local/bin/december") || execPath.includes("Programs/december") || env8.DECEMBER_INSTALL_DIR || execPath.endsWith("/december") && !execPath.includes("node_modules") && !execPath.includes("bun") && !execPath.includes("node") || execPath.endsWith("/december.exe") && !execPath.includes("node_modules")) {
266248
+ return "curl";
266249
+ }
266250
+ if (argv1.includes(".bun/bin") || argv1.includes("/.bun/") || execPath.includes("/bun") && !execPath.endsWith("/december")) {
266251
+ return "bun";
266252
+ }
266253
+ if (argv1.includes("pnpm") || argv1.includes(".pnpm") || env8.PNPM_HOME && argv1.includes(env8.PNPM_HOME.replace(/\\/g, "/"))) {
266254
+ return "pnpm";
266255
+ }
266256
+ if (argv1.includes(".yarn/bin") || argv1.includes("/yarn/") || argv1.includes("\\yarn\\")) {
266257
+ return "yarn";
266258
+ }
266259
+ if (argv1.includes("node_modules/@trydecember") || argv1.includes("node_modules/.bin/december") || argv1.includes("/npm/")) {
266260
+ return "npm";
266261
+ }
266262
+ if (execPath.endsWith("/node") || execPath.endsWith("/node.exe")) {
266263
+ return "npm";
266264
+ }
266265
+ return "curl";
266266
+ }
266267
+ function getUpdateCommand(method2, platform4 = process.platform) {
266268
+ switch (method2) {
266269
+ case "curl": {
266270
+ if (platform4 === "win32") {
266271
+ const cmd2 = 'powershell.exe -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/phasehumans/december/main/install.ps1 | iex"';
266272
+ return {
266273
+ command: cmd2,
266274
+ manualCmd: "irm https://raw.githubusercontent.com/phasehumans/december/main/install.ps1 | iex",
266275
+ description: "Standalone binary via install.ps1"
266276
+ };
266277
+ }
266278
+ const cmd = "curl -fsSL https://raw.githubusercontent.com/phasehumans/december/main/install.sh | bash";
266279
+ return {
266280
+ command: cmd,
266281
+ manualCmd: "curl -fsSL https://raw.githubusercontent.com/phasehumans/december/main/install.sh | bash",
266282
+ description: "Standalone binary via install.sh"
266283
+ };
266284
+ }
266285
+ case "bun": {
266286
+ return {
266287
+ command: "bun install -g @trydecember/cli@latest",
266288
+ manualCmd: "bun install -g @trydecember/cli@latest",
266289
+ description: "Bun global package"
266290
+ };
266291
+ }
266292
+ case "pnpm": {
266293
+ return {
266294
+ command: "pnpm add -g @trydecember/cli@latest",
266295
+ manualCmd: "pnpm add -g @trydecember/cli@latest",
266296
+ description: "PNPM global package"
266297
+ };
266298
+ }
266299
+ case "yarn": {
266300
+ return {
266301
+ command: "yarn global add @trydecember/cli@latest",
266302
+ manualCmd: "yarn global add @trydecember/cli@latest",
266303
+ description: "Yarn global package"
266304
+ };
266305
+ }
266306
+ case "brew": {
266307
+ return {
266308
+ command: "brew upgrade december",
266309
+ manualCmd: "brew upgrade december",
266310
+ description: "Homebrew package"
266311
+ };
266312
+ }
266313
+ case "source": {
266314
+ return {
266315
+ command: "git pull && bun install",
266316
+ manualCmd: "git pull && bun install",
266317
+ description: "Local source repository"
266318
+ };
266319
+ }
266320
+ case "npm":
266321
+ default: {
266322
+ return {
266323
+ command: "npm install -g @trydecember/cli@latest",
266324
+ manualCmd: "npm install -g @trydecember/cli@latest",
266325
+ description: "NPM global package"
266326
+ };
266327
+ }
266328
+ }
266329
+ }
266330
+ async function performCliUpdate(options) {
266331
+ let configInstallMethod = options?.configInstallMethod;
266332
+ if (!configInstallMethod) {
266333
+ try {
266334
+ const config3 = await loadConfig();
266335
+ configInstallMethod = config3.installMethod;
266336
+ } catch {}
266337
+ }
266338
+ const platform4 = options?.platform ?? process.platform;
266339
+ const method2 = detectInstallMethod({ configInstallMethod });
266340
+ const { command, manualCmd, description } = getUpdateCommand(method2, platform4);
266341
+ if (method2 === "source") {
266342
+ const msg = "Running December CLI from local source development directory.";
266343
+ options?.onProgress?.(msg);
266344
+ return {
266345
+ success: true,
266346
+ method: "source",
266347
+ command,
266348
+ manualCmd,
266349
+ output: msg
266350
+ };
266351
+ }
266352
+ options?.onProgress?.(`Updating December CLI via ${description}...`);
266353
+ const execCommand = options?.execFn ?? exec5;
266354
+ return new Promise((resolve4) => {
266355
+ execCommand(command, { timeout: 120000 }, async (error6, stdout, stderr) => {
266356
+ if (error6) {
266357
+ const errMessage = (stderr || error6.message || "Unknown update failure").trim();
266358
+ options?.onError?.(errMessage, manualCmd);
266359
+ resolve4({
266360
+ success: false,
266361
+ method: method2,
266362
+ command,
266363
+ manualCmd,
266364
+ error: errMessage
266365
+ });
266366
+ return;
266367
+ }
266368
+ try {
266369
+ await clearVersionCheckCache();
266370
+ } catch {}
266371
+ if (options?.onSuccess) {
266372
+ try {
266373
+ await options.onSuccess();
266374
+ } catch {}
266375
+ }
266376
+ resolve4({
266377
+ success: true,
266378
+ method: method2,
266379
+ command,
266380
+ manualCmd,
266381
+ output: (stdout || "Update completed successfully.").trim()
266382
+ });
266383
+ });
266384
+ });
266385
+ }
266386
+ var init_updater = __esm(() => {
266387
+ init_config();
266388
+ init_version_check();
266389
+ });
266390
+
266064
266391
  // src/hooks/use-agent-session.ts
266065
266392
  var exports_use_agent_session = {};
266066
266393
  __export(exports_use_agent_session, {
@@ -266184,32 +266511,21 @@ function useAgentSession({
266184
266511
  settingsFollowUpMode,
266185
266512
  setSettingsFollowUpMode
266186
266513
  } = state;
266187
- const [expandCommands, setExpandCommands] = import_react58.useState(true);
266188
- const toggleExpandCommands = import_react58.useCallback(() => {
266514
+ const [expandCommands, setExpandCommands] = import_react60.useState(true);
266515
+ const toggleExpandCommands = import_react60.useCallback(() => {
266189
266516
  setExpandCommands((prev2) => !prev2);
266190
266517
  }, []);
266191
- import_react58.useEffect(() => {
266192
- setIsAuthenticated(initialAuth);
266193
- setAuthMethod(initialAuthMethod);
266194
- if (initialHasBothAuth !== undefined)
266195
- setHasBothAuth(initialHasBothAuth);
266196
- if (initialSettingsAuthPriority !== undefined)
266197
- setSettingsAuthPriority(initialSettingsAuthPriority);
266198
- if (userEmail !== undefined)
266199
- setCurrentEmail(userEmail);
266200
- }, [
266201
- initialAuth,
266202
- initialAuthMethod,
266203
- initialHasBothAuth,
266204
- initialSettingsAuthPriority,
266205
- userEmail,
266206
- setIsAuthenticated,
266207
- setAuthMethod,
266208
- setHasBothAuth,
266209
- setSettingsAuthPriority,
266210
- setCurrentEmail
266211
- ]);
266212
- import_react58.useEffect(() => {
266518
+ import_react60.useEffect(() => {
266519
+ useCliStore.setState((prev2) => ({
266520
+ ...prev2,
266521
+ isAuthenticated: initialAuth,
266522
+ authMethod: initialAuthMethod,
266523
+ hasBothAuth: initialHasBothAuth !== undefined ? initialHasBothAuth : prev2.hasBothAuth,
266524
+ settingsAuthPriority: initialSettingsAuthPriority !== undefined ? initialSettingsAuthPriority : prev2.settingsAuthPriority,
266525
+ currentEmail: userEmail !== undefined ? userEmail : prev2.currentEmail
266526
+ }));
266527
+ }, [initialAuth, initialAuthMethod, initialHasBothAuth, initialSettingsAuthPriority, userEmail]);
266528
+ import_react60.useEffect(() => {
266213
266529
  if (agent2) {
266214
266530
  setupAgentInterceptors(agent2, {
266215
266531
  setAuthMode,
@@ -266218,8 +266534,8 @@ function useAgentSession({
266218
266534
  });
266219
266535
  }
266220
266536
  }, [agent2, setAuthMode, setPendingQuestions, setPendingToolCall]);
266221
- const activeShellAbortRef = import_react58.useRef(null);
266222
- import_react58.useEffect(() => {
266537
+ const activeShellAbortRef = import_react60.useRef(null);
266538
+ import_react60.useEffect(() => {
266223
266539
  if (authMode === "tasks_mode") {
266224
266540
  const update3 = () => {
266225
266541
  setTasksData([...taskManager.getTasks()]);
@@ -266229,7 +266545,7 @@ function useAgentSession({
266229
266545
  return () => clearInterval(interval);
266230
266546
  }
266231
266547
  }, [authMode, setTasksData]);
266232
- import_react58.useEffect(() => {
266548
+ import_react60.useEffect(() => {
266233
266549
  if (selectedProvider === "openrouter" || authMode === "model_select") {
266234
266550
  loadConfig().then((config3) => {
266235
266551
  if (config3.activeProvider === "openrouter" || selectedProvider === "openrouter") {
@@ -266241,11 +266557,11 @@ function useAgentSession({
266241
266557
  });
266242
266558
  }
266243
266559
  }, [authMode, selectedProvider, setOpenRouterModels]);
266244
- const handleKillTask = import_react58.useCallback((taskId) => {
266560
+ const handleKillTask = import_react60.useCallback((taskId) => {
266245
266561
  taskManager.killTask(taskId);
266246
266562
  setTasksData([...taskManager.getTasks()]);
266247
266563
  }, [setTasksData]);
266248
- const generateGrillQuestions = import_react58.useCallback(async (userPrompt) => {
266564
+ const generateGrillQuestions = import_react60.useCallback(async (userPrompt) => {
266249
266565
  const trimmedPrompt = userPrompt.trim();
266250
266566
  const displayPrompt = trimmedPrompt.startsWith("/") ? trimmedPrompt : `/grill ${trimmedPrompt}`;
266251
266567
  if (!isAuthenticated) {
@@ -266357,7 +266673,6 @@ function useAgentSession({
266357
266673
  }, [
266358
266674
  agent2,
266359
266675
  isAuthenticated,
266360
- addToast,
266361
266676
  setActiveMessages,
266362
266677
  setAuthMode,
266363
266678
  setCurrentGrillIndex,
@@ -266368,7 +266683,7 @@ function useAgentSession({
266368
266683
  setIsStreaming,
266369
266684
  setStaticMessages
266370
266685
  ]);
266371
- const generatePlanFromGrill = import_react58.useCallback(async (answers) => {
266686
+ const generatePlanFromGrill = import_react60.useCallback(async (answers) => {
266372
266687
  setAuthMode("none");
266373
266688
  const originalPrompt = grillPrompt;
266374
266689
  setGrillPrompt(null);
@@ -266449,7 +266764,7 @@ function useAgentSession({
266449
266764
  setIsStreaming,
266450
266765
  setStaticMessages
266451
266766
  ]);
266452
- const handleGrillSelect = import_react58.useCallback(async (item) => {
266767
+ const handleGrillSelect = import_react60.useCallback(async (item) => {
266453
266768
  if (item.value === "custom") {
266454
266769
  setCustomInputMode(true);
266455
266770
  return;
@@ -266470,7 +266785,7 @@ function useAgentSession({
266470
266785
  setCustomInputMode,
266471
266786
  setGrillAnswers
266472
266787
  ]);
266473
- const handleSubmit = import_react58.useCallback(async (text3) => {
266788
+ const handleSubmit = import_react60.useCallback(async (text3) => {
266474
266789
  if (text3.trim() === "/exit") {
266475
266790
  setShouldExit(true);
266476
266791
  process.exit(0);
@@ -266689,6 +267004,25 @@ Explain which files need to be created, modified, or deleted, and what the chang
266689
267004
  addToast("Initialized December workspace successfully!", "success");
266690
267005
  return;
266691
267006
  }
267007
+ if (text3.trim() === "/update") {
267008
+ const { performCliUpdate: performCliUpdate2 } = await Promise.resolve().then(() => (init_updater(), exports_updater));
267009
+ const result2 = await performCliUpdate2({
267010
+ onProgress: (msg) => addToast(msg, "info"),
267011
+ onSuccess: async () => {
267012
+ if (agent2) {
267013
+ await agent2.saveContext().catch(() => {});
267014
+ }
267015
+ }
267016
+ });
267017
+ if (result2.method === "source") {
267018
+ addToast('Running December CLI from local source. Run "git pull && bun install" to update.', "info");
267019
+ } else if (result2.success) {
267020
+ addToast(`December CLI updated successfully via ${result2.method}! Please restart the CLI in your terminal.`, "success");
267021
+ } else {
267022
+ addToast(`Update failed (${result2.method}): ${result2.error || "Unknown error"}. Try running: ${result2.manualCmd}`, "error");
267023
+ }
267024
+ return;
267025
+ }
266692
267026
  if (text3.trim() === "/context") {
266693
267027
  setAuthMode("context_select");
266694
267028
  return;
@@ -266950,7 +267284,7 @@ If it doesn't open automatically, please click here:
266950
267284
  authMethod,
266951
267285
  selectedProvider
266952
267286
  ]);
266953
- const handleAbort = import_react58.useCallback(() => {
267287
+ const handleAbort = import_react60.useCallback(() => {
266954
267288
  if (activeShellAbortRef.current) {
266955
267289
  activeShellAbortRef.current();
266956
267290
  activeShellAbortRef.current = null;
@@ -266977,7 +267311,7 @@ If it doesn't open automatically, please click here:
266977
267311
  handleOllamaCancel,
266978
267312
  handleOllamaProceed
266979
267313
  } = useAuthHandlers(agent2, onLogin, onLoginHeadless);
266980
- const handlePlanApprovalSelect = import_react58.useCallback(async (item) => {
267314
+ const handlePlanApprovalSelect = import_react60.useCallback(async (item) => {
266981
267315
  setAuthMode("none");
266982
267316
  const originalPrompt = currentPlannedPrompt;
266983
267317
  setCurrentPlannedPrompt(null);
@@ -267138,7 +267472,7 @@ If it doesn't open automatically, please click here:
267138
267472
  handleReloadMcp
267139
267473
  };
267140
267474
  }
267141
- var import_react58;
267475
+ var import_react60;
267142
267476
  var init_use_agent_session = __esm(async () => {
267143
267477
  init_src5();
267144
267478
  init_src();
@@ -267150,14 +267484,14 @@ var init_use_agent_session = __esm(async () => {
267150
267484
  init_error_parser();
267151
267485
  init_models5();
267152
267486
  init_openrouter_models();
267153
- init_usage_rates();
267487
+ init_usage_rates2();
267154
267488
  init_use_agent_runner();
267155
267489
  await __promiseAll([
267156
267490
  init_store(),
267157
267491
  init_use_auth_handlers(),
267158
267492
  init_use_settings_handlers()
267159
267493
  ]);
267160
- import_react58 = __toESM(require_react(), 1);
267494
+ import_react60 = __toESM(require_react(), 1);
267161
267495
  });
267162
267496
 
267163
267497
  // src/local-operations.ts
@@ -267169,15 +267503,15 @@ __export(exports_local_operations, {
267169
267503
  setActiveScopeDir: () => setActiveScopeDir
267170
267504
  });
267171
267505
  import { exec as exec6, spawn as spawn6 } from "node:child_process";
267172
- import fs20 from "node:fs/promises";
267173
- import path19 from "node:path";
267506
+ import fs21 from "node:fs/promises";
267507
+ import path20 from "node:path";
267174
267508
  import { promisify as promisify4 } from "node:util";
267175
267509
  function setActiveScopeDir(dir) {
267176
267510
  activeScopeDir = dir;
267177
267511
  }
267178
267512
  function getScopedCwd() {
267179
267513
  if (activeScopeDir) {
267180
- return path19.resolve(process.cwd(), activeScopeDir);
267514
+ return path20.resolve(process.cwd(), activeScopeDir);
267181
267515
  }
267182
267516
  return process.cwd();
267183
267517
  }
@@ -267198,13 +267532,17 @@ var init_local_operations = __esm(() => {
267198
267532
  cwd: targetCwd,
267199
267533
  detached: process.platform !== "win32",
267200
267534
  env: options.env ?? process.env,
267201
- shell: true
267535
+ shell: true,
267536
+ stdio: ["pipe", "pipe", "pipe"]
267202
267537
  });
267538
+ try {
267539
+ child.stdin?.end?.();
267540
+ } catch {}
267203
267541
  const task = taskManager.addTask(command, child);
267204
267542
  let output = "";
267205
267543
  let resolved = false;
267206
267544
  const handleData = (data2) => {
267207
- const chunk2 = data2.toString();
267545
+ const chunk2 = typeof data2 === "string" ? data2 : data2.toString();
267208
267546
  output += chunk2;
267209
267547
  taskManager.appendOutput(task.id, chunk2);
267210
267548
  if (!resolved && options.onData) {
@@ -267226,7 +267564,7 @@ var init_local_operations = __esm(() => {
267226
267564
  resolve4({ exitCode: null, output, taskId: task.id });
267227
267565
  }
267228
267566
  }, options.waitMsBeforeAsync) : undefined;
267229
- child.on("close", (code) => {
267567
+ const finish = (code) => {
267230
267568
  if (bgTimeout)
267231
267569
  clearTimeout(bgTimeout);
267232
267570
  if (timeoutHandle)
@@ -267236,6 +267574,25 @@ var init_local_operations = __esm(() => {
267236
267574
  resolved = true;
267237
267575
  resolve4({ exitCode: code, output });
267238
267576
  }
267577
+ };
267578
+ child.on("close", finish);
267579
+ child.on("exit", (code) => {
267580
+ setTimeout(() => finish(code), 50);
267581
+ });
267582
+ child.on("error", (err) => {
267583
+ if (bgTimeout)
267584
+ clearTimeout(bgTimeout);
267585
+ if (timeoutHandle)
267586
+ clearTimeout(timeoutHandle);
267587
+ taskManager.markCompleted(task.id, 1);
267588
+ if (!resolved) {
267589
+ resolved = true;
267590
+ const errMsg = `
267591
+ Failed to start process: ${err?.message || err}
267592
+ `;
267593
+ output += errMsg;
267594
+ resolve4({ exitCode: 1, output });
267595
+ }
267239
267596
  });
267240
267597
  });
267241
267598
  },
@@ -267252,19 +267609,19 @@ var init_local_operations = __esm(() => {
267252
267609
  fs: {
267253
267610
  readFile: async (filepath) => {
267254
267611
  const root2 = getScopedCwd();
267255
- const absolutePath = path19.isAbsolute(filepath) ? filepath : path19.resolve(root2, filepath);
267256
- return fs20.readFile(absolutePath, "utf8");
267612
+ const absolutePath = path20.isAbsolute(filepath) ? filepath : path20.resolve(root2, filepath);
267613
+ return fs21.readFile(absolutePath, "utf8");
267257
267614
  },
267258
267615
  writeFile: async (filepath, content) => {
267259
267616
  const root2 = getScopedCwd();
267260
- const absolutePath = path19.isAbsolute(filepath) ? filepath : path19.resolve(root2, filepath);
267261
- await fs20.mkdir(path19.dirname(absolutePath), { recursive: true });
267262
- await fs20.writeFile(absolutePath, content, "utf8");
267617
+ const absolutePath = path20.isAbsolute(filepath) ? filepath : path20.resolve(root2, filepath);
267618
+ await fs21.mkdir(path20.dirname(absolutePath), { recursive: true });
267619
+ await fs21.writeFile(absolutePath, content, "utf8");
267263
267620
  },
267264
267621
  readdir: async (dirPath) => {
267265
267622
  const root2 = getScopedCwd();
267266
- const absolutePath = path19.isAbsolute(dirPath) ? dirPath : path19.resolve(root2, dirPath);
267267
- const entries = await fs20.readdir(absolutePath, { withFileTypes: true });
267623
+ const absolutePath = path20.isAbsolute(dirPath) ? dirPath : path20.resolve(root2, dirPath);
267624
+ const entries = await fs21.readdir(absolutePath, { withFileTypes: true });
267268
267625
  const ignores = getWorkspaceIgnores(root2);
267269
267626
  return entries.filter((entry) => !isPathIgnored(entry.name, ignores)).map((entry) => {
267270
267627
  const type4 = entry.isDirectory() ? "DIR " : "FILE";
@@ -267273,14 +267630,14 @@ var init_local_operations = __esm(() => {
267273
267630
  },
267274
267631
  mkdir: async (dirPath, options) => {
267275
267632
  const root2 = getScopedCwd();
267276
- const absolutePath = path19.isAbsolute(dirPath) ? dirPath : path19.resolve(root2, dirPath);
267277
- await fs20.mkdir(absolutePath, options);
267633
+ const absolutePath = path20.isAbsolute(dirPath) ? dirPath : path20.resolve(root2, dirPath);
267634
+ await fs21.mkdir(absolutePath, options);
267278
267635
  },
267279
267636
  exists: async (filepath) => {
267280
267637
  const root2 = getScopedCwd();
267281
- const absolutePath = path19.isAbsolute(filepath) ? filepath : path19.resolve(root2, filepath);
267638
+ const absolutePath = path20.isAbsolute(filepath) ? filepath : path20.resolve(root2, filepath);
267282
267639
  try {
267283
- await fs20.access(absolutePath);
267640
+ await fs21.access(absolutePath);
267284
267641
  return true;
267285
267642
  } catch {
267286
267643
  return false;
@@ -267290,7 +267647,7 @@ var init_local_operations = __esm(() => {
267290
267647
  search: {
267291
267648
  find: async (dirPath, query3) => {
267292
267649
  const root2 = getScopedCwd();
267293
- const targetDir = path19.isAbsolute(dirPath) ? dirPath : path19.resolve(root2, dirPath);
267650
+ const targetDir = path20.isAbsolute(dirPath) ? dirPath : path20.resolve(root2, dirPath);
267294
267651
  const ignores = getWorkspaceIgnores(root2);
267295
267652
  const files = await import_fast_glob2.default([query3], {
267296
267653
  cwd: targetDir,
@@ -267302,7 +267659,7 @@ var init_local_operations = __esm(() => {
267302
267659
  },
267303
267660
  grep: async (dirPath, query3) => {
267304
267661
  const root2 = getScopedCwd();
267305
- const targetDir = path19.isAbsolute(dirPath) ? dirPath : path19.resolve(root2, dirPath);
267662
+ const targetDir = path20.isAbsolute(dirPath) ? dirPath : path20.resolve(root2, dirPath);
267306
267663
  const ignores = getWorkspaceIgnores(root2);
267307
267664
  try {
267308
267665
  const cmd = `git grep -nI "${query3}" ${targetDir} || grep -rnI --exclude-dir=node_modules --exclude-dir=.git "${query3}" ${targetDir}`;
@@ -267360,110 +267717,12 @@ var init_local_operations = __esm(() => {
267360
267717
  };
267361
267718
  });
267362
267719
 
267363
- // src/utils/version-check.ts
267364
- var exports_version_check = {};
267365
- __export(exports_version_check, {
267366
- CHECK_TTL_MS: () => CHECK_TTL_MS,
267367
- checkForLatestVersion: () => checkForLatestVersion,
267368
- clearVersionCheckCache: () => clearVersionCheckCache,
267369
- isNewerVersion: () => isNewerVersion
267370
- });
267371
- import https2 from "node:https";
267372
- function isNewerVersion(current, latest) {
267373
- const cleanCurrent = current.replace(/^v/, "");
267374
- const cleanLatest = latest.replace(/^v/, "");
267375
- const p1 = cleanCurrent.split(".").map((n) => Number(n) || 0);
267376
- const p2 = cleanLatest.split(".").map((n) => Number(n) || 0);
267377
- for (let i2 = 0;i2 < Math.max(p1.length, p2.length); i2++) {
267378
- const v1 = p1[i2] ?? 0;
267379
- const v2 = p2[i2] ?? 0;
267380
- if (v2 > v1)
267381
- return true;
267382
- if (v1 > v2)
267383
- return false;
267384
- }
267385
- return false;
267386
- }
267387
- async function checkForLatestVersion(currentVersion) {
267388
- try {
267389
- const config3 = await loadConfig();
267390
- const now2 = Date.now();
267391
- if (config3.versionCheckCache) {
267392
- const { latestVersion, checkedAt } = config3.versionCheckCache;
267393
- if (now2 - checkedAt < CHECK_TTL_MS) {
267394
- if (latestVersion && isNewerVersion(currentVersion, latestVersion)) {
267395
- return latestVersion;
267396
- }
267397
- return null;
267398
- }
267399
- }
267400
- const freshLatest = await fetchLatestFromNpm();
267401
- if (freshLatest) {
267402
- config3.versionCheckCache = {
267403
- latestVersion: freshLatest,
267404
- checkedAt: now2
267405
- };
267406
- await saveConfig(config3).catch(() => {});
267407
- if (isNewerVersion(currentVersion, freshLatest)) {
267408
- return freshLatest;
267409
- }
267410
- }
267411
- } catch {}
267412
- return null;
267413
- }
267414
- function fetchLatestFromNpm() {
267415
- return new Promise((resolve4) => {
267416
- const req = https2.get("https://registry.npmjs.org/@trydecember/cli/latest", { timeout: 1200 }, (res) => {
267417
- if (res.statusCode !== 200) {
267418
- resolve4(null);
267419
- return;
267420
- }
267421
- let data2 = "";
267422
- res.on("data", (chunk2) => {
267423
- data2 += chunk2;
267424
- });
267425
- res.on("end", () => {
267426
- try {
267427
- const parsed = JSON.parse(data2);
267428
- const latest = parsed.version;
267429
- if (latest && typeof latest === "string") {
267430
- resolve4(latest);
267431
- } else {
267432
- resolve4(null);
267433
- }
267434
- } catch {
267435
- resolve4(null);
267436
- }
267437
- });
267438
- });
267439
- req.on("error", () => resolve4(null));
267440
- req.on("timeout", () => {
267441
- req.destroy();
267442
- resolve4(null);
267443
- });
267444
- });
267445
- }
267446
- async function clearVersionCheckCache() {
267447
- try {
267448
- const config3 = await loadConfig();
267449
- if (config3.versionCheckCache) {
267450
- delete config3.versionCheckCache;
267451
- await saveConfig(config3);
267452
- }
267453
- } catch {}
267454
- }
267455
- var CHECK_TTL_MS;
267456
- var init_version_check = __esm(() => {
267457
- init_config();
267458
- CHECK_TTL_MS = 24 * 60 * 60 * 1000;
267459
- });
267460
-
267461
267720
  // src/index.ts
267462
- import path20 from "node:path";
267721
+ import path21 from "node:path";
267463
267722
  // package.json
267464
267723
  var package_default = {
267465
267724
  name: "@trydecember/cli",
267466
- version: "0.3.12",
267725
+ version: "0.3.14",
267467
267726
  description: "AI coding agent for terminal and cloud.",
267468
267727
  homepage: "https://trydecember.com",
267469
267728
  repository: {
@@ -267697,7 +267956,7 @@ Waiting for authorization...`);
267697
267956
  if (parsedArgs.scope) {
267698
267957
  setActiveScopeDir2(parsedArgs.scope);
267699
267958
  }
267700
- const React30 = reactModule.default || reactModule;
267959
+ const React32 = reactModule.default || reactModule;
267701
267960
  const { render: render4 } = inkModule;
267702
267961
  const { ChatApp: App2, RootLayout: RootLayout2 } = tuiModule;
267703
267962
  suppressConsole2();
@@ -267738,7 +267997,7 @@ Waiting for authorization...`);
267738
267997
  },
267739
267998
  sessionRepository,
267740
267999
  sessionId: parsedArgs.sessionId || sessionId,
267741
- workspaceDir: parsedArgs.scope ? path20.resolve(process.cwd(), parsedArgs.scope) : process.cwd(),
268000
+ workspaceDir: parsedArgs.scope ? path21.resolve(process.cwd(), parsedArgs.scope) : process.cwd(),
267742
268001
  hooks: {
267743
268002
  beforeToolCall: async (toolCall) => {}
267744
268003
  },
@@ -267765,8 +268024,8 @@ Executing Headless Task: "${parsedArgs.prompt}"
267765
268024
  harness.initMCP().catch(() => {});
267766
268025
  agent2.loadContext().catch((err) => {});
267767
268026
  function AppWrapper(props) {
267768
- const [latestVersion, setLatestVersion] = React30.useState(undefined);
267769
- React30.useEffect(() => {
268027
+ const [latestVersion, setLatestVersion] = React32.useState(undefined);
268028
+ React32.useEffect(() => {
267770
268029
  Promise.resolve().then(() => (init_version_check(), exports_version_check)).then(({ checkForLatestVersion: checkForLatestVersion2 }) => {
267771
268030
  checkForLatestVersion2(package_default.version).then((v2) => {
267772
268031
  if (v2)
@@ -267774,12 +268033,12 @@ Executing Headless Task: "${parsedArgs.prompt}"
267774
268033
  });
267775
268034
  }).catch(() => {});
267776
268035
  }, []);
267777
- const handleUpdateSuccess = React30.useCallback(async () => {
268036
+ const handleUpdateSuccess = React32.useCallback(async () => {
267778
268037
  const { clearVersionCheckCache: clearVersionCheckCache2 } = await Promise.resolve().then(() => (init_version_check(), exports_version_check));
267779
268038
  await clearVersionCheckCache2();
267780
268039
  }, []);
267781
268040
  const session = useAgentSession2(props);
267782
- return React30.createElement(App2, {
268041
+ return React32.createElement(App2, {
267783
268042
  ...props,
267784
268043
  latestVersion,
267785
268044
  onUpdateSuccess: handleUpdateSuccess,
@@ -267787,7 +268046,7 @@ Executing Headless Task: "${parsedArgs.prompt}"
267787
268046
  });
267788
268047
  }
267789
268048
  const userEmail = config3.decemberToken ? config3.email : undefined;
267790
- render4(React30.createElement(RootLayout2, null, React30.createElement(AppWrapper, {
268049
+ render4(React32.createElement(RootLayout2, null, React32.createElement(AppWrapper, {
267791
268050
  agent: agent2,
267792
268051
  isAuthenticated,
267793
268052
  authMethod: providerConfig?.authMethod,