@trydecember/cli 0.2.23 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/december.js +430 -301
  2. package/package.json +1 -1
package/dist/december.js CHANGED
@@ -103245,15 +103245,12 @@ Interrupted · What should December do instead?`,
103245
103245
  }
103246
103246
  if (errorMsg.includes("402") || errorMsg.toLowerCase().includes("insufficient credits")) {
103247
103247
  errorMsg = `Insufficient credits in December Wallet. Please add credits at https://trydecember.com/settings/billing to continue using December Cloud.
103248
-
103249
103248
  ` + errorMsg;
103250
103249
  } else if (errorMsg.includes("429") || errorMsg.toLowerCase().includes("quota") || errorMsg.toLowerCase().includes("rate limit")) {
103251
103250
  errorMsg = `Rate limit or quota exhausted from LLM provider. Please upgrade your API key tier with your provider (OpenAI, Anthropic, Gemini) or switch to December Cloud Subscription at https://trydecember.com/pricing
103252
-
103253
103251
  ` + errorMsg;
103254
103252
  } else if (errorMsg.includes("503") || errorMsg.includes("529") || errorMsg.toLowerCase().includes("high demand") || errorMsg.toLowerCase().includes("overloaded") || errorMsg.toLowerCase().includes("capacity")) {
103255
103253
  errorMsg = `This model is currently experiencing high demand or capacity limits from the provider. Spikes in demand are usually temporary. Please try again in a few moments or switch to a different model at https://trydecember.com/pricing
