- Add opencode to SupportedIde with JSON providers.json output - Add defaultModel parameter for IDE config generation - Add model selector dropdown in ToolsTab for IDE configurations - Use getServiceOptional for graceful degradation when proxy is stopped - Add fallback IDE config generation using ConfigManager when NestJS is offline - Update IPC router schema to accept defaultModel parameter
148 lines
4.1 KiB
TypeScript
148 lines
4.1 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import { networkInterfaces } from 'os';
|
|
import { getServerConfig } from '../../server-config';
|
|
import { registerProxyAdvancedService } from '../../../ipc/proxy-advanced/service-registry';
|
|
|
|
export type SupportedIde =
|
|
| 'cursor'
|
|
| 'vscode'
|
|
| 'claude-code'
|
|
| 'jetbrains'
|
|
| 'opencide'
|
|
| 'opencode';
|
|
|
|
export interface IdeConfigResult {
|
|
ide: SupportedIde;
|
|
format: 'json' | 'shell' | 'env' | 'instructions';
|
|
content: Record<string, any> | string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class ProxyIdeConfigService {
|
|
private readonly logger = new Logger(ProxyIdeConfigService.name);
|
|
|
|
constructor() {
|
|
registerProxyAdvancedService('proxyIdeConfig', this);
|
|
}
|
|
|
|
/**
|
|
* Return the first non-internal IPv4 address found on the machine.
|
|
* Falls back to '127.0.0.1' if no external interface is available.
|
|
*/
|
|
getLocalIp(): string {
|
|
const interfaces = networkInterfaces();
|
|
for (const iface of Object.values(interfaces)) {
|
|
if (!iface) {
|
|
continue;
|
|
}
|
|
for (const entry of iface) {
|
|
if (entry.family === 'IPv4' && !entry.internal) {
|
|
return entry.address;
|
|
}
|
|
}
|
|
}
|
|
return '127.0.0.1';
|
|
}
|
|
|
|
/**
|
|
* Generate a ready-to-paste IDE configuration for the given IDE.
|
|
*/
|
|
generateIdeConfig(
|
|
ide: SupportedIde,
|
|
port: number,
|
|
apiKey: string,
|
|
localIp: string,
|
|
defaultModel: string = 'gemini-3.1-pro-high',
|
|
): IdeConfigResult {
|
|
const baseUrl = `http://${localIp}:${port}/v1`;
|
|
|
|
switch (ide) {
|
|
case 'cursor': {
|
|
return {
|
|
ide,
|
|
format: 'json',
|
|
content: {
|
|
OPENAI_API_KEY: apiKey,
|
|
OPENAI_BASE_URL: baseUrl,
|
|
},
|
|
};
|
|
}
|
|
case 'vscode': {
|
|
return {
|
|
ide,
|
|
format: 'json',
|
|
content: {
|
|
'openai.url': baseUrl,
|
|
'openai.apiKey': apiKey,
|
|
},
|
|
};
|
|
}
|
|
case 'claude-code': {
|
|
return {
|
|
ide,
|
|
format: 'shell',
|
|
content: `export OPENAI_API_KEY=${apiKey} && export OPENAI_BASE_URL=${baseUrl}`,
|
|
};
|
|
}
|
|
case 'jetbrains': {
|
|
return {
|
|
ide,
|
|
format: 'instructions',
|
|
content: [
|
|
'JetBrains AI Assistant Setup:',
|
|
'1. Open Settings (File > Settings or Ctrl+Alt+S).',
|
|
'2. Navigate to Languages & Frameworks > AI Assistant.',
|
|
'3. Under "Custom OpenAI Endpoint", set:',
|
|
` - Base URL: ${baseUrl}`,
|
|
` - API Key: ${apiKey}`,
|
|
'4. Click "Apply" and restart the IDE if prompted.',
|
|
].join('\n'),
|
|
};
|
|
}
|
|
case 'opencide': {
|
|
return {
|
|
ide,
|
|
format: 'env',
|
|
content: `OPENAI_API_KEY=${apiKey}\nOPENAI_BASE_URL=${baseUrl}`,
|
|
};
|
|
}
|
|
case 'opencode': {
|
|
return {
|
|
ide,
|
|
format: 'json',
|
|
content: {
|
|
apiType: 'openai',
|
|
apiKey: apiKey,
|
|
baseURL: baseUrl,
|
|
models: {
|
|
chat: [defaultModel],
|
|
},
|
|
},
|
|
};
|
|
}
|
|
default: {
|
|
// Exhaustive fallback to satisfy TypeScript
|
|
const exhaustiveCheck: never = ide;
|
|
this.logger.warn(`Unsupported IDE requested: ${String(exhaustiveCheck)}`);
|
|
throw new Error(`Unsupported IDE: ${String(exhaustiveCheck)}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convenience helper that reads the current server config and local IP,
|
|
* then delegates to generateIdeConfig.
|
|
*/
|
|
generateConfigForCurrentServer(ide: SupportedIde, defaultModel?: string): IdeConfigResult | null {
|
|
const config = getServerConfig();
|
|
if (!config) {
|
|
this.logger.warn('Server config not available; cannot generate IDE config');
|
|
return null;
|
|
}
|
|
const port = config.port;
|
|
const apiKey = config.api_key;
|
|
const localIp = this.getLocalIp();
|
|
return this.generateIdeConfig(ide, port, apiKey, localIp, defaultModel);
|
|
}
|
|
}
|