File size: 5,575 Bytes
88c4c60 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | // End-to-end integration test: hit live local proxy and verify [RTK] behavior.
// Run with: RUN_E2E=1 RTK_E2E_PORT=... RTK_E2E_KEY=... RTK_E2E_LOG=<absolute path to server stdout file> npm test rtk.e2e.test.js
// Requires: dev server running, rtkEnabled=true, API key present.
import { describe, it, expect } from "vitest";
import fs from "node:fs";
const PORT = process.env.RTK_E2E_PORT || "20128";
const BASE = `http://localhost:${PORT}`;
const API_KEY = process.env.RTK_E2E_KEY || "";
const LOG_FILE = process.env.RTK_E2E_LOG || "";
const RUN = process.env.RUN_E2E === "1";
const maybe = RUN ? describe : describe.skip;
function readLogTail(bytes = 8192) {
if (!LOG_FILE || !fs.existsSync(LOG_FILE)) return "";
const stat = fs.statSync(LOG_FILE);
const start = Math.max(0, stat.size - bytes);
const fd = fs.openSync(LOG_FILE, "r");
const buf = Buffer.alloc(stat.size - start);
fs.readSync(fd, buf, 0, buf.length, start);
fs.closeSync(fd);
return buf.toString("utf8");
}
// Read new bytes appended to log since `offset`. Returns text + new offset.
function readLogSince(offset) {
if (!LOG_FILE || !fs.existsSync(LOG_FILE)) return { text: "", next: offset };
const stat = fs.statSync(LOG_FILE);
if (stat.size <= offset) return { text: "", next: stat.size };
const fd = fs.openSync(LOG_FILE, "r");
const buf = Buffer.alloc(stat.size - offset);
fs.readSync(fd, buf, 0, buf.length, offset);
fs.closeSync(fd);
return { text: buf.toString("utf8"), next: stat.size };
}
function logOffset() {
if (!LOG_FILE || !fs.existsSync(LOG_FILE)) return 0;
return fs.statSync(LOG_FILE).size;
}
async function sendChat(body) {
return fetch(`${BASE}/v1/chat/completions`, {
method: "POST",
headers: { "content-type": "application/json", "authorization": `Bearer ${API_KEY}` },
body: JSON.stringify(body)
});
}
function makeBigDiff(fileCount = 3, linesPerFile = 80) {
const out = [];
for (let f = 0; f < fileCount; f++) {
out.push(`diff --git a/src/file${f}.js b/src/file${f}.js`);
out.push(`index abc${f}..def${f} 100644`);
out.push(`--- a/src/file${f}.js`);
out.push(`+++ b/src/file${f}.js`);
out.push(`@@ -1,${linesPerFile} +1,${linesPerFile} @@`);
for (let i = 0; i < linesPerFile; i++) {
out.push(`-const old${f}_${i} = "removed value ${i} padding padding padding";`);
out.push(`+const new${f}_${i} = "added value ${i} padding padding padding padding";`);
}
}
return out.join("\n");
}
maybe("RTK end-to-end", () => {
it("server is reachable", async () => {
const res = await fetch(`${BASE}/api/health`);
expect(res.ok).toBe(true);
});
it("rtkEnabled flag is true (user must enable via dashboard)", async () => {
const res = await fetch(`${BASE}/api/settings`);
const data = await res.json();
expect(data.rtkEnabled).toBe(true);
});
it("compresses git diff tool_result and writes [RTK] savings to log", async () => {
const diff = makeBigDiff(2, 60);
expect(diff.length).toBeGreaterThan(500);
const offset = logOffset();
const res = await sendChat({
model: "cc/claude-opus-4-7",
stream: false,
max_tokens: 64,
messages: [
{ role: "user", content: "run git diff" },
{ role: "assistant", content: null, tool_calls: [{ id: "call_1", type: "function", function: { name: "Bash", arguments: JSON.stringify({ command: "git diff" }) } }] },
{ role: "tool", tool_call_id: "call_1", content: diff },
{ role: "user", content: "summarize in 10 words" }
]
});
expect([200, 400, 401, 402, 500]).toContain(res.status);
if (!LOG_FILE) return;
await new Promise(r => setTimeout(r, 500));
const { text } = readLogSince(offset);
const matches = [...text.matchAll(/\[RTK\] saved (\d+)B \/ (\d+)B \([\d.]+%\) via \[([\w,-]+)\] hits=(\d+)/g)];
// Find the log line that corresponds to OUR request (total ≥ diff.length and contains git-diff)
const mine = matches.find(m => Number(m[2]) >= diff.length && m[3].includes("git-diff"));
expect(mine, `no matching [RTK] line for our request (diff=${diff.length}B) in ${matches.length} log entries`).toBeTruthy();
expect(Number(mine[1])).toBeGreaterThan(500);
expect(mine[3]).toContain("git-diff");
expect(Number(mine[4])).toBeGreaterThanOrEqual(1);
});
it("compresses grep-style tool_result", async () => {
const lines = [];
for (let i = 1; i <= 30; i++) lines.push(`src/lib/foo.js:${i}:const v${i} = "matching content with enough padding to exceed threshold";`);
const grepOut = lines.join("\n");
expect(grepOut.length).toBeGreaterThan(500);
const offset = logOffset();
const res = await sendChat({
model: "cc/claude-opus-4-7",
stream: false,
max_tokens: 32,
messages: [
{ role: "user", content: "grep" },
{ role: "assistant", content: null, tool_calls: [{ id: "c3", type: "function", function: { name: "Bash", arguments: "{}" } }] },
{ role: "tool", tool_call_id: "c3", content: grepOut },
{ role: "user", content: "ok" }
]
});
expect([200, 400, 401, 402, 500]).toContain(res.status);
if (!LOG_FILE) return;
await new Promise(r => setTimeout(r, 500));
const { text } = readLogSince(offset);
const matches = [...text.matchAll(/\[RTK\] saved (\d+)B \/ (\d+)B \([\d.]+%\) via \[([\w,-]+)\] hits=(\d+)/g)];
const mine = matches.find(m => Number(m[2]) >= grepOut.length && m[3].includes("grep"));
expect(mine, `no matching [RTK] line for grep payload`).toBeTruthy();
});
});
|