103256
-
103257
103254
  ` + errorMsg;
103258
103255
  }
103259
103256
  eventQueue.push({ type: "AgentError", error: errorMsg });
@@ -103460,8 +103457,8 @@ ${rule.content}
103460
103457
  try {
103461
103458
  const candidateFiles = [
103462
103459
  path7.join(this.config.workspaceDir, "AGENTS.md"),
103463
- path7.join(this.config.workspaceDir, ".december", "AGENTS.md"),
103464
- path7.join(this.config.workspaceDir, ".december", "rules.md")
103460
+ path7.join(this.config.workspaceDir, ".december", "rules.md"),
103461
+ path7.join(this.config.workspaceDir, ".december", "AGENTS.md")
103465
103462
  ];
103466
103463
  for (const rulePath of candidateFiles) {
103467
103464
  if (fs6.existsSync(rulePath)) {
@@ -169267,6 +169264,12 @@ var init_commands = __esm(() => {
169267
169264
  ctx.exit();
169268
169265
  }
169269
169266
  },
169267
+ {
169268
+ name: "feedback",
169269
+ description: "Submit feedback, report a bug, or request a feature",
169270
+ value: "/feedback",
169271
+ action: (ctx) => {}
169272
+ },
169270
169273
  {
169271
169274
  name: "fork",
169272
169275
  description: "Create a branch of the current conversation at this point",
@@ -169380,26 +169383,31 @@ var init_commands = __esm(() => {
169380
169383
  },
169381
169384
  {
169382
169385
  name: "init",
169383
- description: "Create a .december folder with initial rules, skills, and configuration",
169386
+ description: "Create initial rules, skills, and AGENTS.md configuration",
169384
169387
  value: "/init",
169385
169388
  action: (ctx) => {
169386
169389
  try {
169387
169390
  const rootDir = process.cwd();
169388
169391
  const decDir = path8.join(rootDir, ".december");
169389
- if (fs9.existsSync(decDir)) {
169392
+ const agentsFile = path8.join(rootDir, "AGENTS.md");
169393
+ const rulesFile = path8.join(decDir, "rules.md");
169394
+ const skillsFile = path8.join(decDir, "skills.md");
169395
+ if (fs9.existsSync(agentsFile) && fs9.existsSync(rulesFile) && fs9.existsSync(skillsFile)) {
169390
169396
  ctx.toast.show({ message: "December workspace is already initialized." });
169391
169397
  return;
169392
169398
  }
169393
169399
  fs9.mkdirSync(decDir, { recursive: true });
169394
- const agentsFile = path8.join(decDir, "AGENTS.md");
169395
- const rulesFile = path8.join(decDir, "rules.md");
169396
- const skillsFile = path8.join(decDir, "skills.md");
169397
- fs9.writeFileSync(agentsFile, `# AGENTS.md
169398
- `);
169399
- fs9.writeFileSync(rulesFile, `# Rules
169400
+ if (!fs9.existsSync(agentsFile)) {
169401
+ fs9.writeFileSync(agentsFile, "");
169402
+ }
169403
+ if (!fs9.existsSync(rulesFile)) {
169404
+ fs9.writeFileSync(rulesFile, `Add rules in this file for the agent to use as context.
169400
169405
  `);
169401
- fs9.writeFileSync(skillsFile, `# Skills
169406
+ }
169407
+ if (!fs9.existsSync(skillsFile)) {
169408
+ fs9.writeFileSync(skillsFile, `Add skills in this file for the agent to use as context.
169402
169409
  `);
169410
+ }
169403
169411
  ctx.toast.show({
169404
169412
  variant: "success",
169405
169413
  message: "Initialized December workspace successfully!"
@@ -169881,7 +169889,13 @@ var init_shortcuts_menu = __esm(async () => {
169881
169889
  { key: "ctrl+w", desc: "Delete word" },
169882
169890
  { key: "up/down", desc: "Input history" },
169883
169891
  { key: "ctrl+y", desc: "Quick copy (yank)" },
169884
- { key: "ctrl+c", desc: "Exit / Graceful interrupt" }
169892
+ { key: "ctrl+c", desc: "Exit / Graceful interrupt" },
169893
+ { key: "ctrl+h", desc: "Session history" },
169894
+ { key: "ctrl+l", desc: "Login / Account menu" },
169895
+ { key: "ctrl+o", desc: "Toggle expand commands" },
169896
+ { key: "ctrl+t", desc: "Tasks mode" },
169897
+ { key: "alt+enter", desc: "Insert newline" },
169898
+ { key: "esc", desc: "Cancel / Close menu" }
169885
169899
  ];
169886
169900
  });
169887
169901
 
@@ -170055,7 +170069,8 @@ function InputBar({
170055
170069
  contextTokens,
170056
170070
  history,
170057
170071
  showExitConfirm = false,
170058
- toasts
170072
+ toasts,
170073
+ queuedPrompts
170059
170074
  }) {
170060
170075
  const [value, setValue] = import_react41.useState("");
170061
170076
  const toast = useToast();
@@ -170116,10 +170131,15 @@ function InputBar({
170116
170131
  const handleCommand = import_react41.useCallback((command) => {
170117
170132
  if (!command)
170118
170133
  return;
170134
+ const currentValue = value.trim();
170119
170135
  setValue("");
170120
170136
  handleContentChange("");
170121
- if (command.value === "/grill-me" || command.value === "/login" || command.value === "/logout" || command.value === "/exit" || command.value === "/model" || command.value === "/resume" || command.value === "/settings" || command.value === "/context" || command.value === "/tasks" || command.value === "/usage") {
170122
- onSubmit(command.value);
170137
+ if (command.value === "/grill-me" || command.value === "/login" || command.value === "/logout" || command.value === "/exit" || command.value === "/model" || command.value === "/resume" || command.value === "/settings" || command.value === "/context" || command.value === "/tasks" || command.value === "/usage" || command.value === "/feedback") {
170138
+ if (currentValue.length > command.value.length && currentValue.toLowerCase().startsWith(command.value.toLowerCase())) {
170139
+ onSubmit(currentValue);
170140
+ } else {
170141
+ onSubmit(command.value);
170142
+ }
170123
170143
  return;
170124
170144
  }
170125
170145
  if (command.action) {
@@ -170171,6 +170191,17 @@ function InputBar({
170171
170191
  close: dialog.close
170172
170192
  }, undefined, false, undefined, this)
170173
170193
  }, undefined, false, undefined, this),
170194
+ queuedPrompts && queuedPrompts.length > 0 && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
170195
+ width: "100%",
170196
+ marginBottom: 0,
170197
+ children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text3, {
170198
+ color: "#89B4F8",
170199
+ children: [
170200
+ `Queued (${queuedPrompts.length}): "${queuedPrompts[0]}"`,
170201
+ queuedPrompts.length > 1 ? ` (+${queuedPrompts.length - 1} more)` : ""
170202
+ ]
170203
+ }, undefined, true, undefined, this)
170204
+ }, undefined, false, undefined, this),
170174
170205
  /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
170175
170206
  overflow: "hidden",
170176
170207
  height: 1,
@@ -170213,7 +170244,7 @@ function InputBar({
170213
170244
  children: sep4
170214
170245
  }, undefined, false, undefined, this)
170215
170246
  }, undefined, false, undefined, this),
170216
- !showCommandMenu && !showShortcutsMenu && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
170247
+ !showCommandMenu && !showShortcutsMenu && !authUI && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
170217
170248
  width: "100%",
170218
170249
  justifyContent: "space-between",
170219
170250
  children: [
@@ -170229,7 +170260,7 @@ function InputBar({
170229
170260
  color: "#AAAAAA",
170230
170261
  children: [
170231
170262
  activeModel,
170232
- hasBothAuth && authMethod ? ` (via ${authMethod === "december" ? "December Cloud" : "BYOK"})` : ""
170263
+ hasBothAuth && authMethod ? ` (${authMethod === "december" ? "December Cloud" : "BYOK"})` : ""
170233
170264
  ]
170234
170265
  }, undefined, true, undefined, this),
170235
170266
  activeToast ? /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text3, {
@@ -214464,68 +214495,76 @@ var init_marked_esm = __esm(() => {
214464
214495
 
214465
214496
  // ../../packages/tui/src/components/markdown.tsx
214466
214497
  function CodeBlock({ token }) {
214467
- const { isFocused } = use_focus_default();
214498
+ const { isFocused } = use_focus_default({ autoFocus: true });
214468
214499
  const [expanded, setExpanded] = import_react43.useState(false);
214469
214500
  use_input_default((input, key) => {
214470
- if (isFocused && key.return) {
214501
+ if (key.ctrl && (key.name === "o" || input?.toLowerCase() === "o") || input === "\x0F" || isFocused && key.return) {
214471
214502
  setExpanded((prev2) => !prev2);
214472
214503
  }
214473
214504
  });
214474
- const lines = token.text.split(`
214475
- `);
214476
- const isLarge = lines.length > 30;
214505
+ const lines = token.text.split(/\r?\n/);
214477
214506
  const lang = token.lang || "typescript";
214478
214507
  const barWidth = 60;
214479
214508
  const topBarLength = Math.max(0, barWidth - lang.length - 4);
214480
214509
  const topBar = `┌── ${lang} ${"─".repeat(topBarLength)}`;
214481
214510
  const bottomBar = `└${"─".repeat(barWidth - 1)}`;
214482
- let contentToHighlight = token.text;
214483
- if (isLarge && !expanded) {
214484
- contentToHighlight = lines.slice(0, 15).join(`
214485
- `);
214486
- }
214511
+ const MAX_VISIBLE_LINES = 20;
214512
+ const visibleLines = expanded ? lines.slice(0, MAX_VISIBLE_LINES) : [];
214513
+ const isTruncated = expanded && lines.length > MAX_VISIBLE_LINES;
214487
214514
  const highlighted = import_react43.default.useMemo(() => {
214488
- return import_cli_highlight.highlight(contentToHighlight, {
214515
+ if (visibleLines.length === 0)
214516
+ return "";
214517
+ return import_cli_highlight.highlight(visibleLines.join(`
214518
+ `), {
214489
214519
  language: lang,
214490
214520
  ignoreIllegals: true
214491
214521
  });
214492
- }, [contentToHighlight, lang]);
214522
+ }, [visibleLines, lang]);
214493
214523
  return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
214494
214524
  flexDirection: "column",
214495
214525
  paddingY: 1,
214496
214526
  children: [
214497
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214498
- color: isFocused ? "#89B4F8" : "#475569",
214499
- children: topBar
214500
- }, undefined, false, undefined, this),
214501
214527
  /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
214502
- flexDirection: "column",
214503
- paddingLeft: 2,
214504
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214505
- children: highlighted
214506
- }, undefined, false, undefined, this)
214507
- }, undefined, false, undefined, this),
214508
- isLarge && !expanded ? /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
214509
- flexDirection: "column",
214510
- paddingLeft: 2,
214528
+ alignItems: "center",
214529
+ gap: 1,
214511
214530
  children: [
214512
214531
  /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214513
- color: "#475569",
214514
- children: "..."
214532
+ color: isFocused ? "#89B4F8" : "#475569",
214533
+ children: topBar
214515
214534
  }, undefined, false, undefined, this),
214516
214535
  /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214517
- color: isFocused ? "#89B4F8" : "#888888",
214518
- children: isFocused ? "> Press Enter to expand (" + (lines.length - 15) + " more lines)" : "... (truncated, tab to focus)"
214536
+ color: "gray",
214537
+ children: [
214538
+ "(",
214539
+ expanded ? "ctrl+o / enter to collapse" : "ctrl+o / enter to expand",
214540
+ ")"
214541
+ ]
214542
+ }, undefined, true, undefined, this)
214543
+ ]
214544
+ }, undefined, true, undefined, this),
214545
+ expanded && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(jsx_dev_runtime9.Fragment, {
214546
+ children: [
214547
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
214548
+ flexDirection: "column",
214549
+ paddingLeft: 2,
214550
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214551
+ children: highlighted
214552
+ }, undefined, false, undefined, this)
214553
+ }, undefined, false, undefined, this),
214554
+ isTruncated && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
214555
+ flexDirection: "column",
214556
+ paddingLeft: 2,
214557
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214558
+ color: "#AAAAAA",
214559
+ children: [
214560
+ "... (",
214561
+ lines.length - MAX_VISIBLE_LINES,
214562
+ " more lines)"
214563
+ ]
214564
+ }, undefined, true, undefined, this)
214519
214565
  }, undefined, false, undefined, this)
214520
214566
  ]
214521
- }, undefined, true, undefined, this) : isLarge && expanded ? /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
214522
- flexDirection: "column",
214523
- paddingLeft: 2,
214524
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214525
- color: isFocused ? "#89B4F8" : "#888888",
214526
- children: isFocused ? "> Press Enter to collapse" : ""
214527
- }, undefined, false, undefined, this)
214528
- }, undefined, false, undefined, this) : null,
214567
+ }, undefined, true, undefined, this),
214529
214568
  /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text3, {
214530
214569
  color: isFocused ? "#89B4F8" : "#475569",
214531
214570
  children: bottomBar
@@ -214781,6 +214820,9 @@ function CollapsibleCommandOutput({
214781
214820
  }
214782
214821
  });
214783
214822
  const lines = output ? output.trim().split(/\r?\n/) : [];
214823
+ const MAX_VISIBLE_LINES = 20;
214824
+ const visibleLines = isExpanded ? lines.slice(0, MAX_VISIBLE_LINES) : [];
214825
+ const isTruncated = isExpanded && lines.length > MAX_VISIBLE_LINES;
214784
214826
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214785
214827
  flexDirection: "column",
214786
214828
  marginY: 0,
@@ -214806,29 +214848,42 @@ function CollapsibleCommandOutput({
214806
214848
  flexDirection: "column",
214807
214849
  marginTop: 0,
214808
214850
  paddingX: 1,
214809
- children: lines.map((line, lidx) => {
214810
- let color = "#d1d5db";
214811
- let bgColor = undefined;
214812
- if (line.startsWith("+")) {
214813
- color = "#6EE7B7";
214814
- bgColor = "#122f1e";
214815
- } else if (line.startsWith("-")) {
214816
- color = "#FCA5A5";
214817
- bgColor = "#3f1316";
214818
- } else if (line.startsWith("@@") || line.startsWith("diff --git") || line.startsWith("---") || line.startsWith("+++")) {
214819
- color = "#d1d5db";
214820
- }
214821
- return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214822
- backgroundColor: bgColor,
214823
- flexDirection: "row",
214851
+ children: [
214852
+ visibleLines.map((line, lidx) => {
214853
+ let color = "#d1d5db";
214854
+ let bgColor = undefined;
214855
+ if (line.startsWith("+")) {
214856
+ color = "#6EE7B7";
214857
+ bgColor = "#122f1e";
214858
+ } else if (line.startsWith("-")) {
214859
+ color = "#FCA5A5";
214860
+ bgColor = "#3f1316";
214861
+ } else if (line.startsWith("@@") || line.startsWith("diff --git") || line.startsWith("---") || line.startsWith("+++")) {
214862
+ color = "#d1d5db";
214863
+ }
214864
+ return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214865
+ backgroundColor: bgColor,
214866
+ flexDirection: "row",
214867
+ children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214868
+ color,
214869
+ wrap: "truncate-end",
214870
+ children: line
214871
+ }, undefined, false, undefined, this)
214872
+ }, lidx, false, undefined, this);
214873
+ }),
214874
+ isTruncated && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214875
+ paddingTop: 0,
214824
214876
  children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214825
- color,
214826
- wrap: "truncate-end",
214827
- children: line
214828
- }, undefined, false, undefined, this)
214829
- }, lidx, false, undefined, this);
214830
- })
214831
- }, undefined, false, undefined, this)
214877
+ color: "#AAAAAA",
214878
+ children: [
214879
+ "... (",
214880
+ lines.length - MAX_VISIBLE_LINES,
214881
+ " more lines)"
214882
+ ]
214883
+ }, undefined, true, undefined, this)
214884
+ }, undefined, false, undefined, this)
214885
+ ]
214886
+ }, undefined, true, undefined, this)
214832
214887
  ]
214833
214888
  }, undefined, true, undefined, this);
214834
214889
  }
@@ -214838,8 +214893,19 @@ function BotMessage({ blocks, usage, expandCommands }) {
214838
214893
  paddingX: 4,
214839
214894
  paddingY: 0,
214840
214895
  gap: 0,
214841
- marginTop: 0.5,
214896
+ marginTop: 0,
214842
214897
  children: blocks.map((block, idx) => {
214898
+ let prevBlock = null;
214899
+ for (let i2 = idx - 1;i2 >= 0; i2--) {
214900
+ const b2 = blocks[i2];
214901
+ if (!b2)
214902
+ continue;
214903
+ if (b2.type === "text" && (!b2.content || b2.content.trim() === ""))
214904
+ continue;
214905
+ prevBlock = b2;
214906
+ break;
214907
+ }
214908
+ const needsTopMargin = Boolean(prevBlock && (prevBlock.type === "command" || prevBlock.type === "thinking" || prevBlock.type === "compaction"));
214843
214909
  switch (block.type) {
214844
214910
  case "text": {
214845
214911
  if (!block.content || block.content.trim() === "")
@@ -214849,58 +214915,81 @@ function BotMessage({ blocks, usage, expandCommands }) {
214849
214915
  if (idx !== blocks.length - 1)
214850
214916
  return null;
214851
214917
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214852
- gap: 1,
214853
- alignItems: "center",
214918
+ flexDirection: "column",
214854
214919
  children: [
214855
- /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Spinner2, {}, undefined, false, undefined, this),
214856
- /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214857
- color: "gray",
214858
- children: block.content
214859
- }, undefined, false, undefined, this)
214920
+ needsTopMargin && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214921
+ children: " "
214922
+ }, undefined, false, undefined, this),
214923
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214924
+ gap: 1,
214925
+ alignItems: "center",
214926
+ children: [
214927
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Spinner2, {}, undefined, false, undefined, this),
214928
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214929
+ color: "gray",
214930
+ children: block.content
214931
+ }, undefined, false, undefined, this)
214932
+ ]
214933
+ }, undefined, true, undefined, this)
214860
214934
  ]
214861
214935
  }, idx, true, undefined, this);
214862
214936
  }
214863
214937
  if (block.color) {
214864
214938
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214865
- children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214866
- color: block.color,
214867
- children: block.content
214868
- }, undefined, false, undefined, this)
214869
- }, idx, false, undefined, this);
214939
+ flexDirection: "column",
214940
+ children: [
214941
+ needsTopMargin && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214942
+ children: " "
214943
+ }, undefined, false, undefined, this),
214944
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214945
+ color: block.color,
214946
+ children: block.content
214947
+ }, undefined, false, undefined, this)
214948
+ ]
214949
+ }, idx, true, undefined, this);
214870
214950
  }
214871
214951
  const parts = block.content.split(/(<thought(?:>| [^>]*>)[\s\S]*?<\/thought>|<thought(?:>| [^>]*>)[\s\S]*)/i);
214872
214952
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214873
214953
  flexDirection: "column",
214874
- children: parts.map((part, pidx) => {
214875
- if (/^<thought(?:>| [^>]*>)/i.test(part)) {
214876
- const isClosed = /<\/thought>$/i.test(part);
214877
- const isStreaming = !isClosed && idx === blocks.length - 1 && pidx === parts.length - 1;
214878
- const thoughtContent = part.replace(/^<thought(?:>| [^>]*>)/i, "").replace(/<\/thought>$/i, "").trim();
214879
- return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(CollapsibleThought, {
214880
- content: thoughtContent,
214881
- isStreaming
214954
+ children: [
214955
+ needsTopMargin && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214956
+ children: " "
214957
+ }, undefined, false, undefined, this),
214958
+ parts.map((part, pidx) => {
214959
+ if (/^<thought(?:>| [^>]*>)/i.test(part)) {
214960
+ const isClosed = /<\/thought>$/i.test(part);
214961
+ const isStreaming = !isClosed && idx === blocks.length - 1 && pidx === parts.length - 1;
214962
+ const thoughtContent = part.replace(/^<thought(?:>| [^>]*>)/i, "").replace(/<\/thought>$/i, "").trim();
214963
+ return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(CollapsibleThought, {
214964
+ content: thoughtContent,
214965
+ isStreaming
214966
+ }, pidx, false, undefined, this);
214967
+ }
214968
+ if (part.trim() === "")
214969
+ return null;
214970
+ return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214971
+ children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(SmoothMarkdown, {
214972
+ text: part.trim(),
214973
+ isRunning: true
214974
+ }, undefined, false, undefined, this)
214882
214975
  }, pidx, false, undefined, this);
214883
- }
214884
- if (part.trim() === "")
214885
- return null;
214886
- return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214887
- children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(SmoothMarkdown, {
214888
- text: part.trim(),
214889
- isRunning: true
214890
- }, undefined, false, undefined, this)
214891
- }, pidx, false, undefined, this);
214892
- })
214893
- }, idx, false, undefined, this);
214976
+ })
214977
+ ]
214978
+ }, idx, true, undefined, this);
214894
214979
  }
214895
214980
  case "error": {
214896
214981
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
214897
214982
  flexDirection: "column",
214898
- marginY: 0.5,
214899
- children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214900
- color: "#FCA5A5",
214901
- children: block.error
214902
- }, undefined, false, undefined, this)
214903
- }, idx, false, undefined, this);
214983
+ children: [
214984
+ needsTopMargin && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214985
+ children: " "
214986
+ }, undefined, false, undefined, this),
214987
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text3, {
214988
+ color: "#FCA5A5",
214989
+ children: block.error
214990
+ }, undefined, false, undefined, this)
214991
+ ]
214992
+ }, idx, true, undefined, this);
214904
214993
  }
214905
214994
  case "interrupt": {
214906
214995
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
@@ -215228,15 +215317,21 @@ var init_header = __esm(async () => {
215228
215317
  });
215229
215318
 
215230
215319
  // ../../packages/tui/src/components/messages/error-message.tsx
215231
- function ErrorMessage({ message }) {
215320
+ function ErrorMessage({ message, hasTopMargin = false }) {
215232
215321
  return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
215233
215322
  paddingX: 4,
215234
- paddingY: 0.5,
215235
- children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text3, {
215236
- color: "#FCA5A5",
215237
- children: message
215238
- }, undefined, false, undefined, this)
215239
- }, undefined, false, undefined, this);
215323
+ paddingY: 0,
215324
+ flexDirection: "column",
215325
+ children: [
215326
+ hasTopMargin && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text3, {
215327
+ children: " "
215328
+ }, undefined, false, undefined, this),
215329
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text3, {
215330
+ color: "#FCA5A5",
215331
+ children: message.trim()
215332
+ }, undefined, false, undefined, this)
215333
+ ]
215334
+ }, undefined, true, undefined, this);
215240
215335
  }
215241
215336
  var jsx_dev_runtime13;
215242
215337
  var init_error_message = __esm(async () => {
@@ -215251,7 +215346,7 @@ function UserMessage({ message }) {
215251
215346
  paddingRight: 4,
215252
215347
  paddingY: 0,
215253
215348
  marginTop: 1,
215254
- marginBottom: 0.5,
215349
+ marginBottom: 1,
215255
215350
  flexDirection: "row",
215256
215351
  children: [
215257
215352
  /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Box_default, {
@@ -215302,10 +215397,14 @@ function MessageList({
215302
215397
  return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(UserMessage, {
215303
215398
  message: msg.text ?? ""
215304
215399
  }, key, false, undefined, this);
215305
- if (msg.role === "error")
215400
+ if (msg.role === "error") {
215401
+ const prevRole = index2 > 0 ? allMessages[index2 - 1]?.role : null;
215402
+ const hasTopMargin = prevRole !== "user";
215306
215403
  return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(ErrorMessage, {
215307
- message: msg.text ?? ""
215404
+ message: msg.text ?? "",
215405
+ hasTopMargin
215308
215406
  }, key, false, undefined, this);
215407
+ }
215309
215408
  return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(BotMessage, {
215310
215409
  blocks: msg.blocks ?? [],
215311
215410
  usage: msg.usage,
@@ -215520,8 +215619,7 @@ function ByokKeyMenu(props) {
215520
215619
  focus: true,
215521
215620
  value: apiKey,
215522
215621
  onChange: setApiKey,
215523
- onSubmit: handleKeySubmit,
215524
- mask: "*"
215622
+ onSubmit: handleKeySubmit
215525
215623
  }, undefined, false, undefined, this)
215526
215624
  ]
215527
215625
  }, undefined, true, undefined, this),
@@ -216340,6 +216438,15 @@ function GrillQuestionMenu(props) {
216340
216438
  marginBottom: 1,
216341
216439
  flexDirection: "column",
216342
216440
  children: [
216441
+ q2.docSource && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text3, {
216442
+ color: "#7DD3FC",
216443
+ bold: true,
216444
+ children: [
216445
+ "[Doc Grounding: ",
216446
+ q2.docSource,
216447
+ "]"
216448
+ ]
216449
+ }, undefined, true, undefined, this),
216343
216450
  /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text3, {
216344
216451
  color: "#89B4F8",
216345
216452
  bold: true,
@@ -216425,8 +216532,10 @@ function GrillQuestionMenu(props) {
216425
216532
  onChange: setCustomAnswer,
216426
216533
  onSubmit: (value) => {
216427
216534
  const answer = value.trim();
216428
- if (answer.length === 0)
216535
+ if (answer.length === 0) {
216536
+ setCustomInputMode(false);
216429
216537
  return;
216538
+ }
216430
216539
  setCustomInputMode(false);
216431
216540
  setCustomAnswer("");
216432
216541
  const nextAnswers = [...grillAnswers, answer];
@@ -216939,7 +217048,9 @@ function SessionSelectMenu(props) {
216939
217048
  }, session.id, true, undefined, this);
216940
217049
  }
216941
217050
  const isCustomName = !session.id.startsWith("session-");
216942
- const title = isCustomName ? session.id : session.preview || session.id;
217051
+ const rawTitle = isCustomName ? session.id : session.preview || session.id;
217052
+ const singleLineTitle = (rawTitle || "").replace(/\s+/g, " ").trim();
217053
+ const title = singleLineTitle.length > 50 ? singleLineTitle.slice(0, 50) + "..." : singleLineTitle;
216943
217054
  const timeStr = timeAgo(session.updatedAt).padStart(10);
216944
217055
  return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
216945
217056
  flexDirection: "row",
@@ -217203,13 +217314,12 @@ function TasksModeMenu(props) {
217203
217314
  const getStatusColor = (status) => {
217204
217315
  switch (status) {
217205
217316
  case "running":
217206
- return "#2ECC71";
217317
+ return "#fef08a";
217207
217318
  case "completed":
217208
- return "#3498DB";
217319
+ return "#6EE7B7";
217209
217320
  case "failed":
217210
- return "#E74C3C";
217211
217321
  case "killed":
217212
- return "#F1C40F";
217322
+ return "#FCA5A5";
217213
217323
  default:
217214
217324
  return "white";
217215
217325
  }
@@ -217792,6 +217902,14 @@ function GlobalShortcuts(session) {
217792
217902
  }
217793
217903
  if (authMode !== "none") {
217794
217904
  if (key.escape && authMode !== "login") {
217905
+ if (authMode === "grill_question") {
217906
+ setGrillQuestions([]);
217907
+ setCurrentGrillIndex(0);
217908
+ setGrillAnswers([]);
217909
+ setGrillPrompt(null);
217910
+ setCustomInputMode(false);
217911
+ setGrillMode(false);
217912
+ }
217795
217913
  setAuthMode("none");
217796
217914
  }
217797
217915
  return;
@@ -217936,8 +218054,10 @@ function ChatApp({
217936
218054
  setStaticMessages([{ id: "header-" + Date.now(), role: "header" }]);
217937
218055
  setStaticKey((k) => k + 1);
217938
218056
  setActiveMessages([]);
218057
+ session.setQueuedPrompts?.([]);
217939
218058
  session.addToast?.("Started a new conversation.", "success");
217940
218059
  },
218060
+ queuedPrompts: session.queuedPrompts,
217941
218061
  grillMode,
217942
218062
  customInputMode: false,
217943
218063
  showExitConfirm: exitConfirm
@@ -218233,6 +218353,10 @@ var init_store = __esm(async () => {
218233
218353
  })),
218234
218354
  isStreaming: false,
218235
218355
  setIsStreaming: (isStreaming) => set2({ isStreaming }),
218356
+ queuedPrompts: [],
218357
+ setQueuedPrompts: (updater) => set2((state) => ({
218358
+ queuedPrompts: typeof updater === "function" ? updater(state.queuedPrompts) : updater
218359
+ })),
218236
218360
  sessionItems: [],
218237
218361
  setSessionItems: (sessionItems) => set2({ sessionItems }),
218238
218362
  sessionsData: [],
@@ -218398,7 +218522,6 @@ function parseErrorMessage(err) {
218398
218522
  }
218399
218523
  }
218400
218524
  const rateLimitNotice = `Rate limit or quota exhausted from LLM provider. Please upgrade your API key tier with your provider (OpenAI, Anthropic, Gemini) or switch to December Cloud Subscription at https://trydecember.com/pricing
218401
-
218402
218525
  `;
218403
218526
  const lowerStr = (errMsg + " " + (finalResult || "")).toLowerCase();
218404
218527
  const isRateLimit = lowerStr.includes("429") || lowerStr.includes("quota") || lowerStr.includes("rate limit") || lowerStr.includes("rate_limit") || lowerStr.includes("resource_exhausted") || lowerStr.includes("generativelanguage.googleapis.com");
@@ -227591,42 +227714,6 @@ var BrowserTool = {
227591
227714
  }
227592
227715
  }
227593
227716
  };
227594
- // ../../packages/tools/src/github.ts
227595
- var githubSchema = Type2.Object({
227596
- endpoint: Type2.String({ description: "GitHub API endpoint (e.g. /repos/owner/repo/issues)" }),
227597
- method: Type2.Optional(Type2.String({ description: "GET, POST, PATCH, etc. Defaults to GET." })),
227598
- body: Type2.Optional(Type2.String({ description: "JSON string of the request body" }))
227599
- });
227600
- var GitHubTool = {
227601
- name: "github",
227602
- description: "Interact with GitHub API (create PRs, read issues, etc). Automatically injects GITHUB_TOKEN if available in the environment.",
227603
- inputSchema: githubSchema,
227604
- execute: async ({ endpoint, method = "GET", body }, context) => {
227605
- try {
227606
- const token = context.operations.env.get("GITHUB_TOKEN");
227607
- const headers = {
227608
- Accept: "application/vnd.github.v3+json",
227609
- "User-Agent": "December-Agent"
227610
- };
227611
- if (token) {
227612
- headers["Authorization"] = `token ${token}`;
227613
- }
227614
- const url = endpoint.startsWith("http") ? endpoint : `https://api.github.com${endpoint.startsWith("/") ? "" : "/"}${endpoint}`;
227615
- const res = await fetch(url, {
227616
- method,
227617
- headers,
227618
- body: body ? body : undefined
227619
- });
227620
- const text = await res.text();
227621
- if (!res.ok) {
227622
- return `GitHub API Error (${res.status}): ${text}`;
227623
- }
227624
- return text;
227625
- } catch (error3) {
227626
- return `Failed to fetch from GitHub: ${error3.message}`;
227627
- }
227628
- }
227629
- };
227630
227717
  // ../../packages/tools/src/web_search.ts
