Commita5705cfunknown_key
fix: upgrade all AI calls from Haiku to Sonnet 4.6 — quality first across every feature
10 files changed+22−22a5705cf47baddef90d57f5810f201ada73fe6734
10 changed files+22−22
Modifiedsrc/lib/ai-client.ts+2−2View fileUnifiedSplit
@@ -22,9 +22,9 @@ export function isAiAvailable(): boolean {
2222 return !!config.anthropicApiKey;
2323}
2424
25/** Default model for code understanding + review */
25/** Primary model for all AI features — code understanding, review, generation */
2626export const MODEL_SONNET = "claude-sonnet-4-6";
27/** Fast model for lightweight tasks (commit messages, titles) */
27/** Legacy constant — kept for backwards compatibility, do not use in new code */
2828export const MODEL_HAIKU = "claude-haiku-4-5-20251001";
2929
3030/**
Modifiedsrc/lib/ai-commit-message.ts+2−2View fileUnifiedSplit
@@ -273,7 +273,7 @@ export async function generateCommitMessage(
273273 try {
274274 const client = getAnthropic();
275275 const message = await client.messages.create({
276 model: MODEL_HAIKU,
276 model: MODEL_SONNET,
277277 max_tokens: 512,
278278 messages: [
279279 {
@@ -286,7 +286,7 @@ export async function generateCommitMessage(
286286 const { recordAiCost, extractUsage } = await import("./ai-cost-tracker");
287287 const usage = extractUsage(message);
288288 await recordAiCost({
289 model: MODEL_HAIKU,
289 model: MODEL_SONNET,
290290 inputTokens: usage.input,
291291 outputTokens: usage.output,
292292 category: "other",
Modifiedsrc/lib/ai-completion.ts+4−4View fileUnifiedSplit
@@ -7,7 +7,7 @@
77 * JetBrains) call on every keystroke.
88 *
99 * Design notes:
10 * - Uses Haiku because latency matters more than depth for inline suggestions.
10 * - Uses Sonnet 4.6 for quality inline suggestions.
1111 * - Input is clipped aggressively (8k chars before, 2k chars after) so a huge
1212 * file doesn't blow the token budget.
1313 * - Never throws. On any error (bad key, timeout, rate limit) we return an
@@ -120,13 +120,13 @@ export async function completeCode(
120120 const key = cacheKey(prefix, suffix, language);
121121 const hit = cacheGet(key);
122122 if (hit !== undefined) {
123 return { completion: hit, model: MODEL_HAIKU, cached: true };
123 return { completion: hit, model: MODEL_SONNET, cached: true };
124124 }
125125
126126 try {
127127 const client = getAnthropic();
128128 const response = await client.messages.create({
129 model: MODEL_HAIKU,
129 model: MODEL_SONNET,
130130 max_tokens: maxTokens,
131131 system:
132132 "You are a code completion engine. Given a prefix and optional suffix, output ONLY the characters that should be inserted at the cursor. No explanations. No markdown fences. No commentary.",
@@ -145,7 +145,7 @@ export async function completeCode(
145145 const raw = extractText(response);
146146 const completion = stripCodeFences(raw);
147147 cacheSet(key, completion);
148 return { completion, model: MODEL_HAIKU, cached: false };
148 return { completion, model: MODEL_SONNET, cached: false };
149149 } catch (err) {
150150 // Never throw — the editor should degrade silently. Log length only, not
151151 // the prefix itself, which can contain secrets.
Modifiedsrc/lib/ai-generators.ts+3−3View fileUnifiedSplit
@@ -18,7 +18,7 @@ export async function generateCommitMessage(diff: string): Promise<string> {
1818 }
1919 const client = getAnthropic();
2020 const message = await client.messages.create({
21 model: MODEL_HAIKU,
21 model: MODEL_SONNET,
2222 max_tokens: 512,
2323 messages: [
2424 {
@@ -124,7 +124,7 @@ export async function triageIssue(
124124 if (!isAiAvailable()) return fallback;
125125 const client = getAnthropic();
126126 const message = await client.messages.create({
127 model: MODEL_HAIKU,
127 model: MODEL_SONNET,
128128 max_tokens: 512,
129129 messages: [
130130 {
@@ -200,7 +200,7 @@ export async function triagePullRequest(
200200 try {
201201 const client = getAnthropic();
202202 const message = await client.messages.create({
203 model: MODEL_HAIKU,
203 model: MODEL_SONNET,
204204 max_tokens: 512,
205205 messages: [
206206 {
Modifiedsrc/lib/claude-semantic-search.ts+1−1View fileUnifiedSplit
@@ -322,7 +322,7 @@ Only include files with confidence > 0.2. Return [] if nothing is relevant.`;
322322
323323 try {
324324 const message = await client.messages.create({
325 model: MODEL_HAIKU,
325 model: MODEL_SONNET,
326326 max_tokens: 1000,
327327 messages: [{ role: "user", content: prompt }],
328328 });
Modifiedsrc/lib/dev-env.ts+2−2View fileUnifiedSplit
@@ -166,7 +166,7 @@ export async function readDevYml(
166166}
167167
168168/**
169 * Ask Claude (Haiku) to draft a `.gluecron/dev.yml` for a repo. Used when
169 * Ask Claude (Sonnet) to draft a `.gluecron/dev.yml` for a repo. Used when
170170 * the repo hasn't committed one. Returns the YAML body, or
171171 * `DEFAULT_DEV_YML` if AI is unavailable / errors. Never throws.
172172 */
@@ -175,7 +175,7 @@ export async function generateDevYml(repoHint: string): Promise<string> {
175175 try {
176176 const client = getAnthropic();
177177 const message = await client.messages.create({
178 model: MODEL_HAIKU,
178 model: MODEL_SONNET,
179179 max_tokens: 800,
180180 messages: [
181181 {
Modifiedsrc/lib/hosted-claude-loop.ts+2−2View fileUnifiedSplit
@@ -62,7 +62,7 @@ const RUN_LOG_CAP_BYTES = 32 * 1024;
6262const COST_CATEGORY: AiCostCategory = "other";
6363
6464/** Default model fallback when the snippet didn't tell us what it ran. */
65const DEFAULT_MODEL = "claude-haiku-4-5";
65const DEFAULT_MODEL = "claude-sonnet-4-6";
6666
6767// ---------------------------------------------------------------------------
6868// Pure helpers
@@ -170,7 +170,7 @@ const input = JSON.parse(process.env.INPUT || "{}");
170170const repo = input.repo || "ccantynz-alt/Gluecron.com";
171171
172172const result = await client.messages.create({
173 model: "claude-haiku-4-5",
173 model: "claude-sonnet-4-6",
174174 max_tokens: 1024,
175175 messages: [
176176 { role: "user", content: \`Summarise repo \${repo} in 3 bullets\` },
Modifiedsrc/lib/pr-risk.ts+3−3View fileUnifiedSplit
@@ -5,14 +5,14 @@
55 * the reviewer can see at a glance before clicking Merge. The score is a
66 * pure function over a small set of signals (file count, line count,
77 * teams affected, schema migrations touched, dependency churn, test
8 * ratio). The LLM (Haiku — fast + cheap) only writes the one-paragraph
8 * ratio). The LLM (Sonnet 4.6) only writes the one-paragraph
99 * prose summary; it never influences the numeric score.
1010 *
1111 * Architecture:
1212 *
1313 * 1. `computePrRiskScore(signals)` — pure helper. Same input always
1414 * yields the same score. Documented inline; auditable.
15 * 2. `generatePrRiskSummary(args)` — calls Haiku for prose. Never
15 * 2. `generatePrRiskSummary(args)` — calls Sonnet for prose. Never
1616 * throws — falls back to a deterministic sentence when no API key
1717 * is set or the call fails.
1818 * 3. `computePrRiskForPullRequest(prId)` — DB-backed orchestrator.
@@ -174,7 +174,7 @@ export async function generatePrRiskSummary(args: {
174174 try {
175175 const client = getAnthropic();
176176 const message = await client.messages.create({
177 model: MODEL_HAIKU,
177 model: MODEL_SONNET,
178178 max_tokens: 200,
179179 messages: [
180180 {
Modifiedsrc/lib/pr-sandbox.ts+2−2View fileUnifiedSplit
@@ -150,7 +150,7 @@ export async function readPlaygroundYml(
150150}
151151
152152/**
153 * Ask Claude (Haiku) to draft a playground.yml for a repo. Used when the
153 * Ask Claude (Sonnet) to draft a playground.yml for a repo. Used when the
154154 * repo hasn't committed one. Returns the YAML body, or
155155 * `DEFAULT_PLAYGROUND_YML` if AI is unavailable / errors. Never throws.
156156 *
@@ -164,7 +164,7 @@ export async function generatePlaygroundYml(
164164 try {
165165 const client = getAnthropic();
166166 const message = await client.messages.create({
167 model: MODEL_HAIKU,
167 model: MODEL_SONNET,
168168 max_tokens: 800,
169169 messages: [
170170 {
Modifiedsrc/routes/ai-editor.ts+1−1View fileUnifiedSplit
@@ -90,7 +90,7 @@ aiEditor.post("/api/ai/suggest", requireAuth, async (c) => {
9090 try {
9191 const anthropic = getAnthropic();
9292 const message = await anthropic.messages.create({
93 model: MODEL_HAIKU,
93 model: MODEL_SONNET,
9494 max_tokens: 256,
9595 system:
9696 "You are a code completion AI. Complete the code snippet at the cursor. " +
9797