Skip to content

Commit 225aefd

Browse files
committed
🤖 fix: auto-naming works with mux-gateway
When users only have mux-gateway configured (no direct Anthropic/OpenAI API keys), getPreferredNameModel now tries gateway versions of preferred models. The fix: 1. After trying each preferred model directly (anthropic:claude-haiku-4-5), also try the gateway version (mux-gateway:anthropic/claude-haiku-4-5) 2. Still prefers direct access when available for lower latency This ensures auto-naming works for gateway-only users while maintaining optimal performance for users with direct API keys. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high`_
1 parent b98b323 commit 225aefd

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

src/node/services/workspaceTitleGenerator.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ function createMockAIService(availableModels: string[]): AIService {
3030
describe("workspaceTitleGenerator", () => {
3131
const HAIKU_ID = getKnownModel("HAIKU").id;
3232
const GPT_MINI_ID = getKnownModel("GPT_MINI").id;
33+
// Gateway format: mux-gateway:provider/model instead of provider:model
34+
const HAIKU_GATEWAY = "mux-gateway:anthropic/claude-haiku-4-5";
35+
const GPT_MINI_GATEWAY = "mux-gateway:openai/gpt-5.1-codex-mini";
3336

3437
it("getPreferredNameModel returns null when no models available", async () => {
3538
const aiService = createMockAIService([]);
@@ -47,4 +50,25 @@ describe("workspaceTitleGenerator", () => {
4750
const model = await getPreferredNameModel(aiService);
4851
expect(model).toBe(GPT_MINI_ID);
4952
});
53+
54+
it("getPreferredNameModel uses gateway Haiku when direct is unavailable", async () => {
55+
// User has mux-gateway configured but no direct Anthropic/OpenAI API keys
56+
const aiService = createMockAIService([HAIKU_GATEWAY, GPT_MINI_GATEWAY]);
57+
const model = await getPreferredNameModel(aiService);
58+
expect(model).toBe(HAIKU_GATEWAY);
59+
});
60+
61+
it("getPreferredNameModel falls back to gateway GPT Mini", async () => {
62+
// Only GPT Mini available via gateway
63+
const aiService = createMockAIService([GPT_MINI_GATEWAY]);
64+
const model = await getPreferredNameModel(aiService);
65+
expect(model).toBe(GPT_MINI_GATEWAY);
66+
});
67+
68+
it("getPreferredNameModel prefers direct over gateway", async () => {
69+
// Both direct and gateway available - should prefer direct
70+
const aiService = createMockAIService([HAIKU_ID, HAIKU_GATEWAY]);
71+
const model = await getPreferredNameModel(aiService);
72+
expect(model).toBe(HAIKU_ID);
73+
});
5074
});

src/node/services/workspaceTitleGenerator.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ import crypto from "crypto";
1111
/** Models to try in order of preference for name generation (small, fast models) */
1212
const PREFERRED_MODELS = [getKnownModel("HAIKU").id, getKnownModel("GPT_MINI").id] as const;
1313

14+
/**
15+
* Convert a canonical model string (provider:model) to mux-gateway format.
16+
* Example: "anthropic:claude-haiku-4-5" → "mux-gateway:anthropic/claude-haiku-4-5"
17+
*/
18+
function toGatewayModel(modelId: string): string {
19+
const [provider, model] = modelId.split(":", 2);
20+
if (!provider || !model) return modelId;
21+
return `mux-gateway:${provider}/${model}`;
22+
}
23+
1424
/** Schema for AI-generated workspace identity (area name + descriptive title) */
1525
const workspaceIdentitySchema = z.object({
1626
name: z
@@ -39,14 +49,24 @@ export interface WorkspaceIdentity {
3949
* Get the preferred model for name generation by testing which models the AIService
4050
* can actually create. This delegates credential checking to AIService, avoiding
4151
* duplication of provider-specific API key logic.
52+
*
53+
* Tries each preferred model first as direct provider access, then via mux-gateway.
54+
* This ensures gateway users still get fast/cheap models for name generation.
4255
*/
4356
export async function getPreferredNameModel(aiService: AIService): Promise<string | null> {
4457
for (const modelId of PREFERRED_MODELS) {
45-
const result = await aiService.createModel(modelId);
46-
if (result.success) {
58+
// Try direct provider access first
59+
const directResult = await aiService.createModel(modelId);
60+
if (directResult.success) {
4761
return modelId;
4862
}
49-
// If it's an API key error, try the next model; other errors are also skipped
63+
64+
// Try via mux-gateway (for users without direct provider API keys)
65+
const gatewayModelId = toGatewayModel(modelId);
66+
const gatewayResult = await aiService.createModel(gatewayModelId);
67+
if (gatewayResult.success) {
68+
return gatewayModelId;
69+
}
5070
}
5171
return null;
5272
}

0 commit comments

Comments
 (0)