feat: consume server model reasoning capabilities

This commit is contained in:
2026-09-01 14:16:18 +08:00
parent 850947c092
commit ae79361742
20 changed files with 711 additions and 20 deletions

View File

@@ -2,7 +2,7 @@ import type { CapabilityResultV1 } from './data-service';
export type { CapabilityBillingReceiptV1, CapabilityResultV1 } from './data-service';
export type ConversationThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high';
export type ConversationThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'max';
export interface ProductModelRef {
accountId: string;

View File

@@ -54,7 +54,7 @@ const RUN_STATUSES = new Set([
]);
const WORKER_STATUSES = new Set(['stopped', 'starting', 'ready', 'recovering', 'error']);
const THINKING_LEVELS = new Set(['off', 'minimal', 'low', 'medium', 'high']);
const THINKING_LEVELS = new Set(['off', 'minimal', 'low', 'medium', 'high', 'max']);
const ERROR_CODES = new Set([
'CODING_RUNTIME_START_FAILED',
'CODING_RUNTIME_READY_TIMEOUT',

View File

@@ -1,6 +1,28 @@
export type ImportedModelModality = 'text' | 'audio' | 'image' | 'pdf';
export type ImportedVisionTokenEstimator = 'qwen-32px-grid';
export type ImportedThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high';
export type ImportedThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'max';
export const IMPORTED_REASONING_EFFORTS = ['low', 'high', 'max'] as const;
export type ImportedReasoningEffort = (typeof IMPORTED_REASONING_EFFORTS)[number];
export interface ImportedModelCapability {
reasoningEfforts: ImportedReasoningEffort[];
reasoningCanDisable: boolean;
}
export type ImportedModelCapabilities = Record<string, ImportedModelCapability>;
export function thinkingLevelMapForImportedModelCapability(
capability: ImportedModelCapability,
): Partial<Record<ImportedThinkingLevel, string | null>> {
return {
...(capability.reasoningCanDisable ? {} : { off: null }),
minimal: null,
low: capability.reasoningEfforts.includes('low') ? 'low' : null,
medium: null,
high: capability.reasoningEfforts.includes('high') ? 'high' : null,
max: capability.reasoningEfforts.includes('max') ? 'max' : null,
};
}
export interface ImportedPiModelProfile {
reasoning: boolean;
@@ -62,14 +84,15 @@ export function getImportedModelProfile(rawModelId: string): ImportedModelProfil
pi: {
reasoning: true,
thinkingLevelMap: {
off: null,
minimal: null,
low: null,
low: 'low',
medium: null,
high: 'high',
max: 'max',
},
compat: {
thinkingFormat: 'deepseek',
supportsReasoningEffort: true,
requiresReasoningContentOnAssistantMessages: true,
},
},

View File

@@ -1,3 +1,10 @@
import {
IMPORTED_REASONING_EFFORTS,
type ImportedModelCapabilities,
type ImportedModelCapability,
type ImportedReasoningEffort,
} from './imported-model-profile';
export const NIANCODE_USER_MODEL_ACCOUNT_ID = 'niancode-user-models';
export const NIANCODE_USER_MODEL_ACCOUNT_LABEL = 'Makelore Models';
@@ -23,6 +30,37 @@ export function normalizeImportedUserModelId(rawModel: string): string {
: trimmed;
}
function normalizeImportedModelCapability(value: unknown): ImportedModelCapability | null {
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
const record = value as Record<string, unknown>;
const rawEfforts = record.reasoning_efforts ?? record.reasoningEfforts;
const reasoningCanDisable = record.reasoning_can_disable ?? record.reasoningCanDisable;
if (!Array.isArray(rawEfforts) || typeof reasoningCanDisable !== 'boolean') return null;
const reasoningEfforts = IMPORTED_REASONING_EFFORTS.filter((effort) => (
rawEfforts.some((candidate) => candidate === effort)
)) as ImportedReasoningEffort[];
if (reasoningEfforts.length === 0 && rawEfforts.length > 0) return null;
return { reasoningEfforts, reasoningCanDisable };
}
export function normalizeImportedModelCapabilities(
value: unknown,
modelIds?: readonly string[],
): ImportedModelCapabilities | undefined {
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
const allowedModelIds = modelIds
? new Set(modelIds.map(normalizeImportedUserModelId))
: null;
const result: ImportedModelCapabilities = {};
for (const [rawModelId, rawCapability] of Object.entries(value as Record<string, unknown>)) {
const modelId = normalizeImportedUserModelId(rawModelId);
if (!modelId || (allowedModelIds && !allowedModelIds.has(modelId))) continue;
const capability = normalizeImportedModelCapability(rawCapability);
if (capability && !result[modelId]) result[modelId] = capability;
}
return Object.keys(result).length > 0 ? result : undefined;
}
export function selectUserModelRuntimeAccounts<T extends NianCodeUserModelAccountLike>(
accounts: T[],
): T[] {