From 0bffd78c2428d635ed6c18f023f564cc96027d98 Mon Sep 17 00:00:00 2001 From: enjoyer-hub Date: Fri, 19 Jun 2026 13:24:00 +0300 Subject: [PATCH] feat(ponytail): add minimal-code system-prompt injector toggle Adds a Ponytail token/complexity saver alongside Caveman: injects a lazy-senior-dev (write the minimum that works) system prompt to curb over-engineering, while never cutting validation, error handling, security or accessibility. Refactors the format-aware system-prompt injection out of caveman.js into a shared open-sse/rtk/systemInject.js used by both caveman and ponytail (DRY). Wires ponytailEnabled/ponytailLevel through chatCore + chat settings, adds defaults, and a dashboard toggle next to Caveman. Ruleset adapted from DietrichGebert/ponytail (MIT). Adds tests/unit/ponytail.test.js (10 cases: OpenAI/Claude/Gemini shapes, levels, no-ops). --- CHANGELOG.md | 3 + README.md | 1 + open-sse/handlers/chatCore.js | 9 +- open-sse/rtk/caveman.js | 96 +---------------- open-sse/rtk/ponytail.js | 11 ++ open-sse/rtk/ponytailPrompts.js | 33 ++++++ open-sse/rtk/systemInject.js | 102 ++++++++++++++++++ .../dashboard/endpoint/EndpointPageClient.js | 62 +++++++++++ .../dashboard/endpoint/endpointConstants.js | 5 + src/lib/db/repos/settingsRepo.js | 2 + src/sse/handlers/chat.js | 2 + tests/unit/ponytail.test.js | 74 +++++++++++++ 12 files changed, 306 insertions(+), 94 deletions(-) create mode 100644 open-sse/rtk/ponytail.js create mode 100644 open-sse/rtk/ponytailPrompts.js create mode 100644 open-sse/rtk/systemInject.js create mode 100644 tests/unit/ponytail.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9b066e2c..7d5cb4996c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # v0.5.4 (2026-06-18) +## Features +- **Ponytail**: inject a lazy-senior-dev (minimal-code) system prompt to curb over-engineering; dashboard toggle next to Caveman, lite/full levels. Caveman and Ponytail now share one format-aware system-prompt injector. + ## Fixes - **Kiro**: honor thinking effort budgets - **AG/Kiro/Xiaomi**: provider fixes diff --git a/README.md b/README.md index 4345d21bb4..2a09d7ae77 100644 --- a/README.md +++ b/README.md @@ -408,6 +408,7 @@ Default URLs: |---------|--------------|----------------| | 🚀 **RTK Token Saver** ([RTK](https://github.com/rtk-ai/rtk) ⭐40K) | Compress tool outputs (`git diff`, `grep`, `ls`, `tree`...) before sending to LLM | Save **20-40% input tokens** per request | | 🪨 **Caveman Mode** ([Caveman](https://github.com/JuliusBrussee/caveman) ⭐52K) | Inject caveman-speak prompt → LLM replies terse, technical substance preserved | Save **up to 65% output tokens** | +| 🐴 **Ponytail Mode** ([Ponytail](https://github.com/DietrichGebert/ponytail) ⭐38K) | Inject lazy-senior-dev prompt → LLM writes the minimum code that works, never cutting validation/security | **Less over-engineering**, fewer files | | 🎯 **Smart 3-Tier Fallback** | Auto-route: Subscription → Cheap → Free | Never stop coding, zero downtime | | 📊 **Real-Time Quota Tracking** | Live token count + reset countdown | Maximize subscription value | | 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro ↔ Vertex | Works with any CLI tool | diff --git a/open-sse/handlers/chatCore.js b/open-sse/handlers/chatCore.js index c1a026034a..30f0963eb2 100644 --- a/open-sse/handlers/chatCore.js +++ b/open-sse/handlers/chatCore.js @@ -20,6 +20,7 @@ import { handleStreamingResponse, buildOnStreamComplete } from "./chatCore/strea import { detectClientTool, isNativePassthrough } from "../utils/clientDetector.js"; import { dedupeTools } from "../utils/toolDeduper.js"; import { injectCaveman } from "../rtk/caveman.js"; +import { injectPonytail } from "../rtk/ponytail.js"; import { compressMessages, formatRtkLog } from "../rtk/index.js"; import { getCapabilitiesForModel } from "../providers/capabilities.js"; import { stripUnsupportedModalities } from "../translator/concerns/modality.js"; @@ -32,7 +33,7 @@ import { prefetchRemoteImages } from "../translator/concerns/prefetch.js"; * @param {object} options.credentials - Provider credentials * @param {string} options.sourceFormatOverride - Override detected source format (e.g. "openai-responses") */ -export async function handleChatCore({ body, modelInfo, credentials, log, onCredentialsRefreshed, onRequestSuccess, onDisconnect, clientRawRequest, connectionId, userAgent, apiKey, ccFilterNaming, rtkEnabled, cavemanEnabled, cavemanLevel, sourceFormatOverride, providerThinking }) { +export async function handleChatCore({ body, modelInfo, credentials, log, onCredentialsRefreshed, onRequestSuccess, onDisconnect, clientRawRequest, connectionId, userAgent, apiKey, ccFilterNaming, rtkEnabled, cavemanEnabled, cavemanLevel, ponytailEnabled, ponytailLevel, sourceFormatOverride, providerThinking }) { const { provider, model } = modelInfo; const requestStartTime = Date.now(); @@ -155,6 +156,12 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred log?.debug?.("CAVEMAN", `${cavemanLevel} | ${finalFormat}`); } + // Ponytail: inject minimal-code (lazy senior dev) system prompt + if (ponytailEnabled && ponytailLevel) { + injectPonytail(translatedBody, finalFormat, ponytailLevel); + log?.debug?.("PONYTAIL", `${ponytailLevel} | ${finalFormat}`); + } + const executor = getExecutor(provider); trackPendingRequest(model, provider, connectionId, true); appendRequestLog({ model, provider, connectionId, status: "PENDING" }).catch(() => { }); diff --git a/open-sse/rtk/caveman.js b/open-sse/rtk/caveman.js index 09cc8cfb4d..9add8414bd 100644 --- a/open-sse/rtk/caveman.js +++ b/open-sse/rtk/caveman.js @@ -1,100 +1,10 @@ // Caveman injector: appends a caveman-style instruction into the system message // of the final request body, just before it is dispatched to the provider executor. -// Dispatches by format so it works for both translated and native-passthrough flows. +// Format-aware injection lives in the shared systemInject helper. -import { FORMATS } from "../translator/formats.js"; +import { injectSystemPrompt } from "./systemInject.js"; import { CAVEMAN_PROMPTS } from "./cavemanPrompts.js"; -const SEP = "\n\n"; - export function injectCaveman(body, format, level) { - const prompt = CAVEMAN_PROMPTS[level]; - if (!body || !prompt) return; - - switch (format) { - case FORMATS.CLAUDE: - injectClaudeSystem(body, prompt); - return; - case FORMATS.GEMINI: - case FORMATS.GEMINI_CLI: - case FORMATS.VERTEX: - case FORMATS.ANTIGRAVITY: - // Antigravity wraps Gemini shape in body.request → injectGeminiSystem handles it - injectGeminiSystem(body, prompt); - return; - default: - // OpenAI and OpenAI-shaped formats (responses/codex/cursor/kiro/ollama) - injectMessagesSystem(body, prompt); - } -} - -// OpenAI-shaped: messages[] (chat) or input[] (responses) or instructions (responses string) -function injectMessagesSystem(body, prompt) { - // OpenAI Responses API: top-level string field - if (typeof body.instructions === "string") { - body.instructions = body.instructions - ? `${body.instructions}${SEP}${prompt}` - : prompt; - return; - } - - const arr = Array.isArray(body.messages) ? body.messages - : Array.isArray(body.input) ? body.input - : null; - if (!arr) return; - - const idx = arr.findIndex(m => m && (m.role === "system" || m.role === "developer")); - if (idx >= 0) { - appendToOpenAIMessage(arr[idx], prompt); - } else { - arr.unshift({ role: "system", content: prompt }); - } -} - -function appendToOpenAIMessage(msg, prompt) { - if (typeof msg.content === "string") { - msg.content = `${msg.content}${SEP}${prompt}`; - } else if (Array.isArray(msg.content)) { - // Responses-style array of parts {type:"input_text"|"text", text} - msg.content.push({ type: "input_text", text: prompt }); - } else { - msg.content = prompt; - } -} - -// Claude shape: body.system as string | array of {type:"text", text} -// Insert before the last cache_control block to keep caveman inside the cached prefix. -function injectClaudeSystem(body, prompt) { - if (typeof body.system === "string" && body.system.length > 0) { - body.system = `${body.system}${SEP}${prompt}`; - return; - } - if (Array.isArray(body.system)) { - const block = { type: "text", text: prompt }; - let lastCacheIdx = -1; - for (let i = body.system.length - 1; i >= 0; i--) { - if (body.system[i]?.cache_control) { lastCacheIdx = i; break; } - } - if (lastCacheIdx >= 0) { - body.system.splice(lastCacheIdx, 0, block); - } else { - body.system.push(block); - } - return; - } - body.system = prompt; -} - -// Gemini shape: body.system_instruction | body.systemInstruction | body.request.systemInstruction -// Each shape: { parts: [{ text }] } -function injectGeminiSystem(body, prompt) { - const target = body.request && typeof body.request === "object" ? body.request : body; - const useSnake = Object.prototype.hasOwnProperty.call(target, "system_instruction"); - const key = useSnake ? "system_instruction" : "systemInstruction"; - const sys = target[key]; - if (sys && Array.isArray(sys.parts)) { - sys.parts.push({ text: prompt }); - return; - } - target[key] = { parts: [{ text: prompt }] }; + injectSystemPrompt(body, format, CAVEMAN_PROMPTS[level]); } diff --git a/open-sse/rtk/ponytail.js b/open-sse/rtk/ponytail.js new file mode 100644 index 0000000000..24cea60bb1 --- /dev/null +++ b/open-sse/rtk/ponytail.js @@ -0,0 +1,11 @@ +// Ponytail injector: appends a "lazy senior dev / write minimal code" instruction +// into the system message of the final request body, just before it is dispatched +// to the provider executor. Format-aware injection lives in the shared +// systemInject helper (same as caveman). + +import { injectSystemPrompt } from "./systemInject.js"; +import { PONYTAIL_PROMPTS } from "./ponytailPrompts.js"; + +export function injectPonytail(body, format, level) { + injectSystemPrompt(body, format, PONYTAIL_PROMPTS[level]); +} diff --git a/open-sse/rtk/ponytailPrompts.js b/open-sse/rtk/ponytailPrompts.js new file mode 100644 index 0000000000..0300ad486b --- /dev/null +++ b/open-sse/rtk/ponytailPrompts.js @@ -0,0 +1,33 @@ +// Ponytail intensity-level prompts injected into the system message to curb +// over-engineering (less code, fewer deps, fewer files) while never cutting +// validation, error handling, security or accessibility. +// Adapted from the ponytail ruleset (https://github.com/DietrichGebert/ponytail, MIT). + +export const PONYTAIL_LEVELS = { + LITE: "lite", + FULL: "full", +}; + +const SHARED_LADDER = "Before writing code, stop at the first rung that holds: 1. Does this need to exist? (YAGNI) 2. Stdlib does it? Use it. 3. Native platform feature? Use it. 4. Installed dependency? Use it. 5. One line? One line. 6. Only then: the minimum that works."; + +const SHARED_GUARDS = "Never lazy about: input validation at trust boundaries, error handling that prevents data loss, security, accessibility, anything explicitly requested. Lazy means less code, not the flimsier algorithm."; + +const SHARED_PERSISTENCE = "ACTIVE EVERY RESPONSE. No revert after many turns. Still active if unsure."; + +export const PONYTAIL_PROMPTS = { + [PONYTAIL_LEVELS.LITE]: [ + "Act like a lazy senior dev: lazy means efficient, not careless. Prefer the smallest change that fully solves the task.", + "No abstractions, dependencies, or boilerplate that were not requested. Deletion over addition. Boring over clever.", + SHARED_GUARDS, + SHARED_PERSISTENCE, + ].join(" "), + + [PONYTAIL_LEVELS.FULL]: [ + "Act like the laziest senior dev in the room. The best code is the code never written.", + SHARED_LADDER, + "No abstractions that were not requested. No new dependency if it can be avoided. No boilerplate nobody asked for. Deletion over addition. Boring over clever. Fewest files possible.", + "Question complex requests: \"Do you actually need X, or does Y cover it?\" Mark intentional simplifications with a `ponytail:` comment naming any known ceiling.", + SHARED_GUARDS, + SHARED_PERSISTENCE, + ].join(" "), +}; diff --git a/open-sse/rtk/systemInject.js b/open-sse/rtk/systemInject.js new file mode 100644 index 0000000000..8dc89fe2e7 --- /dev/null +++ b/open-sse/rtk/systemInject.js @@ -0,0 +1,102 @@ +// Shared system-prompt injector: appends an instruction string into the system +// message of the final request body, just before it is dispatched to the provider +// executor. Dispatches by format so it works for both translated and +// native-passthrough flows. Used by both caveman (terse output) and ponytail +// (minimal code) token savers so the format-handling logic lives in one place. + +import { FORMATS } from "../translator/formats.js"; + +const SEP = "\n\n"; + +// Append `prompt` to the system instruction of `body`, picking the right shape +// for `format`. No-op when body or prompt is missing. +export function injectSystemPrompt(body, format, prompt) { + if (!body || !prompt) return; + + switch (format) { + case FORMATS.CLAUDE: + injectClaudeSystem(body, prompt); + return; + case FORMATS.GEMINI: + case FORMATS.GEMINI_CLI: + case FORMATS.VERTEX: + case FORMATS.ANTIGRAVITY: + // Antigravity wraps Gemini shape in body.request → injectGeminiSystem handles it + injectGeminiSystem(body, prompt); + return; + default: + // OpenAI and OpenAI-shaped formats (responses/codex/cursor/kiro/ollama) + injectMessagesSystem(body, prompt); + } +} + +// OpenAI-shaped: messages[] (chat) or input[] (responses) or instructions (responses string) +function injectMessagesSystem(body, prompt) { + // OpenAI Responses API: top-level string field + if (typeof body.instructions === "string") { + body.instructions = body.instructions + ? `${body.instructions}${SEP}${prompt}` + : prompt; + return; + } + + const arr = Array.isArray(body.messages) ? body.messages + : Array.isArray(body.input) ? body.input + : null; + if (!arr) return; + + const idx = arr.findIndex(m => m && (m.role === "system" || m.role === "developer")); + if (idx >= 0) { + appendToOpenAIMessage(arr[idx], prompt); + } else { + arr.unshift({ role: "system", content: prompt }); + } +} + +function appendToOpenAIMessage(msg, prompt) { + if (typeof msg.content === "string") { + msg.content = `${msg.content}${SEP}${prompt}`; + } else if (Array.isArray(msg.content)) { + // Responses-style array of parts {type:"input_text"|"text", text} + msg.content.push({ type: "input_text", text: prompt }); + } else { + msg.content = prompt; + } +} + +// Claude shape: body.system as string | array of {type:"text", text} +// Insert before the last cache_control block to keep the prompt inside the cached prefix. +function injectClaudeSystem(body, prompt) { + if (typeof body.system === "string" && body.system.length > 0) { + body.system = `${body.system}${SEP}${prompt}`; + return; + } + if (Array.isArray(body.system)) { + const block = { type: "text", text: prompt }; + let lastCacheIdx = -1; + for (let i = body.system.length - 1; i >= 0; i--) { + if (body.system[i]?.cache_control) { lastCacheIdx = i; break; } + } + if (lastCacheIdx >= 0) { + body.system.splice(lastCacheIdx, 0, block); + } else { + body.system.push(block); + } + return; + } + body.system = prompt; +} + +// Gemini shape: body.system_instruction | body.systemInstruction | body.request.systemInstruction +// Each shape: { parts: [{ text }] } +function injectGeminiSystem(body, prompt) { + const target = body.request && typeof body.request === "object" ? body.request : body; + const useSnake = Object.prototype.hasOwnProperty.call(target, "system_instruction"); + const key = useSnake ? "system_instruction" : "systemInstruction"; + const sys = target[key]; + if (sys && Array.isArray(sys.parts)) { + sys.parts.push({ text: prompt }); + return; + } + target[key] = { parts: [{ text: prompt }] }; +} diff --git a/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.js b/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.js index d679f596e2..b726cf2331 100644 --- a/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.js +++ b/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.js @@ -14,6 +14,7 @@ import { REACHABLE_MISS_THRESHOLD, CLIENT_PING_FAST_MS, CAVEMAN_LEVELS, + PONYTAIL_LEVELS, } from "./endpointConstants"; import { clientPingUrl, clientPingAny } from "./endpointPing"; import EndpointRow from "./components/EndpointRow"; @@ -35,6 +36,8 @@ export default function APIPageClient({ machineId }) { const [rtkEnabled, setRtkEnabledState] = useState(true); const [cavemanEnabled, setCavemanEnabled] = useState(false); const [cavemanLevel, setCavemanLevel] = useState("full"); + const [ponytailEnabled, setPonytailEnabled] = useState(false); + const [ponytailLevel, setPonytailLevel] = useState("full"); const [locale, setLocale] = useState("en"); // Cloudflare Tunnel state @@ -234,6 +237,8 @@ export default function APIPageClient({ machineId }) { setRtkEnabledState(data.rtkEnabled !== false); setCavemanEnabled(!!data.cavemanEnabled); setCavemanLevel(data.cavemanLevel || "full"); + setPonytailEnabled(!!data.ponytailEnabled); + setPonytailLevel(data.ponytailLevel || "full"); } if (statusRes.ok) { const data = await statusRes.json(); @@ -318,6 +323,16 @@ export default function APIPageClient({ machineId }) { patchSetting({ cavemanLevel: level }); }; + const handlePonytailEnabled = (value) => { + setPonytailEnabled(value); + patchSetting({ ponytailEnabled: value }); + }; + + const handlePonytailLevel = (level) => { + setPonytailLevel(level); + patchSetting({ ponytailLevel: level }); + }; + const fetchData = async () => { try { const keysRes = await fetch("/api/keys"); @@ -1090,6 +1105,53 @@ export default function APIPageClient({ machineId }) { /> +
+
+