227631
227718
  init_src();
227632
227719
 
@@ -241054,64 +241141,6 @@ var WebSearchTool = {
241054
241141
  }
241055
241142
  }
241056
241143
  };
241057
- // ../../packages/tools/src/wiki.ts
241058
- var readWikiSchema = Type2.Object({
241059
- pageId: Type2.String({ description: "The ID or title of the wiki page to read" })
241060
- });
241061
- var readWikiTool = {
241062
- name: "read_wiki",
241063
- description: "Read a wiki page from the project folder documentation.",
241064
- inputSchema: readWikiSchema,
241065
- execute: async (args, context) => {
241066
- const { pageId } = args;
241067
- return `Wiki content for ${pageId} retrieved.`;
241068
- }
241069
- };
241070
- var updateWikiSchema = Type2.Object({
241071
- pageId: Type2.String({ description: "The ID or title of the wiki page to update" }),
241072
- content: Type2.String({ description: "The markdown content to save" })
241073
- });
241074
- var updateWikiTool = {
241075
- name: "update_wiki",
241076
- description: "Update or create a wiki page in the project folder documentation.",
241077
- inputSchema: updateWikiSchema,
241078
- execute: async (args, context) => {
241079
- const { pageId, content } = args;
241080
- return `Wiki page ${pageId} updated successfully.`;
241081
- }
241082
- };
241083
- // ../../packages/tools/src/pr.ts
241084
- var createPrReviewSchema = Type2.Object({
241085
- prUrl: Type2.String({ description: "The GitHub Pull Request URL" }),
241086
- comments: Type2.Array(Type2.Object({
241087
- path: Type2.String(),
241088
- line: Type2.Number(),
241089
- body: Type2.String()
241090
- }), { description: "List of review comments" })
241091
- });
241092
- var createPrReviewTool = {
241093
- name: "create_pr_review",
241094
- description: "Create a PR review on GitHub with line-specific comments.",
241095
- inputSchema: createPrReviewSchema,
241096
- execute: async (args, context) => {
241097
- const { prUrl } = args;
241098
- return `Successfully submitted PR review for ${prUrl}.`;
241099
- }
241100
- };
241101
- var submitPrSchema = Type2.Object({
241102
- branch: Type2.String({ description: "The branch name to push" }),
241103
- title: Type2.String({ description: "The PR title" }),
241104
- body: Type2.String({ description: "The PR description body" })
241105
- });
241106
- var submitPrTool = {
241107
- name: "submit_pr",
241108
- description: "Push changes and submit a new Pull Request on GitHub.",
241109
- inputSchema: submitPrSchema,
241110
- execute: async (args, context) => {
241111
- const { branch, title } = args;
241112
- return `Successfully submitted PR "${title}" from branch ${branch}.`;
241113
- }
241114
- };
241115
241144
  // src/index.ts
