omnius 1.0.512 → 1.0.514

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/index.js CHANGED
@@ -38536,29 +38536,29 @@ ${earlyError ? "\n" + earlyError : ""}${earlyOutput ? "\n" + earlyOutput : ""}`;
38536
38536
  });
38537
38537
  }
38538
38538
  const inferResult = parsed.result;
38539
- let responseText = "";
38539
+ let responseText2 = "";
38540
38540
  if (typeof inferResult === "string") {
38541
- responseText = inferResult;
38541
+ responseText2 = inferResult;
38542
38542
  } else if (inferResult) {
38543
38543
  const events = Array.isArray(inferResult) ? inferResult : [inferResult];
38544
38544
  for (const evt of events) {
38545
38545
  if (evt.event === "result" && evt.data) {
38546
38546
  try {
38547
38547
  const data = typeof evt.data === "string" ? JSON.parse(evt.data) : evt.data;
38548
- responseText = data.response || data.content || JSON.stringify(data);
38548
+ responseText2 = data.response || data.content || JSON.stringify(data);
38549
38549
  } catch {
38550
- responseText = String(evt.data);
38550
+ responseText2 = String(evt.data);
38551
38551
  }
38552
38552
  }
38553
38553
  }
38554
- if (!responseText) {
38555
- responseText = JSON.stringify(inferResult, null, 2);
38554
+ if (!responseText2) {
38555
+ responseText2 = JSON.stringify(inferResult, null, 2);
38556
38556
  }
38557
38557
  }
38558
38558
  const lines = [
38559
38559
  `Remote inference result (${model} via ${peerUsed.slice(0, 20)}...):`,
38560
38560
  ``,
38561
- responseText,
38561
+ responseText2,
38562
38562
  ``,
38563
38563
  `--- Metadata ---`,
38564
38564
  `Model: ${parsed.model || model}`,
@@ -254056,14 +254056,14 @@ async function fetchXML(url, init2) {
254056
254056
  if (contentType?.includes("/xml") !== true) {
254057
254057
  throw new Error(`Bad content type: ${contentType}`);
254058
254058
  }
254059
- const responseText = await response.text();
254060
- log8.trace("<-", responseText);
254059
+ const responseText2 = await response.text();
254060
+ log8.trace("<-", responseText2);
254061
254061
  const parser2 = new import_xml2js.default.Parser({
254062
254062
  explicitRoot: false,
254063
254063
  explicitArray: false,
254064
254064
  attrkey: "@"
254065
254065
  });
254066
- const responseBody = await parser2.parseStringPromise(responseText);
254066
+ const responseBody = await parser2.parseStringPromise(responseText2);
254067
254067
  if (!response.ok) {
254068
254068
  const soapns = getNamespace(responseBody, NS_SOAP);
254069
254069
  const body = responseBody[`${soapns}Body`];
@@ -578108,8 +578108,8 @@ function extractSignificantNgrams(text2) {
578108
578108
  }
578109
578109
  return grams;
578110
578110
  }
578111
- function computeGroundedness(responseText, contextSpans, turn) {
578112
- const claims = extractClaims(responseText);
578111
+ function computeGroundedness(responseText2, contextSpans, turn) {
578112
+ const claims = extractClaims(responseText2);
578113
578113
  const total_claims = claims.length;
578114
578114
  if (total_claims === 0) {
578115
578115
  return {
@@ -579005,10 +579005,10 @@ The sub-agent works in its own small context; when it folds back, run the build
579005
579005
  * Compute per-turn groundedness for an assistant response.
579006
579006
  * Stores the result in an internal history and returns the report.
579007
579007
  */
579008
- computeGroundedness(responseText, messages2, turn) {
579008
+ computeGroundedness(responseText2, messages2, turn) {
579009
579009
  try {
579010
579010
  const contextSpans = extractContextSpansForGroundedness(messages2);
579011
- const report2 = computeGroundedness(responseText, contextSpans, turn);
579011
+ const report2 = computeGroundedness(responseText2, contextSpans, turn);
579012
579012
  this._groundednessHistory.push(report2);
579013
579013
  return report2;
579014
579014
  } catch {
@@ -603047,9 +603047,9 @@ ${description}`
603047
603047
  const choices = data.choices ?? [];
603048
603048
  const usage = data.usage;
603049
603049
  const firstChoice = choices[0];
603050
- const responseText = firstChoice ? String(firstChoice.message?.content ?? "") : "";
603051
- const outcome = this.recordThinkOutcome(responseText, effectiveThink === true);
603052
- const independentOutcome = effectiveThink !== true ? classifyThinkOutcome(responseText) : null;
603050
+ const responseText2 = firstChoice ? String(firstChoice.message?.content ?? "") : "";
603051
+ const outcome = this.recordThinkOutcome(responseText2, effectiveThink === true);
603052
+ const independentOutcome = effectiveThink !== true ? classifyThinkOutcome(responseText2) : null;
603053
603053
  const shouldRecoverFromEmpty = request.disableEmptyContentRecovery !== true && responseFormat !== void 0 && independentOutcome !== null && (independentOutcome === "empty_after_strip" || independentOutcome === "unclosed_think");
603054
603054
  const justSuppressed = this._thinkSuppressed && this._thinkFailStreak === _OllamaAgenticBackend._thinkFailThreshold;
603055
603055
  const shouldRetryThinkGuard = outcome !== null && effectiveThink === true && (justSuppressed || outcome === "empty_after_strip" || outcome === "unclosed_think");
@@ -617966,6 +617966,128 @@ var init_conversation_context = __esm({
617966
617966
  }
617967
617967
  });
617968
617968
 
617969
+ // packages/cli/src/tui/prompt-enhance.ts
617970
+ function stripThinkBlocks2(text2) {
617971
+ let out = text2.replace(/<think>[\s\S]*?<\/think>/gi, "");
617972
+ const open2 = out.search(/<think>/i);
617973
+ if (open2 >= 0) out = out.slice(0, open2);
617974
+ const close = out.search(/<\/think>/i);
617975
+ if (close >= 0) out = out.slice(close + "</think>".length);
617976
+ return out.trim();
617977
+ }
617978
+ function extractEnhancedPrompt(raw) {
617979
+ const text2 = stripThinkBlocks2(raw.trim());
617980
+ if (!text2) return null;
617981
+ const tryParse = (candidate) => {
617982
+ try {
617983
+ const obj = JSON.parse(candidate);
617984
+ const v = obj["enhancedPrompt"] ?? obj["enhanced_prompt"] ?? obj["prompt"] ?? obj["result"];
617985
+ return typeof v === "string" && v.trim() ? v : null;
617986
+ } catch {
617987
+ return null;
617988
+ }
617989
+ };
617990
+ const direct = tryParse(text2);
617991
+ if (direct) return direct;
617992
+ const fenced = text2.match(/```(?:json)?\s*([\s\S]*?)```/i);
617993
+ if (fenced?.[1]) {
617994
+ const f2 = tryParse(fenced[1].trim());
617995
+ if (f2) return f2;
617996
+ }
617997
+ const brace = text2.match(/\{[\s\S]*\}/);
617998
+ if (brace?.[0]) {
617999
+ const b = tryParse(brace[0]);
618000
+ if (b) return b;
618001
+ }
618002
+ const keyed = text2.match(/"enhanced_?[Pp]rompt"\s*:\s*"((?:[^"\\]|\\.)*)"/);
618003
+ if (keyed?.[1]) {
618004
+ try {
618005
+ return JSON.parse('"' + keyed[1] + '"');
618006
+ } catch {
618007
+ return keyed[1];
618008
+ }
618009
+ }
618010
+ if (!text2.startsWith("{") && !text2.startsWith("[")) return text2;
618011
+ return null;
618012
+ }
618013
+ function responseText(resp) {
618014
+ const msg = resp.choices?.[0]?.message;
618015
+ if (!msg) return "";
618016
+ const content = (msg.content ?? "").trim();
618017
+ if (content) return content;
618018
+ const reasoning = (msg.reasoning_content ?? msg.reasoning ?? "").trim();
618019
+ return reasoning;
618020
+ }
618021
+ function acceptableEnhancement(clean5, seedText) {
618022
+ if (!clean5) return false;
618023
+ if (clean5 === seedText) return false;
618024
+ if (/<think>/i.test(clean5)) return false;
618025
+ if (clean5.length > 12e3) return false;
618026
+ if (clean5.length < Math.min(24, seedText.length / 2)) return false;
618027
+ return true;
618028
+ }
618029
+ async function enhancePromptViaInference(seed, backend, ctx3) {
618030
+ const seedText = seed.trim();
618031
+ if (!seedText) return null;
618032
+ const recent = ctx3.recentHistory.filter((h) => h && h.trim()).slice(0, 5).map((h, i2) => ` ${i2 + 1}. ${h.trim().slice(0, 240)}`).join("\n");
618033
+ const runtimeCtx = ctx3.runtimeContext ?? "";
618034
+ const userPrompt = [
618035
+ "Expand the SEED PROMPT below into a comprehensive, precise, self-contained instruction set for an agentic coding assistant.",
618036
+ "Preserve the user's original intent exactly. Do NOT answer or solve it, do NOT invent unrelated scope.",
618037
+ "Clarify the goal, surface implied requirements, relevant constraints, edge cases, and concrete acceptance criteria.",
618038
+ "Fold in only the session context that is actually relevant. Keep it phrased as an instruction in the user's voice.",
618039
+ "Return no preamble and no meta-commentary about the prompt itself.",
618040
+ ctx3.activeGoal ? `
618041
+ Task currently in progress: ${ctx3.activeGoal.slice(0, 400)}` : "",
618042
+ recent ? `
618043
+ Recent prompts this session (newest first):
618044
+ ${recent}` : "",
618045
+ runtimeCtx ? `
618046
+ Session/runtime context:
618047
+ ${runtimeCtx}` : "",
618048
+ `
618049
+ SEED PROMPT:
618050
+ ${seedText}`
618051
+ ].filter(Boolean).join("\n");
618052
+ const jsonSystem = `You are a prompt-expansion engine. You rewrite a user's short seed prompt into a richer, unambiguous instruction that fully captures their intent. Return strict JSON only: {"enhancedPrompt": string}.`;
618053
+ const plainSystem = "You are a prompt-expansion engine. You rewrite a user's short seed prompt into a richer, unambiguous instruction that fully captures their intent. Return ONLY the rewritten prompt as plain text — no JSON, no preamble, no commentary.";
618054
+ const call = (system, withJsonMode) => backend.chatCompletion({
618055
+ messages: [
618056
+ { role: "system", content: system },
618057
+ { role: "user", content: userPrompt }
618058
+ ],
618059
+ tools: [],
618060
+ temperature: 0.4,
618061
+ maxTokens: 1400,
618062
+ timeoutMs: 9e4,
618063
+ think: false,
618064
+ ...withJsonMode ? { responseFormat: { type: "json_object" } } : {}
618065
+ });
618066
+ const attempt = async (system, withJsonMode) => {
618067
+ try {
618068
+ const resp = await call(system, withJsonMode);
618069
+ const raw = responseText(resp);
618070
+ if (!raw) return null;
618071
+ const enhanced = extractEnhancedPrompt(raw);
618072
+ if (!enhanced) return null;
618073
+ const clean5 = enhanced.trim();
618074
+ return acceptableEnhancement(clean5, seedText) ? clean5 : null;
618075
+ } catch {
618076
+ return null;
618077
+ }
618078
+ };
618079
+ const strict = await attempt(jsonSystem, true);
618080
+ if (strict) return strict;
618081
+ const loose = await attempt(jsonSystem, false);
618082
+ if (loose) return loose;
618083
+ return attempt(plainSystem, false);
618084
+ }
618085
+ var init_prompt_enhance = __esm({
618086
+ "packages/cli/src/tui/prompt-enhance.ts"() {
618087
+ "use strict";
618088
+ }
618089
+ });
618090
+
617969
618091
  // packages/cli/src/tui/generative-progress.ts