+ Write less code{" "} + + (Ponytail) + +

+

+ Lazy-senior-dev system prompt → less over-engineering, fewer files +

+
+
+ {ponytailEnabled && ( +
+
+ {PONYTAIL_LEVELS.map((lvl) => ( + + ))} +
+

+ {PONYTAIL_LEVELS.find((lvl) => lvl.id === ponytailLevel)?.desc} +

+
+ )} + handlePonytailEnabled(!ponytailEnabled)} + /> +
+
{/* API Keys */} diff --git a/src/app/(dashboard)/dashboard/endpoint/endpointConstants.js b/src/app/(dashboard)/dashboard/endpoint/endpointConstants.js index eb71a4aff6..e170e49bdf 100644 --- a/src/app/(dashboard)/dashboard/endpoint/endpointConstants.js +++ b/src/app/(dashboard)/dashboard/endpoint/endpointConstants.js @@ -24,3 +24,8 @@ export const CAVEMAN_LEVELS = [ { id: "wenyan", label: "文 Full", desc: "Maximum 文言文, 80-90% reduction", wenyan: true }, { id: "wenyan-ultra", label: "文 Ultra", desc: "Extreme classical compression", wenyan: true }, ]; + +export const PONYTAIL_LEVELS = [ + { id: "lite", label: "Lite", desc: "Smallest change that solves it" }, + { id: "full", label: "Full", desc: "YAGNI ladder, fewest files" }, +]; diff --git a/src/lib/db/repos/settingsRepo.js b/src/lib/db/repos/settingsRepo.js index 7201a76099..f683e9fbd8 100644 --- a/src/lib/db/repos/settingsRepo.js +++ b/src/lib/db/repos/settingsRepo.js @@ -36,6 +36,8 @@ const DEFAULT_SETTINGS = { rtkEnabled: true, cavemanEnabled: false, cavemanLevel: "full", + ponytailEnabled: false, + ponytailLevel: "full", }; async function readRaw() { diff --git a/src/sse/handlers/chat.js b/src/sse/handlers/chat.js index 75c26b5d49..65699927c3 100644 --- a/src/sse/handlers/chat.js +++ b/src/sse/handlers/chat.js @@ -253,6 +253,8 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re rtkEnabled: !!chatSettings.rtkEnabled, cavemanEnabled: !!chatSettings.cavemanEnabled, cavemanLevel: chatSettings.cavemanLevel || "full", + ponytailEnabled: !!chatSettings.ponytailEnabled, + ponytailLevel: chatSettings.ponytailLevel || "full", providerThinking, // Detect source format by endpoint + body sourceFormatOverride: request?.url ? detectFormatByEndpoint(new URL(request.url).pathname, body) : null, diff --git a/tests/unit/ponytail.test.js b/tests/unit/ponytail.test.js new file mode 100644 index 0000000000..d2dbda9007 --- /dev/null +++ b/tests/unit/ponytail.test.js @@ -0,0 +1,74 @@ +import { describe, it, expect } from "vitest"; +import { injectPonytail } from "../../open-sse/rtk/ponytail.js"; +import { injectCaveman } from "../../open-sse/rtk/caveman.js"; +import { PONYTAIL_PROMPTS, PONYTAIL_LEVELS } from "../../open-sse/rtk/ponytailPrompts.js"; +import { FORMATS } from "../../open-sse/translator/formats.js"; + +const FULL = PONYTAIL_PROMPTS[PONYTAIL_LEVELS.FULL]; + +describe("injectPonytail", () => { + it("appends to an existing OpenAI system message", () => { + const body = { messages: [{ role: "system", content: "Base." }, { role: "user", content: "hi" }] }; + injectPonytail(body, FORMATS.OPENAI, "full"); + expect(body.messages[0].content).toBe(`Base.\n\n${FULL}`); + }); + + it("prepends a system message when none exists (OpenAI)", () => { + const body = { messages: [{ role: "user", content: "hi" }] }; + injectPonytail(body, FORMATS.OPENAI, "full"); + expect(body.messages[0]).toEqual({ role: "system", content: FULL }); + expect(body.messages[1].role).toBe("user"); + }); + + it("appends to the OpenAI Responses instructions string", () => { + const body = { instructions: "Base.", input: [] }; + injectPonytail(body, FORMATS.OPENAI_RESPONSES, "full"); + expect(body.instructions).toBe(`Base.\n\n${FULL}`); + }); + + it("appends to a Claude system string", () => { + const body = { system: "Base." }; + injectPonytail(body, FORMATS.CLAUDE, "full"); + expect(body.system).toBe(`Base.\n\n${FULL}`); + }); + + it("inserts before the last cache_control block in a Claude system array", () => { + const body = { system: [{ type: "text", text: "Base.", cache_control: { type: "ephemeral" } }] }; + injectPonytail(body, FORMATS.CLAUDE, "full"); + expect(body.system).toHaveLength(2); + expect(body.system[0]).toEqual({ type: "text", text: FULL }); + expect(body.system[1].cache_control).toBeDefined(); + }); + + it("adds a Gemini systemInstruction part", () => { + const body = { systemInstruction: { parts: [{ text: "Base." }] } }; + injectPonytail(body, FORMATS.GEMINI, "full"); + expect(body.systemInstruction.parts).toHaveLength(2); + expect(body.systemInstruction.parts[1]).toEqual({ text: FULL }); + }); + + it("uses the lite prompt for the lite level", () => { + const body = { messages: [] }; + injectPonytail(body, FORMATS.OPENAI, "lite"); + expect(body.messages[0].content).toBe(PONYTAIL_PROMPTS[PONYTAIL_LEVELS.LITE]); + }); + + it("is a no-op for an unknown level", () => { + const body = { messages: [{ role: "user", content: "hi" }] }; + injectPonytail(body, FORMATS.OPENAI, "nope"); + expect(body.messages).toHaveLength(1); + }); + + it("is a no-op for a missing body", () => { + expect(() => injectPonytail(null, FORMATS.OPENAI, "full")).not.toThrow(); + }); +}); + +describe("shared injector keeps caveman working", () => { + it("still injects caveman after the refactor", () => { + const body = { messages: [{ role: "user", content: "hi" }] }; + injectCaveman(body, FORMATS.OPENAI, "full"); + expect(body.messages[0].role).toBe("system"); + expect(body.messages[0].content.length).toBeGreaterThan(0); + }); +});