dsh-codebase-chat 0.25.3 → 0.25.5

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/cli.js CHANGED
@@ -1623,6 +1623,10 @@ function formatHealthReport(r, lang = "fr") {
1623
1623
  };
1624
1624
  const out = [];
1625
1625
  out.push(`== ${t2.title} \u2014 ${basename(r.projectPath)} ==`);
1626
+ if (r.analyzedFiles === 0) {
1627
+ out.push(lang === "en" ? "No code files detected in this project \u2014 check the path or your .codebase-chat.json ignore rules." : "Aucun fichier de code d\xE9tect\xE9 dans ce projet \u2014 v\xE9rifie le chemin ou les r\xE8gles ignore de .codebase-chat.json.");
1628
+ return out.join("\n");
1629
+ }
1626
1630
  out.push(`${t2.score}: ${r.score}/100 (${r.grade}) \xB7 ${r.analyzedFiles} ${t2.files} \xB7 ${r.importEdges} ${t2.edges}`);
1627
1631
  out.push("");
1628
1632
  out.push(`\u25CF ${t2.cycles} (${r.cycles.length})`);
@@ -2584,13 +2588,42 @@ async function callLocalLlm(prompt, lang = "fr") {
2584
2588
  contextSequence: context.getSequence(),
2585
2589
  systemPrompt: lang === "en" ? "You are a senior codebase analyst. Be precise and cite files with [source: path:line]." : "Tu es un analyste codebase senior. Sois precis et cite les fichiers avec [source: chemin:ligne]."
2586
2590
  });
2587
- return await session.prompt(prompt, { temperature: 0.2, maxTokens: LOCAL_MAX_TOKENS });
2591
+ return await session.prompt(prompt, {
2592
+ temperature: 0.2,
2593
+ maxTokens: LOCAL_MAX_TOKENS,
2594
+ // Small models degenerate into loops at low temperature — penalize
2595
+ // repeated tokens so the answer moves forward instead of echoing.
2596
+ repeatPenalty: { lastTokens: 128, penalty: 1.2, penalizeNewLine: false }
2597
+ });
2588
2598
  } finally {
2589
2599
  await context.dispose();
2590
2600
  }
2591
2601
  }
2592
2602
 
2593
2603
  // src/cli.ts
2604
+ var ANSI = { reset: "\x1B[0m", bold: "\x1B[1m", dim: "\x1B[2m", cyan: "\x1B[36m", yellow: "\x1B[33m", magenta: "\x1B[35m", green: "\x1B[32m" };
2605
+ function renderAnswerTerminal(md) {
2606
+ let inCode = false;
2607
+ const inline = (s) => s.replace(/\*\*([^*]+)\*\*/g, `${ANSI.bold}$1${ANSI.reset}`).replace(/`([^`]+)`/g, `${ANSI.cyan}$1${ANSI.reset}`).replace(/\[source: ([^\]]+)\]/g, `${ANSI.dim}${ANSI.cyan}[source: $1]${ANSI.reset}`);
2608
+ return md.split("\n").map((line) => {
2609
+ if (/^\s*```/.test(line)) {
2610
+ inCode = !inCode;
2611
+ return `${ANSI.dim} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${ANSI.reset}`;
2612
+ }
2613
+ if (inCode) return `${ANSI.dim} ${line}${ANSI.reset}`;
2614
+ const h = line.match(/^(#{1,6})\s+(.*)/);
2615
+ if (h) {
2616
+ const color = h[1].length <= 2 ? `${ANSI.bold}${ANSI.magenta}` : `${ANSI.bold}${ANSI.yellow}`;
2617
+ return `
2618
+ ${color}${h[2]}${ANSI.reset}`;
2619
+ }
2620
+ const bullet = line.match(/^(\s*)([-*•]|\d+\.)\s+(.*)/);
2621
+ if (bullet) return `${bullet[1]}${ANSI.cyan}${bullet[2]}${ANSI.reset} ${inline(bullet[3])}`;
2622
+ if (/^\s*>/.test(line)) return `${ANSI.dim}${ANSI.green}\u2502${ANSI.reset}${ANSI.dim} ${inline(line.replace(/^\s*>\s?/, ""))}${ANSI.reset}`;
2623
+ if (/^\s*(---+|\*\*\*+)\s*$/.test(line)) return `${ANSI.dim}${"\u2500".repeat(60)}${ANSI.reset}`;
2624
+ return inline(line);
2625
+ }).join("\n");
2626
+ }
2594
2627
  var ExitSignal = class {
2595
2628
  constructor(code) {
2596
2629
  this.code = code;
@@ -2813,7 +2846,8 @@ ${lang === "en" ? "Answer" : "R\xE9ponse"} :` : buildToolPrompt(tool, {
2813
2846
  }
2814
2847
  if (values.local || isLocalLlmEnabled()) {
2815
2848
  console.error(lang === "en" ? "Answering with the embedded local model (first run downloads ~1 GB)..." : "R\xE9ponse via le mod\xE8le local embarqu\xE9 (premier lancement : ~1 Go de t\xE9l\xE9chargement)...");
2816
- console.log(await callLocalLlm(prompt, lang));
2849
+ const answer = await callLocalLlm(prompt, lang);
2850
+ console.log(process.stdout.isTTY ? renderAnswerTerminal(answer) : answer);
2817
2851
  exit(0);
2818
2852
  }
2819
2853
  if (values.call) {
@@ -2844,7 +2878,8 @@ ${lang === "en" ? "Answer" : "R\xE9ponse"} :` : buildToolPrompt(tool, {
2844
2878
  exit(1);
2845
2879
  }
2846
2880
  const data = await res.json();
2847
- console.log(data.choices?.[0]?.message?.content || "");
2881
+ const answer = data.choices?.[0]?.message?.content || "";
2882
+ console.log(process.stdout.isTTY ? renderAnswerTerminal(answer) : answer);
2848
2883
  exit(0);
2849
2884
  }
2850
2885
  console.log(prompt);
@@ -2869,7 +2904,7 @@ ${lang === "en" ? "Answer" : "R\xE9ponse"} :` : buildToolPrompt(tool, {
2869
2904
  exit(0);
2870
2905
  }
2871
2906
  printHelp();
2872
- exit(1);
2907
+ exit(0);
2873
2908
  }
2874
2909
  main().catch((err) => {
2875
2910
  disposeTreeSitter();