617970
618092
  function generationKindForToolName(toolName) {
617971
618093
  if (toolName === "generate_image") return "image";
@@ -625466,6 +625588,67 @@ function toolColorSeq(code8, bold = false) {
625466
625588
  function toolResetSeq() {
625467
625589
  return _colorsEnabled && stdoutIsTTY() ? RESET2 : "";
625468
625590
  }
625591
+ function truecolorOk() {
625592
+ if (_truecolorCache !== null) return _truecolorCache;
625593
+ const ct = process.env.COLORTERM;
625594
+ _truecolorCache = ct === "truecolor" || ct === "24bit" || /-256color$|-truecolor$|kitty|wezterm|alacritty|ghostty|rio|contour/.test(
625595
+ process.env.TERM ?? ""
625596
+ );
625597
+ return _truecolorCache;
625598
+ }
625599
+ function xterm256ToRgb(idx) {
625600
+ if (idx >= 16 && idx <= 231) {
625601
+ const n2 = idx - 16;
625602
+ const lv = [0, 95, 135, 175, 215, 255];
625603
+ return [lv[Math.floor(n2 / 36)], lv[Math.floor(n2 / 6) % 6], lv[n2 % 6]];
625604
+ }
625605
+ if (idx >= 232 && idx <= 255) {
625606
+ const v = 8 + 10 * (idx - 232);
625607
+ return [v, v, v];
625608
+ }
625609
+ const basic = [
625610
+ [0, 0, 0],
625611
+ [205, 49, 49],
625612
+ [13, 188, 121],
625613
+ [229, 229, 16],
625614
+ [36, 114, 200],
625615
+ [188, 63, 188],
625616
+ [17, 168, 205],
625617
+ [229, 229, 229],
625618
+ [102, 102, 102],
625619
+ [241, 76, 76],
625620
+ [35, 209, 139],
625621
+ [245, 245, 67],
625622
+ [59, 142, 234],
625623
+ [214, 112, 214],
625624
+ [41, 184, 219],
625625
+ [255, 255, 255]
625626
+ ];
625627
+ return basic[Math.max(0, Math.min(15, idx))] ?? [200, 200, 200];
625628
+ }
625629
+ function toolGradSeq(colorCode, frac) {
625630
+ if (!_colorsEnabled || !stdoutIsTTY()) return "";
625631
+ if (!truecolorOk()) return toolColorSeq(colorCode);
625632
+ const [r2, g, b] = xterm256ToRgb(colorCode);
625633
+ const f2 = Math.max(0, Math.min(1, frac));
625634
+ const scale = 0.78 + 0.36 * f2;
625635
+ const cl = (v) => Math.max(0, Math.min(255, Math.round(v * scale)));
625636
+ return `\x1B[38;2;${cl(r2)};${cl(g)};${cl(b)}m`;
625637
+ }
625638
+ function paintToolBorder(glyphs, startCol, totalWidth, colorCode) {
625639
+ if (glyphs.length === 0) return "";
625640
+ if (!_colorsEnabled || !stdoutIsTTY() || !truecolorOk()) {
625641
+ return `${toolColorSeq(colorCode)}${glyphs}`;
625642
+ }
625643
+ const SEG = 6;
625644
+ const denom = Math.max(1, totalWidth - 1);
625645
+ let out = "";
625646
+ for (let i2 = 0; i2 < glyphs.length; i2 += SEG) {
625647
+ out += toolGradSeq(colorCode, (startCol + i2) / denom);
625648
+ out += glyphs.slice(i2, i2 + SEG);
625649
+ }
625650
+ return out;
625651
+ }
625469
625652
  function charWidth2(ch) {
625470
625653
  const cp2 = ch.codePointAt(0);
625471
625654
  if (cp2 >= 4352 && cp2 <= 4447 || // Hangul Jamo
@@ -625600,45 +625783,86 @@ function buildToolTopBorder(title, metrics2, width, colorCode, metricsColorCode
625600
625783
  const titleSpan = titleChip.length + 2;
625601
625784
  const metricsChip = metricsVisible ? ` ${metricsVisible} ` : "";
625602
625785
  const metricsSpan = metricsChip ? metricsChip.length + 2 : 0;
625603
- let titleSegment;
625604
- let metricsSegment = "";
625786
+ void border;
625787
+ let col = 0;
625788
+ const grad = (glyphs) => {
625789
+ const s2 = paintToolBorder(glyphs, col, width, colorCode);
625790
+ col += glyphs.length;
625791
+ return s2;
625792
+ };
625793
+ let effTitleChip = titleChip;
625794
+ let metricsIncluded = false;
625605
625795
  let fillerWidth;
625606
625796
  if (titleSpan + metricsSpan + 4 <= inner) {
625607
- titleSegment = `${border}┤${titleColor}${titleChip}${reset}${border}├`;
625608
- metricsSegment = metricsChip ? `${border}┤${metricColor}${metricsChip}${reset}${border}├` : "";
625797
+ metricsIncluded = !!metricsChip;
625609
625798
  fillerWidth = inner - titleSpan - metricsSpan - 2;
625610
625799
  } else if (titleSpan + 4 <= inner) {
625611
- titleSegment = `${border}┤${titleColor}${titleChip}${reset}${border}├`;
625612
625800
  fillerWidth = inner - titleSpan - 2;
625613
625801
  } else {
625614
625802
  const room = Math.max(3, inner - 8);
625615
625803
  const truncated = titleVisible.length > room ? titleVisible.slice(0, Math.max(1, room - 1)) + "…" : titleVisible;
625616
- titleSegment = `${border}┤${titleColor} ${truncated} ${reset}${border}├`;
625804
+ effTitleChip = ` ${truncated} `;
625617
625805
  fillerWidth = Math.max(0, inner - (truncated.length + 4) - 2);
625618
625806
  }
625619
- return `${border}${BOX_TL2}${BOX_H2}${titleSegment}${BOX_H2.repeat(Math.max(0, fillerWidth))}${metricsSegment}${BOX_H2}${BOX_TR2}${reset}`;
625807
+ let out = grad(`${BOX_TL2}${BOX_H2}`);
625808
+ out += grad("┤");
625809
+ out += `${titleColor}${effTitleChip}${reset}`;
625810
+ col += effTitleChip.length;
625811
+ out += grad("├");
625812
+ out += grad(BOX_H2.repeat(Math.max(0, fillerWidth)));
625813
+ if (metricsIncluded) {
625814
+ out += grad("┤");
625815
+ out += `${metricColor}${metricsChip}${reset}`;
625816
+ col += metricsChip.length;
625817
+ out += grad("├");
625818
+ }
625819
+ out += grad(`${BOX_H2}${BOX_TR2}`);
625820
+ return out + reset;
625620
625821
  }
625621
625822
  function buildToolDivider(width, colorCode) {
625622
- const border = toolColorSeq(colorCode);
625623
- return `${border}${BOX_TJ_L2}${BOX_H2.repeat(Math.max(0, width - 2))}${BOX_TJ_R2}${toolResetSeq()}`;
625823
+ return paintToolBorder(
625824
+ `${BOX_TJ_L2}${BOX_H2.repeat(Math.max(0, width - 2))}${BOX_TJ_R2}`,
625825
+ 0,
625826
+ width,
625827
+ colorCode
625828
+ ) + toolResetSeq();
625624
625829
  }
625625
625830
  function buildRoutingHeader(title, _metrics, width, colorCode, _metricsColorCode = 222) {
625626
625831
  const border = toolColorSeq(colorCode);
625627
625832
  const titleColor = toolColorSeq(colorCode, true);
625628
625833
  const reset = toolResetSeq();
625629
625834
  const w = Math.max(40, width);
625835
+ void border;
625630
625836
  const titleVisible = stripAnsi(title);
625631
625837
  const titleChip = ` ${titleVisible} `;
625632
625838
  const shortBoxWidth = titleChip.length + 7;
625633
- const line1 = `${border}${BOX_TL2}${BOX_H2}${border}${BOX_TJ_L2}${titleColor}${titleChip}${reset}${border}${BOX_TJ_R2}${BOX_H2}${BOX_H2}${BOX_TR2}${reset}`;
625839
+ let col = 0;
625840
+ const grad1 = (glyphs) => {
625841
+ const s2 = paintToolBorder(glyphs, col, w, colorCode);
625842
+ col += glyphs.length;
625843
+ return s2;
625844
+ };
625845
+ let line1 = grad1(`${BOX_TL2}${BOX_H2}${BOX_TJ_L2}`);
625846
+ line1 += `${titleColor}${titleChip}${reset}`;
625847
+ col += titleChip.length;
625848
+ line1 += grad1(`${BOX_TJ_R2}${BOX_H2}${BOX_H2}${BOX_TR2}`) + reset;
625634
625849
  const gap = Math.max(0, shortBoxWidth - 1);
625635
625850
  const dashCount = Math.max(0, w - shortBoxWidth - 2);
625636
- const line2 = `${border}${BOX_TJ_L2}${reset}` + " ".repeat(gap) + `${border}╰${BOX_H2.repeat(dashCount)}${BOX_TJ_R2}${reset}`;
625851
+ const line2 = `${paintToolBorder(BOX_TJ_L2, 0, w, colorCode)}${reset}` + " ".repeat(gap) + paintToolBorder(
625852
+ `╰${BOX_H2.repeat(dashCount)}${BOX_TJ_R2}`,
625853
+ gap + 1,
625854
+ w,
625855
+ colorCode
625856
+ ) + reset;
625637
625857
  return [line1, line2];
625638
625858
  }
625639
625859
  function buildToolBottom(width, colorCode) {
625640
- const border = toolColorSeq(colorCode);
625641
- return `${border}${BOX_BL2}${BOX_H2.repeat(Math.max(0, width - 2))}${BOX_BR2}${toolResetSeq()}`;
625860
+ return paintToolBorder(
625861
+ `${BOX_BL2}${BOX_H2.repeat(Math.max(0, width - 2))}${BOX_BR2}`,
625862
+ 0,
625863
+ width,
625864
+ colorCode
625865
+ ) + toolResetSeq();
625642
625866
  }
625643
625867
  function dimSeqOrEmpty() {
625644
625868
  return _colorsEnabled && stdoutIsTTY() ? "\x1B[2m" : "";
@@ -625749,14 +625973,15 @@ function renderPersistedDynamicBlockSpec(spec, width, id2) {
625749
625973
  }
625750
625974
  }
625751
625975
  function buildToolContentRow(content, width, colorCode) {
625752
- const border = toolColorSeq(colorCode);
625753
625976
  const reset = toolResetSeq();
625754
625977
  const innerWidth = Math.max(1, width - 4);
625755
625978
  content = sanitizeToolBoxContent(content);
625756
625979
  let padded = visibleLen(content) > innerWidth ? truncateAnsiToWidth(content, innerWidth) : content;
625757
625980
  const visible = visibleLen(padded);
625758
625981
  if (visible < innerWidth) padded += " ".repeat(innerWidth - visible);
625759
- return `${border}${BOX_V2}${reset} ${padded} ${border}${BOX_V2}${reset}`;
625982
+ const left = truecolorOk() ? toolGradSeq(colorCode, 0) : toolColorSeq(colorCode);
625983
+ const right = truecolorOk() ? toolGradSeq(colorCode, 1) : toolColorSeq(colorCode);
625984
+ return `${left}${BOX_V2}${reset} ${padded} ${right}${BOX_V2}${reset}`;
625760
625985
  }
625761
625986
  function formatToolBoxLine(line, kind) {
625762
625987
  line = sanitizeToolBoxContent(line);
@@ -627036,7 +627261,7 @@ function formatDuration4(ms) {
627036
627261
  const secs = Math.floor(totalSecs % 60);
627037
627262
  return `${mins}m ${secs}s`;
627038
627263
  }
627039
- var c3, ui, pastel, _emojisEnabled, _colorsEnabled, MD, TOOL_LABELS, TOOL_COLOR_CODES, TOOL_ERROR_COLOR_CODE, BOX_TL2, BOX_TR2, BOX_BL2, BOX_BR2, BOX_H2, BOX_V2, BOX_TJ_L2, BOX_TJ_R2, RESET2, _telegramCoalesce, _pendingToolCall, _voiceChatCoalesce, VOICECHAT_VISIBLE_ROWS, VOICECHAT_EXPAND_LABEL, VOICECHAT_COLLAPSE_LABEL, DIFF_LINE_RE, _contentWriteHook, HINTS, TOOL_NAMES, COMMAND_NAMES, SLASH_COMMANDS2;
627264
+ var c3, ui, pastel, _emojisEnabled, _colorsEnabled, MD, TOOL_LABELS, TOOL_COLOR_CODES, TOOL_ERROR_COLOR_CODE, BOX_TL2, BOX_TR2, BOX_BL2, BOX_BR2, BOX_H2, BOX_V2, BOX_TJ_L2, BOX_TJ_R2, RESET2, _truecolorCache, _telegramCoalesce, _pendingToolCall, _voiceChatCoalesce, VOICECHAT_VISIBLE_ROWS, VOICECHAT_EXPAND_LABEL, VOICECHAT_COLLAPSE_LABEL, DIFF_LINE_RE, _contentWriteHook, HINTS, TOOL_NAMES, COMMAND_NAMES, SLASH_COMMANDS2;
627040
627265
  var init_render = __esm({
627041
627266
  "packages/cli/src/tui/render.ts"() {
627042
627267
  "use strict";
@@ -627195,6 +627420,7 @@ var init_render = __esm({
627195
627420
  BOX_TJ_L2 = "├";
627196
627421
  BOX_TJ_R2 = "┤";
627197
627422
  RESET2 = "\x1B[0m";
627423
+ _truecolorCache = null;
627198
627424
  _telegramCoalesce = null;
627199
627425
  _pendingToolCall = null;
627200
627426
  _voiceChatCoalesce = null;
@@ -635555,6 +635781,19 @@ var init_dist9 = __esm({
635555
635781
  });
635556
635782
 
635557
635783
  // packages/cli/src/tui/stageIndicator.ts
635784
+ function tri360(x) {
635785
+ const t2 = (x % 360 + 360) % 360;
635786
+ return t2 < 180 ? t2 / 90 - 1 : 3 - t2 / 90;
635787
+ }
635788
+ function stageHueAt(stage2, col, phase) {
635789
+ const meta = STAGE_META[stage2];
635790
+ const wave = tri360(col * 9 + phase);
635791
+ const hue = meta.baseHue + wave * STAGE_HUE_SPAN;
635792
+ return (Math.round(hue) % 360 + 360) % 360;
635793
+ }
635794
+ function stageGradientRgb(stage2, col, phase) {
635795
+ return HUE_LUT[stageHueAt(stage2, col, phase)] ?? HUE_LUT[0];
635796
+ }
635558
635797
  function supportsTruecolor() {
635559
635798
  const colorterm = process.env.COLORTERM;
635560
635799
  if (colorterm === "truecolor" || colorterm === "24bit") return true;
@@ -635566,6 +635805,12 @@ function supportsTruecolor() {
635566
635805
  function isSweepingStage(stage2) {
635567
635806
  return SWEEPING_STAGES.has(stage2);
635568
635807
  }
635808
+ function stageBlockNeededWidth(stage2, detail) {
635809
+ const meta = STAGE_META[stage2];
635810
+ let body = meta.label;
635811
+ if (detail && detail.length > 0) body += ` ${detail}`;
635812
+ return 2 + body.length + 1;
635813
+ }
635569
635814
  function stageBlockText(stage2, detail, width) {
635570
635815
  const meta = STAGE_META[stage2];
635571
635816
  const lead = "▌ ";
@@ -635596,8 +635841,7 @@ function renderStageBlock(stage2, detail, width, phase, truecolor) {
635596
635841
  out += " ";
635597
635842
  continue;
635598
635843
  }
635599
- const hue = sweeping ? (meta.baseHue + i2 * 4 + normPhase) % 360 : meta.baseHue;
635600
- const [r2, g, b] = HUE_LUT[hue] ?? HUE_LUT[0];
635844
+ const [r2, g, b] = sweeping ? stageGradientRgb(stage2, i2, normPhase) : HUE_LUT[meta.baseHue] ?? HUE_LUT[0];
635601
635845
  out += `\x1B[38;2;${r2};${g};${b}m${ch}`;
635602
635846
  }
635603
635847
  out += "\x1B[0m";
@@ -635652,7 +635896,14 @@ function setStage(stage2, detail) {
635652
635896
  function getStage() {
635653
635897
  return { stage: _currentStage, detail: _currentDetail };
635654
635898
  }
635655
- var STAGE_META, SWEEPING_STAGES, MAX_GRADIENT_COLS, HUE_LUT, _currentStage, _currentDetail, _subscribers;
635899
+ function onStageChange(cb) {
635900
+ _subscribers.push(cb);
635901
+ return () => {
635902
+ const i2 = _subscribers.indexOf(cb);
635903
+ if (i2 >= 0) _subscribers.splice(i2, 1);
635904
+ };
635905
+ }
635906
+ var STAGE_META, SWEEPING_STAGES, MAX_GRADIENT_COLS, STAGE_HUE_SPAN, HUE_LUT, _currentStage, _currentDetail, _subscribers;
635656
635907
  var init_stageIndicator = __esm({
635657
635908
  "packages/cli/src/tui/stageIndicator.ts"() {
635658
635909
  "use strict";
@@ -635691,6 +635942,7 @@ var init_stageIndicator = __esm({
635691
635942
  "failed"
635692
635943
  ]);
635693
635944
  MAX_GRADIENT_COLS = 120;
635945
+ STAGE_HUE_SPAN = 28;
635694
635946
  HUE_LUT = (() => {
635695
635947
  const lut = [];
635696
635948
  for (let h = 0; h < 360; h++) {
@@ -635703,6 +635955,595 @@ var init_stageIndicator = __esm({
635703
635955
  }
635704
635956
  });
635705
635957
 
635958
+ // packages/cli/src/tui/tui-tasks-renderer.ts
635959
+ var tui_tasks_renderer_exports = {};
635960
+ __export(tui_tasks_renderer_exports, {
635961
+ __testOrderTodosForDisplay: () => __testOrderTodosForDisplay,
635962
+ __testSelectPanelTodoRows: () => __testSelectPanelTodoRows,
635963
+ getTuiTasksScope: () => getTuiTasksScope,
635964
+ handleTuiTasksClick: () => handleTuiTasksClick,
635965
+ isTuiTasksExpanded: () => isTuiTasksExpanded,
635966
+ onTuiTasksHeightChange: () => onTuiTasksHeightChange,
635967
+ refreshTuiTasks: () => refreshTuiTasks,
635968
+ refreshTuiTasksSync: () => refreshTuiTasksSync,
635969
+ refreshTuiTasksThemeVars: () => refreshTuiTasksThemeVars,
635970
+ setTasksRendererWriter: () => setTasksRendererWriter,
635971
+ setTuiTasksEnabled: () => setTuiTasksEnabled,
635972
+ setTuiTasksScope: () => setTuiTasksScope,
635973
+ setTuiTasksSession: () => setTuiTasksSession,
635974
+ teardownTuiTasks: () => teardownTuiTasks
635975
+ });
635976
+ import { existsSync as existsSync126, readFileSync as readFileSync105, watch as fsWatch3 } from "node:fs";
635977
+ import { join as join140 } from "node:path";
635978
+ import { homedir as homedir44 } from "node:os";
635979
+ function setTasksRendererWriter(writer) {
635980
+ chromeWrite = writer;
635981
+ }
635982
+ function expandedRowCap() {
635983
+ const rows = termRows();
635984
+ return Math.max(MAX_VISIBLE_ROWS, Math.min(64, rows - 8 - 8));
635985
+ }
635986
+ function paintActiveRowGradient(text2) {
635987
+ const { stage: stage2 } = getStage();
635988
+ if (!supportsTruecolor() || !isSweepingStage(stage2)) return null;
635989
+ let out = "";
635990
+ const SEG = 2;
635991
+ for (let i2 = 0; i2 < text2.length; i2 += SEG) {
635992
+ const [r2, g, b] = stageGradientRgb(stage2, Math.floor(i2 / SEG), _gradPhase);
635993
+ out += `\x1B[38;2;${r2};${g};${b}m${text2.slice(i2, i2 + SEG)}`;
635994
+ }
635995
+ return out + RESET3;
635996
+ }
635997
+ function panelEffectivelyVisible() {
635998
+ return _enabled && !_scopeOverlayActive && !_scopeNeovimActive && !_scopePagerActive && _scopeMainViewActive;
635999
+ }
636000
+ function todoDir2() {
636001
+ return join140(homedir44(), ".omnius", "todos");
636002
+ }
636003
+ function todoPath2(sessionId) {
636004
+ const safe = sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
636005
+ return join140(todoDir2(), `${safe}.json`);
636006
+ }
636007
+ function setTuiTasksSession(sessionId) {
636008
+ if (sessionId === _activeSessionId) return;
636009
+ _activeSessionId = sessionId || null;
636010
+ if (_watcher) {
636011
+ try {
636012
+ _watcher.close();
636013
+ } catch {
636014
+ }
636015
+ _watcher = null;
636016
+ }
636017
+ if (!_activeSessionId) {
636018
+ _lastTodos = [];
636019
+ applyHeightChange(0);
636020
+ return;
636021
+ }
636022
+ loadTodos();
636023
+ installWatcher();
636024
+ scheduleRedraw();
636025
+ }
636026
+ function onTuiTasksHeightChange(cb) {
636027
+ _onResizeChange = cb;
636028
+ }
636029
+ function setTuiTasksEnabled(enabled2) {
636030
+ _enabled = enabled2;
636031
+ scheduleRedraw();
636032
+ }
636033
+ function setTuiTasksScope(scope) {
636034
+ let changed = false;
636035
+ if (scope.overlayActive !== void 0 && scope.overlayActive !== _scopeOverlayActive) {
636036
+ _scopeOverlayActive = scope.overlayActive;
636037
+ changed = true;
636038
+ }
636039
+ if (scope.mainViewActive !== void 0 && scope.mainViewActive !== _scopeMainViewActive) {
636040
+ _scopeMainViewActive = scope.mainViewActive;
636041
+ changed = true;
636042
+ }
636043
+ if (scope.neovimActive !== void 0 && scope.neovimActive !== _scopeNeovimActive) {
636044
+ _scopeNeovimActive = scope.neovimActive;
636045
+ changed = true;
636046
+ }
636047
+ if (scope.pagerActive !== void 0 && scope.pagerActive !== _scopePagerActive) {
636048
+ _scopePagerActive = scope.pagerActive;
636049
+ changed = true;
636050
+ }
636051
+ if (changed) {
636052
+ if (!panelEffectivelyVisible()) {
636053
+ clearLastPaintedRows();
636054
+ applyHeightChange(0);
636055
+ } else {
636056
+ scheduleRedraw();
636057
+ }
636058
+ }
636059
+ }
636060
+ function getTuiTasksScope() {
636061
+ return {
636062
+ enabled: _enabled,
636063
+ overlayActive: _scopeOverlayActive,
636064
+ mainViewActive: _scopeMainViewActive,
636065
+ neovimActive: _scopeNeovimActive,
636066
+ pagerActive: _scopePagerActive,
636067
+ visible: panelEffectivelyVisible()
636068
+ };
636069
+ }
636070
+ function refreshTuiTasks() {
636071
+ if (!_activeSessionId) return;
636072
+ loadTodos();
636073
+ scheduleRedraw();
636074
+ }
636075
+ function refreshTuiTasksSync() {
636076
+ if (!_activeSessionId) return;
636077
+ loadTodos();
636078
+ if (!_enabled) return;
636079
+ _redrawScheduled = false;
636080
+ render();
636081
+ }
636082
+ function teardownTuiTasks() {
636083
+ if (_watcher) {
636084
+ try {
636085
+ _watcher.close();
636086
+ } catch {
636087
+ }
636088
+ _watcher = null;
636089
+ }
636090
+ _activeSessionId = null;
636091
+ _lastTodos = [];
636092
+ _expanded = false;
636093
+ _toggleRowAbs = -1;
636094
+ applyHeightChange(0);
636095
+ }
636096
+ function installWatcher() {
636097
+ if (!_activeSessionId) return;
636098
+ try {
636099
+ _watcher = fsWatch3(todoDir2(), { persistent: false }, (_evt, fname) => {
636100
+ if (!fname || !_activeSessionId) return;
636101
+ const expected = `${_activeSessionId.replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`;
636102
+ if (fname !== expected) return;
636103
+ loadTodos();
636104
+ scheduleRedraw();
636105
+ });
636106
+ } catch {
636107
+ }
636108
+ }
636109
+ function loadTodos() {
636110
+ if (!_activeSessionId) {
636111
+ _lastTodos = [];
636112
+ return;
636113
+ }
636114
+ try {
636115
+ const fp = todoPath2(_activeSessionId);
636116
+ if (!existsSync126(fp)) {
636117
+ _lastTodos = [];
636118
+ return;
636119
+ }
636120
+ const parsed = JSON.parse(readFileSync105(fp, "utf-8"));
636121
+ _lastTodos = Array.isArray(parsed) ? parsed : [];
636122
+ } catch {
636123
+ _lastTodos = [];
636124
+ }
636125
+ }
636126
+ function scheduleRedraw() {
636127
+ if (_redrawScheduled || !_enabled) return;
636128
+ _redrawScheduled = true;
636129
+ setImmediate(() => {
636130
+ _redrawScheduled = false;
636131
+ render();
636132
+ });
636133
+ }
636134
+ function computeTargetHeight() {
636135
+ if (!panelEffectivelyVisible()) return 0;
636136
+ if (!_lastTodos || _lastTodos.length === 0) return 0;
636137
+ const allDone = _lastTodos.every((t2) => t2 && t2.status === "completed");
636138
+ if (allDone) return 0;
636139
+ const itemRows = _expanded ? selectExpandedTodoRows(_lastTodos, expandedRowCap() - 1).rowCount : selectPanelTodoRows(_lastTodos, MAX_VISIBLE_ROWS - 1).rowCount;
636140
+ return 1 + itemRows;
636141
+ }
636142
+ function applyHeightChange(nextHeight) {
636143
+ const changed = setTasksHeight(nextHeight);
636144
+ if (changed) {
636145
+ notifyLayoutResize();
636146
+ }
636147
+ if (_onResizeChange) {
636148
+ try {
636149
+ _onResizeChange(nextHeight);
636150
+ } catch {
636151
+ }
636152
+ }
636153
+ }
636154
+ function fg2562(idx, fallback = -1) {
636155
+ const n2 = idx < 0 ? fallback : idx;
636156
+ return n2 < 0 ? "\x1B[39m" : `\x1B[38;5;${n2}m`;
636157
+ }
636158
+ function refreshTuiTasksThemeVars() {
636159
+ BG = tuiBgSeq();
636160
+ DIM_LABEL = fg2562(tuiTextDim(), 240);
636161
+ ACCENT = tuiAccentFg();
636162
+ DONE2 = fg2562(tuiTextDim(), 240);
636163
+ PENDING = fg2562(tuiTextDim(), 240);
636164
+ }
636165
+ function statusToAnsi(status) {
636166
+ switch (status) {
636167
+ case "completed":
636168
+ return { mark: "◉", color: DONE2 };
636169
+ case "in_progress":
636170
+ return { mark: "◐", color: ACCENT };
636171
+ case "blocked":
636172
+ return { mark: "◍", color: BLOCKED };
636173
+ default:
636174
+ return { mark: "○", color: PENDING };
636175
+ }
636176
+ }
636177
+ function truncate2(s2, max) {
636178
+ if (s2.length <= max) return s2.padEnd(max, " ");
636179
+ return s2.slice(0, Math.max(0, max - 1)) + "…";
636180
+ }
636181
+ function stripAnsi2(s2) {
636182
+ return s2.replace(/\x1B\[[0-9;]*[A-Za-z]/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B[()][A-Z0-9]/g, "").replace(/\x1B\[?\??[0-9;]*[a-zA-Z]/g, "").replace(/\x1B/g, "");
636183
+ }
636184
+ function visualLen(s2) {
636185
+ return stripAnsi2(s2).length;
636186
+ }
636187
+ function buildTodoProgressBar(todos, maxWidth) {
636188
+ if (maxWidth <= 0 || todos.length === 0) return "";
636189
+ let cells = Math.min(todos.length, maxWidth);
636190
+ const truncated = cells < todos.length;
636191
+ const inIdx = todos.findIndex((t2) => t2.status === "in_progress");
636192
+ let nextIdx = -1;
636193
+ if (inIdx >= 0) {
636194
+ nextIdx = todos.findIndex((t2, i2) => i2 > inIdx && t2.status !== "completed");
636195
+ }
636196
+ if (nextIdx < 0) nextIdx = todos.findIndex((t2) => t2.status === "pending");
636197
+ const PEND = DIM_LABEL;
636198
+ const INPROG = ACCENT;
636199
+ const NEXT = ACCENT;
636200
+ const DONE_Y = ACCENT;
636201
+ let out = "";
636202
+ for (let i2 = 0; i2 < cells; i2++) {
636203
+ const t2 = todos[i2];
636204
+ if (t2.status === "completed") {
636205
+ out += `\x1B[1m${DONE_Y}█${RESET3}`;
636206
+ } else if (i2 === inIdx) {
636207
+ out += `${INPROG}▒${RESET3}`;
636208
+ } else if (i2 === nextIdx && inIdx >= 0) {
636209
+ out += `${NEXT}▒${RESET3}`;
636210
+ } else {
636211
+ out += `${PEND}░${RESET3}`;
636212
+ }
636213
+ }
636214
+ if (truncated && maxWidth > 0) out += `${DIM_LABEL}…${RESET3}`;
636215
+ return out;
636216
+ }
636217
+ function buildTodoTreeIndex(todos) {
636218
+ const byParent = /* @__PURE__ */ new Map();
636219
+ const byId = new Map(todos.map((t2) => [t2.id, t2]));
636220
+ const roots = [];
636221
+ for (const todo of todos) {
636222
+ if (todo.parentId && byId.has(todo.parentId)) {
636223
+ const arr = byParent.get(todo.parentId) ?? [];
636224
+ arr.push(todo);
636225
+ byParent.set(todo.parentId, arr);
636226
+ } else {
636227
+ roots.push(todo);
636228
+ }
636229
+ }
636230
+ return { byId, byParent, roots };
636231
+ }
636232
+ function childLeafStats(todo, index) {
636233
+ const children2 = index.byParent.get(todo.id) ?? [];
636234
+ if (children2.length === 0) return void 0;
636235
+ let completed = 0;
636236
+ let total = 0;
636237
+ const seen = /* @__PURE__ */ new Set();
636238
+ const visit = (node) => {
636239
+ if (seen.has(node.id)) return;
636240
+ seen.add(node.id);
636241
+ const nested = index.byParent.get(node.id) ?? [];
636242
+ if (nested.length === 0) {
636243
+ total++;
636244
+ if (node.status === "completed") completed++;
636245
+ return;
636246
+ }
636247
+ for (const child of nested) visit(child);
636248
+ };
636249
+ for (const child of children2) visit(child);
636250
+ return { completed, total };
636251
+ }
636252
+ function displayStatusFor(todo, index, seen = /* @__PURE__ */ new Set()) {
636253
+ if (seen.has(todo.id)) return todo.status;
636254
+ seen.add(todo.id);
636255
+ const children2 = index.byParent.get(todo.id) ?? [];
636256
+ if (children2.length === 0) return todo.status;
636257
+ const childStatuses = children2.map((child) => displayStatusFor(child, index, new Set(seen)));
636258
+ if (childStatuses.some((status) => status === "blocked")) return "blocked";
636259
+ if (childStatuses.some((status) => status === "in_progress")) return "in_progress";
636260
+ if (childStatuses.every((status) => status === "completed")) return "completed";
636261
+ if (todo.status === "completed") return "in_progress";
636262
+ return todo.status;
636263
+ }
636264
+ function toDisplayTodo(todo, depth, index) {
636265
+ return {
636266
+ ...todo,
636267
+ depth: Math.min(depth, 4),
636268
+ displayStatus: displayStatusFor(todo, index),
636269
+ childSummary: childLeafStats(todo, index)
636270
+ };
636271
+ }
636272
+ function orderTodosForDisplay(todos) {
636273
+ const index = buildTodoTreeIndex(todos);
636274
+ const out = [];
636275
+ const seen = /* @__PURE__ */ new Set();
636276
+ const visit = (todo, depth) => {
636277
+ if (seen.has(todo.id)) return;
636278
+ seen.add(todo.id);
636279
+ out.push(toDisplayTodo(todo, depth, index));
636280
+ for (const child of index.byParent.get(todo.id) ?? []) {
636281
+ visit(child, depth + 1);
636282
+ }
636283
+ };
636284
+ for (const root of index.roots) visit(root, 0);
636285
+ for (const todo of todos) visit(todo, 0);
636286
+ return out;
636287
+ }
636288
+ function leafTodosForProgress(todos) {
636289
+ const index = buildTodoTreeIndex(todos);
636290
+ const leaves = todos.filter((todo) => (index.byParent.get(todo.id) ?? []).length === 0);
636291
+ return leaves.length > 0 ? leaves : todos;
636292
+ }
636293
+ function activeDisplayIndex(displayTodos) {
636294
+ const inProgressLeaf = displayTodos.findIndex(
636295
+ (todo, index, all2) => todo.status === "in_progress" && !all2.some((candidate) => candidate.parentId === todo.id)
636296
+ );
636297
+ if (inProgressLeaf >= 0) return inProgressLeaf;
636298
+ const inProgress = displayTodos.findIndex((todo) => todo.displayStatus === "in_progress");
636299
+ if (inProgress >= 0) return inProgress;
636300
+ const blocked = displayTodos.findIndex((todo) => todo.displayStatus === "blocked");
636301
+ if (blocked >= 0) return blocked;
636302
+ return displayTodos.findIndex((todo) => todo.displayStatus === "pending");
636303
+ }
636304
+ function selectFocusedTodoItems(todos, maxItems) {
636305
+ const displayTodos = orderTodosForDisplay(todos);
636306
+ if (maxItems <= 0) return [];
636307
+ if (displayTodos.length <= maxItems) return displayTodos;
636308
+ const activeIndex = activeDisplayIndex(displayTodos);
636309
+ if (activeIndex < 0 || activeIndex < maxItems) return displayTodos.slice(0, maxItems);
636310
+ const rawIndex = buildTodoTreeIndex(todos);
636311
+ const displayById = new Map(displayTodos.map((todo) => [todo.id, todo]));
636312
+ const selected = [];
636313
+ const seen = /* @__PURE__ */ new Set();
636314
+ const add3 = (todo) => {
636315
+ if (!todo || selected.length >= maxItems || seen.has(todo.id)) return;
636316
+ selected.push(todo);
636317
+ seen.add(todo.id);
636318
+ };
636319
+ const active = displayTodos[activeIndex];
636320
+ const ancestors = [];
636321
+ let cursor = active;
636322
+ while (cursor?.parentId && rawIndex.byId.has(cursor.parentId)) {
636323
+ const parent = rawIndex.byId.get(cursor.parentId);
636324
+ if (!parent) break;
636325
+ const displayParent = displayById.get(parent.id);
636326
+ if (displayParent) ancestors.unshift(displayParent);
636327
+ cursor = parent;
636328
+ }
636329
+ for (const ancestor of ancestors) add3(ancestor);
636330
+ const siblings = active.parentId ? rawIndex.byParent.get(active.parentId) ?? [] : rawIndex.roots;
636331
+ const activeSiblingIndex = siblings.findIndex((todo) => todo.id === active.id);
636332
+ if (activeSiblingIndex > 0) add3(displayById.get(siblings[activeSiblingIndex - 1].id));
636333
+ add3(active);
636334
+ const descendants = [];
636335
+ const walkDescendants = (id2) => {
636336
+ for (const child of rawIndex.byParent.get(id2) ?? []) {
636337
+ const d2 = displayById.get(child.id);
636338
+ if (d2) descendants.push(d2);
636339
+ walkDescendants(child.id);
636340
+ }
636341
+ };
636342
+ walkDescendants(active.id);
636343
+ for (const d2 of descendants) add3(d2);
636344
+ for (let i2 = activeSiblingIndex + 1; i2 < siblings.length && selected.length < maxItems; i2++) {
636345
+ add3(displayById.get(siblings[i2].id));
636346
+ }
636347
+ for (let i2 = activeIndex + 1; i2 < displayTodos.length && selected.length < maxItems; i2++) {
636348
+ add3(displayTodos[i2]);
636349
+ }
636350
+ for (let i2 = activeIndex - 1; i2 >= 0 && selected.length < maxItems; i2--) {
636351
+ add3(displayTodos[i2]);
636352
+ }
636353
+ return selected;
636354
+ }
636355
+ function selectPanelTodoRows(todos, maxRows) {
636356
+ const displayTodos = orderTodosForDisplay(todos);
636357
+ if (maxRows <= 0 || displayTodos.length === 0) {
636358
+ return { items: [], omitted: displayTodos.length, rowCount: 0 };
636359
+ }
636360
+ if (displayTodos.length <= maxRows) {
636361
+ return { items: displayTodos, omitted: 0, rowCount: displayTodos.length };
636362
+ }
636363
+ const itemBudget = Math.max(1, maxRows - 1);
636364
+ const items = selectFocusedTodoItems(todos, itemBudget);
636365
+ const omitted = Math.max(0, displayTodos.length - items.length);
636366
+ return {
636367
+ items,
636368
+ omitted,
636369
+ rowCount: Math.min(maxRows, items.length + (omitted > 0 ? 1 : 0))
636370
+ };
636371
+ }
636372
+ function selectExpandedTodoRows(todos, maxRows) {
636373
+ const displayTodos = orderTodosForDisplay(todos);
636374
+ if (maxRows <= 1 || displayTodos.length === 0) {
636375
+ return { items: [], omitted: displayTodos.length, rowCount: 0 };
636376
+ }
636377
+ const items = displayTodos.slice(0, maxRows - 1);
636378
+ const omitted = Math.max(0, displayTodos.length - items.length);
636379
+ return { items, omitted, rowCount: items.length + 1 };
636380
+ }
636381
+ function __testOrderTodosForDisplay(todos) {
636382
+ return orderTodosForDisplay(todos);
636383
+ }
636384
+ function __testSelectPanelTodoRows(todos, maxRows) {
636385
+ return selectPanelTodoRows(todos, maxRows);
636386
+ }
636387
+ function render() {
636388
+ if (!_enabled) return;
636389
+ if (!panelEffectivelyVisible()) {
636390
+ clearLastPaintedRows();
636391
+ applyHeightChange(0);
636392
+ return;
636393
+ }
636394
+ const target = computeTargetHeight();
636395
+ applyHeightChange(target);
636396
+ if (target === 0) {
636397
+ clearLastPaintedRows();
636398
+ return;
636399
+ }
636400
+ const L = layout();
636401
+ const cols = Math.max(20, termCols());
636402
+ const progressTodos = leafTodosForProgress(_lastTodos);
636403
+ const completed = progressTodos.filter((t2) => t2.status === "completed").length;
636404
+ const total = progressTodos.length;
636405
+ const headerColor = ACCENT;
636406
+ const lines = [];
636407
+ const headerPrefix = `tasks ${headerColor}${completed}/${total}${RESET3} `;
636408
+ const headerPrefixWidth = visualLen(headerPrefix);
636409
+ const maxBarWidth = Math.max(0, cols - 2 - headerPrefixWidth);
636410
+ const progressBar = buildTodoProgressBar(progressTodos, maxBarWidth);
636411
+ const headerText = `${headerPrefix}${progressBar}`;
636412
+ lines.push(headerText);
636413
+ const selection = _expanded ? selectExpandedTodoRows(_lastTodos, expandedRowCap() - 1) : selectPanelTodoRows(_lastTodos, MAX_VISIBLE_ROWS - 1);
636414
+ const visible = selection.items;
636415
+ _gradPhase = (_gradPhase + 10) % 360;
636416
+ const displayAll = orderTodosForDisplay(_lastTodos);
636417
+ const activeIdx = activeDisplayIndex(displayAll);
636418
+ const activeId = activeIdx >= 0 ? displayAll[activeIdx].id : null;
636419
+ let toggleLineIdx = -1;
636420
+ for (const t2 of visible) {
636421
+ const { mark, color } = statusToAnsi(t2.displayStatus);
636422
+ const contentWidth = Math.max(4, cols - 8);
636423
+ const indent2 = t2.depth > 0 ? `${" ".repeat(t2.depth)}- ` : "";
636424
+ const childSummary = t2.childSummary && t2.childSummary.total > 0 ? ` [${t2.childSummary.completed}/${t2.childSummary.total}]` : "";
636425
+ const contentText = indent2 + t2.content + childSummary + (t2.blocker ? ` (blocked: ${t2.blocker})` : "");
636426
+ const truncated = truncate2(contentText, contentWidth);
636427
+ if (activeId && t2.id === activeId) {
636428
+ const grad = paintActiveRowGradient(truncated);
636429
+ if (grad) {
636430
+ lines.push(`${color}${mark}${RESET3} ${grad}`);
636431
+ continue;
636432
+ }
636433
+ }
636434
+ lines.push(`${color}${mark}${RESET3} ${color}${truncated}${RESET3}`);
636435
+ }
636436
+ if (_expanded) {
636437
+ toggleLineIdx = lines.length;
636438
+ const omittedNote = selection.omitted > 0 ? ` (+${selection.omitted} clipped)` : "";
636439
+ lines.push(`${ACCENT}▴ show active stages${RESET3}${DIM_LABEL}${omittedNote}${RESET3}`);
636440
+ } else if (selection.omitted > 0) {
636441
+ toggleLineIdx = lines.length;
636442
+ lines.push(`${DIM_LABEL}… +${selection.omitted} more tasks ${RESET3}${ACCENT}▸${RESET3}`);
636443
+ }
636444
+ let out = HIDE + SAVE;
636445
+ const newTop = L.tasksTop;
636446
+ const newBottom = Math.min(L.tasksBottom, L.tasksTop + lines.length - 1);
636447
+ const safeClearTop = L.headerBottom + 1;
636448
+ const safeClearBottom = L.contentBottom;
636449
+ if (_lastPaintedTop >= 0 && _lastPaintedBottom >= _lastPaintedTop) {
636450
+ for (let row = _lastPaintedTop; row <= _lastPaintedBottom; row++) {
636451
+ if (row >= newTop && row <= newBottom) continue;
636452
+ if (row < safeClearTop || row > safeClearBottom) continue;
636453
+ out += `\x1B[${row};1H${CLEAR_LINE}`;
636454
+ }
636455
+ }
636456
+ for (let i2 = 0; i2 < lines.length; i2++) {
636457
+ const row = L.tasksTop + i2;
636458
+ if (row > L.tasksBottom) break;
636459
+ out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET3}`;
636460
+ }
636461
+ out += RESTORE + SHOW;
636462
+ try {
636463
+ chromeWrite(out);
636464
+ } catch {
636465
+ }
636466
+ _lastPaintedTop = newTop;
636467
+ _lastPaintedBottom = newBottom;
636468
+ _toggleRowAbs = toggleLineIdx >= 0 && L.tasksTop + toggleLineIdx <= L.tasksBottom ? L.tasksTop + toggleLineIdx : -1;
636469
+ }
636470
+ function handleTuiTasksClick(row) {
636471
+ if (!panelEffectivelyVisible()) return false;
636472
+ if (_toggleRowAbs < 0 || row !== _toggleRowAbs) return false;
636473
+ _expanded = !_expanded;
636474
+ loadTodos();
636475
+ render();
636476
+ return true;
636477
+ }
636478
+ function isTuiTasksExpanded() {
636479
+ return _expanded;
636480
+ }
636481
+ function clearLastPaintedRows() {
636482
+ if (_lastPaintedTop < 0 || _lastPaintedBottom < _lastPaintedTop) return;
636483
+ const L = layout();
636484
+ const safeTop = L.headerBottom + 1;
636485
+ const safeBottom = Math.max(L.contentBottom, safeTop - 1);
636486
+ let out = HIDE + SAVE;
636487
+ for (let row = _lastPaintedTop; row <= _lastPaintedBottom; row++) {
636488
+ if (row < safeTop || row > safeBottom) continue;
636489
+ out += `\x1B[${row};1H${CLEAR_LINE}`;
636490
+ }
636491
+ out += RESTORE + SHOW;
636492
+ try {
636493
+ chromeWrite(out);
636494
+ } catch {
636495
+ }
636496
+ _lastPaintedTop = -1;
636497
+ _lastPaintedBottom = -1;
636498
+ }
636499
+ var chromeWrite, _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, _scopeOverlayActive, _scopeMainViewActive, _scopeNeovimActive, _scopePagerActive, _lastPaintedTop, _lastPaintedBottom, MAX_VISIBLE_ROWS, _expanded, _toggleRowAbs, _gradPhase, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET3, BG, DIM_LABEL, ACCENT, DONE2, PENDING, BLOCKED;
636500
+ var init_tui_tasks_renderer = __esm({
636501
+ "packages/cli/src/tui/tui-tasks-renderer.ts"() {
636502
+ "use strict";
636503
+ init_layout2();
636504
+ init_theme();
636505
+ init_stageIndicator();
636506
+ chromeWrite = ((data) => {
636507
+ process.stdout.write(data);
636508
+ });
636509
+ _activeSessionId = null;
636510
+ _watcher = null;
636511
+ _lastTodos = [];
636512
+ _enabled = true;
636513
+ _redrawScheduled = false;
636514
+ _onResizeChange = null;
636515
+ _scopeOverlayActive = false;
636516
+ _scopeMainViewActive = true;
636517
+ _scopeNeovimActive = false;
636518
+ _scopePagerActive = false;
636519
+ _lastPaintedTop = -1;
636520
+ _lastPaintedBottom = -1;
636521
+ MAX_VISIBLE_ROWS = 8;
636522
+ _expanded = false;
636523
+ _toggleRowAbs = -1;
636524
+ _gradPhase = 0;
636525
+ SAVE = "\x1B[s";
636526
+ RESTORE = "\x1B[u";
636527
+ HIDE = "\x1B[?25l";
636528
+ SHOW = "\x1B[?25h";
636529
+ CLEAR_LINE = "\x1B[2K";
636530
+ RESET3 = "\x1B[0m";
636531
+ BG = tuiBgSeq();
636532
+ DIM_LABEL = "";
636533
+ ACCENT = "";
636534
+ DONE2 = "";
636535
+ PENDING = "";
636536
+ BLOCKED = "\x1B[38;5;196m";
636537
+ refreshTuiTasksThemeVars();
636538
+ onStageChange(() => {
636539
+ if (!panelEffectivelyVisible()) return;
636540
+ if (_lastTodos.length === 0) return;
636541
+ if (!_lastTodos.some((t2) => t2.status === "in_progress")) return;
636542
+ scheduleRedraw();
636543
+ });
636544
+ }
636545
+ });
636546
+
635706
636547
  // packages/cli/src/tui/braille-spinner.ts
635707
636548
  function buildColorRamp(ramp) {
635708
636549
  return [...ramp, ...ramp.slice(1, -1).reverse()];
@@ -636000,9 +636841,9 @@ var init_braille_spinner = __esm({
636000
636841
  });
636001
636842
 
636002
636843
  // packages/cli/src/tui/project-context.ts
636003
- import { existsSync as existsSync126, readFileSync as readFileSync105, readdirSync as readdirSync42, mkdirSync as mkdirSync78, statSync as statSync50, writeFileSync as writeFileSync66 } from "node:fs";
636004
- import { dirname as dirname43, join as join140, basename as basename28, resolve as resolve60 } from "node:path";
636005
- import { homedir as homedir44 } from "node:os";
636844
+ import { existsSync as existsSync127, readFileSync as readFileSync106, readdirSync as readdirSync42, mkdirSync as mkdirSync78, statSync as statSync50, writeFileSync as writeFileSync66 } from "node:fs";
636845
+ import { dirname as dirname43, join as join141, basename as basename28, resolve as resolve60 } from "node:path";
636846
+ import { homedir as homedir45 } from "node:os";
636006
636847
  function projectContextUrlSpanAt(text2, index) {
636007
636848
  PROJECT_CONTEXT_URL_RE.lastIndex = 0;
636008
636849
  for (const match of text2.matchAll(PROJECT_CONTEXT_URL_RE)) {
@@ -636048,10 +636889,10 @@ function loadProjectMap(repoRoot) {
636048
636889
  if (!hasOmniusDirectory(repoRoot)) {
636049
636890
  initOmniusDirectory(repoRoot);
636050
636891
  }
636051
- const mapPath2 = join140(repoRoot, OMNIUS_DIR, "context", "project-map.md");
636052
- if (existsSync126(mapPath2)) {
636892
+ const mapPath2 = join141(repoRoot, OMNIUS_DIR, "context", "project-map.md");
636893
+ if (existsSync127(mapPath2)) {
636053
636894
  try {
636054
- const content = readFileSync105(mapPath2, "utf-8");
636895
+ const content = readFileSync106(mapPath2, "utf-8");
636055
636896
  return content;
636056
636897
  } catch {
636057
636898
  }
@@ -636061,10 +636902,10 @@ function loadProjectMap(repoRoot) {
636061
636902
  function findGitDir(repoRoot) {
636062
636903
  let dir = resolve60(repoRoot);
636063
636904
  for (; ; ) {
636064
- const gitPath = join140(dir, ".git");
636065
- if (existsSync126(gitPath)) {
636905
+ const gitPath = join141(dir, ".git");
636906
+ if (existsSync127(gitPath)) {
636066
636907
  try {
636067
- const raw = readFileSync105(gitPath, "utf8").trim();
636908
+ const raw = readFileSync106(gitPath, "utf8").trim();
636068
636909
  const match = raw.match(/^gitdir:\s*(.+)$/i);
636069
636910
  if (match?.[1]) {
636070
636911
  return resolve60(dir, match[1]);
@@ -636084,12 +636925,12 @@ function getGitInfo(repoRoot) {
636084
636925
  if (!gitDir) return "";
636085
636926
  const lines = [];
636086
636927
  try {
636087
- const head = readFileSync105(join140(gitDir, "HEAD"), "utf-8").trim();
636928
+ const head = readFileSync106(join141(gitDir, "HEAD"), "utf-8").trim();
636088
636929
  const refMatch = head.match(/^ref:\s+refs\/heads\/(.+)$/);
636089
636930
  if (refMatch?.[1]) {
636090
636931
  lines.push(`Branch: ${refMatch[1]}`);
636091
636932
  try {
636092
- const refHash = readFileSync105(join140(gitDir, "refs", "heads", refMatch[1]), "utf-8").trim();
636933
+ const refHash = readFileSync106(join141(gitDir, "refs", "heads", refMatch[1]), "utf-8").trim();
636093
636934
  if (refHash) lines.push(`HEAD: ${refHash.slice(0, 12)}`);
636094
636935
  } catch {
636095
636936
  }
@@ -636099,8 +636940,8 @@ function getGitInfo(repoRoot) {
636099
636940
  } catch {
636100
636941
  }
636101
636942
  try {
636102
- const indexPath = join140(gitDir, "index");
636103
- if (existsSync126(indexPath)) lines.push("Working tree: status not probed during prompt assembly");
636943
+ const indexPath = join141(gitDir, "index");
636944
+ if (existsSync127(indexPath)) lines.push("Working tree: status not probed during prompt assembly");
636104
636945
  } catch {
636105
636946
  }
636106
636947
  return lines.join("\n");
@@ -636109,7 +636950,7 @@ function emptyMemoryContextBundle() {
636109
636950
  return { text: "", memoryPrefix: "", prefixHash: "" };
636110
636951
  }
636111
636952
  function countJsonMemoryEntries(dir) {
636112
- if (!existsSync126(dir)) return { topics: 0, entries: 0 };
636953
+ if (!existsSync127(dir)) return { topics: 0, entries: 0 };
636113
636954
  let topics = 0;
636114
636955
  let entries = 0;
636115
636956
  try {
@@ -636117,7 +636958,7 @@ function countJsonMemoryEntries(dir) {
636117
636958
  if (!file.endsWith(".json")) continue;
636118
636959
  topics++;
636119
636960
  try {
636120
- const parsed = JSON.parse(readFileSync105(join140(dir, file), "utf8"));
636961
+ const parsed = JSON.parse(readFileSync106(join141(dir, file), "utf8"));
636121
636962
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
636122
636963
  entries += Object.keys(parsed).length;
636123
636964
  }
@@ -636130,35 +636971,35 @@ function countJsonMemoryEntries(dir) {
636130
636971
  return { topics, entries };
636131
636972
  }
636132
636973
  function countReflectionBuffer(repoRoot) {
636133
- const path15 = join140(repoRoot, OMNIUS_DIR, "memory", "reflections.json");
636134
- if (!existsSync126(path15)) return 0;
636974
+ const path15 = join141(repoRoot, OMNIUS_DIR, "memory", "reflections.json");
636975
+ if (!existsSync127(path15)) return 0;
636135
636976
  try {
636136
- const parsed = JSON.parse(readFileSync105(path15, "utf8"));
636977
+ const parsed = JSON.parse(readFileSync106(path15, "utf8"));
636137
636978
  return Array.isArray(parsed.reflections) ? parsed.reflections.length : 0;
636138
636979
  } catch {
636139
636980
  return 0;
636140
636981
  }
636141
636982
  }
636142
636983
  function countJsonlLines(path15, maxBytes = 1e6) {
636143
- if (!existsSync126(path15)) return 0;
636984
+ if (!existsSync127(path15)) return 0;
636144
636985
  try {
636145
- const text2 = readFileSync105(path15, "utf8").slice(-maxBytes);
636986
+ const text2 = readFileSync106(path15, "utf8").slice(-maxBytes);
636146
636987
  return text2.split(/\r?\n/).filter((line) => line.trim()).length;
636147
636988
  } catch {
636148
636989
  return 0;
636149
636990
  }
636150
636991
  }
636151
636992
  function buildWorkspaceMemorySubstrateCensus(repoRoot) {
636152
- const projectMemoryDir = join140(repoRoot, OMNIUS_DIR, "memory");
636153
- const legacyMemoryDir = join140(repoRoot, ".omnius", "memory");
636993
+ const projectMemoryDir = join141(repoRoot, OMNIUS_DIR, "memory");
636994
+ const legacyMemoryDir = join141(repoRoot, ".omnius", "memory");
636154
636995
  const projectMemory = countJsonMemoryEntries(projectMemoryDir);
636155
636996
  const legacyMemory = legacyMemoryDir === projectMemoryDir ? { topics: 0, entries: 0 } : countJsonMemoryEntries(legacyMemoryDir);
636156
- const globalMemory = countJsonMemoryEntries(join140(homedir44(), ".omnius", "memory"));
636997
+ const globalMemory = countJsonMemoryEntries(join141(homedir45(), ".omnius", "memory"));
636157
636998
  const reflectionCount = countReflectionBuffer(repoRoot);
636158
- const evidenceCount = countJsonlLines(join140(repoRoot, ".omnius", "evidence", "events.jsonl"));
636159
- const unifiedPresent = existsSync126(join140(repoRoot, OMNIUS_DIR, "unified-memory.db"));
636160
- const episodesPresent = existsSync126(join140(repoRoot, OMNIUS_DIR, "episodes.db"));
636161
- const knowledgePresent = existsSync126(join140(repoRoot, OMNIUS_DIR, "knowledge.db"));
636999
+ const evidenceCount = countJsonlLines(join141(repoRoot, ".omnius", "evidence", "events.jsonl"));
637000
+ const unifiedPresent = existsSync127(join141(repoRoot, OMNIUS_DIR, "unified-memory.db"));
637001
+ const episodesPresent = existsSync127(join141(repoRoot, OMNIUS_DIR, "episodes.db"));
637002
+ const knowledgePresent = existsSync127(join141(repoRoot, OMNIUS_DIR, "knowledge.db"));
636162
637003
  const topicCount = projectMemory.topics + legacyMemory.topics + globalMemory.topics;
636163
637004
  const entryCount = projectMemory.entries + legacyMemory.entries + globalMemory.entries;
636164
637005
  const hasMemory = topicCount + entryCount + reflectionCount + evidenceCount > 0 || unifiedPresent || episodesPresent || knowledgePresent;
@@ -636181,12 +637022,12 @@ function loadMemoryContextBundle(repoRoot, task = "", taskEmbedding) {
636181
637022
  if (unified.text) return unified;
636182
637023
  const all2 = [];
636183
637024
  const collect = (dir, scope) => {
636184
- if (!existsSync126(dir)) return;
637025
+ if (!existsSync127(dir)) return;
636185
637026
  try {
636186
637027
  const files = readdirSync42(dir).filter((f2) => f2.endsWith(".json"));
636187
637028
  for (const file of files.slice(0, 10)) {
636188
637029
  try {
636189
- const raw = readFileSync105(join140(dir, file), "utf-8");
637030
+ const raw = readFileSync106(join141(dir, file), "utf-8");
636190
637031
  const entries = JSON.parse(raw);
636191
637032
  const topic = basename28(file, ".json");
636192
637033
  for (const [k, v] of Object.entries(entries)) {
@@ -636207,11 +637048,11 @@ function loadMemoryContextBundle(repoRoot, task = "", taskEmbedding) {
636207
637048
  } catch {
636208
637049
  }
636209
637050
  };
636210
- const omniusMemDir = join140(repoRoot, OMNIUS_DIR, "memory");
637051
+ const omniusMemDir = join141(repoRoot, OMNIUS_DIR, "memory");
636211
637052
  collect(omniusMemDir, "project");
636212
- const legacyMemDir = join140(repoRoot, ".omnius", "memory");
637053
+ const legacyMemDir = join141(repoRoot, ".omnius", "memory");
636213
637054
  if (legacyMemDir !== omniusMemDir) collect(legacyMemDir, "project");
636214
- const globalMemDir = join140(homedir44(), ".omnius", "memory");
637055
+ const globalMemDir = join141(homedir45(), ".omnius", "memory");
636215
637056
  collect(globalMemDir, "global");
636216
637057
  const seen = /* @__PURE__ */ new Set();
636217
637058
  const deduped = [];
@@ -636292,8 +637133,8 @@ function loadMemoryContextBundle(repoRoot, task = "", taskEmbedding) {
636292
637133
  };
636293
637134
  }
636294
637135
  function loadUnifiedMemoryContextBundle(repoRoot, task = "", taskEmbedding) {
636295
- const dbPath = join140(repoRoot, OMNIUS_DIR, "unified-memory.db");
636296
- if (!existsSync126(dbPath)) return emptyMemoryContextBundle();
637136
+ const dbPath = join141(repoRoot, OMNIUS_DIR, "unified-memory.db");
637137
+ if (!existsSync127(dbPath)) return emptyMemoryContextBundle();
636297
637138
  let db = null;
636298
637139
  try {
636299
637140
  db = initDb(dbPath);
@@ -636610,11 +637451,11 @@ function buildPythonBootstrapContext(repoRoot, task = "") {
636610
637451
  }
636611
637452
  function inspectPythonBootstrap(repoRoot, task = "") {
636612
637453
  const rootEntries = safeReadDir(repoRoot);
636613
- const scriptsEntries = safeReadDir(join140(repoRoot, "scripts"));
636614
- const binEntries = safeReadDir(join140(repoRoot, "bin"));
636615
- const relExists = (rel) => existsSync126(join140(repoRoot, rel));
636616
- const venvs = [".venv", "venv", "env"].filter((rel) => isDirectory2(join140(repoRoot, rel))).filter(
636617
- (rel) => existsSync126(join140(repoRoot, rel, process.platform === "win32" ? "Scripts" : "bin")) || existsSync126(join140(repoRoot, rel, "pyvenv.cfg"))
637454
+ const scriptsEntries = safeReadDir(join141(repoRoot, "scripts"));
637455
+ const binEntries = safeReadDir(join141(repoRoot, "bin"));
637456
+ const relExists = (rel) => existsSync127(join141(repoRoot, rel));
637457
+ const venvs = [".venv", "venv", "env"].filter((rel) => isDirectory2(join141(repoRoot, rel))).filter(
637458
+ (rel) => existsSync127(join141(repoRoot, rel, process.platform === "win32" ? "Scripts" : "bin")) || existsSync127(join141(repoRoot, rel, "pyvenv.cfg"))
636618
637459
  );
636619
637460
  const requirements = rootEntries.filter((name10) => /^requirements(?:[-_.][A-Za-z0-9_-]+)?\.txt$/.test(name10)).sort();
636620
637461
  const managers2 = [
@@ -636638,7 +637479,7 @@ function inspectPythonBootstrap(repoRoot, task = "") {
636638
637479
  ...findBootstrapEntries(binEntries, "bin")
636639
637480
  ].slice(0, 8);
636640
637481
  const makeTargets = extractMakeBootstrapTargets(repoRoot).slice(0, 6);
636641
- const hasPythonSource = rootEntries.some((name10) => name10.endsWith(".py")) || scriptsEntries.some((name10) => name10.endsWith(".py")) || relExists("src") && safeReadDir(join140(repoRoot, "src")).some((name10) => name10.endsWith(".py"));
637482
+ const hasPythonSource = rootEntries.some((name10) => name10.endsWith(".py")) || scriptsEntries.some((name10) => name10.endsWith(".py")) || relExists("src") && safeReadDir(join141(repoRoot, "src")).some((name10) => name10.endsWith(".py"));
636642
637483
  const taskNeedsPython = /\b(?:python|pip|pip3|venv|virtualenv|pytest|pyproject|requirements|uv|poetry|pdm|pipenv|conda)\b/i.test(task);
636643
637484
  const hasPyproject = relExists("pyproject.toml");
636644
637485
  const hasAnchors = venvs.length > 0 || bootstrapFiles.length > 0 || managers2.length > 0 || makeTargets.length > 0 || hasPythonSource;
@@ -636673,10 +637514,10 @@ function findBootstrapEntries(entries, prefix) {
636673
637514
  ).map((name10) => prefix ? `${prefix}/${name10}` : name10).sort();
636674
637515
  }
636675
637516
  function extractMakeBootstrapTargets(repoRoot) {
636676
- const makefile = ["Makefile", "makefile"].find((name10) => existsSync126(join140(repoRoot, name10)));
637517
+ const makefile = ["Makefile", "makefile"].find((name10) => existsSync127(join141(repoRoot, name10)));
636677
637518
  if (!makefile) return [];
636678
637519
  try {
636679
- const text2 = readFileSync105(join140(repoRoot, makefile), "utf8");
637520
+ const text2 = readFileSync106(join141(repoRoot, makefile), "utf8");
636680
637521
  const targets = [];
636681
637522
  for (const line of text2.split(/\r?\n/)) {
636682
637523
  const match = line.match(/^([A-Za-z0-9_.-]+)\s*:(?![=])/);
@@ -636886,10 +637727,10 @@ function sanitizeToolName(value2) {
636886
637727
  }
636887
637728
  function loadCustomToolsContext(repoRoot) {
636888
637729
  try {
636889
- const registryPath = join140(repoRoot, ".omnius", "tools", "registry.json");
636890
- const indexPath = join140(repoRoot, ".omnius", "tools", "README.md");
636891
- if (!existsSync126(registryPath)) return "";
636892
- const registry4 = JSON.parse(readFileSync105(registryPath, "utf-8"));
637730
+ const registryPath = join141(repoRoot, ".omnius", "tools", "registry.json");
637731
+ const indexPath = join141(repoRoot, ".omnius", "tools", "README.md");
637732
+ if (!existsSync127(registryPath)) return "";
637733
+ const registry4 = JSON.parse(readFileSync106(registryPath, "utf-8"));
636893
637734
  const tools = (registry4.tools ?? []).filter((tool) => tool.qualityGate?.lastTest?.status === "passed").sort((a2, b) => {
636894
637735
  const byRate = (b.analytics?.successRate ?? 0) - (a2.analytics?.successRate ?? 0);
636895
637736
  if (byRate !== 0) return byRate;
@@ -636904,7 +637745,7 @@ function loadCustomToolsContext(repoRoot) {
636904
637745
  const bits = [
636905
637746
  `- ${tool.name} v${tool.version ?? 1}: ${truncateProjectContextText(String(tool.description ?? ""), 140, "")}`,
636906
637747
  `docs=${tool.docsPath ?? "missing"}`,
636907
- existsSync126(indexPath) ? `index=${indexPath}` : "",
637748
+ existsSync127(indexPath) ? `index=${indexPath}` : "",
636908
637749
  `test=${tested}${schema ? `, schema=${schema}` : ""}`,
636909
637750
  `success=${successRate}`,
636910
637751
  example?.args ? `example=${tool.name}(${JSON.stringify(example.args)})` : "",
@@ -636948,7 +637789,7 @@ function buildProjectContext(repoRoot, stores, task = "", taskEmbedding) {
636948
637789
  }
636949
637790
  function writeCompressedSkillsArtifact(repoRoot, skills) {
636950
637791
  try {
636951
- const contextDir = join140(repoRoot, OMNIUS_DIR, "context");
637792
+ const contextDir = join141(repoRoot, OMNIUS_DIR, "context");
636952
637793
  mkdirSync78(contextDir, { recursive: true });
636953
637794
  const bySource = /* @__PURE__ */ new Map();
636954
637795
  for (const skill of skills) bySource.set(skill.source, (bySource.get(skill.source) ?? 0) + 1);
@@ -636959,7 +637800,7 @@ function writeCompressedSkillsArtifact(repoRoot, skills) {
636959
637800
  triggers: skill.triggers.slice(0, 4)
636960
637801
  }));
636961
637802
  writeFileSync66(
636962
- join140(contextDir, "skills-compressed.json"),
637803
+ join141(contextDir, "skills-compressed.json"),
636963
637804
  JSON.stringify(
636964
637805
  {
636965
637806
  schema: "omnius.skills-compressed.v1",
@@ -637237,6 +638078,39 @@ async function collectNetworkMetrics() {
637237
638078
  }
637238
638079
  return { rxBytesPerSec: 0, txBytesPerSec: 0 };
637239
638080
  }
638081
+ async function hasNvidiaDevice() {
638082
+ try {
638083
+ const { readdirSync: readdirSync62 } = await import("node:fs");
638084
+ const dev = readdirSync62("/dev");
638085
+ if (dev.some((f2) => f2 === "nvidia0" || /^nvidia\d+$/.test(f2) || f2.startsWith("nvidia"))) {
638086
+ return true;
638087
+ }
638088
+ } catch {
638089
+ }
638090
+ return new Promise((resolve78) => {
638091
+ exec4("command -v nvidia-smi", { encoding: "utf8", timeout: 2e3 }, (err) => resolve78(!err));
638092
+ });
638093
+ }
638094
+ function nvidiaPresentFallback() {
638095
+ return {
638096
+ available: true,
638097
+ count: 1,
638098
+ name: "NVIDIA GPU",
638099
+ utilization: 0,
638100
+ vramUsedMB: 0,
638101
+ vramTotalMB: 0,
638102
+ vramUtilization: 0,
638103
+ devices: [{
638104
+ index: 0,
638105
+ uuid: "nvidia-fallback",
638106
+ name: "NVIDIA GPU",
638107
+ utilization: 0,
638108
+ vramUsedMB: 0,
638109
+ vramTotalMB: 0,
638110
+ vramUtilization: 0
638111
+ }]
638112
+ };
638113
+ }
637240
638114
  async function collectGpuMetrics() {
637241
638115
  const noGpu = {
637242
638116
  available: false,
@@ -637269,7 +638143,10 @@ async function collectGpuMetrics() {
637269
638143
  }]
637270
638144
  };
637271
638145
  }
637272
- if (_nvidiaSmiAvailable2 === false) return noGpu;
638146
+ if (_nvidiaSmiAvailable2 === false) {
638147
+ if (await hasNvidiaDevice()) return nvidiaPresentFallback();
638148
+ return noGpu;
638149
+ }
637273
638150
  try {
637274
638151
  const smi = await new Promise((resolve78, reject) => {
637275
638152
  exec4(
@@ -637298,7 +638175,10 @@ async function collectGpuMetrics() {
637298
638175
  vramUtilization: vramTotal2 > 0 ? Math.round(vramUsed2 / vramTotal2 * 100) : 0
637299
638176
  });
637300
638177
  }
637301
- if (devices.length === 0) return noGpu;
638178
+ if (devices.length === 0) {
638179
+ if (await hasNvidiaDevice()) return nvidiaPresentFallback();
638180
+ return noGpu;
638181
+ }
637302
638182
  const vramUsed = devices.reduce((sum2, gpu) => sum2 + gpu.vramUsedMB, 0);
637303
638183
  const vramTotal = devices.reduce((sum2, gpu) => sum2 + gpu.vramTotalMB, 0);
637304
638184
  const avgUtil = Math.round(devices.reduce((sum2, gpu) => sum2 + gpu.utilization, 0) / devices.length);
@@ -637316,6 +638196,7 @@ async function collectGpuMetrics() {
637316
638196
  };
637317
638197
  } catch {
637318
638198
  _nvidiaSmiAvailable2 = false;
638199
+ if (await hasNvidiaDevice()) return nvidiaPresentFallback();
637319
638200
  return noGpu;
637320
638201
  }
637321
638202
  }
@@ -637766,520 +638647,6 @@ var init_overlay_lock = __esm({
637766
638647
  }
637767
638648
  });
637768
638649
 
637769
- // packages/cli/src/tui/tui-tasks-renderer.ts
637770
- var tui_tasks_renderer_exports = {};
637771
- __export(tui_tasks_renderer_exports, {
637772
- __testOrderTodosForDisplay: () => __testOrderTodosForDisplay,
637773
- __testSelectPanelTodoRows: () => __testSelectPanelTodoRows,
637774
- getTuiTasksScope: () => getTuiTasksScope,
637775
- onTuiTasksHeightChange: () => onTuiTasksHeightChange,
637776
- refreshTuiTasks: () => refreshTuiTasks,
637777
- refreshTuiTasksSync: () => refreshTuiTasksSync,
637778
- refreshTuiTasksThemeVars: () => refreshTuiTasksThemeVars,
637779
- setTasksRendererWriter: () => setTasksRendererWriter,
637780
- setTuiTasksEnabled: () => setTuiTasksEnabled,
637781
- setTuiTasksScope: () => setTuiTasksScope,
637782
- setTuiTasksSession: () => setTuiTasksSession,
637783
- teardownTuiTasks: () => teardownTuiTasks
637784
- });
637785
- import { existsSync as existsSync127, readFileSync as readFileSync106, watch as fsWatch3 } from "node:fs";
637786
- import { join as join141 } from "node:path";
637787
- import { homedir as homedir45 } from "node:os";
637788
- function setTasksRendererWriter(writer) {
637789
- chromeWrite = writer;
637790
- }
637791
- function panelEffectivelyVisible() {
637792
- return _enabled && !_scopeOverlayActive && !_scopeNeovimActive && !_scopePagerActive && _scopeMainViewActive;
637793
- }
637794
- function todoDir2() {
637795
- return join141(homedir45(), ".omnius", "todos");
637796
- }
637797
- function todoPath2(sessionId) {
637798
- const safe = sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
637799
- return join141(todoDir2(), `${safe}.json`);
637800
- }
637801
- function setTuiTasksSession(sessionId) {
637802
- if (sessionId === _activeSessionId) return;
637803
- _activeSessionId = sessionId || null;
637804
- if (_watcher) {
637805
- try {
637806
- _watcher.close();
637807
- } catch {
637808
- }
637809
- _watcher = null;
637810
- }
637811
- if (!_activeSessionId) {
637812
- _lastTodos = [];
637813
- applyHeightChange(0);
637814
- return;
637815
- }
637816
- loadTodos();
637817
- installWatcher();
637818
- scheduleRedraw();
637819
- }
637820
- function onTuiTasksHeightChange(cb) {
637821
- _onResizeChange = cb;
637822
- }
637823
- function setTuiTasksEnabled(enabled2) {
637824
- _enabled = enabled2;
637825
- scheduleRedraw();
637826
- }
637827
- function setTuiTasksScope(scope) {
637828
- let changed = false;
637829
- if (scope.overlayActive !== void 0 && scope.overlayActive !== _scopeOverlayActive) {
637830
- _scopeOverlayActive = scope.overlayActive;
637831
- changed = true;
637832
- }
637833
- if (scope.mainViewActive !== void 0 && scope.mainViewActive !== _scopeMainViewActive) {
637834
- _scopeMainViewActive = scope.mainViewActive;
637835
- changed = true;
637836
- }
637837
- if (scope.neovimActive !== void 0 && scope.neovimActive !== _scopeNeovimActive) {
637838
- _scopeNeovimActive = scope.neovimActive;
637839
- changed = true;
637840
- }
637841
- if (scope.pagerActive !== void 0 && scope.pagerActive !== _scopePagerActive) {
637842
- _scopePagerActive = scope.pagerActive;
637843
- changed = true;
637844
- }
637845
- if (changed) {
637846
- if (!panelEffectivelyVisible()) {
637847
- clearLastPaintedRows();
637848
- applyHeightChange(0);
637849
- } else {
637850
- scheduleRedraw();
637851
- }
637852
- }
637853
- }
637854
- function getTuiTasksScope() {
637855
- return {
637856
- enabled: _enabled,
637857
- overlayActive: _scopeOverlayActive,
637858
- mainViewActive: _scopeMainViewActive,
637859
- neovimActive: _scopeNeovimActive,
637860
- pagerActive: _scopePagerActive,
637861
- visible: panelEffectivelyVisible()
637862
- };
637863
- }
637864
- function refreshTuiTasks() {
637865
- if (!_activeSessionId) return;
637866
- loadTodos();
637867
- scheduleRedraw();
637868
- }
637869
- function refreshTuiTasksSync() {
637870
- if (!_activeSessionId) return;
637871
- loadTodos();
637872
- if (!_enabled) return;
637873
- _redrawScheduled = false;
637874
- render();
637875
- }
637876
- function teardownTuiTasks() {
637877
- if (_watcher) {
637878
- try {
637879
- _watcher.close();
637880
- } catch {
637881
- }
637882
- _watcher = null;
637883
- }
637884
- _activeSessionId = null;
637885
- _lastTodos = [];
637886
- applyHeightChange(0);
637887
- }
637888
- function installWatcher() {
637889
- if (!_activeSessionId) return;
637890
- try {
637891
- _watcher = fsWatch3(todoDir2(), { persistent: false }, (_evt, fname) => {
637892
- if (!fname || !_activeSessionId) return;
637893
- const expected = `${_activeSessionId.replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`;
637894
- if (fname !== expected) return;
637895
- loadTodos();
637896
- scheduleRedraw();
637897
- });
637898
- } catch {
637899
- }
637900
- }
637901
- function loadTodos() {
637902
- if (!_activeSessionId) {
637903
- _lastTodos = [];
637904
- return;
637905
- }
637906
- try {
637907
- const fp = todoPath2(_activeSessionId);
637908
- if (!existsSync127(fp)) {
637909
- _lastTodos = [];
637910
- return;
637911
- }
637912
- const parsed = JSON.parse(readFileSync106(fp, "utf-8"));
637913
- _lastTodos = Array.isArray(parsed) ? parsed : [];
637914
- } catch {
637915
- _lastTodos = [];
637916
- }
637917
- }
637918
- function scheduleRedraw() {
637919
- if (_redrawScheduled || !_enabled) return;
637920
- _redrawScheduled = true;
637921
- setImmediate(() => {
637922
- _redrawScheduled = false;
637923
- render();
637924
- });
637925
- }
637926
- function computeTargetHeight() {
637927
- if (!panelEffectivelyVisible()) return 0;
637928
- if (!_lastTodos || _lastTodos.length === 0) return 0;
637929
- const allDone = _lastTodos.every((t2) => t2 && t2.status === "completed");
637930
- if (allDone) return 0;
637931
- const itemRows = selectPanelTodoRows(_lastTodos, MAX_VISIBLE_ROWS - 1).rowCount;
637932
- return 1 + itemRows;
637933
- }
637934
- function applyHeightChange(nextHeight) {
637935
- const changed = setTasksHeight(nextHeight);
637936
- if (changed) {
637937
- notifyLayoutResize();
637938
- }
637939
- if (_onResizeChange) {
637940
- try {
637941
- _onResizeChange(nextHeight);
637942
- } catch {
637943
- }
637944
- }
637945
- }
637946
- function fg2562(idx, fallback = -1) {
637947
- const n2 = idx < 0 ? fallback : idx;
637948
- return n2 < 0 ? "\x1B[39m" : `\x1B[38;5;${n2}m`;
637949
- }
637950
- function refreshTuiTasksThemeVars() {
637951
- BG = tuiBgSeq();
637952
- DIM_LABEL = fg2562(tuiTextDim(), 240);
637953
- ACCENT = tuiAccentFg();
637954
- DONE2 = fg2562(tuiTextDim(), 240);
637955
- PENDING = fg2562(tuiTextDim(), 240);
637956
- }
637957
- function statusToAnsi(status) {
637958
- switch (status) {
637959
- case "completed":
637960
- return { mark: "◉", color: DONE2 };
637961
- case "in_progress":
637962
- return { mark: "◐", color: ACCENT };
637963
- case "blocked":
637964
- return { mark: "◍", color: BLOCKED };
637965
- default:
637966
- return { mark: "○", color: PENDING };
637967
- }
637968
- }
637969
- function truncate2(s2, max) {
637970
- if (s2.length <= max) return s2.padEnd(max, " ");
637971
- return s2.slice(0, Math.max(0, max - 1)) + "…";
637972
- }
637973
- function stripAnsi2(s2) {
637974
- return s2.replace(/\x1B\[[0-9;]*[A-Za-z]/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B[()][A-Z0-9]/g, "").replace(/\x1B\[?\??[0-9;]*[a-zA-Z]/g, "").replace(/\x1B/g, "");
637975
- }
637976
- function visualLen(s2) {
637977
- return stripAnsi2(s2).length;
637978
- }
637979
- function buildTodoProgressBar(todos, maxWidth) {
637980
- if (maxWidth <= 0 || todos.length === 0) return "";
637981
- let cells = Math.min(todos.length, maxWidth);
637982
- const truncated = cells < todos.length;
637983
- const inIdx = todos.findIndex((t2) => t2.status === "in_progress");
637984
- let nextIdx = -1;
637985
- if (inIdx >= 0) {
637986
- nextIdx = todos.findIndex((t2, i2) => i2 > inIdx && t2.status !== "completed");
637987
- }
637988
- if (nextIdx < 0) nextIdx = todos.findIndex((t2) => t2.status === "pending");
637989
- const PEND = DIM_LABEL;
637990
- const INPROG = ACCENT;
637991
- const NEXT = ACCENT;
637992
- const DONE_Y = ACCENT;
637993
- let out = "";
637994
- for (let i2 = 0; i2 < cells; i2++) {
637995
- const t2 = todos[i2];
637996
- if (t2.status === "completed") {
637997
- out += `\x1B[1m${DONE_Y}█${RESET3}`;
637998
- } else if (i2 === inIdx) {
637999
- out += `${INPROG}▒${RESET3}`;
638000
- } else if (i2 === nextIdx && inIdx >= 0) {
638001
- out += `${NEXT}▒${RESET3}`;
638002
- } else {
638003
- out += `${PEND}░${RESET3}`;
638004
- }
638005
- }
638006
- if (truncated && maxWidth > 0) out += `${DIM_LABEL}…${RESET3}`;
638007
- return out;
638008
- }
638009
- function buildTodoTreeIndex(todos) {
638010
- const byParent = /* @__PURE__ */ new Map();
638011
- const byId = new Map(todos.map((t2) => [t2.id, t2]));
638012
- const roots = [];
638013
- for (const todo of todos) {
638014
- if (todo.parentId && byId.has(todo.parentId)) {
638015
- const arr = byParent.get(todo.parentId) ?? [];
638016
- arr.push(todo);
638017
- byParent.set(todo.parentId, arr);
638018
- } else {
638019
- roots.push(todo);
638020
- }
638021
- }
638022
- return { byId, byParent, roots };
638023
- }
638024
- function childLeafStats(todo, index) {
638025
- const children2 = index.byParent.get(todo.id) ?? [];
638026
- if (children2.length === 0) return void 0;
638027
- let completed = 0;
638028
- let total = 0;
638029
- const seen = /* @__PURE__ */ new Set();
638030
- const visit = (node) => {
638031
- if (seen.has(node.id)) return;
638032
- seen.add(node.id);
638033
- const nested = index.byParent.get(node.id) ?? [];
638034
- if (nested.length === 0) {
638035
- total++;
638036
- if (node.status === "completed") completed++;
638037
- return;
638038
- }
638039
- for (const child of nested) visit(child);
638040
- };
638041
- for (const child of children2) visit(child);
638042
- return { completed, total };
638043
- }
638044
- function displayStatusFor(todo, index, seen = /* @__PURE__ */ new Set()) {
638045
- if (seen.has(todo.id)) return todo.status;
638046
- seen.add(todo.id);
638047
- const children2 = index.byParent.get(todo.id) ?? [];
638048
- if (children2.length === 0) return todo.status;
638049
- const childStatuses = children2.map((child) => displayStatusFor(child, index, new Set(seen)));
638050
- if (childStatuses.some((status) => status === "blocked")) return "blocked";
638051
- if (childStatuses.some((status) => status === "in_progress")) return "in_progress";
638052
- if (childStatuses.every((status) => status === "completed")) return "completed";
638053
- if (todo.status === "completed") return "in_progress";
638054
- return todo.status;
638055
- }
638056
- function toDisplayTodo(todo, depth, index) {
638057
- return {
638058
- ...todo,
638059
- depth: Math.min(depth, 4),
638060
- displayStatus: displayStatusFor(todo, index),
638061
- childSummary: childLeafStats(todo, index)
638062
- };
638063
- }
638064
- function orderTodosForDisplay(todos) {
638065
- const index = buildTodoTreeIndex(todos);
638066
- const out = [];
638067
- const seen = /* @__PURE__ */ new Set();
638068
- const visit = (todo, depth) => {
638069
- if (seen.has(todo.id)) return;
638070
- seen.add(todo.id);
638071
- out.push(toDisplayTodo(todo, depth, index));
638072
- for (const child of index.byParent.get(todo.id) ?? []) {
638073
- visit(child, depth + 1);
638074
- }
638075
- };
638076
- for (const root of index.roots) visit(root, 0);
638077
- for (const todo of todos) visit(todo, 0);
638078
- return out;
638079
- }
638080
- function leafTodosForProgress(todos) {
638081
- const index = buildTodoTreeIndex(todos);
638082
- const leaves = todos.filter((todo) => (index.byParent.get(todo.id) ?? []).length === 0);
638083
- return leaves.length > 0 ? leaves : todos;
638084
- }
638085
- function activeDisplayIndex(displayTodos) {
638086
- const inProgressLeaf = displayTodos.findIndex(
638087
- (todo, index, all2) => todo.status === "in_progress" && !all2.some((candidate) => candidate.parentId === todo.id)
638088
- );
638089
- if (inProgressLeaf >= 0) return inProgressLeaf;
638090
- const inProgress = displayTodos.findIndex((todo) => todo.displayStatus === "in_progress");
638091
- if (inProgress >= 0) return inProgress;
638092
- const blocked = displayTodos.findIndex((todo) => todo.displayStatus === "blocked");
638093
- if (blocked >= 0) return blocked;
638094
- return displayTodos.findIndex((todo) => todo.displayStatus === "pending");
638095
- }
638096
- function selectFocusedTodoItems(todos, maxItems) {
638097
- const displayTodos = orderTodosForDisplay(todos);
638098
- if (maxItems <= 0) return [];
638099
- if (displayTodos.length <= maxItems) return displayTodos;
638100
- const activeIndex = activeDisplayIndex(displayTodos);
638101
- if (activeIndex < 0 || activeIndex < maxItems) return displayTodos.slice(0, maxItems);
638102
- const rawIndex = buildTodoTreeIndex(todos);
638103
- const displayById = new Map(displayTodos.map((todo) => [todo.id, todo]));
638104
- const selected = [];
638105
- const seen = /* @__PURE__ */ new Set();
638106
- const add3 = (todo) => {
638107
- if (!todo || selected.length >= maxItems || seen.has(todo.id)) return;
638108
- selected.push(todo);
638109
- seen.add(todo.id);
638110
- };
638111
- const active = displayTodos[activeIndex];
638112
- const ancestors = [];
638113
- let cursor = active;
638114
- while (cursor?.parentId && rawIndex.byId.has(cursor.parentId)) {
638115
- const parent = rawIndex.byId.get(cursor.parentId);
638116
- if (!parent) break;
638117
- const displayParent = displayById.get(parent.id);
638118
- if (displayParent) ancestors.unshift(displayParent);
638119
- cursor = parent;
638120
- }
638121
- for (const ancestor of ancestors) add3(ancestor);
638122
- const siblings = active.parentId ? rawIndex.byParent.get(active.parentId) ?? [] : rawIndex.roots;
638123
- const activeSiblingIndex = siblings.findIndex((todo) => todo.id === active.id);
638124
- if (activeSiblingIndex > 0) add3(displayById.get(siblings[activeSiblingIndex - 1].id));
638125
- add3(active);
638126
- for (let i2 = activeSiblingIndex + 1; i2 < siblings.length && selected.length < maxItems; i2++) {
638127
- add3(displayById.get(siblings[i2].id));
638128
- }
638129
- const activeChildren = rawIndex.byParent.get(active.id) ?? [];
638130
- for (const child of activeChildren) add3(displayById.get(child.id));
638131
- for (let i2 = activeIndex + 1; i2 < displayTodos.length && selected.length < maxItems; i2++) {
638132
- add3(displayTodos[i2]);
638133
- }
638134
- for (let i2 = activeIndex - 1; i2 >= 0 && selected.length < maxItems; i2--) {
638135
- add3(displayTodos[i2]);
638136
- }
638137
- return selected;
638138
- }
638139
- function selectPanelTodoRows(todos, maxRows) {
638140
- const displayTodos = orderTodosForDisplay(todos);
638141
- if (maxRows <= 0 || displayTodos.length === 0) {
638142
- return { items: [], omitted: displayTodos.length, rowCount: 0 };
638143
- }
638144
- if (displayTodos.length <= maxRows) {
638145
- return { items: displayTodos, omitted: 0, rowCount: displayTodos.length };
638146
- }
638147
- const itemBudget = Math.max(1, maxRows - 1);
638148
- const items = selectFocusedTodoItems(todos, itemBudget);
638149
- const omitted = Math.max(0, displayTodos.length - items.length);
638150
- return {
638151
- items,
638152
- omitted,
638153
- rowCount: Math.min(maxRows, items.length + (omitted > 0 ? 1 : 0))
638154
- };
638155
- }
638156
- function __testOrderTodosForDisplay(todos) {
638157
- return orderTodosForDisplay(todos);
638158
- }
638159
- function __testSelectPanelTodoRows(todos, maxRows) {
638160
- return selectPanelTodoRows(todos, maxRows);
638161
- }
638162
- function render() {
638163
- if (!_enabled) return;
638164
- if (!panelEffectivelyVisible()) {
638165
- clearLastPaintedRows();
638166
- applyHeightChange(0);
638167
- return;
638168
- }
638169
- const target = computeTargetHeight();
638170
- applyHeightChange(target);
638171
- if (target === 0) {
638172
- clearLastPaintedRows();
638173
- return;
638174
- }
638175
- const L = layout();
638176
- const cols = Math.max(20, termCols());
638177
- const progressTodos = leafTodosForProgress(_lastTodos);
638178
- const completed = progressTodos.filter((t2) => t2.status === "completed").length;
638179
- const total = progressTodos.length;
638180
- const headerColor = ACCENT;
638181
- const lines = [];
638182
- const headerPrefix = `tasks ${headerColor}${completed}/${total}${RESET3} `;
638183
- const headerPrefixWidth = visualLen(headerPrefix);
638184
- const maxBarWidth = Math.max(0, cols - 2 - headerPrefixWidth);
638185
- const progressBar = buildTodoProgressBar(progressTodos, maxBarWidth);
638186
- const headerText = `${headerPrefix}${progressBar}`;
638187
- lines.push(headerText);
638188
- const selection = selectPanelTodoRows(_lastTodos, MAX_VISIBLE_ROWS - 1);
638189
- const visible = selection.items;
638190
- for (const t2 of visible) {
638191
- const { mark, color } = statusToAnsi(t2.displayStatus);
638192
- const contentWidth = Math.max(4, cols - 8);
638193
- const indent2 = t2.depth > 0 ? `${" ".repeat(t2.depth)}- ` : "";
638194
- const childSummary = t2.childSummary && t2.childSummary.total > 0 ? ` [${t2.childSummary.completed}/${t2.childSummary.total}]` : "";
638195
- const contentText = indent2 + t2.content + childSummary + (t2.blocker ? ` (blocked: ${t2.blocker})` : "");
638196
- const truncated = truncate2(contentText, contentWidth);
638197
- lines.push(`${color}${mark}${RESET3} ${color}${truncated}${RESET3}`);
638198
- }
638199
- if (selection.omitted > 0) {
638200
- lines.push(`${DIM_LABEL}… +${selection.omitted} more${RESET3}`);
638201
- }
638202
- let out = HIDE + SAVE;
638203
- const newTop = L.tasksTop;
638204
- const newBottom = Math.min(L.tasksBottom, L.tasksTop + lines.length - 1);
638205
- const safeClearTop = L.headerBottom + 1;
638206
- const safeClearBottom = L.contentBottom;
638207
- if (_lastPaintedTop >= 0 && _lastPaintedBottom >= _lastPaintedTop) {
638208
- for (let row = _lastPaintedTop; row <= _lastPaintedBottom; row++) {
638209
- if (row >= newTop && row <= newBottom) continue;
638210
- if (row < safeClearTop || row > safeClearBottom) continue;
638211
- out += `\x1B[${row};1H${CLEAR_LINE}`;
638212
- }
638213
- }
638214
- for (let i2 = 0; i2 < lines.length; i2++) {
638215
- const row = L.tasksTop + i2;
638216
- if (row > L.tasksBottom) break;
638217
- out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET3}`;
638218
- }
638219
- out += RESTORE + SHOW;
638220
- try {
638221
- chromeWrite(out);
638222
- } catch {
638223
- }
638224
- _lastPaintedTop = newTop;
638225
- _lastPaintedBottom = newBottom;
638226
- }
638227
- function clearLastPaintedRows() {
638228
- if (_lastPaintedTop < 0 || _lastPaintedBottom < _lastPaintedTop) return;
638229
- const L = layout();
638230
- const safeTop = L.headerBottom + 1;
638231
- const safeBottom = Math.max(L.contentBottom, safeTop - 1);
638232
- let out = HIDE + SAVE;
638233
- for (let row = _lastPaintedTop; row <= _lastPaintedBottom; row++) {
638234
- if (row < safeTop || row > safeBottom) continue;
638235
- out += `\x1B[${row};1H${CLEAR_LINE}`;
638236
- }
638237
- out += RESTORE + SHOW;
638238
- try {
638239
- chromeWrite(out);
638240
- } catch {
638241
- }
638242
- _lastPaintedTop = -1;
638243
- _lastPaintedBottom = -1;
638244
- }
638245
- var chromeWrite, _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, _scopeOverlayActive, _scopeMainViewActive, _scopeNeovimActive, _scopePagerActive, _lastPaintedTop, _lastPaintedBottom, MAX_VISIBLE_ROWS, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET3, BG, DIM_LABEL, ACCENT, DONE2, PENDING, BLOCKED;
638246
- var init_tui_tasks_renderer = __esm({
638247
- "packages/cli/src/tui/tui-tasks-renderer.ts"() {
638248
- "use strict";
638249
- init_layout2();
638250
- init_theme();
638251
- chromeWrite = ((data) => {
638252
- process.stdout.write(data);
638253
- });
638254
- _activeSessionId = null;
638255
- _watcher = null;
638256
- _lastTodos = [];
638257
- _enabled = true;
638258
- _redrawScheduled = false;
638259
- _onResizeChange = null;
638260
- _scopeOverlayActive = false;
638261
- _scopeMainViewActive = true;
638262
- _scopeNeovimActive = false;
638263
- _scopePagerActive = false;
638264
- _lastPaintedTop = -1;
638265
- _lastPaintedBottom = -1;
638266
- MAX_VISIBLE_ROWS = 8;
638267
- SAVE = "\x1B[s";
638268
- RESTORE = "\x1B[u";
638269
- HIDE = "\x1B[?25l";
638270
- SHOW = "\x1B[?25h";
638271
- CLEAR_LINE = "\x1B[2K";
638272
- RESET3 = "\x1B[0m";
638273
- BG = tuiBgSeq();
638274
- DIM_LABEL = "";
638275
- ACCENT = "";
638276
- DONE2 = "";
638277
- PENDING = "";
638278
- BLOCKED = "\x1B[38;5;196m";
638279
- refreshTuiTasksThemeVars();
638280
- }
638281
- });
638282
-
638283
638650
  // packages/cli/src/tui/status-bar.ts
638284
638651
  var status_bar_exports = {};
638285
638652
  __export(status_bar_exports, {
@@ -638315,7 +638682,7 @@ function stripSubAgentPrefix(label) {
638315
638682
  const stripped = label.replace(/^\s*sub[-\s]?agents?\b[\s:_–—-]*/i, "").trim();
638316
638683
  return stripped.length > 0 ? stripped : label.trim();
638317
638684
  }
638318
- function xterm256ToRgb(i2) {
638685
+ function xterm256ToRgb2(i2) {
638319
638686
  if (i2 >= 232) {
638320
638687
  const v = 8 + (i2 - 232) * 10;
638321
638688
  return [v, v, v];
@@ -638350,7 +638717,7 @@ function xterm256ToRgb(i2) {
638350
638717
  return base3[i2] ?? [0, 0, 0];
638351
638718
  }
638352
638719
  function contrastTextColor(colorIndex) {
638353
- const [r2, g, b] = xterm256ToRgb(colorIndex);
638720
+ const [r2, g, b] = xterm256ToRgb2(colorIndex);
638354
638721
  const luma = 0.299 * r2 + 0.587 * g + 0.114 * b;
638355
638722
  return luma >= 140 ? 16 : 231;
638356
638723
  }
@@ -638411,6 +638778,7 @@ var init_status_bar = __esm({
638411
638778
  "use strict";
638412
638779
  init_render();
638413
638780
  init_stageIndicator();
638781
+ init_tui_tasks_renderer();
638414
638782
  init_braille_spinner();
638415
638783
  init_project_context();
638416
638784
  init_dist8();
@@ -640000,6 +640368,12 @@ var init_status_bar = __esm({
640000
640368
  this._metricsCollector.startLocal((m2) => {
640001
640369
  this._localUnifiedMetrics = m2;
640002
640370
  this._unifiedMetrics = m2;
640371
+ const hw = m2.hardware;
640372
+ if (hw) {
640373
+ this._gpuName = hw.gpuName || "";
640374
+ this._vramTotal = hw.vramTotalMB || 0;
640375
+ this._vramUsed = hw.vramUsedMB || 0;
640376
+ }
640003
640377
  if (this._remoteUnifiedMetrics) {
640004
640378
  this._remoteUnifiedMetrics = {
640005
640379
  ...this._remoteUnifiedMetrics,
@@ -640850,6 +641224,17 @@ var init_status_bar = __esm({
640850
641224
  if (viewId) this.switchToView(viewId);
640851
641225
  return;
640852
641226
  }
641227
+ if (type === "press") {
641228
+ const Lt = layout();
641229
+ if (Lt.tasksTop > 0 && row >= Lt.tasksTop && row <= Lt.tasksBottom) {
641230
+ let consumed = false;
641231
+ try {
641232
+ consumed = handleTuiTasksClick(row);
641233
+ } catch {
641234
+ }
641235
+ if (consumed) return;
641236
+ }
641237
+ }
640853
641238
  if (type === "press" && this.handleFooterInputClick(row, col)) return;
640854
641239
  const L = layout();
640855
641240
  const inContent = row >= this.scrollRegionTop && row <= L.contentBottom;
@@ -641135,8 +641520,8 @@ var init_status_bar = __esm({
641135
641520
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
641136
641521
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
641137
641522
  buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
641138
- buf += `${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
641139
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
641523
+ buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
641524
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
641140
641525
  }
641141
641526
  buf += this.buildEnhanceSegment(
641142
641527
  w,
@@ -642155,11 +642540,11 @@ ${CONTENT_BG_SEQ}`);
642155
642540
  * on the metrics row, beside the scroll-down / copy-tui controls. The block
642156
642541
  * is a fixed-width cell so it never bleeds into the metrics sections.
642157
642542
  */
642158
- buildStageBlock() {
642543
+ buildStageBlock(maxWidth) {
642159
642544
  const { stage: stage2, detail } = getStage();
642160
- const termWidth = getTermWidth();
642545
+ const needed = stageBlockNeededWidth(stage2, detail);
642161
642546
  const reserved = clampGradientWidth(
642162
- Math.min(28, Math.max(12, Math.floor(termWidth * 0.22)))
642547
+ Math.max(12, Math.min(needed, maxWidth))
642163
642548
  );
642164
642549
  const truecolor = supportsTruecolor();
642165
642550
  this._stagePhase = (this._stagePhase + 6) % 360;
@@ -642175,7 +642560,6 @@ ${CONTENT_BG_SEQ}`);
642175
642560
  ) + " ";
642176
642561
  }
642177
642562
  buildMetricsLine() {
642178
- const stageBlock = this.buildStageBlock();
642179
642563
  const m2 = this.metrics;
642180
642564
  const termWidth = getTermWidth();
642181
642565
  const uptime2 = this.formatUptime();
@@ -642254,8 +642638,11 @@ ${CONTENT_BG_SEQ}`);
642254
642638
  const pageIdx = this._debugPanelPage + 2;
642255
642639
  const indicator = `\x1B[38;5;240m[${pageIdx > 5 ? 1 : pageIdx}/${pageTotal}]\x1B[0m `;
642256
642640
  const fullRight = pageLabel + rightSide + indicator + arrow;
642257
- const stageW = stripAnsi(stageBlock).length;
642258
642641
  const rightW = stripAnsi(fullRight).length;
642642
+ const stageBlock = this.buildStageBlock(
642643
+ Math.max(12, termWidth - rightW - 2)
642644
+ );
642645
+ const stageW = stripAnsi(stageBlock).length;
642259
642646
  const padNeeded = termWidth - stageW - rightW - 1;
642260
642647
  const gap = padNeeded > 0 ? " ".repeat(padNeeded) : " ";
642261
642648
  return (stageBlock + gap + fullRight).replace(
@@ -642325,23 +642712,70 @@ ${CONTENT_BG_SEQ}`);
642325
642712
  const seg = this.enhanceSegEnabled(w) ? ENHANCE_SEG_INNER + 1 : 0;
642326
642713
  return Math.max(1, w - this.promptWidth - 2 - seg);
642327
642714
  }
642715
+ // ── stage-matched border gradient ────────────────────────────────────
642716
+ /** True when the input-box border should flow with the stage gradient:
642717
+ * a run is active (sweeping stage) and the terminal supports truecolor. */
642718
+ stageBorderActive() {
642719
+ return supportsTruecolor() && isSweepingStage(getStage().stage);
642720
+ }
642721
+ /** Paint a raw run of border glyphs with the current stage's gradient band
642722
+ * (same hue range as the stage indicator block, so the box edges match
642723
+ * the stage color). Colors in 4-column segments to keep the footer hot
642724
+ * path cheap. Falls back to plain BOX_FG when idle / no truecolor. */
642725
+ paintInputBorder(glyphs, startCol = 0) {
642726
+ if (!this.stageBorderActive()) {
642727
+ return `${BOX_FG}${glyphs}${RESET4}`;
642728
+ }
642729
+ const { stage: stage2 } = getStage();
642730
+ const SEG = 4;
642731
+ let out = "";
642732
+ for (let i2 = 0; i2 < glyphs.length; i2 += SEG) {
642733
+ const [r2, g, b] = stageGradientRgb(
642734
+ stage2,
642735
+ Math.floor((startCol + i2) / SEG),
642736
+ this._stagePhase
642737
+ );
642738
+ out += `\x1B[38;2;${r2};${g};${b}m${glyphs.slice(i2, i2 + SEG)}`;
642739
+ }
642740
+ return out + RESET4;
642741
+ }
642742
+ /** Color sequence for a single vertical border bar at absolute column
642743
+ * `col` (1-based) — matches what paintInputBorder gives that column. */
642744
+ borderVSeq(col) {
642745
+ if (!this.stageBorderActive()) return BOX_FG;
642746
+ const { stage: stage2 } = getStage();
642747
+ const [r2, g, b] = stageGradientRgb(
642748
+ stage2,
642749
+ Math.floor(Math.max(0, col - 1) / 4),
642750
+ this._stagePhase
642751
+ );
642752
+ return `\x1B[38;2;${r2};${g};${b}m`;
642753
+ }
642328
642754
  /** Box top border with an optional ┬ carving out the enhance segment. */
642329
642755
  buildInputBoxTop(w) {
642330
642756
  if (!this.enhanceSegEnabled(w)) {
642331
- return `${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, w - 2))}${BOX_TR3}${RESET4}`;
642757
+ return this.paintInputBorder(
642758
+ `${BOX_TL3}${BOX_H3.repeat(Math.max(0, w - 2))}${BOX_TR3}`
642759
+ );
642332
642760
  }
642333
642761
  const dividerCol = this.enhanceDividerCol(w);
642334
642762
  const leftDashes = Math.max(0, dividerCol - 2);
642335
- return `${BOX_FG}${BOX_TL3}${BOX_H3.repeat(leftDashes)}${BOX_TJ}${BOX_H3.repeat(ENHANCE_SEG_INNER)}${BOX_TR3}${RESET4}`;
642763
+ return this.paintInputBorder(
642764
+ `${BOX_TL3}${BOX_H3.repeat(leftDashes)}${BOX_TJ}${BOX_H3.repeat(ENHANCE_SEG_INNER)}${BOX_TR3}`
642765
+ );
642336
642766
  }
642337
642767
  /** Box bottom border with an optional ┴ closing the enhance segment. */
642338
642768
  buildInputBoxBottom(w) {
642339
642769
  if (!this.enhanceSegEnabled(w)) {
642340
- return `${BOX_FG}${BOX_BL3}${BOX_H3.repeat(Math.max(0, w - 2))}${BOX_BR3}${RESET4}`;
642770
+ return this.paintInputBorder(
642771
+ `${BOX_BL3}${BOX_H3.repeat(Math.max(0, w - 2))}${BOX_BR3}`
642772
+ );
642341
642773
  }
642342
642774
  const dividerCol = this.enhanceDividerCol(w);
642343
642775
  const leftDashes = Math.max(0, dividerCol - 2);
642344
- return `${BOX_FG}${BOX_BL3}${BOX_H3.repeat(leftDashes)}${BOX_BJ}${BOX_H3.repeat(ENHANCE_SEG_INNER)}${BOX_BR3}${RESET4}`;
642776
+ return this.paintInputBorder(
642777
+ `${BOX_BL3}${BOX_H3.repeat(leftDashes)}${BOX_BJ}${BOX_H3.repeat(ENHANCE_SEG_INNER)}${BOX_BR3}`
642778
+ );
642345
642779
  }
642346
642780
  /**
642347
642781
  * Draw the │ divider down each input row plus the enhance/confirm button in
@@ -642361,7 +642795,7 @@ ${CONTENT_BG_SEQ}`);
642361
642795
  let buf = "";
642362
642796
  for (let i2 = 0; i2 < rowCount; i2++) {
642363
642797
  const row = firstInputRow + i2;
642364
- buf += `\x1B[${row};${dividerCol}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
642798
+ buf += `\x1B[${row};${dividerCol}H${this.borderVSeq(dividerCol)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
642365
642799
  if (i2 > 0) {
642366
642800
  buf += `\x1B[${row};${cellStart}H${PANEL_BG_SEQ}${" ".repeat(ENHANCE_SEG_INNER)}`;
642367
642801
  }
@@ -642816,9 +643250,9 @@ ${CONTENT_BG_SEQ}`);
642816
643250
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
642817
643251
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
642818
643252
  buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
642819
- buf += `${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
643253
+ buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
642820
643254
  buf += `${PANEL_BG_SEQ}\x1B[K`;
642821
- buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643255
+ buf += `\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
642822
643256
  }
642823
643257
  buf += this.buildEnhanceSegment(
642824
643258
  w,
@@ -642835,10 +643269,10 @@ ${CONTENT_BG_SEQ}`);
642835
643269
  const fg2 = isHighlighted ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
642836
643270
  const slash = isHighlighted ? `\x1B[38;5;245m` : `\x1B[38;5;${TEXT_DIM}m`;
642837
643271
  const marker = isHighlighted ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
642838
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643272
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
642839
643273
  buf += `${bg} ${marker}${slash}/${fg2}${cmd}`;
642840
643274
  buf += `${PANEL_BG_SEQ}\x1B[K`;
642841
- buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643275
+ buf += `\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
642842
643276
  }
642843
643277
  const suggestBottomRow = pos.suggestStartRow + this._suggestions.length;
642844
643278
  buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
@@ -642890,8 +643324,8 @@ ${CONTENT_BG_SEQ}`);
642890
643324
  const isHl = si === this._suggestIndex;
642891
643325
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
642892
643326
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
642893
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
642894
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}`;
643327
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
643328
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
642895
643329
  }
642896
643330
  buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
642897
643331
  } else {
@@ -642954,7 +643388,7 @@ ${CONTENT_BG_SEQ}`);
642954
643388
  const row = pos.inputStartRow + 1 + i2;
642955
643389
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
642956
643390
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
642957
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}`;
643391
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
642958
643392
  }
642959
643393
  buf += this.buildEnhanceSegment(
642960
643394
  w,
@@ -642969,9 +643403,9 @@ ${CONTENT_BG_SEQ}`);
642969
643403
  const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
642970
643404
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
642971
643405
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
642972
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643406
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
642973
643407
  buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
642974
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}`;
643408
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
642975
643409
  }
642976
643410
  }
642977
643411
  buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
@@ -642997,9 +643431,9 @@ ${CONTENT_BG_SEQ}`);
642997
643431
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
642998
643432
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
642999
643433
  buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
643000
- buf += `${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
643434
+ buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
643001
643435
  buf += `${PANEL_BG_SEQ}\x1B[K`;
643002
- buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643436
+ buf += `\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643003
643437
  }
643004
643438
  buf += this.buildEnhanceSegment(
643005
643439
  w,
@@ -643014,9 +643448,9 @@ ${CONTENT_BG_SEQ}`);
643014
643448
  const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
643015
643449
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
643016
643450
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
643017
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643451
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643018
643452
  buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
643019
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643453
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
643020
643454
  }
643021
643455
  }
643022
643456
  buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
@@ -734740,11 +735174,11 @@ ${task}` : task,
734740
735174
  return;
734741
735175
  }
734742
735176
  const j = JSON.parse(result2.body);
734743
- const responseText = j?.choices?.[0]?.text ?? "";
735177
+ const responseText2 = j?.choices?.[0]?.text ?? "";
734744
735178
  jsonResponse(res, 200, {
734745
735179
  model: model.replace(/^[a-z]+\//, ""),
734746
735180
  created_at: createdAt,
734747
- response: responseText,
735181
+ response: responseText2,
734748
735182
  done: true,
734749
735183
  done_reason: "stop"
734750
735184
  });
@@ -746253,107 +746687,19 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
746253
746687
  }
746254
746688
  };
746255
746689
  }
746256
- function extractEnhancedPrompt(raw) {
746257
- const text2 = raw.trim();
746258
- if (!text2) return null;
746259
- const tryParse = (candidate) => {
746260
- try {
746261
- const obj = JSON.parse(candidate);
746262
- const v = obj["enhancedPrompt"] ?? obj["enhanced_prompt"] ?? obj["prompt"] ?? obj["result"];
746263
- return typeof v === "string" && v.trim() ? v : null;
746264
- } catch {
746265
- return null;
746266
- }
746267
- };
746268
- const direct = tryParse(text2);
746269
- if (direct) return direct;
746270
- const fenced = text2.match(/```(?:json)?\s*([\s\S]*?)```/i);
746271
- if (fenced?.[1]) {
746272
- const f2 = tryParse(fenced[1].trim());
746273
- if (f2) return f2;
746274
- }
746275
- const brace = text2.match(/\{[\s\S]*\}/);
746276
- if (brace?.[0]) {
746277
- const b = tryParse(brace[0]);
746278
- if (b) return b;
746279
- }
746280
- const keyed = text2.match(/"enhanced_?[Pp]rompt"\s*:\s*"((?:[^"\\]|\\.)*)"/);
746281
- if (keyed?.[1]) {
746282
- try {
746283
- return JSON.parse('"' + keyed[1] + '"');
746284
- } catch {
746285
- return keyed[1];
746286
- }
746287
- }
746288
- if (!text2.startsWith("{") && !text2.startsWith("[")) return text2;
746289
- return null;
746290
- }
746291
- async function enhancePromptViaInference(seed, backend, ctx3) {
746292
- const seedText = seed.trim();
746293
- if (!seedText) return null;
746294
- const recent = ctx3.recentHistory.filter((h) => h && h.trim()).slice(0, 5).map((h, i2) => ` ${i2 + 1}. ${h.trim().slice(0, 240)}`).join("\n");
746690
+ async function enhancePromptViaInference2(seed, backend, ctx3) {
746295
746691
  let runtimeCtx = "";
746296
746692
  try {
746297
746693
  runtimeCtx = buildConversationRuntimeContext(/* @__PURE__ */ new Date(), ctx3.repoRoot);
746298
746694
  } catch {
746299
746695
  runtimeCtx = "";
746300
746696
  }
746301
- const userPrompt = [
746302
- "Expand the SEED PROMPT below into a comprehensive, precise, self-contained instruction set for an agentic coding assistant.",
746303
- "Preserve the user's original intent exactly. Do NOT answer or solve it, do NOT invent unrelated scope.",
746304
- "Clarify the goal, surface implied requirements, relevant constraints, edge cases, and concrete acceptance criteria.",
746305
- "Fold in only the session context that is actually relevant. Keep it phrased as an instruction in the user's voice.",
746306
- "Return no preamble and no meta-commentary about the prompt itself.",
746307
- ctx3.activeGoal ? `
746308
- Task currently in progress: ${ctx3.activeGoal.slice(0, 400)}` : "",
746309
- recent ? `
746310
- Recent prompts this session (newest first):
746311
- ${recent}` : "",
746312
- runtimeCtx ? `
746313
- Session/runtime context:
746314
- ${runtimeCtx}` : "",
746315
- `
746316
- SEED PROMPT:
746317
- ${seedText}`
746318
- ].filter(Boolean).join("\n");
746319
- try {
746320
- const messages2 = [
746321
- {
746322
- role: "system",
746323
- content: `You are a prompt-expansion engine. You rewrite a user's short seed prompt into a richer, unambiguous instruction that fully captures their intent. Return strict JSON only: {"enhancedPrompt": string}.`
746324
- },
746325
- { role: "user", content: userPrompt }
746326
- ];
746327
- let resp;
746328
- try {
746329
- resp = await backend.chatCompletion({
746330
- messages: messages2,
746331
- tools: [],
746332
- temperature: 0.4,
746333
- maxTokens: 1400,
746334
- timeoutMs: 6e4,
746335
- think: false,
746336
- responseFormat: { type: "json_object" }
746337
- });
746338
- } catch {
746339
- resp = await backend.chatCompletion({
746340
- messages: messages2,
746341
- tools: [],
746342
- temperature: 0.4,
746343
- maxTokens: 1400,
746344
- timeoutMs: 6e4,
746345
- think: false
746346
- });
746347
- }
746348
- const rawContent2 = resp.choices?.[0]?.message?.content ?? "";
746349
- if (!rawContent2) return null;
746350
- const enhanced = extractEnhancedPrompt(rawContent2);
746351
- if (!enhanced) return null;
746352
- const clean5 = enhanced.trim();
746353
- return clean5 && clean5 !== seedText ? clean5 : null;
746354
- } catch {
746355
- return null;
746356
- }
746697
+ return enhancePromptViaInference(seed, backend, {
746698
+ repoRoot: ctx3.repoRoot,
746699
+ recentHistory: ctx3.recentHistory,
746700
+ activeGoal: ctx3.activeGoal,
746701
+ runtimeContext: runtimeCtx
746702
+ });
746357
746703
  }
746358
746704
  async function startInteractive(config, repoPath2) {
746359
746705
  const repoRoot = resolve74(repoPath2 ?? cwd());
@@ -747952,7 +748298,7 @@ This is an independent background session started from /background.`
747952
748298
  } catch {
747953
748299
  return null;
747954
748300
  }
747955
- return enhancePromptViaInference(seedPrompt, enhanceBackend, {
748301
+ return enhancePromptViaInference2(seedPrompt, enhanceBackend, {
747956
748302
  repoRoot,
747957
748303
  recentHistory: savedHistory,
747958
748304
  activeGoal: activeTask ? lastSubmittedPrompt : void 0
@@ -752983,6 +753329,7 @@ var init_interactive = __esm({
752983
753329
  init_visual_sensor_guidance();
752984
753330
  init_live_sensors();
752985
753331
  init_conversation_context();
753332
+ init_prompt_enhance();
752986
753333
  init_dist8();
752987
753334
  init_dist8();
752988
753335
  init_dist8();
@@ -753045,6 +753392,7 @@ var init_interactive = __esm({
753045
753392
  init_neovim_mode();
753046
753393
  init_task_manager_singleton();
753047
753394
  init_tui_tasks_renderer();
753395
+ init_prompt_enhance();
753048
753396
  NEXUS_DIRECTORY_ORIGIN3 = (process.env["OMNIUS_NEXUS_DIRECTORY_ORIGIN"] || process.env["OMNIUS_NEXUS_SIGNALING_SERVER"] || "https://openagents.nexus").replace(/\/+$/, "");
753049
753397
  NEXUS_AGENT_DIRECTORY_URL = `${NEXUS_DIRECTORY_ORIGIN3}/api/v1/directory`;
753050
753398
  localOllamaModelCache = null;