241116
241145
  await __promiseAll([
241117
241146
  init_src6(),
@@ -241125,7 +241154,7 @@ var package_default = {
241125
241154
  module: "src/index.ts",
241126
241155
  type: "module",
241127
241156
  private: false,
241128
- version: "0.2.23",
241157
+ version: "0.2.24",
241129
241158
  description: "Turn ideas into reality.",
241130
241159
  author: "Chaitanya Sonawane",
241131
241160
  license: "Apache-2.0",
@@ -241326,33 +241355,49 @@ async function handleLogoutCommand() {
241326
241355
  await saveConfig(config);
241327
241356
  console.log("Logged out successfully. Stored credentials removed.");
241328
241357
  }
241329
- var DEFAULT_AGENTS_MD = `# AGENTS.md
241330
- `;
241331
- var DEFAULT_RULES_MD = `# Rules
241358
+ var DEFAULT_AGENTS_MD = "";
241359
+ var DEFAULT_RULES_MD = `Add rules in this file for the agent to use as context.
241332
241360
  `;
241333
- var DEFAULT_SKILLS_MD = `# Skills
241361
+ var DEFAULT_SKILLS_MD = `Add skills in this file for the agent to use as context.
241334
241362
  `;
241335
241363
  async function handleInitCommand() {
241336
- const decDir = path11.join(process.cwd(), ".december");
241364
+ const rootDir = process.cwd();
241365
+ const decDir = path11.join(rootDir, ".december");
241337
241366
  await fs12.mkdir(decDir, { recursive: true });
241338
241367
  const filesToScaffold = [
241339
- { name: "AGENTS.md", content: DEFAULT_AGENTS_MD },
241340
- { name: "rules.md", content: DEFAULT_RULES_MD },
241341
- { name: "skills.md", content: DEFAULT_SKILLS_MD },
241368
+ {
241369
+ name: "AGENTS.md",
241370
+ targetPath: path11.join(rootDir, "AGENTS.md"),
241371
+ displayPath: "AGENTS.md",
241372
+ content: DEFAULT_AGENTS_MD
241373
+ },
241374
+ {
241375
+ name: "rules.md",
241376
+ targetPath: path11.join(decDir, "rules.md"),
241377
+ displayPath: ".december/rules.md",
241378
+ content: DEFAULT_RULES_MD
241379
+ },
241380
+ {
241381
+ name: "skills.md",
241382
+ targetPath: path11.join(decDir, "skills.md"),
241383
+ displayPath: ".december/skills.md",
241384
+ content: DEFAULT_SKILLS_MD
241385
+ },
241342
241386
  {
241343
241387
  name: "settings.json",
241388
+ targetPath: path11.join(decDir, "settings.json"),
241389
+ displayPath: ".december/settings.json",
241344
241390
  content: JSON.stringify({ thinkingLevel: "low", steeringMode: "all" }, null, 2) + `
241345
241391
  `
241346
241392
  }
241347
241393
  ];
241348
241394
  for (const file of filesToScaffold) {
241349
- const filePath = path11.join(decDir, file.name);
241350
241395
  try {
241351
- await fs12.access(filePath);
241352
- console.log(`.december/${file.name} already exists.`);
241396
+ await fs12.access(file.targetPath);
241397
+ console.log(`${file.displayPath} already exists.`);
241353
241398
  } catch {
241354
- await fs12.writeFile(filePath, file.content, "utf-8");
241355
- console.log(`Created .december/${file.name}`);
241399
+ await fs12.writeFile(file.targetPath, file.content, "utf-8");
241400
+ console.log(`Created ${file.displayPath}`);
241356
241401
  }
241357
241402
  }
241358
241403
  console.log(`
@@ -241701,7 +241746,7 @@ ${projectContext ? `<project_context>
241701
241746
  ${projectContext}
241702
241747
  </project_context>
241703
241748
  ` : ""}
241704
- Generate 5 to 8 targeted, high-impact multiple-choice questions to clarify requirements, architectural choices, tech stack decisions, edge cases, and potential breaking changes.
241749
+ Generate exactly 10 targeted, high-impact multiple-choice questions to clarify requirements, architectural choices, tech stack decisions, edge cases, and potential breaking changes.
241705
241750
 
241706
241751
  Requirements for questions:
241707
241752
  1. Focus on technical depth: probe architectural tradeoffs, API design, state management, edge cases, and error handling.
@@ -241823,6 +241868,38 @@ if (!globalSymbols.__taskManagerCleanupAdded) {
241823
241868
 
241824
241869
  // src/hooks/use-agent-session.ts
241825
241870
  init_error_parser();
241871
+
241872
+ // src/utils/json-parser.ts
241873
+ function extractJsonArray(rawText) {
241874
+ const trimmed = rawText.trim();
241875
+ try {
241876
+ const parsed = JSON.parse(trimmed);
241877
+ if (Array.isArray(parsed)) {
241878
+ return parsed;
241879
+ }
241880
+ } catch {}
241881
+ const codeblockMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
241882
+ if (codeblockMatch && codeblockMatch[1]) {
241883
+ try {
241884
+ const parsed = JSON.parse(codeblockMatch[1].trim());
241885
+ if (Array.isArray(parsed)) {
241886
+ return parsed;
241887
+ }
241888
+ } catch {}
241889
+ }
241890
+ const arrayBracketMatch = trimmed.match(/\[\s*\{[\s\S]*\}\s*\]/);
241891
+ if (arrayBracketMatch) {
241892
+ try {
241893
+ const parsed = JSON.parse(arrayBracketMatch[0]);
241894
+ if (Array.isArray(parsed)) {
241895
+ return parsed;
241896
+ }
241897
+ } catch {}
241898
+ }
241899
+ throw new Error("Failed to extract a valid JSON array from model output.");
241900
+ }
241901
+
241902
+ // src/hooks/use-agent-session.ts
241826
241903
  init_models5();
241827
241904
 
241828
241905
  // src/hooks/use-agent-runner.ts
@@ -242119,7 +242196,7 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242119
242196
  throw new Error("Login functionality is not provided by the host environment.");
242120
242197
  }
242121
242198
  const codeMsgId = getNextMsgId();
242122
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242199
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242123
242200
  setActiveMessages([
242124
242201
  {
242125
242202
  id: codeMsgId,
@@ -242167,7 +242244,7 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242167
242244
  setHasBothAuth(authStatus.hasByok && authStatus.hasDecember);
242168
242245
  setSettingsAuthPriority(authStatus.authPriority);
242169
242246
  }
242170
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242247
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242171
242248
  setActiveMessages([
242172
242249
  {
242173
242250
  id: getNextMsgId(),
@@ -242182,7 +242259,7 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242182
242259
  }
242183
242260
  const errorText = `Login failed: ${cleanMsg}`;
242184
242261
  setAuthError(errorText);
242185
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242262
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242186
242263
  setActiveMessages([{ id: getNextMsgId(), role: "error", text: errorText }]);
242187
242264
  } finally {
242188
242265
  setIsStreaming(false);
@@ -242327,7 +242404,7 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242327
242404
  setAuthError(errorText);
242328
242405
  setAuthMode("none");
242329
242406
  setApiKey("");
242330
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242407
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242331
242408
  setActiveMessages([
242332
242409
  {
242333
242410
  id: getNextMsgId(),
@@ -242374,7 +242451,7 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242374
242451
  } else {
242375
242452
  setAuthMethod(undefined);
242376
242453
  }
242377
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242454
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242378
242455
  setActiveMessages([]);
242379
242456
  addToast(`Removed credentials for: ${removedName}`, "success");
242380
242457
  };
@@ -242389,15 +242466,6 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242389
242466
  resumedMessages.push({ id: getNextMsgId(), role: "user", text: msg.content });
242390
242467
  } else if (msg.role === "assistant") {
242391
242468
  const blocks = [];
242392
- if (msg.errorMessage) {
242393
- const { parseErrorMessage: parseErrorMessage2 } = await Promise.resolve().then(() => (init_error_parser(), exports_error_parser));
242394
- blocks.push({
242395
- type: "error",
242396
- error: parseErrorMessage2({ message: msg.errorMessage })
242397
- });
242398
- } else if (msg.content) {
242399
- blocks.push({ type: "text", content: msg.content });
242400
- }
242401
242469
  if (msg.toolCalls && msg.toolCalls.length > 0) {
242402
242470
  for (const tc of msg.toolCalls) {
242403
242471
  const toolMsg = agent2.messages.find((m3) => m3.role === "tool" && m3.toolCallId === tc.id);
@@ -242414,6 +242482,15 @@ function useAuthHandlers(agent2, onLogin, onLoginHeadless) {
242414
242482
  });
242415
242483
  }
242416
242484
  }
242485
+ if (msg.errorMessage) {
242486
+ const { parseErrorMessage: parseErrorMessage2 } = await Promise.resolve().then(() => (init_error_parser(), exports_error_parser));
242487
+ blocks.push({
242488
+ type: "error",
242489
+ error: parseErrorMessage2({ message: msg.errorMessage })
242490
+ });
242491
+ } else if (msg.content) {
242492
+ blocks.push({ type: "text", content: msg.content });
242493
+ }
242417
242494
  if (blocks.length > 0) {
242418
242495
  resumedMessages.push({
242419
242496
  id: getNextMsgId(),
@@ -242650,6 +242727,8 @@ function useAgentSession({
242650
242727
  setActiveMessages,
242651
242728
  isStreaming,
242652
242729
  setIsStreaming,
242730
+ queuedPrompts,
242731
+ setQueuedPrompts,
242653
242732
  pendingQuestions,
242654
242733
  setPendingQuestions,
242655
242734
  pendingToolCall,
@@ -242779,7 +242858,7 @@ function useAgentSession({
242779
242858
  }, [setTasksData]);
242780
242859
  const generateGrillQuestions = import_react53.useCallback(async (userPrompt) => {
242781
242860
  setIsStreaming(true);
242782
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242861
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242783
242862
  setActiveMessages([
242784
242863
  {
242785
242864
  id: getNextMsgId(),
@@ -242793,7 +242872,7 @@ function useAgentSession({
242793
242872
  }
242794
242873
  ]);
242795
242874
  try {
242796
- const prompt = getGrillPrompt(userPrompt, agent2.systemPrompt);
242875
+ const prompt = getGrillPrompt(userPrompt);
242797
242876
  const stream = agent2.llm.stream([{ role: "user", content: prompt }], undefined, undefined, agent2.modelOptions);
242798
242877
  let accumulatedText = "";
242799
242878
  for await (const chunk2 of stream) {
@@ -242801,12 +242880,7 @@ function useAgentSession({
242801
242880
  accumulatedText += chunk2.text;
242802
242881
  }
242803
242882
  }
242804
- let cleanJson = accumulatedText.trim();
242805
- if (cleanJson.startsWith("```")) {
242806
- cleanJson = cleanJson.replace(/^```[a-zA-Z]*\n/, "").replace(/\n```$/, "");
242807
- }
242808
- cleanJson = cleanJson.trim();
242809
- const questions = JSON.parse(cleanJson);
242883
+ const questions = extractJsonArray(accumulatedText);
242810
242884
  if (!Array.isArray(questions) || questions.length === 0) {
242811
242885
  throw new Error("Invalid questions format returned from model.");
242812
242886
  }
@@ -242823,7 +242897,7 @@ function useAgentSession({
242823
242897
  } finally {
242824
242898
  setIsStreaming(false);
242825
242899
  }
242826
- }, [agent2, activeMessages]);
242900
+ }, [agent2]);
242827
242901
  const generatePlanFromGrill = import_react53.useCallback(async (answers) => {
242828
242902
  setAuthMode("none");
242829
242903
  const originalPrompt = grillPrompt;
@@ -242835,7 +242909,7 @@ function useAgentSession({
242835
242909
  setCurrentPlannedPrompt(originalPrompt);
242836
242910
  const planPrompt = getPlanPrompt(originalPrompt || "", grillQuestions.map((q2, i2) => ({ question: q2.question, answer: answers[i2] || "" })));
242837
242911
  setIsStreaming(true);
242838
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
242912
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
242839
242913
  const assistantMsgId = getNextMsgId();
242840
242914
  setActiveMessages([
242841
242915
  {
@@ -242934,7 +243008,12 @@ Please run \`/login\` to:
242934
243008
  }
242935
243009
  ]
242936
243010
  };
242937
- setStaticMessages((prev2) => [...prev2, ...activeMessages, userMsg, noticeMsg]);
243011
+ setStaticMessages((prev2) => [
243012
+ ...prev2,
243013
+ ...useCliStore.getState().activeMessages,
243014
+ userMsg,
243015
+ noticeMsg
243016
+ ]);
242938
243017
  setActiveMessages([]);
242939
243018
  return;
242940
243019
  }
@@ -242955,7 +243034,12 @@ Please run \`/login\` to:
242955
243034
  role: "assistant",
242956
243035
  blocks: [{ type: "text", content: "Session repository not available." }]
242957
243036
  };
242958
- setStaticMessages((prev2) => [...prev2, ...activeMessages, userMsg, noticeMsg]);
243037
+ setStaticMessages((prev2) => [
243038
+ ...prev2,
243039
+ ...useCliStore.getState().activeMessages,
243040
+ userMsg,
243041
+ noticeMsg
243042
+ ]);
242959
243043
  setActiveMessages([]);
242960
243044
  return;
242961
243045
  }
@@ -243016,10 +243100,39 @@ Please run \`/login\` to:
243016
243100
  blocks: [
243017
243101
  {
243018
243102
  type: "text",
243019
- content: `Opening usage dashboard...
243103
+ content: `
243104
+ Opening usage dashboard...
243105
+
243106
+ If it doesn't open automatically, please click here:
243107
+ [${url}](${url})
243108
+
243109
+ *Note: BYOK (Bring Your Own Key) usage is not tracked. Only usage via December login (December Wallet) is tracked.*`
243110
+ }
243111
+ ]
243112
+ }
243113
+ ]);
243114
+ Promise.resolve().then(() => (init_open(), exports_open)).then((openUtils) => {
243115
+ openUtils.openUrl(url);
243116
+ }).catch(console.error);
243117
+ return;
243118
+ }
243119
+ if (text3.trim() === "/feedback") {
243120
+ const url = "https://github.com/phasehumans/december/issues";
243121
+ setActiveMessages((prev2) => [
243122
+ ...prev2,
243123
+ {
243124
+ id: getNextMsgId(),
243125
+ role: "assistant",
243126
+ blocks: [
243127
+ {
243128
+ type: "text",
243129
+ content: `
243130
+ Opening GitHub issues...
243020
243131
 
243021
243132
  If it doesn't open automatically, please click here:
243022
- [${url}](${url})`
243133
+ [${url}](${url})
243134
+
243135
+ *Have feedback, found a bug, or have a feature request? Let us know on GitHub issues!*`
243023
243136
  }
243024
243137
  ]
243025
243138
  }
@@ -243045,33 +243158,50 @@ Please run \`/login\` to:
243045
243158
  }
243046
243159
  ]
243047
243160
  };
243048
- setStaticMessages((prev2) => [...prev2, ...activeMessages, userMsg, noticeMsg]);
243161
+ setStaticMessages((prev2) => [
243162
+ ...prev2,
243163
+ ...useCliStore.getState().activeMessages,
243164
+ userMsg,
243165
+ noticeMsg
243166
+ ]);
243049
243167
  setActiveMessages([]);
243050
243168
  return;
243051
243169
  }
243052
243170
  if (isStreaming) {
243053
- agent2.steer({ role: "user", content: text3, isUI: true });
243054
- setActiveMessages((prev2) => [...prev2, { id: getNextMsgId(), role: "user", text: text3 }]);
243171
+ setQueuedPrompts((prev2) => [...prev2, text3.trim()]);
243055
243172
  return;
243056
243173
  }
243057
- setIsStreaming(true);
243058
- const assistantMsgId = getNextMsgId();
243059
- const newUserMsg = { id: getNextMsgId(), role: "user", text: text3 };
243060
- setStaticMessages((prev2) => [...prev2, ...activeMessages, newUserMsg]);
243061
- setActiveMessages([{ id: assistantMsgId, role: "assistant", blocks: [] }]);
243062
- const promptToSend = text3;
243063
- try {
243064
- const stream = runAgentLoop(agent2, promptToSend);
243065
- await processAgentStream({ stream, setActiveMessages, assistantMsgId });
243066
- } catch (err) {
243067
- setActiveMessages((prev2) => [
243174
+ let currentText = text3.trim();
243175
+ while (currentText) {
243176
+ setIsStreaming(true);
243177
+ const assistantMsgId = getNextMsgId();
243178
+ const newUserMsg = { id: getNextMsgId(), role: "user", text: currentText };
243179
+ setStaticMessages((prev2) => [
243068
243180
  ...prev2,
243069
- { id: getNextMsgId(), role: "error", text: err.message }
243181
+ ...useCliStore.getState().activeMessages,
243182
+ newUserMsg
243070
243183
  ]);
243071
- } finally {
243072
- setIsStreaming(false);
243073
- setStaticMessages((prev2) => [...prev2, ...activeMessages]);
243074
- setActiveMessages([]);
243184
+ setActiveMessages([{ id: assistantMsgId, role: "assistant", blocks: [] }]);
243185
+ try {
243186
+ const stream = runAgentLoop(agent2, currentText);
243187
+ await processAgentStream({ stream, setActiveMessages, assistantMsgId });
243188
+ } catch (err) {
243189
+ setActiveMessages((prev2) => [
243190
+ ...prev2,
243191
+ { id: getNextMsgId(), role: "error", text: err.message }
243192
+ ]);
243193
+ } finally {
243194
+ setIsStreaming(false);
243195
+ setStaticMessages((prev2) => [...prev2, ...useCliStore.getState().activeMessages]);
243196
+ setActiveMessages([]);
243197
+ }
243198
+ const nextQueue = useCliStore.getState().queuedPrompts;
243199
+ if (nextQueue.length > 0) {
243200
+ currentText = nextQueue[0];
243201
+ useCliStore.getState().setQueuedPrompts(nextQueue.slice(1));
243202
+ } else {
243203
+ currentText = undefined;
243204
+ }
243075
243205
  }
243076
243206
  }, [
243077
243207
  agent2,
@@ -243086,13 +243216,15 @@ Please run \`/login\` to:
243086
243216
  sessionRepository,
243087
243217
  authMode,
243088
243218
  currentGrillIndex,
243089
- grillMode
243219
+ grillMode,
243220
+ setQueuedPrompts
243090
243221
  ]);
243091
243222
  const handleAbort = import_react53.useCallback(() => {
243092
243223
  if (isStreaming && agent2) {
243093
243224
  agent2.abort();
243225
+ setQueuedPrompts([]);
243094
243226
  }
243095
- }, [isStreaming, agent2]);
243227
+ }, [isStreaming, agent2, setQueuedPrompts]);
243096
243228
  const {
243097
243229
  handleSettingsMainSelect,
243098
243230
  handleSettingsAgentSelect,
@@ -243218,7 +243350,9 @@ Please run \`/login\` to:
243218
243350
  toasts,
243219
243351
  addToast,
243220
243352
  expandCommands,
243221
- toggleExpandCommands
243353
+ toggleExpandCommands,
243354
+ queuedPrompts,
243355
+ setQueuedPrompts
243222
243356
  };
243223
243357
  }
243224
243358
 
@@ -243427,12 +243561,7 @@ async function main() {
243427
243561
  AskQuestionTool,
243428
243562
  ManageTaskTool,
243429
243563
  BrowserTool,
243430
- GitHubTool,
243431
- WebSearchTool,
243432
- readWikiTool,
243433
- updateWikiTool,
243434
- createPrReviewTool,
243435
- submitPrTool
243564
+ WebSearchTool
243436
243565
  ],
243437
243566
  operations: localOperations,
243438
243567
  modelOptions: {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "module": "src/index.ts",
4
4
  "type": "module",
5
5
  "private": false,
6
- "version": "0.2.23",
6
+ "version": "0.2.24",
7
7
  "description": "Turn ideas into reality.",
8
8
  "author": "Chaitanya Sonawane",
9
9
  "license": "Apache-2.0",