1- import { generateObject , type LanguageModel } from "ai" ;
1+ import { generateObject } from "ai" ;
22import { z } from "zod" ;
3- import type { Config } from "@/node/config " ;
3+ import type { AIService } from "./aiService " ;
44import { log } from "./log" ;
5- import { createAnthropic } from "@ai-sdk/anthropic" ;
6- import { createOpenAI } from "@ai-sdk/openai" ;
7- import { PROVIDER_REGISTRY } from "@/common/constants/providers" ;
8-
95import type { Result } from "@/common/types/result" ;
106import { Ok , Err } from "@/common/types/result" ;
117import type { SendMessageError } from "@/common/types/errors" ;
@@ -27,39 +23,16 @@ const workspaceNameSchema = z.object({
2723export async function generateWorkspaceName (
2824 message : string ,
2925 modelString : string ,
30- config : Config
26+ aiService : AIService
3127) : Promise < Result < string , SendMessageError > > {
3228 try {
33- const model = await getModelForTitleGeneration ( modelString , config ) ;
34-
35- if ( ! model ) {
36- // Infer error from provider + config (mirrors createModel in aiService)
37- const [ providerName , modelId ] = modelString . split ( ":" , 2 ) ;
38- if ( ! providerName || ! modelId ) {
39- return Err ( {
40- type : "invalid_model_string" ,
41- message : `Invalid model string format: "${ modelString } ". Expected "provider:model-id"` ,
42- } ) ;
43- }
44-
45- const providers = config . loadProvidersConfig ( ) ;
46-
47- // Require API keys for providers that need them
48- if (
49- ( providerName === "anthropic" ||
50- providerName === "openai" ||
51- providerName === "openrouter" ) &&
52- ! providers ?. [ providerName ] ?. apiKey
53- ) {
54- return Err ( { type : "api_key_not_found" , provider : providerName } ) ;
55- }
56-
57- // Unknown/unsupported provider
58- return Err ( { type : "provider_not_supported" , provider : providerName } ) ;
29+ const modelResult = await aiService . createModel ( modelString ) ;
30+ if ( ! modelResult . success ) {
31+ return Err ( modelResult . error ) ;
5932 }
6033
6134 const result = await generateObject ( {
62- model,
35+ model : modelResult . data ,
6336 schema : workspaceNameSchema ,
6437 prompt : `Generate a git-safe branch/workspace name for this development task:\n\n"${ message } "\n\nRequirements:\n- Git-safe identifier (e.g., "automatic-title-generation")\n- Lowercase, hyphens only, no spaces\n- Concise (2-5 words) and descriptive of the task` ,
6538 } ) ;
@@ -72,72 +45,6 @@ export async function generateWorkspaceName(
7245 }
7346}
7447
75- /**
76- * Get model for title generation - prefers fast/cheap models
77- * Priority: Haiku 4.5 (Anthropic) → GPT-5-mini (OpenAI) → fallback to user's model
78- * Falls back to null if no provider configured
79- */
80- async function getModelForTitleGeneration (
81- modelString : string ,
82- config : Config
83- ) : Promise < LanguageModel | null > {
84- const providersConfig = config . loadProvidersConfig ( ) ;
85-
86- if ( ! providersConfig ) {
87- return null ;
88- }
89-
90- try {
91- // Use exactly what the user selected. Prefer their model over any defaults.
92- const [ providerName , modelId ] = modelString . split ( ":" , 2 ) ;
93- if ( ! providerName || ! modelId ) {
94- log . error ( "Invalid model string format:" , modelString ) ;
95- return null ;
96- }
97-
98- if ( providerName === "anthropic" ) {
99- if ( ! providersConfig . anthropic ?. apiKey ) return null ;
100- const provider = createAnthropic ( { apiKey : String ( providersConfig . anthropic . apiKey ) } ) ;
101- return provider ( modelId ) ;
102- }
103-
104- if ( providerName === "openai" ) {
105- if ( ! providersConfig . openai ?. apiKey ) return null ;
106- const provider = createOpenAI ( { apiKey : String ( providersConfig . openai . apiKey ) } ) ;
107- // Use Responses API model variant to match aiService
108- return provider . responses ( modelId ) ;
109- }
110-
111- if ( providerName === "openrouter" ) {
112- if ( ! providersConfig . openrouter ?. apiKey ) return null ;
113- const { createOpenRouter } = await PROVIDER_REGISTRY . openrouter ( ) ;
114- const provider = createOpenRouter ( {
115- apiKey : String ( providersConfig . openrouter . apiKey ) ,
116- baseURL : providersConfig . openrouter . baseUrl ,
117- headers : providersConfig . openrouter . headers as Record < string , string > | undefined ,
118- } ) ;
119- return provider ( modelId ) ;
120- }
121-
122- if ( providerName === "ollama" ) {
123- const { createOllama } = await PROVIDER_REGISTRY . ollama ( ) ;
124- const provider = createOllama ( {
125- baseURL : ( providersConfig . ollama ?. baseUrl ?? providersConfig . ollama ?. baseURL ) as
126- | string
127- | undefined ,
128- } ) ;
129- return provider ( modelId ) ;
130- }
131-
132- // Unknown provider
133- log . error ( `Provider ${ providerName } not configured or not supported for titles` ) ;
134- return null ;
135- } catch ( error ) {
136- log . error ( `Failed to create model for title generation` , error ) ;
137- return null ;
138- }
139- }
140-
14148/**
14249 * Validate and sanitize branch name to be git-safe
14350 */
0 commit comments