Ship Paseo-equivalent provider snapshot, AgentComposerBar, ACP dispatch rewrite with streaming/persist, permission prompts, and agent commands. Follow-up: pane-scoped chat resolution, CoderMessageList tool timeline, WS user-delta replace, and inference orphan tool_call stripping. Archive openspec v2-2; update CHANGELOG and CURRENT. Co-authored-by: Cursor <cursoragent@cursor.com>
40 lines
1.4 KiB
TypeScript
40 lines
1.4 KiB
TypeScript
/**
|
|
* Cursor model list parser — lifted from Paseo cursor-acp-agent.ts
|
|
*/
|
|
import type { ProviderModel } from './provider-types.js';
|
|
|
|
const CURSOR_MODEL_MARKER_PATTERN = /\s+\((?:default|current)\)$/;
|
|
|
|
export function parseCursorAgentModelsOutput(output: string): ProviderModel[] {
|
|
const parsed = output
|
|
.split(/\r?\n/)
|
|
.map((line) => line.trim())
|
|
.filter((line) => line && line !== 'Available models' && !line.startsWith('Tip:'))
|
|
.map((line) => {
|
|
const separatorIndex = line.indexOf(' - ');
|
|
if (separatorIndex <= 0) return null;
|
|
|
|
const id = line.slice(0, separatorIndex).trim();
|
|
const rawLabel = line.slice(separatorIndex + 3).trim();
|
|
if (!id || !rawLabel) return null;
|
|
|
|
let marker: 'default' | 'current' | null = null;
|
|
if (rawLabel.endsWith(' (default)')) marker = 'default';
|
|
else if (rawLabel.endsWith(' (current)')) marker = 'current';
|
|
|
|
return { id, label: rawLabel.replace(CURSOR_MODEL_MARKER_PATTERN, ''), marker };
|
|
})
|
|
.filter((m): m is { id: string; label: string; marker: 'default' | 'current' | null } => m !== null);
|
|
|
|
const defaultModelId =
|
|
parsed.find((m) => m.marker === 'default')?.id ??
|
|
parsed.find((m) => m.marker === 'current')?.id ??
|
|
parsed[0]?.id;
|
|
|
|
return parsed.map((model) => ({
|
|
id: model.id,
|
|
label: model.label,
|
|
isDefault: model.id === defaultModelId,
|
|
}));
|
|
}
|