dsh-codebase-chat 0.27.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/dist/cli.js +10 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,13 @@
|
|
|
22
22
|
|
|
23
23
|
<br>
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
dsh plugin --profile web add dsh-codebase-chat
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
or as a standalone MCP server / CLI:
|
|
26
32
|
|
|
27
33
|
```bash
|
|
28
34
|
npx dsh-codebase-chat-mcp setup
|
|
@@ -39,7 +45,9 @@ Other paths — DeepSeek Harness plugin · CLI · from source · manual config:
|
|
|
39
45
|
<em>Real MCP session on a real 422-file codebase — <code>codebase_health</code> finds 324 circular deps, <code>codebase_chat</code> answers with <code>[source: file:line]</code> receipts · <a href="docs/assets/demo-power.gif">PR review (--diff + --watch)</a> · <a href="docs/assets/demo.gif">CLI tour</a> · <a href="docs/assets/demo-mcp.gif">MCP stdio</a> · <a href="docs/assets/demo-fr.gif">French mode</a></em>
|
|
40
46
|
</p>
|
|
41
47
|
|
|
42
|
-
##
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
_What a real session looks like_ —
|
|
43
51
|
|
|
44
52
|
Run on this repository — the exact text the tools return:
|
|
45
53
|
|
package/dist/cli.js
CHANGED
|
@@ -2984,7 +2984,7 @@ async function missingDeps(abs, fileTexts, pkg, indexPaths) {
|
|
|
2984
2984
|
const missing = /* @__PURE__ */ new Set();
|
|
2985
2985
|
for (const spec of importedPackages(fileTexts)) {
|
|
2986
2986
|
const root = pkgRoot(spec);
|
|
2987
|
-
if (!NODE_BUILTINS.has(root) && !declared.has(root)) missing.add(root);
|
|
2987
|
+
if (!NODE_BUILTINS.has(root) && !declared.has(root) && !root.startsWith("@/") && !root.startsWith("~/")) missing.add(root);
|
|
2988
2988
|
}
|
|
2989
2989
|
return [...missing].sort();
|
|
2990
2990
|
}
|
|
@@ -3430,7 +3430,8 @@ async function buildDeterministicReport(projectPath, lang = "fr") {
|
|
|
3430
3430
|
out.push(`- ${docCov.documented}/${docCov.total} ${en ? "exports documented" : "exports document\xE9s"} (${docPct}% ${t2.docCov})`);
|
|
3431
3431
|
if (git2) out.push(`- ${git2.commits} ${t2.gitCommits} \xB7 ${git2.authors.size} ${en ? "author(s)" : "auteur(s)"} \xB7 ${t2.gitLast} : ${git2.lastDate}`);
|
|
3432
3432
|
out.push("");
|
|
3433
|
-
|
|
3433
|
+
let secN = 2;
|
|
3434
|
+
out.push(`## ${secN++}. ${t2.stack}`);
|
|
3434
3435
|
if (pkg.name) out.push(`- **${en ? "Package" : "Package"}** : \`${pkg.name}${pkg.version ? `@${pkg.version}` : ""}\``);
|
|
3435
3436
|
if (langs.length) out.push(`- **${t2.lang}** : ${langs.map(([l, n]) => `${l} (${n})`).join(", ")}`);
|
|
3436
3437
|
if (deps.length) out.push(`- **${t2.deps}** (${deps.length}) : ${deps.slice(0, 12).map((d) => `\`${d}\``).join(", ")}${deps.length > 12 ? " \u2026" : ""}`);
|
|
@@ -3455,7 +3456,7 @@ async function buildDeterministicReport(projectPath, lang = "fr") {
|
|
|
3455
3456
|
out.push(`- **${t2.readmeTitle}** : ${t2.readmeInstall} ${ok(readme.install)} \xB7 ${t2.readmeUsage} ${ok(readme.usage)} \xB7 ${readme.codeBlocks} ${t2.readmeCode} \xB7 ${readme.badges} ${t2.readmeBadges}`);
|
|
3456
3457
|
}
|
|
3457
3458
|
out.push("");
|
|
3458
|
-
out.push(`##
|
|
3459
|
+
out.push(`## ${secN++}. ${t2.arch}`);
|
|
3459
3460
|
if (hubs.length) {
|
|
3460
3461
|
out.push(`**${t2.hubs}** :`, "");
|
|
3461
3462
|
for (const [f, n] of hubs) out.push(`- \`${f}\` \u2190 ${n} ${en ? "importers" : "importeurs"}`);
|
|
@@ -3492,7 +3493,7 @@ async function buildDeterministicReport(projectPath, lang = "fr") {
|
|
|
3492
3493
|
out.push("");
|
|
3493
3494
|
}
|
|
3494
3495
|
if (git2) {
|
|
3495
|
-
out.push(`##
|
|
3496
|
+
out.push(`## ${secN++}. ${t2.gitTitle}`, "");
|
|
3496
3497
|
const topAuthors = [...git2.authors.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([a, n]) => `${a} (${n})`).join(", ");
|
|
3497
3498
|
const soloCount = [...git2.fileAuthors.values()].filter((a) => a.size === 1).length;
|
|
3498
3499
|
out.push(`- ${git2.commits} ${t2.gitCommits} \xB7 **${t2.gitAuthors}** : ${topAuthors}`);
|
|
@@ -3532,7 +3533,7 @@ async function buildDeterministicReport(projectPath, lang = "fr") {
|
|
|
3532
3533
|
out.push(`**${t2.bigCommits}** : ${big.map((c) => `${c.lines} ${en ? "lines" : "lignes"} / ${c.files} ${en ? "files" : "fichiers"}`).join(" \xB7 ")}`, "");
|
|
3533
3534
|
}
|
|
3534
3535
|
}
|
|
3535
|
-
out.push(`##
|
|
3536
|
+
out.push(`## ${secN++}. ${t2.debt}`);
|
|
3536
3537
|
const smellKeys = Object.keys(smells);
|
|
3537
3538
|
if (!smellKeys.length) out.push(en ? "_Nothing detected._" : "_Rien d\xE9tect\xE9._");
|
|
3538
3539
|
for (const key of smellKeys) {
|
|
@@ -3546,7 +3547,7 @@ async function buildDeterministicReport(projectPath, lang = "fr") {
|
|
|
3546
3547
|
for (const a of asyncNoAwait.slice(0, 5)) out.push(` - \`${a.file}\` \u2192 \`${a.name}\``);
|
|
3547
3548
|
}
|
|
3548
3549
|
out.push("");
|
|
3549
|
-
out.push(`##
|
|
3550
|
+
out.push(`## ${secN++}. ${t2.secu}`);
|
|
3550
3551
|
if (sensitive.length) {
|
|
3551
3552
|
out.push(`- **${t2.sensitive}** \u2014 ${sensitive.length}`);
|
|
3552
3553
|
for (const f of sensitive.slice(0, 6)) out.push(` - \`${f}\`${git2?.sensitiveTracked.includes(f) ? en ? " (tracked by git!)" : " (suivi par git !)" : ""}`);
|
|
@@ -3560,10 +3561,10 @@ async function buildDeterministicReport(projectPath, lang = "fr") {
|
|
|
3560
3561
|
if (hits.length > 5) out.push(` - _\u2026${hits.length - 5} ${en ? "more" : "autres"}_`);
|
|
3561
3562
|
}
|
|
3562
3563
|
out.push("");
|
|
3563
|
-
out.push(`##
|
|
3564
|
+
out.push(`## ${secN++}. ${t2.constraints}`);
|
|
3564
3565
|
out.push(index.constraints.length ? index.constraints.map((c) => `- ${c}`).join("\n") : t2.none, "");
|
|
3565
|
-
out.push(formatHealthReportMd(health, lang).replace(/^## /,
|
|
3566
|
-
out.push(`##
|
|
3566
|
+
out.push(formatHealthReportMd(health, lang).replace(/^## /, `## ${secN++}. `).replace(/\n### /g, "\n#### "), "");
|
|
3567
|
+
out.push(`## ${secN++}. ${t2.reco}`, "");
|
|
3567
3568
|
out.push(`| ${t2.sev} | ${t2.action} |`, "|---|---|");
|
|
3568
3569
|
const SEV_ICON = { Critique: "\u{1F534}", "\xC9lev\xE9e": "\u{1F7E0}", Moyenne: "\u{1F7E1}", Faible: "\u{1F535}" };
|
|
3569
3570
|
for (const r of recommendations(health, hasTests, smells, sec, git2, infra, riskFiles, { sensitive, envUndoc: env.undocumented, deadDeps, tsStrict: cfg.tsStrict, untestedRisk: untestedRisk.map((r2) => r2.file), brokenEntries, deepRel: deepRel.length, deepNest: shape.deepNest.map((d) => d.file), commitConv: commitQ?.conventionalPct ?? null, missingDeps: missing, lockDrift }, lang)) out.push(`| ${SEV_ICON[r.severity]} ${r.severity} | ${r.text} |`);
|