mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-08 07:17:39 +00:00
fix(cursor): support ACP parameterized model picker (#969)
* test: reproduce issue #968 * fix: support Cursor parameterized model picker (closes #968)
This commit is contained in:
@@ -6,6 +6,18 @@ export type CursorModelsSnapshot = {
|
||||
currentModelId: string | null;
|
||||
};
|
||||
|
||||
type CursorAcpModelSnapshotBackend = Pick<AcpSdkBackend, 'getSessionModelsMetadata' | 'getConfigOptionByCategory'>
|
||||
& Partial<Pick<AcpSdkBackend, 'getSessionConfigOptions'>>;
|
||||
|
||||
function findConfigOption(
|
||||
backend: CursorAcpModelSnapshotBackend,
|
||||
sessionId: string,
|
||||
key: string
|
||||
) {
|
||||
return backend.getConfigOptionByCategory?.(sessionId, key)
|
||||
?? backend.getSessionConfigOptions?.(sessionId)?.find((option) => option.id === key || option.category === key);
|
||||
}
|
||||
|
||||
function mergeModelEntries(
|
||||
target: Map<string, CursorModelSummary>,
|
||||
entries: Iterable<{ modelId: string; name?: string | null }>
|
||||
@@ -31,19 +43,43 @@ function mergeModelEntries(
|
||||
* `availableModels` alone is often one variant per base family.
|
||||
*/
|
||||
export function buildCursorModelsSnapshotFromAcp(
|
||||
backend: Pick<AcpSdkBackend, 'getSessionModelsMetadata' | 'getConfigOptionByCategory'>,
|
||||
backend: CursorAcpModelSnapshotBackend,
|
||||
sessionId: string
|
||||
): CursorModelsSnapshot | null {
|
||||
const metadata = backend.getSessionModelsMetadata(sessionId);
|
||||
const modelOption = backend.getConfigOptionByCategory?.(sessionId, 'model');
|
||||
const modelOption = findConfigOption(backend, sessionId, 'model');
|
||||
const fastOption = findConfigOption(backend, sessionId, 'fast');
|
||||
|
||||
if (!metadata && !modelOption) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const merged = new Map<string, CursorModelSummary>();
|
||||
const parameterizedFastModels: CursorModelSummary[] = [];
|
||||
|
||||
if (modelOption?.options?.length) {
|
||||
if (modelOption?.options?.length && fastOption?.options?.length) {
|
||||
const fastValues = fastOption.options
|
||||
.map((option) => option.value.trim())
|
||||
.filter((value) => value === 'false' || value === 'true');
|
||||
if (fastValues.length > 0) {
|
||||
for (const option of modelOption.options) {
|
||||
const modelId = option.value.trim();
|
||||
if (!modelId || modelId.includes('[')) {
|
||||
continue;
|
||||
}
|
||||
for (const fast of fastValues) {
|
||||
parameterizedFastModels.push({
|
||||
modelId: `${modelId}[fast=${fast}]`,
|
||||
name: option.name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterizedFastModels.length > 0) {
|
||||
mergeModelEntries(merged, parameterizedFastModels);
|
||||
} else if (modelOption?.options?.length) {
|
||||
mergeModelEntries(merged, modelOption.options.map((option) => ({
|
||||
modelId: option.value,
|
||||
name: option.name
|
||||
@@ -51,16 +87,23 @@ export function buildCursorModelsSnapshotFromAcp(
|
||||
}
|
||||
|
||||
if (metadata?.availableModels?.length) {
|
||||
mergeModelEntries(merged, metadata.availableModels);
|
||||
mergeModelEntries(
|
||||
merged,
|
||||
parameterizedFastModels.length > 0
|
||||
? metadata.availableModels.filter((entry) => entry.modelId.includes('['))
|
||||
: metadata.availableModels
|
||||
);
|
||||
}
|
||||
|
||||
if (merged.size === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentModelId = metadata?.currentModelId
|
||||
?? modelOption?.currentValue
|
||||
?? null;
|
||||
const currentModelId = parameterizedFastModels.length > 0 && modelOption?.currentValue && fastOption?.currentValue
|
||||
? `${modelOption.currentValue}[fast=${fastOption.currentValue}]`
|
||||
: metadata?.currentModelId
|
||||
?? modelOption?.currentValue
|
||||
?? null;
|
||||
|
||||
return {
|
||||
availableModels: [...merged.values()],
|
||||
|
||||
Reference in New Issue
Block a user