@kenkaiiii/ggcoder 5.74.3 → 5.75.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/README.md +1 -1
- package/assets/skills/bulletproof/SKILL.md +1 -1
- package/assets/skills/clarify/SKILL.md +1 -1
- package/assets/skills/code-review/SKILL.md +1 -1
- package/assets/skills/compliance-guard/SKILL.md +1 -1
- package/assets/skills/durable/SKILL.md +1 -1
- package/assets/skills/evidence-led-ui/SKILL.md +1 -1
- package/assets/skills/lean/SKILL.md +1 -1
- package/assets/skills/refactoring/SKILL.md +1 -1
- package/assets/skills/root-cause/SKILL.md +1 -1
- package/assets/skills/shared-language/SKILL.md +1 -1
- package/assets/skills/tdd/SKILL.md +1 -1
- package/dist/app-sidecar/app-settings.d.ts +65 -0
- package/dist/app-sidecar/app-settings.js +147 -0
- package/dist/app-sidecar/app-settings.js.map +1 -0
- package/dist/app-sidecar/attachments.d.ts +11 -0
- package/dist/app-sidecar/attachments.js +47 -0
- package/dist/app-sidecar/attachments.js.map +1 -0
- package/dist/app-sidecar/auth-routes.d.ts +3 -0
- package/dist/app-sidecar/auth-routes.js +290 -0
- package/dist/app-sidecar/auth-routes.js.map +1 -0
- package/dist/app-sidecar/autopilot-runner.d.ts +61 -0
- package/dist/app-sidecar/autopilot-runner.js +367 -0
- package/dist/app-sidecar/autopilot-runner.js.map +1 -0
- package/dist/app-sidecar/file-search.d.ts +15 -0
- package/dist/app-sidecar/file-search.js +103 -0
- package/dist/app-sidecar/file-search.js.map +1 -0
- package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
- package/dist/app-sidecar/hf-pull-manager.js +224 -0
- package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
- package/dist/app-sidecar/history-routes.d.ts +3 -0
- package/dist/app-sidecar/history-routes.js +375 -0
- package/dist/app-sidecar/history-routes.js.map +1 -0
- package/dist/app-sidecar/history.d.ts +67 -0
- package/dist/app-sidecar/history.js +23 -0
- package/dist/app-sidecar/history.js.map +1 -0
- package/dist/app-sidecar/http.d.ts +5 -0
- package/dist/app-sidecar/http.js +27 -0
- package/dist/app-sidecar/http.js.map +1 -0
- package/dist/app-sidecar/integration-routes.d.ts +3 -0
- package/dist/app-sidecar/integration-routes.js +286 -0
- package/dist/app-sidecar/integration-routes.js.map +1 -0
- package/dist/app-sidecar/json-mode.d.ts +10 -0
- package/dist/app-sidecar/json-mode.js +73 -0
- package/dist/app-sidecar/json-mode.js.map +1 -0
- package/dist/app-sidecar/keep-awake.d.ts +4 -0
- package/dist/app-sidecar/keep-awake.js +5 -0
- package/dist/app-sidecar/keep-awake.js.map +1 -0
- package/dist/app-sidecar/ken-context.d.ts +20 -0
- package/dist/app-sidecar/ken-context.js +55 -0
- package/dist/app-sidecar/ken-context.js.map +1 -0
- package/dist/app-sidecar/mcp-routes.d.ts +3 -0
- package/dist/app-sidecar/mcp-routes.js +185 -0
- package/dist/app-sidecar/mcp-routes.js.map +1 -0
- package/dist/app-sidecar/mcp-rows.d.ts +31 -0
- package/dist/app-sidecar/mcp-rows.js +77 -0
- package/dist/app-sidecar/mcp-rows.js.map +1 -0
- package/dist/app-sidecar/progress-manager.d.ts +10 -0
- package/dist/app-sidecar/progress-manager.js +116 -0
- package/dist/app-sidecar/progress-manager.js.map +1 -0
- package/dist/app-sidecar/prompt-routes.d.ts +3 -0
- package/dist/app-sidecar/prompt-routes.js +354 -0
- package/dist/app-sidecar/prompt-routes.js.map +1 -0
- package/dist/app-sidecar/route-context.d.ts +145 -0
- package/dist/app-sidecar/route-context.js +2 -0
- package/dist/app-sidecar/route-context.js.map +1 -0
- package/dist/app-sidecar/run-control-routes.d.ts +3 -0
- package/dist/app-sidecar/run-control-routes.js +430 -0
- package/dist/app-sidecar/run-control-routes.js.map +1 -0
- package/dist/app-sidecar/session-routes.d.ts +3 -0
- package/dist/app-sidecar/session-routes.js +115 -0
- package/dist/app-sidecar/session-routes.js.map +1 -0
- package/dist/app-sidecar/session-types.d.ts +39 -0
- package/dist/app-sidecar/session-types.js +5 -0
- package/dist/app-sidecar/session-types.js.map +1 -0
- package/dist/app-sidecar/task-routes.d.ts +3 -0
- package/dist/app-sidecar/task-routes.js +149 -0
- package/dist/app-sidecar/task-routes.js.map +1 -0
- package/dist/app-sidecar/usage.d.ts +19 -0
- package/dist/app-sidecar/usage.js +153 -0
- package/dist/app-sidecar/usage.js.map +1 -0
- package/dist/app-sidecar/workspace-routes.d.ts +3 -0
- package/dist/app-sidecar/workspace-routes.js +244 -0
- package/dist/app-sidecar/workspace-routes.js.map +1 -0
- package/dist/app-sidecar.js +440 -3720
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/core/acceptance-checks.js +3 -9
- package/dist/core/acceptance-checks.js.map +1 -1
- package/dist/core/agent-session/helpers.d.ts +26 -0
- package/dist/core/agent-session/helpers.js +47 -0
- package/dist/core/agent-session/helpers.js.map +1 -0
- package/dist/core/agent-session/mcp-tools.d.ts +68 -0
- package/dist/core/agent-session/mcp-tools.js +195 -0
- package/dist/core/agent-session/mcp-tools.js.map +1 -0
- package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
- package/dist/core/agent-session/run-loop-monitor.js +164 -0
- package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
- package/dist/core/agent-session/transcript-markers.d.ts +57 -0
- package/dist/core/agent-session/transcript-markers.js +166 -0
- package/dist/core/agent-session/transcript-markers.js.map +1 -0
- package/dist/core/agent-session/verification-tracker.d.ts +46 -0
- package/dist/core/agent-session/verification-tracker.js +246 -0
- package/dist/core/agent-session/verification-tracker.js.map +1 -0
- package/dist/core/agent-session.d.ts +21 -87
- package/dist/core/agent-session.js +141 -712
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-providers.js +3 -3
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/bundled-agents.js +6 -6
- package/dist/core/bundled-agents.js.map +1 -1
- package/dist/core/checklist-git.d.ts +19 -0
- package/dist/core/checklist-git.js +54 -0
- package/dist/core/checklist-git.js.map +1 -0
- package/dist/core/checklist-items.d.ts +10 -1
- package/dist/core/checklist-items.js +22 -0
- package/dist/core/checklist-items.js.map +1 -1
- package/dist/core/checklist-prompt.d.ts +5 -1
- package/dist/core/checklist-prompt.js +16 -5
- package/dist/core/checklist-prompt.js.map +1 -1
- package/dist/core/checklist-snapshot.d.ts +5 -1
- package/dist/core/checklist-snapshot.js +19 -2
- package/dist/core/checklist-snapshot.js.map +1 -1
- package/dist/core/context-limits.js +1 -1
- package/dist/core/context-limits.js.map +1 -1
- package/dist/core/skills.js +6 -9
- package/dist/core/skills.js.map +1 -1
- package/dist/core/style-packs/index.js +2 -11
- package/dist/core/style-packs/index.js.map +1 -1
- package/dist/core/style-packs/packs.d.ts +3 -12
- package/dist/core/style-packs/packs.js +132 -173
- package/dist/core/style-packs/packs.js.map +1 -1
- package/dist/system-prompt.js +55 -78
- package/dist/system-prompt.js.map +1 -1
- package/dist/tools/ask-user.js +13 -74
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/bash.js +13 -78
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/checklist.d.ts +2 -10
- package/dist/tools/checklist.js +7 -39
- package/dist/tools/checklist.js.map +1 -1
- package/dist/tools/code-nav.js +7 -29
- package/dist/tools/code-nav.js.map +1 -1
- package/dist/tools/edit.d.ts +3 -9
- package/dist/tools/edit.js +66 -65
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/enter-plan.js +2 -7
- package/dist/tools/enter-plan.js.map +1 -1
- package/dist/tools/exit-plan.js +2 -3
- package/dist/tools/exit-plan.js.map +1 -1
- package/dist/tools/find.js +3 -4
- package/dist/tools/find.js.map +1 -1
- package/dist/tools/grep.js +6 -18
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/ls.js +3 -3
- package/dist/tools/ls.js.map +1 -1
- package/dist/tools/prompt-hints.js +34 -47
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/read.js +8 -20
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/search-code.js +4 -12
- package/dist/tools/search-code.js.map +1 -1
- package/dist/tools/skill.js +13 -7
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent-control.js +7 -22
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent.js +4 -7
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/task-output.js +4 -15
- package/dist/tools/task-output.js.map +1 -1
- package/dist/tools/task-send.js +5 -17
- package/dist/tools/task-send.js.map +1 -1
- package/dist/tools/task-stop.js +2 -2
- package/dist/tools/task-stop.js.map +1 -1
- package/dist/tools/tool-search.js +2 -7
- package/dist/tools/tool-search.js.map +1 -1
- package/dist/tools/tool-tiers.d.ts +17 -4
- package/dist/tools/tool-tiers.js +38 -15
- package/dist/tools/tool-tiers.js.map +1 -1
- package/dist/tools/web-fetch.js +7 -33
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/write.js +3 -4
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/components/Footer.js +1 -2
- package/dist/ui/components/Footer.js.map +1 -1
- package/package.json +7 -4
- package/dist/core/api-benchmark.d.ts +0 -63
- package/dist/core/api-benchmark.js +0 -381
- package/dist/core/api-benchmark.js.map +0 -1
- package/dist/core/bash-spawn-benchmark.d.ts +0 -1
- package/dist/core/bash-spawn-benchmark.js +0 -139
- package/dist/core/bash-spawn-benchmark.js.map +0 -1
- package/dist/core/cache-warm-benchmark.d.ts +0 -21
- package/dist/core/cache-warm-benchmark.js +0 -170
- package/dist/core/cache-warm-benchmark.js.map +0 -1
- package/dist/core/fast-apply-benchmark.d.ts +0 -25
- package/dist/core/fast-apply-benchmark.js +0 -284
- package/dist/core/fast-apply-benchmark.js.map +0 -1
- package/dist/core/hashline-edit-benchmark.d.ts +0 -88
- package/dist/core/hashline-edit-benchmark.js +0 -518
- package/dist/core/hashline-edit-benchmark.js.map +0 -1
- package/dist/core/semantic-search-benchmark.d.ts +0 -36
- package/dist/core/semantic-search-benchmark.js +0 -211
- package/dist/core/semantic-search-benchmark.js.map +0 -1
- package/dist/core/speed-benchmark.d.ts +0 -132
- package/dist/core/speed-benchmark.js +0 -410
- package/dist/core/speed-benchmark.js.map +0 -1
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Prompt-cache warming micro-benchmark — isolates the cache effect.
|
|
3
|
-
*
|
|
4
|
-
* The existing api-benchmark grows the conversation each turn and uses a tiny
|
|
5
|
-
* (~250 token) system prompt, which is BELOW Anthropic's minimum cacheable
|
|
6
|
-
* prefix (1024 tok Sonnet/Opus, 2048 Haiku) — so caching never engages and the
|
|
7
|
-
* A/B is dominated by turn-to-turn throughput variance.
|
|
8
|
-
*
|
|
9
|
-
* This test uses a large, FIXED prefix (well above the min) and a tiny variable
|
|
10
|
-
* suffix, then measures, per arm:
|
|
11
|
-
* COLD — fresh cache key, first hit (cache WRITE, no read).
|
|
12
|
-
* WARM — prewarm the prefix, then measure the next call's cache_read + TTFT.
|
|
13
|
-
*
|
|
14
|
-
* It reports cache_read tokens and TTFT directly, so the cache effect is visible
|
|
15
|
-
* regardless of throughput noise.
|
|
16
|
-
*
|
|
17
|
-
* Usage: npx tsx src/core/cache-warm-benchmark.ts
|
|
18
|
-
* Env: GG_CW_PROVIDER (default anthropic), GG_CW_MODEL (default claude-haiku-4-5-20251001),
|
|
19
|
-
* GG_CW_REPS (default 4)
|
|
20
|
-
*/
|
|
21
|
-
import { stream } from "@kenkaiiii/gg-ai";
|
|
22
|
-
import { AuthStorage } from "./auth-storage.js";
|
|
23
|
-
/** Build a large, realistic coding-agent system prompt (~well above 2048 tok). */
|
|
24
|
-
function bigPrefix() {
|
|
25
|
-
const toolDoc = (name, desc) => `### ${name}\n${desc}\nParameters are validated with a Zod schema and converted to JSON Schema at the provider boundary. ` +
|
|
26
|
-
`Errors are returned as structured tool results so the agent can self-correct in the same turn. `;
|
|
27
|
-
const tools = [
|
|
28
|
-
toolDoc("read", "Read a file's contents with cat -n style numbered lines, truncated to 2000 lines or 50KB."),
|
|
29
|
-
toolDoc("write", "Write content to a file, creating parent directories. Existing files must be read first."),
|
|
30
|
-
toolDoc("edit", "Replace text via search/replace blocks applied sequentially with a fuzzy fallback ladder."),
|
|
31
|
-
toolDoc("bash", "Execute a shell command in a non-interactive bash shell with combined stdout/stderr."),
|
|
32
|
-
toolDoc("grep", "Search file contents using regex, returning filepath:line:content matches."),
|
|
33
|
-
toolDoc("find", "Find files matching a glob pattern, respecting .gitignore."),
|
|
34
|
-
toolDoc("ls", "List directory contents with file types and sizes."),
|
|
35
|
-
toolDoc("web_fetch", "Fetch and read web page content as Markdown, extracting main content."),
|
|
36
|
-
toolDoc("subagent", "Spawn an isolated sub-agent with its own context window for a focused task."),
|
|
37
|
-
toolDoc("task_output", "Read new output from a background process by id."),
|
|
38
|
-
];
|
|
39
|
-
// Repeat the tool block several times so the prefix clears Anthropic's
|
|
40
|
-
// minimum cacheable size (1024 tok Sonnet/Opus, 2048 Haiku) with headroom.
|
|
41
|
-
const bulkTools = [];
|
|
42
|
-
for (let r = 0; r < 22; r++)
|
|
43
|
-
bulkTools.push(...tools, `<!-- tool block repetition ${r} for prefix sizing -->`);
|
|
44
|
-
return [
|
|
45
|
-
"You are GG Coder — a coding agent that works directly in the user's codebase.",
|
|
46
|
-
"You explore, understand, change, and verify code end-to-end.",
|
|
47
|
-
"",
|
|
48
|
-
"## How to Talk",
|
|
49
|
-
"Lead with the outcome. One idea per line. Bottom line first. No preamble or recap.",
|
|
50
|
-
"Stay silent between tool calls unless you hit a decision, tradeoff, or question.",
|
|
51
|
-
"",
|
|
52
|
-
"## How to Work",
|
|
53
|
-
"Read before edit/write; re-read after formatters, codegen, or any disk mutator.",
|
|
54
|
-
"Match neighbouring code style. Keep edits small; plan multi-file work first.",
|
|
55
|
-
"Choose targeted verification appropriate to the change; read and fix failures.",
|
|
56
|
-
"Do not assume APIs, CLI flags, config schema, or error wording — verify against source.",
|
|
57
|
-
"",
|
|
58
|
-
"## Tools",
|
|
59
|
-
...bulkTools,
|
|
60
|
-
"",
|
|
61
|
-
"## Code Quality",
|
|
62
|
-
"Intent-revealing names; reuse existing deps. Types first; handle I/O, input, and external API errors.",
|
|
63
|
-
"No dead or commented-out code, placeholders, or unasked refactors.",
|
|
64
|
-
"",
|
|
65
|
-
"## Environment",
|
|
66
|
-
"Working directory: /home/user/project. Platform: darwin.",
|
|
67
|
-
].join("\n");
|
|
68
|
-
}
|
|
69
|
-
async function call(cfg, system, user, promptCacheKey, cacheRetention) {
|
|
70
|
-
const messages = [
|
|
71
|
-
{ role: "system", content: system },
|
|
72
|
-
{ role: "user", content: user },
|
|
73
|
-
];
|
|
74
|
-
const start = Date.now();
|
|
75
|
-
let ttftMs = 0;
|
|
76
|
-
let first = true;
|
|
77
|
-
const result = stream({
|
|
78
|
-
provider: cfg.provider,
|
|
79
|
-
model: cfg.model,
|
|
80
|
-
messages,
|
|
81
|
-
maxTokens: 16,
|
|
82
|
-
apiKey: cfg.apiKey,
|
|
83
|
-
baseUrl: cfg.baseUrl,
|
|
84
|
-
accountId: cfg.accountId,
|
|
85
|
-
promptCacheKey,
|
|
86
|
-
cacheRetention,
|
|
87
|
-
});
|
|
88
|
-
for await (const event of result) {
|
|
89
|
-
if (first && (event.type === "text_delta" || event.type === "thinking_delta")) {
|
|
90
|
-
ttftMs = Date.now() - start;
|
|
91
|
-
first = false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const response = await result.response;
|
|
95
|
-
return {
|
|
96
|
-
ttftMs: ttftMs || Date.now() - start,
|
|
97
|
-
wallMs: Date.now() - start,
|
|
98
|
-
inputTokens: response.usage.inputTokens,
|
|
99
|
-
cacheRead: response.usage.cacheRead ?? 0,
|
|
100
|
-
cacheWrite: response.usage.cacheWrite ?? 0,
|
|
101
|
-
outputTokens: response.usage.outputTokens,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function sleep(ms) {
|
|
105
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
106
|
-
}
|
|
107
|
-
async function main() {
|
|
108
|
-
const provider = process.env.GG_CW_PROVIDER ?? "anthropic";
|
|
109
|
-
const model = process.env.GG_CW_MODEL ?? "claude-haiku-4-5-20251001";
|
|
110
|
-
const reps = parseInt(process.env.GG_CW_REPS ?? "4", 10);
|
|
111
|
-
const auth = new AuthStorage();
|
|
112
|
-
await auth.load();
|
|
113
|
-
const c = await auth.resolveCredentials(provider);
|
|
114
|
-
const cfg = {
|
|
115
|
-
provider,
|
|
116
|
-
model,
|
|
117
|
-
apiKey: c.accessToken,
|
|
118
|
-
baseUrl: c.baseUrl,
|
|
119
|
-
accountId: c.accountId,
|
|
120
|
-
};
|
|
121
|
-
const system = bigPrefix();
|
|
122
|
-
// Rough token size of the prefix (chars/3.3) for context.
|
|
123
|
-
console.log(`\n🔥 Cache-warm micro-benchmark: ${provider}/${model}`);
|
|
124
|
-
console.log(` Prefix ~${Math.round(system.length / 3.3)} tokens, ${reps} reps per arm\n`);
|
|
125
|
-
// ── COLD arm: every rep uses a UNIQUE cache key → never reads cache ──
|
|
126
|
-
console.log("▶ COLD (no warming — fresh cache key each call):");
|
|
127
|
-
// Each cold rep gets UNIQUE prefix content (Anthropic caches by content, not
|
|
128
|
-
// by key) so every call is a true cache miss — otherwise rep 2+ would read
|
|
129
|
-
// rep 1's cache and pollute the cold baseline.
|
|
130
|
-
const cold = [];
|
|
131
|
-
for (let i = 0; i < reps; i++) {
|
|
132
|
-
const uniqueSystem = `<!-- cold-sample-${Date.now()}-${i} -->\n${system}`;
|
|
133
|
-
const m = await call(cfg, uniqueSystem, `Question ${i}: name one tool.`, `cold-${Date.now()}-${i}`, "short");
|
|
134
|
-
cold.push(m);
|
|
135
|
-
console.log(` rep ${i + 1}: TTFT ${m.ttftMs}ms | in ${m.inputTokens} | cacheRead ${m.cacheRead} | cacheWrite ${m.cacheWrite}`);
|
|
136
|
-
await sleep(1500);
|
|
137
|
-
}
|
|
138
|
-
await sleep(3000);
|
|
139
|
-
// ── WARM arm: prewarm a SHARED key, then measure subsequent calls (cache reads) ──
|
|
140
|
-
console.log("\n▶ WARM (prewarm shared prefix, then measure cache reads):");
|
|
141
|
-
const warmKey = `warm-${Date.now()}`;
|
|
142
|
-
// Prewarm: a throwaway call that writes the cache.
|
|
143
|
-
const pw = await call(cfg, system, "warm.", warmKey, "long");
|
|
144
|
-
console.log(` prewarm: cacheWrite ${pw.cacheWrite} (cache primed)`);
|
|
145
|
-
await sleep(1500);
|
|
146
|
-
const warm = [];
|
|
147
|
-
for (let i = 0; i < reps; i++) {
|
|
148
|
-
const m = await call(cfg, system, `Question ${i}: name one tool.`, warmKey, "long");
|
|
149
|
-
warm.push(m);
|
|
150
|
-
console.log(` rep ${i + 1}: TTFT ${m.ttftMs}ms | in ${m.inputTokens} | cacheRead ${m.cacheRead} | cacheWrite ${m.cacheWrite}`);
|
|
151
|
-
await sleep(1500);
|
|
152
|
-
}
|
|
153
|
-
const avg = (xs, f) => xs.reduce((s, m) => s + f(m), 0) / xs.length;
|
|
154
|
-
const coldTtft = avg(cold, (m) => m.ttftMs);
|
|
155
|
-
const warmTtft = avg(warm, (m) => m.ttftMs);
|
|
156
|
-
const coldRead = avg(cold, (m) => m.cacheRead);
|
|
157
|
-
const warmRead = avg(warm, (m) => m.cacheRead);
|
|
158
|
-
console.log("\n══════════════════════ RESULTS ══════════════════════");
|
|
159
|
-
console.log(`Avg cacheRead tokens : cold ${coldRead.toFixed(0)} → warm ${warmRead.toFixed(0)}`);
|
|
160
|
-
console.log(`Avg TTFT : cold ${coldTtft.toFixed(0)}ms → warm ${warmTtft.toFixed(0)}ms ` +
|
|
161
|
-
`(${coldTtft > warmTtft ? "-" : "+"}${Math.abs(((coldTtft - warmTtft) / coldTtft) * 100).toFixed(0)}%)`);
|
|
162
|
-
const warmHitRate = warm.filter((m) => m.cacheRead > 0).length / warm.length;
|
|
163
|
-
console.log(`Warm cache hit rate : ${(warmHitRate * 100).toFixed(0)}%`);
|
|
164
|
-
console.log(`Verdict: ${warmRead > 0 ? "caching ENGAGES when prefix exceeds the min — warming converts cold writes to reads" : "caching did NOT engage (prefix below provider minimum, or OAuth path strips cache_control)"}`);
|
|
165
|
-
}
|
|
166
|
-
main().catch((err) => {
|
|
167
|
-
console.error("Benchmark failed:", err);
|
|
168
|
-
process.exit(1);
|
|
169
|
-
});
|
|
170
|
-
//# sourceMappingURL=cache-warm-benchmark.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache-warm-benchmark.js","sourceRoot":"","sources":["../../src/core/cache-warm-benchmark.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +0,0 @@
|
|
|
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 ggcoder 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-6.1-sol)
|
|
23
|
-
* GG_FA_APPLY_PROVIDER / GG_FA_APPLY_MODEL (default gemini / gemini-3.1-flash-lite)
|
|
24
|
-
*/
|
|
25
|
-
export {};
|
|
@@ -1,284 +0,0 @@
|
|
|
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 ggcoder 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-6.1-sol)
|
|
23
|
-
* GG_FA_APPLY_PROVIDER / GG_FA_APPLY_MODEL (default gemini / gemini-3.1-flash-lite)
|
|
24
|
-
*/
|
|
25
|
-
import { stream } from "@kenkaiiii/gg-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-6.1-sol";
|
|
194
|
-
const applyProvider = process.env.GG_FA_APPLY_PROVIDER ?? "gemini";
|
|
195
|
-
const applyModel = process.env.GG_FA_APPLY_MODEL ?? "gemini-3.1-flash-lite";
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fast-apply-benchmark.js","sourceRoot":"","sources":["../../src/core/fast-apply-benchmark.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,88 +0,0 @@
|
|
|
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 ggcoder 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
|
-
* The BASELINE apply path runs ggcoder's REAL edit ladder (fuzzy match +
|
|
25
|
-
* indent-flex + blank-edge strip + dotdotdots — the same edit-diff functions
|
|
26
|
-
* tools/edit.ts uses), so baseline numbers reflect what our tool actually
|
|
27
|
-
* recovers, not a naive exact-replace.
|
|
28
|
-
*
|
|
29
|
-
* Usage:
|
|
30
|
-
* npx tsx src/core/hashline-edit-benchmark.ts
|
|
31
|
-
*
|
|
32
|
-
* Env overrides:
|
|
33
|
-
* GG_HL_PROVIDER / GG_HL_MODEL (default anthropic / claude-sonnet-5)
|
|
34
|
-
* GG_HL_AUTH_KEY (auth.json key when it differs from the provider name,
|
|
35
|
-
* e.g. `xiaomi-credits` for provider `xiaomi`)
|
|
36
|
-
* GG_HL_REPEAT (runs per task, default 1 — raise to average noise)
|
|
37
|
-
*/
|
|
38
|
-
import { type AnchoredFile } from "./hashline.js";
|
|
39
|
-
export interface EditTask {
|
|
40
|
-
name: string;
|
|
41
|
-
approxLines: number;
|
|
42
|
-
file: string;
|
|
43
|
-
instruction: string;
|
|
44
|
-
/** Substrings that MUST appear in the correctly-edited file. */
|
|
45
|
-
mustContain: string[];
|
|
46
|
-
/** Substrings that MUST still be present (unchanged anchors far from the edit). */
|
|
47
|
-
mustPreserve: string[];
|
|
48
|
-
/** Optional extra validator for tasks where substring checks are too weak. */
|
|
49
|
-
validate?: (file: string) => boolean;
|
|
50
|
-
}
|
|
51
|
-
export declare function genFile(lines: number): string;
|
|
52
|
-
/** Near-identical handler blocks — uniqueness pressure for string matching. */
|
|
53
|
-
export declare function genRepetitiveFile(blocks: number): string;
|
|
54
|
-
export declare function buildTasks(): EditTask[];
|
|
55
|
-
export interface ApplyOutcome {
|
|
56
|
-
applied: boolean;
|
|
57
|
-
correct: boolean;
|
|
58
|
-
/** edits whose locator was non-unique / unresolvable (would error in the real tool). */
|
|
59
|
-
ambiguousEdits: number;
|
|
60
|
-
parsedEdits: number;
|
|
61
|
-
}
|
|
62
|
-
export declare function stripFence(s: string): string;
|
|
63
|
-
/**
|
|
64
|
-
* Parse the model's JSON envelope, tolerating literal (unescaped) newlines and
|
|
65
|
-
* tabs inside string values. In production, edits arrive as STRUCTURED
|
|
66
|
-
* tool-call arguments — the JSON envelope is a benchmark artifact — so both
|
|
67
|
-
* strategies get the same repair to keep the comparison about the EDIT FORMAT,
|
|
68
|
-
* not about JSON string-escaping discipline.
|
|
69
|
-
*/
|
|
70
|
-
export declare function parseEnvelope<T>(raw: string): T | null;
|
|
71
|
-
export declare function checkAnchors(file: string, task: EditTask): boolean;
|
|
72
|
-
/**
|
|
73
|
-
* ggcoder's REAL apply ladder, mirroring tools/edit.ts:
|
|
74
|
-
* 1. exact + smart-quote/dash fuzzy
|
|
75
|
-
* 2. indent-flex
|
|
76
|
-
* 3. blank-edge strip, retry 1+2
|
|
77
|
-
* 4. dotdotdots elision
|
|
78
|
-
* Returns the new working buffer or a failure reason.
|
|
79
|
-
*/
|
|
80
|
-
export declare function applyLadder(working: string, oldText: string, newText: string): {
|
|
81
|
-
ok: true;
|
|
82
|
-
working: string;
|
|
83
|
-
} | {
|
|
84
|
-
ok: false;
|
|
85
|
-
reason: "not_found" | "ambiguous";
|
|
86
|
-
};
|
|
87
|
-
export declare function applyBaseline(raw: string, task: EditTask): ApplyOutcome;
|
|
88
|
-
export declare function applyHashline(raw: string, task: EditTask, anchored: AnchoredFile): ApplyOutcome;
|