fix: fence lone commands and give the prompt some warmth
Two problems, one report: asking for a command returned a bare `pwd` with no code block, and every answer read like a spec sheet. The fence rule. Promotion now turns a paragraph that is nothing but one inline code span into a fence, so `pwd` on its own line becomes a real block with a Copy button. The rule is deliberately narrow, a whole line that is exactly one span, so "run `pwd` to check" is left intact. This also repairs answers already sitting in a saved conversation, because the stored text is re-rendered on every open. That work exposed a real bug in the labeller: a closing ``` and an opening bare ``` are identical lines, so every closing fence was read as a new opening one and swallowed the rest of the answer. Any block after a labelled block silently lost its language. The opening-fence pattern now carries the optional language, closing fences are matched separately, and a fence the model labelled itself is left exactly as written. The prompt. "No preamble" plus "when the answer is a single command, the fence is the whole answer" is why the reply was a bare snippet with no words at all. Replaced with a plain instruction to sound like a person and to always say in one sentence what the code does. The anti-slop rules stay, narrowed to the stock service-desk phrasing that actually reads as filler. 171 tests, tsc, eslint and vici build all clean.
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { inferLanguage, labelCodeFences } from "../lib/code";
|
||||
import {
|
||||
inferLanguage,
|
||||
labelCodeFences,
|
||||
promoteStandaloneCodeSpans,
|
||||
repairCodeBlocks,
|
||||
} from "../lib/code";
|
||||
|
||||
describe("inferLanguage", () => {
|
||||
it("returns nothing for empty or whitespace-only code", () => {
|
||||
@@ -79,6 +84,71 @@ describe("inferLanguage", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("promoteStandaloneCodeSpans", () => {
|
||||
it("promotes a paragraph that is one inline span", () => {
|
||||
// The reported case: asking for a command and getting a lone chip back.
|
||||
expect(promoteStandaloneCodeSpans("`pwd`")).toBe("```bash\npwd\n```");
|
||||
});
|
||||
|
||||
it("promotes the same span on its own line within a larger answer", () => {
|
||||
const promoted = promoteStandaloneCodeSpans("Here you go:\n\n`pwd`\n\nThat prints the path.");
|
||||
|
||||
expect(promoted).toContain("```bash\npwd\n```");
|
||||
expect(promoted).toContain("Here you go:");
|
||||
expect(promoted).toContain("That prints the path.");
|
||||
});
|
||||
|
||||
it("tolerates a sentence-ending period", () => {
|
||||
expect(promoteStandaloneCodeSpans("`pwd`.")).toBe("```bash\npwd\n```");
|
||||
});
|
||||
|
||||
it("leaves a span embedded in a sentence alone", () => {
|
||||
const input = "Run `pwd` to see where you are.";
|
||||
expect(promoteStandaloneCodeSpans(input)).toBe(input);
|
||||
});
|
||||
|
||||
it("leaves a bulleted span alone", () => {
|
||||
const input = "- `pwd -P` resolves symlinks";
|
||||
expect(promoteStandaloneCodeSpans(input)).toBe(input);
|
||||
});
|
||||
|
||||
it("never rewrites a span-like line inside an existing fence", () => {
|
||||
const input = "```bash\n`not-a-span`\n```";
|
||||
expect(promoteStandaloneCodeSpans(input)).toBe(input);
|
||||
});
|
||||
|
||||
it("fences a span whose language cannot be inferred, without guessing one", () => {
|
||||
expect(promoteStandaloneCodeSpans("`Get-Location`")).toBe("```\nGet-Location\n```");
|
||||
});
|
||||
|
||||
it("is idempotent", () => {
|
||||
const once = promoteStandaloneCodeSpans("`pwd`");
|
||||
expect(promoteStandaloneCodeSpans(once)).toBe(once);
|
||||
});
|
||||
|
||||
it("is a no-op on ordinary prose", () => {
|
||||
const input = "There is no code here at all.";
|
||||
expect(promoteStandaloneCodeSpans(input)).toBe(input);
|
||||
});
|
||||
});
|
||||
|
||||
describe("repairCodeBlocks", () => {
|
||||
it("promotes a lone command and labels it in one pass", () => {
|
||||
expect(repairCodeBlocks("`pwd`")).toBe("```bash\npwd\n```");
|
||||
});
|
||||
|
||||
it("still labels a bare multi-line fence", () => {
|
||||
expect(repairCodeBlocks("```\ngit status\n```")).toBe("```bash\ngit status\n```");
|
||||
});
|
||||
|
||||
it("handles a promoted block and a plain fence in the same answer", () => {
|
||||
const repaired = repairCodeBlocks("First:\n\n`pwd`\n\nThen:\n\n```\nls -la\n```");
|
||||
|
||||
expect(repaired).toContain("```bash\npwd\n```");
|
||||
expect(repaired).toContain("```bash\nls -la\n```");
|
||||
});
|
||||
});
|
||||
|
||||
describe("labelCodeFences", () => {
|
||||
it("labels a bare fence", () => {
|
||||
const labelled = labelCodeFences("```\ngit status\n```");
|
||||
@@ -123,6 +193,27 @@ describe("labelCodeFences", () => {
|
||||
expect(labelCodeFences(once)).toBe(once);
|
||||
});
|
||||
|
||||
it("does not mistake a closing fence for a new opening one", () => {
|
||||
// A closing ``` and an opening bare ``` are identical lines. Treating the
|
||||
// closing one as an opening fence swallowed everything after it, so the
|
||||
// second block never got labelled.
|
||||
const input = "```bash\npwd\n```\n\n```\nls -la\n```";
|
||||
expect(labelCodeFences(input)).toContain("```bash\nls -la\n```");
|
||||
});
|
||||
|
||||
it("labels a later block even when an earlier one is already labelled", () => {
|
||||
const input = "```rust\nfn main() {}\n```\n\n```\npwd\n```";
|
||||
const labelled = labelCodeFences(input);
|
||||
|
||||
expect(labelled).toContain("```rust");
|
||||
expect(labelled).toContain("```bash\npwd\n```");
|
||||
});
|
||||
|
||||
it("preserves a language the model chose, including multi-word freeform tags", () => {
|
||||
expect(labelCodeFences("```c++\nint main() {}\n```")).toContain("```c++");
|
||||
expect(labelCodeFences("```objective-c\nint x;\n```")).toContain("```objective-c");
|
||||
});
|
||||
|
||||
it("preserves indentation of a nested fence", () => {
|
||||
expect(labelCodeFences(" ```\n ls\n ```")).toContain(" ```bash");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user