feat(prompt): implement prompt injection slice 1
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
buildRootPairBlock,
|
||||
hasRootPairMarker,
|
||||
buildPreInitHint,
|
||||
computeInjectionBudget,
|
||||
modeAllowsPreInitHint,
|
||||
modeAllowsInjection,
|
||||
modeRequiresProtocolPath,
|
||||
ROOT_PAIR_START_MARKER,
|
||||
ROOT_PAIR_END_MARKER,
|
||||
TRUST_BOUNDARY_TEXT,
|
||||
} from "../src/prompt-injection.js";
|
||||
|
||||
describe("prompt-injection helpers", () => {
|
||||
describe("canonical markers", () => {
|
||||
it("builds a root-pair block with markers", () => {
|
||||
const block = buildRootPairBlock("index content", "map content");
|
||||
expect(block).toContain(ROOT_PAIR_START_MARKER);
|
||||
expect(block).toContain(ROOT_PAIR_END_MARKER);
|
||||
expect(block).toContain(TRUST_BOUNDARY_TEXT);
|
||||
expect(block).toContain("index content");
|
||||
expect(block).toContain("map content");
|
||||
});
|
||||
|
||||
it("detects root-pair marker in content", () => {
|
||||
const block = buildRootPairBlock("i", "m");
|
||||
expect(hasRootPairMarker(block)).toBe(true);
|
||||
expect(hasRootPairMarker("plain text")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pre-init hint", () => {
|
||||
it("returns a visible hint with no synthetic artifacts", () => {
|
||||
const hint = buildPreInitHint();
|
||||
expect(hint).toContain("project_map_init");
|
||||
expect(hint).toContain("📋");
|
||||
expect(hint).not.toContain(ROOT_PAIR_START_MARKER);
|
||||
expect(hint).not.toContain("### Root index");
|
||||
expect(hint).not.toContain("### Root map");
|
||||
});
|
||||
});
|
||||
|
||||
describe("budget calculation", () => {
|
||||
it("uses relative percent when smaller than absolute cap", () => {
|
||||
const budget = computeInjectionBudget(
|
||||
{ contextBudgetPercent: 15, contextBudgetMaxTokens: 100_000 },
|
||||
200_000,
|
||||
);
|
||||
expect(budget).toBe(30_000);
|
||||
});
|
||||
|
||||
it("uses absolute cap when smaller than relative percent", () => {
|
||||
const budget = computeInjectionBudget(
|
||||
{ contextBudgetPercent: 15, contextBudgetMaxTokens: 100_000 },
|
||||
10_000_000,
|
||||
);
|
||||
expect(budget).toBe(100_000);
|
||||
});
|
||||
|
||||
it("falls back to absolute cap when context window is unknown", () => {
|
||||
const budget = computeInjectionBudget(
|
||||
{ contextBudgetPercent: 15, contextBudgetMaxTokens: 100_000 },
|
||||
undefined,
|
||||
);
|
||||
expect(budget).toBe(100_000);
|
||||
});
|
||||
|
||||
it("falls back to absolute cap when context window is zero", () => {
|
||||
const budget = computeInjectionBudget(
|
||||
{ contextBudgetPercent: 15, contextBudgetMaxTokens: 100_000 },
|
||||
0,
|
||||
);
|
||||
expect(budget).toBe(100_000);
|
||||
});
|
||||
});
|
||||
|
||||
describe("mode helpers", () => {
|
||||
it("allows pre-init hint for all modes except off", () => {
|
||||
expect(modeAllowsPreInitHint("off")).toBe(false);
|
||||
expect(modeAllowsPreInitHint("advisory")).toBe(true);
|
||||
expect(modeAllowsPreInitHint("strong")).toBe(true);
|
||||
expect(modeAllowsPreInitHint("strict")).toBe(true);
|
||||
});
|
||||
|
||||
it("allows injection only for strong and strict", () => {
|
||||
expect(modeAllowsInjection("off")).toBe(false);
|
||||
expect(modeAllowsInjection("advisory")).toBe(false);
|
||||
expect(modeAllowsInjection("strong")).toBe(true);
|
||||
expect(modeAllowsInjection("strict")).toBe(true);
|
||||
});
|
||||
|
||||
it("requires protocol path only for strict", () => {
|
||||
expect(modeRequiresProtocolPath("off")).toBe(false);
|
||||
expect(modeRequiresProtocolPath("advisory")).toBe(false);
|
||||
expect(modeRequiresProtocolPath("strong")).toBe(false);
|
||||
expect(modeRequiresProtocolPath("strict")).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user