@prestyj/cli 4.13.3 → 5.0.0
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/dist/app-sidecar.js +142 -7
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +5 -2
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/shared.d.ts.map +1 -1
- package/dist/cli/shared.js +2 -0
- package/dist/cli/shared.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +9 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +47 -5
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-providers.d.ts.map +1 -1
- package/dist/core/auth-providers.js +7 -0
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/cache-warm-benchmark.d.ts +22 -0
- package/dist/core/cache-warm-benchmark.d.ts.map +1 -0
- package/dist/core/cache-warm-benchmark.js +170 -0
- package/dist/core/cache-warm-benchmark.js.map +1 -0
- package/dist/core/code-retrieval.d.ts +13 -0
- package/dist/core/code-retrieval.d.ts.map +1 -0
- package/dist/core/code-retrieval.js +87 -0
- package/dist/core/code-retrieval.js.map +1 -0
- package/dist/core/fast-apply-benchmark.d.ts +26 -0
- package/dist/core/fast-apply-benchmark.d.ts.map +1 -0
- package/dist/core/fast-apply-benchmark.js +284 -0
- package/dist/core/fast-apply-benchmark.js.map +1 -0
- package/dist/core/hashline-edit-benchmark.d.ts +55 -0
- package/dist/core/hashline-edit-benchmark.d.ts.map +1 -0
- package/dist/core/hashline-edit-benchmark.js +342 -0
- package/dist/core/hashline-edit-benchmark.js.map +1 -0
- package/dist/core/hashline-edit-benchmark.test.d.ts +2 -0
- package/dist/core/hashline-edit-benchmark.test.d.ts.map +1 -0
- package/dist/core/hashline-edit-benchmark.test.js +141 -0
- package/dist/core/hashline-edit-benchmark.test.js.map +1 -0
- package/dist/core/hashline.d.ts +50 -0
- package/dist/core/hashline.d.ts.map +1 -0
- package/dist/core/hashline.js +76 -0
- package/dist/core/hashline.js.map +1 -0
- package/dist/core/ideal-review.d.ts +12 -1
- package/dist/core/ideal-review.d.ts.map +1 -1
- package/dist/core/ideal-review.js +52 -2
- package/dist/core/ideal-review.js.map +1 -1
- package/dist/core/ideal-review.test.js +41 -1
- package/dist/core/ideal-review.test.js.map +1 -1
- package/dist/core/language-detector.d.ts +11 -0
- package/dist/core/language-detector.d.ts.map +1 -1
- package/dist/core/language-detector.js +102 -0
- package/dist/core/language-detector.js.map +1 -1
- package/dist/core/resolve-start.test.js +1 -0
- package/dist/core/resolve-start.test.js.map +1 -1
- package/dist/core/semantic-search-benchmark.d.ts +37 -0
- package/dist/core/semantic-search-benchmark.d.ts.map +1 -0
- package/dist/core/semantic-search-benchmark.js +211 -0
- package/dist/core/semantic-search-benchmark.js.map +1 -0
- package/dist/core/semantic-search-benchmark.test.d.ts +2 -0
- package/dist/core/semantic-search-benchmark.test.d.ts.map +1 -0
- package/dist/core/semantic-search-benchmark.test.js +89 -0
- package/dist/core/semantic-search-benchmark.test.js.map +1 -0
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +1 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/steering.d.ts +25 -0
- package/dist/core/steering.d.ts.map +1 -0
- package/dist/core/steering.js +29 -0
- package/dist/core/steering.js.map +1 -0
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +2 -1
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +10 -5
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/edit.d.ts +6 -0
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +34 -2
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +112 -0
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +8 -0
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/read.d.ts +1 -0
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +14 -3
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/read.test.js +40 -0
- package/dist/tools/read.test.js.map +1 -1
- package/dist/tools/search-code.d.ts +11 -0
- package/dist/tools/search-code.d.ts.map +1 -0
- package/dist/tools/search-code.js +95 -0
- package/dist/tools/search-code.js.map +1 -0
- package/dist/tools/search-code.test.d.ts +2 -0
- package/dist/tools/search-code.test.d.ts.map +1 -0
- package/dist/tools/search-code.test.js +77 -0
- package/dist/tools/search-code.test.js.map +1 -0
- package/dist/tools/tasks.d.ts +6 -0
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +41 -4
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/tasks.test.d.ts +2 -0
- package/dist/tools/tasks.test.d.ts.map +1 -0
- package/dist/tools/tasks.test.js +62 -0
- package/dist/tools/tasks.test.js.map +1 -0
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +8 -4
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/ModelSelector.d.ts.map +1 -1
- package/dist/ui/components/ModelSelector.js +1 -0
- package/dist/ui/components/ModelSelector.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +6 -4
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/login.d.ts.map +1 -1
- package/dist/ui/login.js +1 -0
- package/dist/ui/login.js.map +1 -1
- package/dist/utils/image.d.ts +17 -0
- package/dist/utils/image.d.ts.map +1 -1
- package/dist/utils/image.js +57 -2
- package/dist/utils/image.js.map +1 -1
- package/dist/utils/prompt-enhancer.d.ts +50 -0
- package/dist/utils/prompt-enhancer.d.ts.map +1 -0
- package/dist/utils/prompt-enhancer.js +127 -0
- package/dist/utils/prompt-enhancer.js.map +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast-apply vs current-edit benchmark — real-API measurement.
|
|
3
|
+
*
|
|
4
|
+
* Two strategies for the same edit task, measured end-to-end against live models:
|
|
5
|
+
*
|
|
6
|
+
* BASELINE (what ezcoder does today): the frontier model emits full
|
|
7
|
+
* search/replace edit blocks (old_text + new_text, verbatim context). Our
|
|
8
|
+
* edit tool then applies them LOCALLY and instantly (no apply model).
|
|
9
|
+
*
|
|
10
|
+
* FAST-APPLY (the proposed feature): the frontier model emits a terse "lazy"
|
|
11
|
+
* edit using `// ... existing code ...` markers (far fewer output tokens), and
|
|
12
|
+
* a cheap/fast "apply" model merges that lazy edit into the full file —
|
|
13
|
+
* regenerating the whole file as output.
|
|
14
|
+
*
|
|
15
|
+
* We measure, per task: frontier output tokens + time, apply-model output tokens
|
|
16
|
+
* + time, total wall-clock, and an anchor-based correctness check.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* npx tsx src/core/fast-apply-benchmark.ts
|
|
20
|
+
*
|
|
21
|
+
* Env overrides:
|
|
22
|
+
* GG_FA_FRONTIER_PROVIDER / GG_FA_FRONTIER_MODEL (default openai / gpt-5.5)
|
|
23
|
+
* GG_FA_APPLY_PROVIDER / GG_FA_APPLY_MODEL (default gemini / gemini-3.1-flash-lite-preview)
|
|
24
|
+
*/
|
|
25
|
+
import { stream } from "@prestyj/ai";
|
|
26
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
27
|
+
function genFile(lines) {
|
|
28
|
+
// Build a realistic-ish TS module with many small functions so the edit
|
|
29
|
+
// target sits in the middle and most of the file is "untouched context".
|
|
30
|
+
const head = [
|
|
31
|
+
`import { EventEmitter } from "node:events";`,
|
|
32
|
+
`import { performance } from "node:perf_hooks";`,
|
|
33
|
+
``,
|
|
34
|
+
`/** Auto-generated module with ${lines} lines for benchmarking. */`,
|
|
35
|
+
`export interface Config {`,
|
|
36
|
+
` retries: number;`,
|
|
37
|
+
` timeoutMs: number;`,
|
|
38
|
+
` label: string;`,
|
|
39
|
+
`}`,
|
|
40
|
+
``,
|
|
41
|
+
`const DEFAULT_TIMEOUT = 3000;`,
|
|
42
|
+
``,
|
|
43
|
+
];
|
|
44
|
+
const body = [];
|
|
45
|
+
let n = 0;
|
|
46
|
+
while (head.length + body.length < lines - 12) {
|
|
47
|
+
body.push(`export function task${n}(x: number): number {`, ` // step ${n}`, ` const y = x * ${n + 1} + DEFAULT_TIMEOUT;`, ` return y - ${n};`, `}`, ``);
|
|
48
|
+
n++;
|
|
49
|
+
}
|
|
50
|
+
const tail = [
|
|
51
|
+
`export function computeTimeout(cfg: Config): number {`,
|
|
52
|
+
` return cfg.timeoutMs > 0 ? cfg.timeoutMs : DEFAULT_TIMEOUT;`,
|
|
53
|
+
`}`,
|
|
54
|
+
``,
|
|
55
|
+
`export const SENTINEL_TAIL = "anchor_${lines}_end";`,
|
|
56
|
+
``,
|
|
57
|
+
];
|
|
58
|
+
return [...head, ...body, ...tail].join("\n");
|
|
59
|
+
}
|
|
60
|
+
function buildTasks() {
|
|
61
|
+
const sizes = [
|
|
62
|
+
{ name: "small", lines: 40 },
|
|
63
|
+
{ name: "medium", lines: 160 },
|
|
64
|
+
{ name: "large", lines: 420 },
|
|
65
|
+
];
|
|
66
|
+
return sizes.map((s) => ({
|
|
67
|
+
name: s.name,
|
|
68
|
+
approxLines: s.lines,
|
|
69
|
+
file: genFile(s.lines),
|
|
70
|
+
instruction: "Change `computeTimeout` so that when `cfg.retries` is greater than 0 it returns " +
|
|
71
|
+
"`cfg.timeoutMs * cfg.retries` (capped at 30000), otherwise it keeps the existing behaviour. " +
|
|
72
|
+
"Also add a one-line JSDoc comment above the function describing it.",
|
|
73
|
+
mustContain: ["cfg.timeoutMs * cfg.retries", "30000", "computeTimeout"],
|
|
74
|
+
mustPreserve: ["DEFAULT_TIMEOUT = 3000", `SENTINEL_TAIL = "anchor_${s.lines}_end"`, "task0"],
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
// ── Prompts ──────────────────────────────────────────────────
|
|
78
|
+
function baselinePrompt(file, instruction) {
|
|
79
|
+
return [
|
|
80
|
+
{
|
|
81
|
+
role: "system",
|
|
82
|
+
content: "You are a coding agent's edit engine. Output ONLY search/replace edit blocks " +
|
|
83
|
+
"in this exact format, nothing else:\n" +
|
|
84
|
+
"<<<<<<< SEARCH\n(exact text from the file)\n=======\n(replacement text)\n>>>>>>> REPLACE\n" +
|
|
85
|
+
"The SEARCH text must be copied verbatim from the file including surrounding context " +
|
|
86
|
+
"so it matches uniquely. Do not output explanations.",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
role: "user",
|
|
90
|
+
content: `FILE:\n\`\`\`ts\n${file}\n\`\`\`\n\nEDIT INSTRUCTION: ${instruction}`,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
function lazyEditPrompt(file, instruction) {
|
|
95
|
+
return [
|
|
96
|
+
{
|
|
97
|
+
role: "system",
|
|
98
|
+
content: "You are a coding agent. Output ONLY a concise 'lazy' edit snippet that shows the " +
|
|
99
|
+
"change, using `// ... existing code ...` to elide all unchanged regions. " +
|
|
100
|
+
"Show just enough surrounding context to locate the change unambiguously. " +
|
|
101
|
+
"Do not reproduce the whole file. Do not explain.",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
role: "user",
|
|
105
|
+
content: `FILE:\n\`\`\`ts\n${file}\n\`\`\`\n\nEDIT INSTRUCTION: ${instruction}`,
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
function applyPrompt(file, lazyEdit) {
|
|
110
|
+
return [
|
|
111
|
+
{
|
|
112
|
+
role: "system",
|
|
113
|
+
content: "You merge a lazy edit into a source file. Given the ORIGINAL file and an EDIT " +
|
|
114
|
+
"snippet that uses `// ... existing code ...` markers, output the COMPLETE final file " +
|
|
115
|
+
"with the edit applied. Output ONLY the raw file contents — no markdown fences, no commentary.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
role: "user",
|
|
119
|
+
content: `ORIGINAL FILE:\n${file}\n\nEDIT:\n${lazyEdit}`,
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
function sleep(ms) {
|
|
124
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
125
|
+
}
|
|
126
|
+
async function call(provider, model, apiKey, baseUrl, accountId, messages, maxTokens) {
|
|
127
|
+
// Retry transient provider errors (429/500) with exponential backoff so a
|
|
128
|
+
// flaky cheap model doesn't abort the whole benchmark.
|
|
129
|
+
let lastErr;
|
|
130
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
131
|
+
try {
|
|
132
|
+
return await callOnce(provider, model, apiKey, baseUrl, accountId, messages, maxTokens);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
lastErr = err;
|
|
136
|
+
await sleep(2000 * (attempt + 1));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
throw lastErr;
|
|
140
|
+
}
|
|
141
|
+
async function callOnce(provider, model, apiKey, baseUrl, accountId, messages, maxTokens) {
|
|
142
|
+
const start = Date.now();
|
|
143
|
+
let ttftMs = 0;
|
|
144
|
+
let first = true;
|
|
145
|
+
let text = "";
|
|
146
|
+
const result = stream({
|
|
147
|
+
provider: provider,
|
|
148
|
+
model,
|
|
149
|
+
messages,
|
|
150
|
+
maxTokens,
|
|
151
|
+
apiKey,
|
|
152
|
+
baseUrl,
|
|
153
|
+
accountId,
|
|
154
|
+
});
|
|
155
|
+
for await (const event of result) {
|
|
156
|
+
if (first && (event.type === "text_delta" || event.type === "thinking_delta")) {
|
|
157
|
+
ttftMs = Date.now() - start;
|
|
158
|
+
first = false;
|
|
159
|
+
}
|
|
160
|
+
if (event.type === "text_delta")
|
|
161
|
+
text += event.text;
|
|
162
|
+
}
|
|
163
|
+
const response = await result.response;
|
|
164
|
+
const wallMs = Date.now() - start;
|
|
165
|
+
const content = response.message.content;
|
|
166
|
+
const finalText = typeof content === "string"
|
|
167
|
+
? content
|
|
168
|
+
: content
|
|
169
|
+
.filter((p) => p.type === "text")
|
|
170
|
+
.map((p) => p.text ?? "")
|
|
171
|
+
.join("");
|
|
172
|
+
return {
|
|
173
|
+
text: finalText || text,
|
|
174
|
+
outputTokens: response.usage.outputTokens,
|
|
175
|
+
inputTokens: response.usage.inputTokens,
|
|
176
|
+
cacheRead: response.usage.cacheRead ?? 0,
|
|
177
|
+
ttftMs,
|
|
178
|
+
wallMs,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// ── Correctness ─────────────────────────────────────────────
|
|
182
|
+
function checkAnchors(finalFile, task) {
|
|
183
|
+
for (const s of task.mustContain)
|
|
184
|
+
if (!finalFile.includes(s))
|
|
185
|
+
return false;
|
|
186
|
+
for (const s of task.mustPreserve)
|
|
187
|
+
if (!finalFile.includes(s))
|
|
188
|
+
return false;
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
async function main() {
|
|
192
|
+
const frontierProvider = process.env.GG_FA_FRONTIER_PROVIDER ?? "openai";
|
|
193
|
+
const frontierModel = process.env.GG_FA_FRONTIER_MODEL ?? "gpt-5.5";
|
|
194
|
+
const applyProvider = process.env.GG_FA_APPLY_PROVIDER ?? "gemini";
|
|
195
|
+
const applyModel = process.env.GG_FA_APPLY_MODEL ?? "gemini-3.1-flash-lite-preview";
|
|
196
|
+
const auth = new AuthStorage();
|
|
197
|
+
await auth.load();
|
|
198
|
+
const resolve = async (p) => {
|
|
199
|
+
const c = await auth.resolveCredentials(p);
|
|
200
|
+
return { apiKey: c.accessToken, baseUrl: c.baseUrl, accountId: c.accountId };
|
|
201
|
+
};
|
|
202
|
+
const fc = await resolve(frontierProvider);
|
|
203
|
+
const ac = await resolve(applyProvider);
|
|
204
|
+
console.log(`\n⚡ Fast-apply benchmark`);
|
|
205
|
+
console.log(` Frontier: ${frontierProvider}/${frontierModel}`);
|
|
206
|
+
console.log(` Apply: ${applyProvider}/${applyModel}\n`);
|
|
207
|
+
const tasks = buildTasks();
|
|
208
|
+
const rows = [];
|
|
209
|
+
for (const task of tasks) {
|
|
210
|
+
process.stdout.write(`▶ ${task.name} (${task.approxLines} lines)\n`);
|
|
211
|
+
await sleep(2500); // space out calls to avoid cheap-model rate limits
|
|
212
|
+
// ── BASELINE: frontier emits full search/replace blocks (local apply = ~0ms) ──
|
|
213
|
+
const baseStart = Date.now();
|
|
214
|
+
const baseFrontier = await call(frontierProvider, frontierModel, fc.apiKey, fc.baseUrl, fc.accountId, baselinePrompt(task.file, task.instruction), 4096);
|
|
215
|
+
// Local apply is deterministic & instant; correctness = did the model produce
|
|
216
|
+
// a SEARCH block whose target text actually exists in the file?
|
|
217
|
+
const searchBlocks = [
|
|
218
|
+
...baseFrontier.text.matchAll(/<<<<<<< SEARCH\n([\s\S]*?)\n=======/g),
|
|
219
|
+
].map((m) => m[1]);
|
|
220
|
+
const replaceBlocks = [
|
|
221
|
+
...baseFrontier.text.matchAll(/=======\n([\s\S]*?)\n>>>>>>> REPLACE/g),
|
|
222
|
+
].map((m) => m[1]);
|
|
223
|
+
let baseFile = task.file;
|
|
224
|
+
let baseApplied = searchBlocks.length > 0;
|
|
225
|
+
for (let i = 0; i < searchBlocks.length; i++) {
|
|
226
|
+
if (baseFile.includes(searchBlocks[i])) {
|
|
227
|
+
baseFile = baseFile.replace(searchBlocks[i], replaceBlocks[i] ?? "");
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
baseApplied = false; // search text didn't match verbatim → would fail/retry
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const baseTotalMs = Date.now() - baseStart;
|
|
234
|
+
const baseOk = baseApplied && checkAnchors(baseFile, task);
|
|
235
|
+
process.stdout.write(` baseline: frontier ${baseFrontier.outputTokens} out tok, ${(baseFrontier.wallMs / 1000).toFixed(1)}s | apply ~0s | ${baseOk ? "OK" : "FAIL"}\n`);
|
|
236
|
+
// ── FAST-APPLY: frontier emits lazy edit, apply model merges whole file ──
|
|
237
|
+
const faStart = Date.now();
|
|
238
|
+
const faFrontier = await call(frontierProvider, frontierModel, fc.apiKey, fc.baseUrl, fc.accountId, lazyEditPrompt(task.file, task.instruction), 2048);
|
|
239
|
+
const apply = await call(applyProvider, applyModel, ac.apiKey, ac.baseUrl, ac.accountId, applyPrompt(task.file, faFrontier.text), 8192);
|
|
240
|
+
const faTotalMs = Date.now() - faStart;
|
|
241
|
+
const faFile = apply.text.replace(/^```[a-z]*\n?/i, "").replace(/\n?```$/i, "");
|
|
242
|
+
const faOk = checkAnchors(faFile, task);
|
|
243
|
+
process.stdout.write(` fast-apply: frontier ${faFrontier.outputTokens} out tok, ${(faFrontier.wallMs / 1000).toFixed(1)}s | apply ${apply.outputTokens} out tok, ${(apply.wallMs / 1000).toFixed(1)}s | ${faOk ? "OK" : "FAIL"}\n\n`);
|
|
244
|
+
rows.push({
|
|
245
|
+
task: task.name,
|
|
246
|
+
lines: task.approxLines,
|
|
247
|
+
baseFrontierTokens: baseFrontier.outputTokens,
|
|
248
|
+
baseFrontierMs: baseFrontier.wallMs,
|
|
249
|
+
baseTotalMs,
|
|
250
|
+
baseOk,
|
|
251
|
+
faFrontierTokens: faFrontier.outputTokens,
|
|
252
|
+
faFrontierMs: faFrontier.wallMs,
|
|
253
|
+
faApplyTokens: apply.outputTokens,
|
|
254
|
+
faApplyMs: apply.wallMs,
|
|
255
|
+
faTotalMs,
|
|
256
|
+
faOk,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// ── Report ──
|
|
260
|
+
console.log("\n══════════════════════ RESULTS ══════════════════════\n");
|
|
261
|
+
console.log("Task Lines | BASELINE total | FAST-APPLY total | Δ wall | base/fa frontier-out-tok | OK");
|
|
262
|
+
for (const r of rows) {
|
|
263
|
+
const delta = ((r.baseTotalMs - r.faTotalMs) / r.baseTotalMs) * 100;
|
|
264
|
+
console.log(`${r.task.padEnd(7)} ${String(r.lines).padStart(4)} | ` +
|
|
265
|
+
`${(r.baseTotalMs / 1000).toFixed(1).padStart(11)}s | ` +
|
|
266
|
+
`${(r.faTotalMs / 1000).toFixed(1).padStart(13)}s | ` +
|
|
267
|
+
`${(delta >= 0 ? "-" : "+") + Math.abs(delta).toFixed(0) + "%"}`.padStart(8) +
|
|
268
|
+
` | ${String(r.baseFrontierTokens).padStart(5)} / ${String(r.faFrontierTokens).padStart(5)}` +
|
|
269
|
+
` | ${r.baseOk ? "B" : "b"}${r.faOk ? "F" : "f"}`);
|
|
270
|
+
}
|
|
271
|
+
const sum = (f) => rows.reduce((s, r) => s + f(r), 0);
|
|
272
|
+
const baseTot = sum((r) => r.baseTotalMs);
|
|
273
|
+
const faTot = sum((r) => r.faTotalMs);
|
|
274
|
+
console.log(`\nTotals: baseline ${(baseTot / 1000).toFixed(1)}s vs fast-apply ${(faTot / 1000).toFixed(1)}s ` +
|
|
275
|
+
`→ ${baseTot > faTot ? "fast-apply faster" : "baseline faster"} by ${Math.abs(((baseTot - faTot) / baseTot) * 100).toFixed(0)}%`);
|
|
276
|
+
console.log(`Frontier output tokens: baseline ${sum((r) => r.baseFrontierTokens)} vs fast-apply ${sum((r) => r.faFrontierTokens)} ` +
|
|
277
|
+
`(${(((sum((r) => r.baseFrontierTokens) - sum((r) => r.faFrontierTokens)) / sum((r) => r.baseFrontierTokens)) * 100).toFixed(0)}% fewer)`);
|
|
278
|
+
console.log(`Correctness: baseline ${rows.filter((r) => r.baseOk).length}/${rows.length}, fast-apply ${rows.filter((r) => r.faOk).length}/${rows.length}`);
|
|
279
|
+
}
|
|
280
|
+
main().catch((err) => {
|
|
281
|
+
console.error("Benchmark failed:", err);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
});
|
|
284
|
+
//# sourceMappingURL=fast-apply-benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-apply-benchmark.js","sourceRoot":"","sources":["../../src/core/fast-apply-benchmark.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hashline (hash-anchored edits) vs current string-match edit — real-API
|
|
3
|
+
* measurement of whether Feature #2 is worth building.
|
|
4
|
+
*
|
|
5
|
+
* Two strategies produce the SAME edit against the SAME file, measured against
|
|
6
|
+
* live gpt-5.5:
|
|
7
|
+
*
|
|
8
|
+
* BASELINE (what ezcoder does today): the model emits { old_text, new_text }
|
|
9
|
+
* edits where old_text must be copied VERBATIM from the file with enough
|
|
10
|
+
* surrounding context to match uniquely (this is exactly our edit tool's
|
|
11
|
+
* contract — see tools/edit.ts). The reproduced context is what costs output
|
|
12
|
+
* tokens, and a non-unique / drifted old_text is what causes apply failures.
|
|
13
|
+
*
|
|
14
|
+
* HASHLINE (the proposed feature): every line is shown with a short content-
|
|
15
|
+
* hash anchor (`a3f1│<line>`). The model references anchors instead of
|
|
16
|
+
* reproducing text — it emits { from, to, lines } where from/to are anchors.
|
|
17
|
+
* Anchors are unique by construction, so an edit either resolves exactly or is
|
|
18
|
+
* rejected (never silently corrupts), and the model writes far fewer tokens.
|
|
19
|
+
*
|
|
20
|
+
* We measure, per task: model OUTPUT tokens (the headline -61% claim), whether
|
|
21
|
+
* the edit applied cleanly + produced the correct file, and an anchor-uniqueness
|
|
22
|
+
* / safety check. Edits are graded deterministically — no second model needed.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* npx tsx src/core/hashline-edit-benchmark.ts
|
|
26
|
+
*
|
|
27
|
+
* Env overrides:
|
|
28
|
+
* GG_HL_PROVIDER / GG_HL_MODEL (default openai / gpt-5.5)
|
|
29
|
+
* GG_HL_REPEAT (runs per task, default 1 — raise to average noise)
|
|
30
|
+
*/
|
|
31
|
+
import { type AnchoredFile } from "./hashline.js";
|
|
32
|
+
export interface EditTask {
|
|
33
|
+
name: string;
|
|
34
|
+
approxLines: number;
|
|
35
|
+
file: string;
|
|
36
|
+
instruction: string;
|
|
37
|
+
/** Substrings that MUST appear in the correctly-edited file. */
|
|
38
|
+
mustContain: string[];
|
|
39
|
+
/** Substrings that MUST still be present (unchanged anchors far from the edit). */
|
|
40
|
+
mustPreserve: string[];
|
|
41
|
+
}
|
|
42
|
+
export declare function genFile(lines: number): string;
|
|
43
|
+
export declare function buildTasks(): EditTask[];
|
|
44
|
+
export interface ApplyOutcome {
|
|
45
|
+
applied: boolean;
|
|
46
|
+
correct: boolean;
|
|
47
|
+
/** edits whose locator was non-unique / unresolvable (would error in the real tool). */
|
|
48
|
+
ambiguousEdits: number;
|
|
49
|
+
parsedEdits: number;
|
|
50
|
+
}
|
|
51
|
+
export declare function stripFence(s: string): string;
|
|
52
|
+
export declare function checkAnchors(file: string, task: EditTask): boolean;
|
|
53
|
+
export declare function applyBaseline(raw: string, task: EditTask): ApplyOutcome;
|
|
54
|
+
export declare function applyHashline(raw: string, task: EditTask, anchored: AnchoredFile): ApplyOutcome;
|
|
55
|
+
//# sourceMappingURL=hashline-edit-benchmark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashline-edit-benchmark.d.ts","sourceRoot":"","sources":["../../src/core/hashline-edit-benchmark.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAI9D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mFAAmF;IACnF,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqC7C;AAED,wBAAgB,UAAU,IAAI,QAAQ,EAAE,CAiBvC;AA2CD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAIlE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,YAAY,CA2BvE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY,CAmC/F"}
|