feat: consume server model reasoning capabilities
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
} from '../route-utils';
|
||||
import { decodeRouteId, sendCodingRouteError } from './coding-route-errors';
|
||||
|
||||
const THINKING_LEVELS = new Set(['off', 'minimal', 'low', 'medium', 'high']);
|
||||
const THINKING_LEVELS = new Set(['off', 'minimal', 'low', 'medium', 'high', 'max']);
|
||||
|
||||
function invalidRequest(message: string): never {
|
||||
throw new CodingConversationServiceError(400, 'CODING_CONVERSATION_REQUEST_INVALID', message);
|
||||
@@ -187,7 +187,7 @@ export async function handleCodingConversationRoutes(
|
||||
sendJson(res, 200, {
|
||||
model: await service.setThinking(
|
||||
conversationId,
|
||||
body.thinkingLevel as 'off' | 'minimal' | 'low' | 'medium' | 'high',
|
||||
body.thinkingLevel as 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'max',
|
||||
),
|
||||
});
|
||||
return true;
|
||||
|
||||
@@ -20,8 +20,10 @@ import { seedWorksSquareAIGatewayCredential } from '../../services/works-square-
|
||||
import {
|
||||
NIANCODE_USER_MODEL_ACCOUNT_ID,
|
||||
NIANCODE_USER_MODEL_ACCOUNT_LABEL,
|
||||
normalizeImportedModelCapabilities,
|
||||
normalizeImportedUserModelId,
|
||||
} from '../../../shared/user-model-config';
|
||||
import type { ImportedModelCapabilities } from '../../../shared/imported-model-profile';
|
||||
|
||||
const legacyProviderRoutesWarned = new Set<string>();
|
||||
|
||||
@@ -141,6 +143,7 @@ type ImportedUserModelConfig = {
|
||||
credentialMode: string;
|
||||
apiKeyExpiresIn: number | null;
|
||||
models: string[];
|
||||
modelCapabilities?: ImportedModelCapabilities;
|
||||
};
|
||||
|
||||
const WORKS_SQUARE_AI_GATEWAY_CREDENTIAL_MODE = 'works_square_ai_gateway';
|
||||
@@ -157,7 +160,7 @@ class WorksSquareModelConfigError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeImportedUserModelConfig(payload: unknown): ImportedUserModelConfig {
|
||||
export function normalizeImportedUserModelConfig(payload: unknown): ImportedUserModelConfig {
|
||||
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
||||
throw new Error('Works Square model config response is invalid');
|
||||
}
|
||||
@@ -181,6 +184,7 @@ function normalizeImportedUserModelConfig(payload: unknown): ImportedUserModelCo
|
||||
const label = typeof record.label === 'string' && record.label.trim()
|
||||
? record.label.trim()
|
||||
: NIANCODE_USER_MODEL_ACCOUNT_LABEL;
|
||||
const modelCapabilities = normalizeImportedModelCapabilities(record.model_capabilities, models);
|
||||
|
||||
return {
|
||||
label,
|
||||
@@ -189,6 +193,7 @@ function normalizeImportedUserModelConfig(payload: unknown): ImportedUserModelCo
|
||||
credentialMode: credentialMode || 'api_key',
|
||||
apiKeyExpiresIn,
|
||||
models,
|
||||
...(modelCapabilities ? { modelCapabilities } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,9 +216,13 @@ function importedUserModelMetadata(
|
||||
if (useLocalAiProxy) {
|
||||
const metadata = { ...(existing?.metadata ?? {}) };
|
||||
delete metadata.worksSquareCredentialExpiresAt;
|
||||
delete metadata.worksSquareModelCapabilities;
|
||||
return {
|
||||
...metadata,
|
||||
customModels: modelConfig.models,
|
||||
...(modelConfig.modelCapabilities
|
||||
? { worksSquareModelCapabilities: modelConfig.modelCapabilities }
|
||||
: {}),
|
||||
worksSquareCredentialMode: WORKS_SQUARE_AI_GATEWAY_PROXY_CREDENTIAL_MODE,
|
||||
worksSquareOneApiBaseUrl: modelConfig.baseUrl,
|
||||
};
|
||||
@@ -222,12 +231,16 @@ function importedUserModelMetadata(
|
||||
const metadata = { ...(existing?.metadata ?? {}) };
|
||||
delete metadata.worksSquareCredentialExpiresAt;
|
||||
delete metadata.worksSquareOneApiBaseUrl;
|
||||
delete metadata.worksSquareModelCapabilities;
|
||||
const credentialExpiresAt = modelConfig.apiKeyExpiresIn === null
|
||||
? undefined
|
||||
: new Date(nowMs + modelConfig.apiKeyExpiresIn * 1000).toISOString();
|
||||
return {
|
||||
...metadata,
|
||||
customModels: modelConfig.models,
|
||||
...(modelConfig.modelCapabilities
|
||||
? { worksSquareModelCapabilities: modelConfig.modelCapabilities }
|
||||
: {}),
|
||||
worksSquareCredentialMode: modelConfig.credentialMode,
|
||||
...(credentialExpiresAt ? { worksSquareCredentialExpiresAt: credentialExpiresAt } : {}),
|
||||
};
|
||||
@@ -295,6 +308,7 @@ function providerAccountRuntimeShape(account: ProviderAccount): unknown {
|
||||
isDefault: account.isDefault,
|
||||
metadata: {
|
||||
customModels: account.metadata?.customModels,
|
||||
worksSquareModelCapabilities: account.metadata?.worksSquareModelCapabilities,
|
||||
worksSquareCredentialMode: account.metadata?.worksSquareCredentialMode,
|
||||
worksSquareOneApiBaseUrl: account.metadata?.worksSquareOneApiBaseUrl,
|
||||
},
|
||||
|
||||
@@ -72,6 +72,7 @@ const THINKING_LEVELS = new Set<ConversationThinkingLevel>([
|
||||
'low',
|
||||
'medium',
|
||||
'high',
|
||||
'max',
|
||||
]);
|
||||
|
||||
function projectConfigPath(projectPath: string): string {
|
||||
|
||||
@@ -17,7 +17,10 @@ import {
|
||||
normalizeImportedUserModelId,
|
||||
selectUserModelRuntimeAccounts,
|
||||
} from '../../../shared/user-model-config';
|
||||
import { getImportedModelProfile } from '../../../shared/imported-model-profile';
|
||||
import {
|
||||
getImportedModelProfile,
|
||||
thinkingLevelMapForImportedModelCapability,
|
||||
} from '../../../shared/imported-model-profile';
|
||||
|
||||
const PI_ENV_PREFIX = 'MAKELORE_PI';
|
||||
const WORKS_SQUARE_AI_GATEWAY_CREDENTIAL_MODE = 'works_square_ai_gateway';
|
||||
@@ -302,6 +305,7 @@ function modelDescriptor(
|
||||
));
|
||||
const backend = backendModels.get(modelId);
|
||||
const profile = getImportedModelProfile(modelId);
|
||||
const serverCapability = account.metadata?.worksSquareModelCapabilities?.[modelId];
|
||||
const backendInput = Array.isArray(backend?.input)
|
||||
? backend.input.filter((input): input is 'text' | 'image' => input === 'text' || input === 'image')
|
||||
: [];
|
||||
@@ -319,17 +323,28 @@ function modelDescriptor(
|
||||
id: modelId,
|
||||
name: summary?.name || (typeof backend?.name === 'string' && backend.name.trim()) || modelId,
|
||||
input: supportsImage ? ['text', 'image'] : ['text'],
|
||||
reasoning: summary?.supportsReasoning === true
|
||||
|| profile?.pi?.reasoning === true
|
||||
|| backend?.reasoning === true,
|
||||
reasoning: serverCapability
|
||||
? serverCapability.reasoningEfforts.length > 0
|
||||
: summary?.supportsReasoning === true
|
||||
|| profile?.pi?.reasoning === true
|
||||
|| backend?.reasoning === true,
|
||||
...(contextWindow ? { contextWindow } : {}),
|
||||
...(maxOutputTokens ? { maxOutputTokens } : {}),
|
||||
...(compat || profile?.pi?.compat || enforcedCompat
|
||||
? { compat: { ...compat, ...profile?.pi?.compat, ...enforcedCompat } }
|
||||
: {}),
|
||||
...(profile?.pi?.thinkingLevelMap
|
||||
? { thinkingLevelMap: { ...profile.pi.thinkingLevelMap } }
|
||||
...(compat || profile?.pi?.compat || enforcedCompat || serverCapability
|
||||
? {
|
||||
compat: {
|
||||
...compat,
|
||||
...profile?.pi?.compat,
|
||||
...enforcedCompat,
|
||||
...(serverCapability ? { supportsReasoningEffort: true } : {}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(serverCapability
|
||||
? { thinkingLevelMap: thinkingLevelMapForImportedModelCapability(serverCapability) }
|
||||
: profile?.pi?.thinkingLevelMap
|
||||
? { thinkingLevelMap: { ...profile.pi.thinkingLevelMap } }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -459,6 +459,7 @@ const PRODUCT_THINKING_LEVELS = new Set<ProductModelRef['thinkingLevel']>([
|
||||
'low',
|
||||
'medium',
|
||||
'high',
|
||||
'max',
|
||||
]);
|
||||
|
||||
function productThinkingLevel(value: unknown): ProductModelRef['thinkingLevel'] | null {
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
} from '../../utils/secure-storage';
|
||||
import type { ProviderWithKeyInfo } from '../../shared/providers/types';
|
||||
import { logger } from '../../utils/logger';
|
||||
import { normalizeImportedModelCapabilities } from '../../../shared/user-model-config';
|
||||
|
||||
function maskApiKey(apiKey: string | null): string | null {
|
||||
if (!apiKey) return null;
|
||||
@@ -69,6 +70,12 @@ function normalizeSyncedMetadata(metadata: Record<string, unknown>): ProviderAcc
|
||||
result.customModels = customModels;
|
||||
}
|
||||
}
|
||||
const worksSquareModelCapabilities = normalizeImportedModelCapabilities(
|
||||
metadata.worksSquareModelCapabilities,
|
||||
);
|
||||
if (worksSquareModelCapabilities) {
|
||||
result.worksSquareModelCapabilities = worksSquareModelCapabilities;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { ImportedModelCapabilities } from '../../../shared/imported-model-profile';
|
||||
|
||||
export const PROVIDER_TYPES = [
|
||||
'anthropic',
|
||||
'openai',
|
||||
@@ -133,6 +135,7 @@ export interface ProviderAccount {
|
||||
email?: string;
|
||||
resourceUrl?: string;
|
||||
customModels?: string[];
|
||||
worksSquareModelCapabilities?: ImportedModelCapabilities;
|
||||
worksSquareCredentialMode?: string;
|
||||
worksSquareCredentialExpiresAt?: string;
|
||||
worksSquareOneApiBaseUrl?: string;
|
||||
|
||||
Reference in New Issue
Block a user