Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/nodeBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,62 @@ class NodeHandlerRegistry {
};
});

// test a specific model
this.messageBus.registerHandler('models.test', async (data) => {
const { cwd, modelId } = data;
const context = await this.getContext(cwd);
const startTime = Date.now();

try {
const { model, error } = await resolveModelWithContext(
modelId,
context,
);

if (error || !model) {
return {
success: false,
error:
error instanceof Error
? error.message
: error || 'Model not found',
responseTime: Date.now() - startTime,
};
}

const m = await model._mCreator();
const result = await m.doGenerate({
prompt: [
{
role: 'user',
content: [{ type: 'text', text: 'Hi' }],
},
],
});

const hasResponse = result.content?.some(
(c) => c.type === 'text' && (c as { text: string }).text,
);

return {
success: true,
data: {
modelId,
providerName: model.provider.name,
modelName: model.model.name,
responseTime: Date.now() - startTime,
hasResponse,
},
};
} catch (err) {
return {
success: false,
error: err instanceof Error ? err.message : 'Unknown error',
responseTime: Date.now() - startTime,
};
}
});

//////////////////////////////////////////////
// outputStyles
this.messageBus.registerHandler('outputStyles.list', async (data) => {
Expand Down Expand Up @@ -2356,6 +2412,17 @@ function buildSignalKey(cwd: string, sessionId: string) {
return `${cwd}/${sessionId}`;
}

// Default API endpoints for providers that use SDK defaults
const DEFAULT_PROVIDER_ENDPOINTS: Record<string, string> = {
openai: 'https://api.openai.com',
google: 'https://generativelanguage.googleapis.com',
xai: 'https://api.x.ai',
anthropic: 'https://api.anthropic.com',
openrouter: 'https://openrouter.ai',
cerebras: 'https://api.cerebras.ai',
antigravity: 'https://antigravity.google',
};

function normalizeProviders(providers: ProvidersMap, context: Context) {
return Object.values(providers as Record<string, Provider>).map(
(provider) => {
Expand All @@ -2382,12 +2449,16 @@ function normalizeProviders(providers: ProvidersMap, context: Context) {
provider.options?.apiKey ||
context.config.provider?.[provider.id]?.options?.apiKey
);
// Use provider.api or fallback to default endpoint
const api =
provider.api || DEFAULT_PROVIDER_ENDPOINTS[provider.id] || undefined;
return {
id: provider.id,
name: provider.name,
doc: provider.doc,
env: provider.env,
apiEnv: provider.apiEnv,
api,
validEnvs,
hasApiKey,
};
Expand Down
19 changes: 19 additions & 0 deletions src/nodeBridge.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,23 @@ type ModelsListOutput = {
};
};

type ModelsTestInput = {
cwd: string;
modelId: string;
};
type ModelsTestOutput = {
success: boolean;
error?: string;
responseTime: number;
data?: {
modelId: string;
providerName: string;
modelName: string;
responseTime: number;
hasResponse: boolean;
};
};

// ============================================================================
// Output Styles Handlers
// ============================================================================
Expand Down Expand Up @@ -435,6 +452,7 @@ type ProvidersListOutput = {
doc?: string;
env?: string[];
apiEnv?: string[];
api?: string;
validEnvs: string[];
hasApiKey: boolean;
}>;
Expand Down Expand Up @@ -863,6 +881,7 @@ export type HandlerMap = {

// Models handlers
'models.list': { input: ModelsListInput; output: ModelsListOutput };
'models.test': { input: ModelsTestInput; output: ModelsTestOutput };

// Output styles handlers
'outputStyles.list': {
Expand Down
2 changes: 2 additions & 0 deletions src/slash-commands/builtin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createLogoutCommand } from './logout';
import { createMcpCommand } from './mcp';
import { createModelCommand } from './model';
import { createOutputStyleCommand } from './output-style';
import { pingCommand } from './ping';
import { createResumeCommand } from './resume';
import { createReviewCommand } from './review';
import { brainstormCommand } from './spec/brainstorm';
Expand All @@ -38,6 +39,7 @@ export function createBuiltinCommands(opts: {
createMcpCommand(opts),
createModelCommand(opts),
createOutputStyleCommand(),
pingCommand,
createResumeCommand(),
createReviewCommand(opts.language),
createTerminalSetupCommand(),
Expand Down
Loading
Loading