import * as nodeFs from "node:fs";import * as nodeOs from "node:os";import * as nodePath from "node:path"; import type { CursorSettings, ModelCapabilities, ProviderOptionSelection, ServerProvider, ServerProviderAuth, ServerProviderModel, ServerProviderState, ServerSettingsError,} from "@t3tools/contracts";import type * as EffectAcpSchema from "effect-acp/schema";import { Cause, Effect, Equal, Exit, Layer, Option, Result, Schema, Stream } from "effect";import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";import { createModelCapabilities, getProviderOptionBooleanSelectionValue, getProviderOptionStringSelectionValue,} from "@t3tools/shared/model"; import { buildBooleanOptionDescriptor, buildSelectOptionDescriptor, buildServerProvider, collectStreamAsString, isCommandMissingCause, providerModelsFromSettings, type CommandResult,} from "../providerSnapshot.ts";import { makeManagedServerProvider } from "../makeManagedServerProvider.ts";import { CursorProvider } from "../Services/CursorProvider.ts";import { AcpSessionRuntime } from "../acp/AcpSessionRuntime.ts";import { CursorListAvailableModelsResponse } from "../acp/CursorAcpExtension.ts";import { ServerSettingsService } from "../../serverSettings.ts"; const PROVIDER = "cursor" as const;const CURSOR_PRESENTATION = { displayName: "Cursor", badgeLabel: "Early Access", showInteractionModeToggle: true,} as const;const EMPTY_CAPABILITIES: ModelCapabilities = createModelCapabilities({ optionDescriptors: [],}); const CURSOR_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15_000;const CURSOR_REFRESH_INTERVAL = "1 hour";const CURSOR_PARAMETERIZED_MODEL_PICKER_MIN_VERSION_DATE = 2026_04_08;export const CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES = { _meta: { parameterizedModelPicker: true, },} satisfies NonNullable<EffectAcpSchema.InitializeRequest["clientCapabilities"]>; function buildInitialCursorProviderSnapshot(cursorSettings: CursorSettings): ServerProvider { const checkedAt = new Date().toISOString(); const models = getCursorFallbackModels(cursorSettings); if (!cursorSettings.enabled) { return buildServerProvider({ provider: PROVIDER, presentation: CURSOR_PRESENTATION, enabled: false, checkedAt, models, probe: { installed: false, version: null, status: "warning", auth: { status: "unknown" }, message: "Cursor is disabled in T3 Code settings.", }, }); } return buildServerProvider({ provider: PROVIDER, presentation: CURSOR_PRESENTATION, enabled: true, checkedAt, models, probe: { installed: true, version: null, status: "warning", auth: { status: "unknown" }, message: "Checking Cursor Agent availability...", }, });} interface CursorSessionSelectOption { readonly value: string; readonly name: string;} interface CursorAcpDiscoveredModel { readonly slug: string; readonly name: string; readonly capabilities: ModelCapabilities;} function flattenSessionConfigSelectOptions( configOption: EffectAcpSchema.SessionConfigOption | undefined,): ReadonlyArray<CursorSessionSelectOption> { if (!configOption || configOption.type !== "select") { return []; } return configOption.options.flatMap((entry) => "value" in entry ? [{ value: entry.value.trim(), name: entry.name.trim() } satisfies CursorSessionSelectOption] : entry.options.map( (option) => ({ value: option.value.trim(), name: option.name.trim(), }) satisfies CursorSessionSelectOption, ), );} function normalizeCursorReasoningValue(value: string | null | undefined): string | undefined { const normalized = value?.trim().toLowerCase(); switch (normalized) { case "low": case "medium": case "high": case "max": return normalized; case "xhigh": case "extra-high": case "extra high": return "xhigh"; default: return undefined; }} function findCursorModelConfigOption( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption>,): EffectAcpSchema.SessionConfigOption | undefined { return configOptions.find((option) => option.category === "model");} function getCursorConfigOptionCategory(option: EffectAcpSchema.SessionConfigOption): string { return option.category?.trim().toLowerCase() ?? "";} function isCursorEffortConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return ( id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") );} function findCursorEffortConfigOption( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption>,): EffectAcpSchema.SessionConfigOption | undefined { const candidates = configOptions.filter( (option) => option.type === "select" && isCursorEffortConfigOption(option), ); return ( candidates.find((option) => getCursorConfigOptionCategory(option) === "model_option") ?? candidates.find((option) => option.id.trim().toLowerCase() === "effort") ?? candidates.find((option) => getCursorConfigOptionCategory(option) === "thought_level") ?? candidates[0] );} function isCursorContextConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return id === "context" || id === "context_size" || name.includes("context");} function isCursorFastConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return id === "fast" || name === "fast" || name.includes("fast mode");} function isCursorThinkingConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return id === "thinking" || name.includes("thinking");} function isBooleanLikeConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { if (option.type === "boolean") { return true; } if (option.type !== "select") { return false; } const values = new Set( flattenSessionConfigSelectOptions(option).map((entry) => entry.value.trim().toLowerCase()), ); return values.has("true") && values.has("false");} function getBooleanCurrentValue( option: EffectAcpSchema.SessionConfigOption | undefined,): boolean | undefined { if (!option) { return undefined; } if (option.type === "boolean") { return option.currentValue; } if (option.type !== "select") { return undefined; } const normalized = option.currentValue?.trim().toLowerCase(); if (normalized === "true") { return true; } if (normalized === "false") { return false; } return undefined;} export function buildCursorCapabilitiesFromConfigOptions( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption> | null | undefined,): ModelCapabilities { if (!configOptions || configOptions.length === 0) { return EMPTY_CAPABILITIES; } const reasoningConfig = findCursorEffortConfigOption(configOptions); const reasoningEffortLevels = reasoningConfig?.type === "select" ? flattenSessionConfigSelectOptions(reasoningConfig).flatMap((entry) => { const normalizedValue = normalizeCursorReasoningValue(entry.value); if (!normalizedValue) { return []; } return [ { value: normalizedValue, label: entry.name, ...(normalizeCursorReasoningValue(reasoningConfig.currentValue) === normalizedValue ? { isDefault: true } : {}), }, ]; }) : []; const contextOption = configOptions.find( (option) => option.category === "model_config" && isCursorContextConfigOption(option), ); const contextWindowOptions = contextOption?.type === "select" ? flattenSessionConfigSelectOptions(contextOption).map((entry) => { if (contextOption.currentValue === entry.value) { return { value: entry.value, label: entry.name, isDefault: true, }; } return { value: entry.value, label: entry.name, }; }) : []; const fastOption = configOptions.find( (option) => option.category === "model_config" && isCursorFastConfigOption(option), ); const thinkingOption = configOptions.find( (option) => option.category === "model_config" && isCursorThinkingConfigOption(option), ); const fastCurrentValue = getBooleanCurrentValue(fastOption); const thinkingCurrentValue = getBooleanCurrentValue(thinkingOption); const optionDescriptors = [ ...(reasoningEffortLevels.length > 0 ? [ buildSelectOptionDescriptor({ id: "reasoning", label: reasoningConfig?.name?.trim() || "Reasoning", options: reasoningEffortLevels, }), ] : []), ...(contextWindowOptions.length > 0 ? [ buildSelectOptionDescriptor({ id: "contextWindow", label: contextOption?.name?.trim() || "Context Window", options: contextWindowOptions, }), ] : []), ...(fastOption && isBooleanLikeConfigOption(fastOption) ? [ typeof fastCurrentValue === "boolean" ? buildBooleanOptionDescriptor({ id: "fastMode", label: fastOption.name?.trim() || "Fast Mode", currentValue: fastCurrentValue, }) : buildBooleanOptionDescriptor({ id: "fastMode", label: fastOption.name?.trim() || "Fast Mode", }), ] : []), ...(thinkingOption && isBooleanLikeConfigOption(thinkingOption) ? [ typeof thinkingCurrentValue === "boolean" ? buildBooleanOptionDescriptor({ id: "thinking", label: thinkingOption.name?.trim() || "Thinking", currentValue: thinkingCurrentValue, }) : buildBooleanOptionDescriptor({ id: "thinking", label: thinkingOption.name?.trim() || "Thinking", }), ] : []), ]; return createModelCapabilities({ optionDescriptors, });} function buildCursorDiscoveredModels( discoveredModels: ReadonlyArray<CursorAcpDiscoveredModel>,): ReadonlyArray<ServerProviderModel> { const seen = new Set<string>(); return discoveredModels.flatMap((model) => { if (!model.slug || seen.has(model.slug)) { return []; } seen.add(model.slug); return [ { slug: model.slug, name: model.name, isCustom: false, capabilities: model.capabilities, } satisfies ServerProviderModel, ]; });} function hasCursorModelCapabilities(model: Pick<ServerProviderModel, "capabilities">): boolean { return (model.capabilities?.optionDescriptors?.length ?? 0) > 0;} export function buildCursorDiscoveredModelsFromConfigOptions( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption> | null | undefined,): ReadonlyArray<ServerProviderModel> { if (!configOptions || configOptions.length === 0) { return []; } const modelOption = findCursorModelConfigOption(configOptions); const modelChoices = flattenSessionConfigSelectOptions(modelOption); if (!modelOption || modelChoices.length === 0) { return []; } const currentModelValue = modelOption.type === "select" ? modelOption.currentValue?.trim() || undefined : undefined; const currentModelCapabilities = buildCursorCapabilitiesFromConfigOptions(configOptions); return buildCursorDiscoveredModels( modelChoices.map((modelChoice) => ({ slug: modelChoice.value.trim(), name: modelChoice.name.trim(), capabilities: currentModelValue === modelChoice.value.trim() ? currentModelCapabilities : EMPTY_CAPABILITIES, })), );} function buildCursorDiscoveredModelsFromAvailableModelsResponse( response: typeof CursorListAvailableModelsResponse.Type,): ReadonlyArray<ServerProviderModel> { return buildCursorDiscoveredModels( response.models.flatMap((model) => { const slug = model.value.trim(); const name = model.name.trim(); if (!slug || !name) { return []; } return [ { slug, name, capabilities: buildCursorCapabilitiesFromConfigOptions(model.configOptions), }, ]; }), );} const makeCursorAcpProbeRuntime = (cursorSettings: CursorSettings) => Effect.gen(function* () { const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const acpContext = yield* Layer.build( AcpSessionRuntime.layer({ spawn: { command: cursorSettings.binaryPath, args: [ ...(cursorSettings.apiEndpoint ? (["-e", cursorSettings.apiEndpoint] as const) : []), "acp", ], cwd: process.cwd(), }, cwd: process.cwd(), clientInfo: { name: "t3-code-provider-probe", version: "0.0.0" }, authMethodId: "cursor_login", clientCapabilities: CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES, }).pipe(Layer.provide(Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, spawner))), ); return yield* Effect.service(AcpSessionRuntime).pipe(Effect.provide(acpContext)); }); const withCursorAcpProbeRuntime = <A, E, R>( cursorSettings: CursorSettings, useRuntime: (acp: AcpSessionRuntime["Service"]) => Effect.Effect<A, E, R>,) => makeCursorAcpProbeRuntime(cursorSettings).pipe(Effect.flatMap(useRuntime), Effect.scoped); function normalizeCursorConfigOptionToken(value: string | null | undefined): string { return ( value ?.trim() .toLowerCase() .replace(/[\s_-]+/g, "-") ?? "" );} function findCursorSelectOptionValue( configOption: EffectAcpSchema.SessionConfigOption | undefined, matcher: (option: CursorSessionSelectOption) => boolean,): string | undefined { return flattenSessionConfigSelectOptions(configOption).find(matcher)?.value;} function findCursorBooleanConfigValue( configOption: EffectAcpSchema.SessionConfigOption | undefined, requested: boolean,): string | boolean | undefined { if (!configOption) { return undefined; } if (configOption.type === "boolean") { return requested; } return findCursorSelectOptionValue( configOption, (option) => normalizeCursorConfigOptionToken(option.value) === String(requested), );} export function resolveCursorAcpBaseModelId(model: string | null | undefined): string { const trimmed = model?.trim(); const base = trimmed && trimmed.length > 0 ? trimmed : "default"; return base.includes("[") ? base.slice(0, base.indexOf("[")) : base;} export function resolveCursorAcpConfigUpdates( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption> | null | undefined, selections: ReadonlyArray<ProviderOptionSelection> | null | undefined,): ReadonlyArray<{ readonly configId: string; readonly value: string | boolean }> { if (!configOptions || configOptions.length === 0) { return []; } const updates: Array<{ readonly configId: string; readonly value: string | boolean }> = []; const reasoningOption = findCursorEffortConfigOption(configOptions); const requestedReasoning = normalizeCursorReasoningValue( getProviderOptionStringSelectionValue(selections, "reasoning"), ); if (reasoningOption && requestedReasoning) { const value = findCursorSelectOptionValue(reasoningOption, (option) => { const normalizedValue = normalizeCursorReasoningValue(option.value); const normalizedName = normalizeCursorReasoningValue(option.name); return normalizedValue === requestedReasoning || normalizedName === requestedReasoning; });Lines 1–500 of 1168. Load more
import * as nodeFs from "node:fs"; import * as nodeOs from "node:os"; import * as nodePath from "node:path"; import type { CursorSettings, ModelCapabilities, ProviderOptionSelection, ServerProvider, ServerProviderAuth, ServerProviderModel, ServerProviderState, ServerSettingsError, } from "@t3tools/contracts"; import type * as EffectAcpSchema from "effect-acp/schema"; import { Cause, Effect, Equal, Exit, Layer, Option, Result, Schema, Stream } from "effect"; import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; import { createModelCapabilities, getProviderOptionBooleanSelectionValue, getProviderOptionStringSelectionValue, } from "@t3tools/shared/model"; import { buildBooleanOptionDescriptor, buildSelectOptionDescriptor, buildServerProvider, collectStreamAsString, isCommandMissingCause, providerModelsFromSettings, type CommandResult, } from "../providerSnapshot.ts"; import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; import { CursorProvider } from "../Services/CursorProvider.ts"; import { AcpSessionRuntime } from "../acp/AcpSessionRuntime.ts"; import { CursorListAvailableModelsResponse } from "../acp/CursorAcpExtension.ts"; import { ServerSettingsService } from "../../serverSettings.ts"; const PROVIDER = "cursor" as const; const CURSOR_PRESENTATION = { displayName: "Cursor", badgeLabel: "Early Access", showInteractionModeToggle: true, } as const; const EMPTY_CAPABILITIES: ModelCapabilities = createModelCapabilities({ optionDescriptors: [], }); const CURSOR_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15_000; const CURSOR_REFRESH_INTERVAL = "1 hour"; const CURSOR_PARAMETERIZED_MODEL_PICKER_MIN_VERSION_DATE = 2026_04_08; export const CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES = { _meta: { parameterizedModelPicker: true, }, } satisfies NonNullable<EffectAcpSchema.InitializeRequest["clientCapabilities"]>; function buildInitialCursorProviderSnapshot(cursorSettings: CursorSettings): ServerProvider { const checkedAt = new Date().toISOString(); const models = getCursorFallbackModels(cursorSettings); if (!cursorSettings.enabled) { return buildServerProvider({ provider: PROVIDER, presentation: CURSOR_PRESENTATION, enabled: false, checkedAt, models, probe: { installed: false, version: null, status: "warning", auth: { status: "unknown" }, message: "Cursor is disabled in T3 Code settings.", }, }); } return buildServerProvider({ provider: PROVIDER, presentation: CURSOR_PRESENTATION, enabled: true, checkedAt, models, probe: { installed: true, version: null, status: "warning", auth: { status: "unknown" }, message: "Checking Cursor Agent availability...", }, }); } interface CursorSessionSelectOption { readonly value: string; readonly name: string; } interface CursorAcpDiscoveredModel { readonly slug: string; readonly name: string; readonly capabilities: ModelCapabilities; } function flattenSessionConfigSelectOptions( configOption: EffectAcpSchema.SessionConfigOption | undefined, ): ReadonlyArray<CursorSessionSelectOption> { if (!configOption || configOption.type !== "select") { return []; } return configOption.options.flatMap((entry) => "value" in entry ? [{ value: entry.value.trim(), name: entry.name.trim() } satisfies CursorSessionSelectOption] : entry.options.map( (option) => ({ value: option.value.trim(), name: option.name.trim(), }) satisfies CursorSessionSelectOption, ), ); } function normalizeCursorReasoningValue(value: string | null | undefined): string | undefined { const normalized = value?.trim().toLowerCase(); switch (normalized) { case "low": case "medium": case "high": case "max": return normalized; case "xhigh": case "extra-high": case "extra high": return "xhigh"; default: return undefined; } } function findCursorModelConfigOption( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption>, ): EffectAcpSchema.SessionConfigOption | undefined { return configOptions.find((option) => option.category === "model"); } function getCursorConfigOptionCategory(option: EffectAcpSchema.SessionConfigOption): string { return option.category?.trim().toLowerCase() ?? ""; } function isCursorEffortConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return ( id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") ); } function findCursorEffortConfigOption( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption>, ): EffectAcpSchema.SessionConfigOption | undefined { const candidates = configOptions.filter( (option) => option.type === "select" && isCursorEffortConfigOption(option), ); return ( candidates.find((option) => getCursorConfigOptionCategory(option) === "model_option") ?? candidates.find((option) => option.id.trim().toLowerCase() === "effort") ?? candidates.find((option) => getCursorConfigOptionCategory(option) === "thought_level") ?? candidates[0] ); } function isCursorContextConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return id === "context" || id === "context_size" || name.includes("context"); } function isCursorFastConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return id === "fast" || name === "fast" || name.includes("fast mode"); } function isCursorThinkingConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { const id = option.id.trim().toLowerCase(); const name = option.name.trim().toLowerCase(); return id === "thinking" || name.includes("thinking"); } function isBooleanLikeConfigOption(option: EffectAcpSchema.SessionConfigOption): boolean { if (option.type === "boolean") { return true; } if (option.type !== "select") { return false; } const values = new Set( flattenSessionConfigSelectOptions(option).map((entry) => entry.value.trim().toLowerCase()), ); return values.has("true") && values.has("false"); } function getBooleanCurrentValue( option: EffectAcpSchema.SessionConfigOption | undefined, ): boolean | undefined { if (!option) { return undefined; } if (option.type === "boolean") { return option.currentValue; } if (option.type !== "select") { return undefined; } const normalized = option.currentValue?.trim().toLowerCase(); if (normalized === "true") { return true; } if (normalized === "false") { return false; } return undefined; } export function buildCursorCapabilitiesFromConfigOptions( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption> | null | undefined, ): ModelCapabilities { if (!configOptions || configOptions.length === 0) { return EMPTY_CAPABILITIES; } const reasoningConfig = findCursorEffortConfigOption(configOptions); const reasoningEffortLevels = reasoningConfig?.type === "select" ? flattenSessionConfigSelectOptions(reasoningConfig).flatMap((entry) => { const normalizedValue = normalizeCursorReasoningValue(entry.value); if (!normalizedValue) { return []; } return [ { value: normalizedValue, label: entry.name, ...(normalizeCursorReasoningValue(reasoningConfig.currentValue) === normalizedValue ? { isDefault: true } : {}), }, ]; }) : []; const contextOption = configOptions.find( (option) => option.category === "model_config" && isCursorContextConfigOption(option), ); const contextWindowOptions = contextOption?.type === "select" ? flattenSessionConfigSelectOptions(contextOption).map((entry) => { if (contextOption.currentValue === entry.value) { return { value: entry.value, label: entry.name, isDefault: true, }; } return { value: entry.value, label: entry.name, }; }) : []; const fastOption = configOptions.find( (option) => option.category === "model_config" && isCursorFastConfigOption(option), ); const thinkingOption = configOptions.find( (option) => option.category === "model_config" && isCursorThinkingConfigOption(option), ); const fastCurrentValue = getBooleanCurrentValue(fastOption); const thinkingCurrentValue = getBooleanCurrentValue(thinkingOption); const optionDescriptors = [ ...(reasoningEffortLevels.length > 0 ? [ buildSelectOptionDescriptor({ id: "reasoning", label: reasoningConfig?.name?.trim() || "Reasoning", options: reasoningEffortLevels, }), ] : []), ...(contextWindowOptions.length > 0 ? [ buildSelectOptionDescriptor({ id: "contextWindow", label: contextOption?.name?.trim() || "Context Window", options: contextWindowOptions, }), ] : []), ...(fastOption && isBooleanLikeConfigOption(fastOption) ? [ typeof fastCurrentValue === "boolean" ? buildBooleanOptionDescriptor({ id: "fastMode", label: fastOption.name?.trim() || "Fast Mode", currentValue: fastCurrentValue, }) : buildBooleanOptionDescriptor({ id: "fastMode", label: fastOption.name?.trim() || "Fast Mode", }), ] : []), ...(thinkingOption && isBooleanLikeConfigOption(thinkingOption) ? [ typeof thinkingCurrentValue === "boolean" ? buildBooleanOptionDescriptor({ id: "thinking", label: thinkingOption.name?.trim() || "Thinking", currentValue: thinkingCurrentValue, }) : buildBooleanOptionDescriptor({ id: "thinking", label: thinkingOption.name?.trim() || "Thinking", }), ] : []), ]; return createModelCapabilities({ optionDescriptors, }); } function buildCursorDiscoveredModels( discoveredModels: ReadonlyArray<CursorAcpDiscoveredModel>, ): ReadonlyArray<ServerProviderModel> { const seen = new Set<string>(); return discoveredModels.flatMap((model) => { if (!model.slug || seen.has(model.slug)) { return []; } seen.add(model.slug); return [ { slug: model.slug, name: model.name, isCustom: false, capabilities: model.capabilities, } satisfies ServerProviderModel, ]; }); } function hasCursorModelCapabilities(model: Pick<ServerProviderModel, "capabilities">): boolean { return (model.capabilities?.optionDescriptors?.length ?? 0) > 0; } export function buildCursorDiscoveredModelsFromConfigOptions( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption> | null | undefined, ): ReadonlyArray<ServerProviderModel> { if (!configOptions || configOptions.length === 0) { return []; } const modelOption = findCursorModelConfigOption(configOptions); const modelChoices = flattenSessionConfigSelectOptions(modelOption); if (!modelOption || modelChoices.length === 0) { return []; } const currentModelValue = modelOption.type === "select" ? modelOption.currentValue?.trim() || undefined : undefined; const currentModelCapabilities = buildCursorCapabilitiesFromConfigOptions(configOptions); return buildCursorDiscoveredModels( modelChoices.map((modelChoice) => ({ slug: modelChoice.value.trim(), name: modelChoice.name.trim(), capabilities: currentModelValue === modelChoice.value.trim() ? currentModelCapabilities : EMPTY_CAPABILITIES, })), ); } function buildCursorDiscoveredModelsFromAvailableModelsResponse( response: typeof CursorListAvailableModelsResponse.Type, ): ReadonlyArray<ServerProviderModel> { return buildCursorDiscoveredModels( response.models.flatMap((model) => { const slug = model.value.trim(); const name = model.name.trim(); if (!slug || !name) { return []; } return [ { slug, name, capabilities: buildCursorCapabilitiesFromConfigOptions(model.configOptions), }, ]; }), ); } const makeCursorAcpProbeRuntime = (cursorSettings: CursorSettings) => Effect.gen(function* () { const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const acpContext = yield* Layer.build( AcpSessionRuntime.layer({ spawn: { command: cursorSettings.binaryPath, args: [ ...(cursorSettings.apiEndpoint ? (["-e", cursorSettings.apiEndpoint] as const) : []), "acp", ], cwd: process.cwd(), }, cwd: process.cwd(), clientInfo: { name: "t3-code-provider-probe", version: "0.0.0" }, authMethodId: "cursor_login", clientCapabilities: CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES, }).pipe(Layer.provide(Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, spawner))), ); return yield* Effect.service(AcpSessionRuntime).pipe(Effect.provide(acpContext)); }); const withCursorAcpProbeRuntime = <A, E, R>( cursorSettings: CursorSettings, useRuntime: (acp: AcpSessionRuntime["Service"]) => Effect.Effect<A, E, R>, ) => makeCursorAcpProbeRuntime(cursorSettings).pipe(Effect.flatMap(useRuntime), Effect.scoped); function normalizeCursorConfigOptionToken(value: string | null | undefined): string { return ( value ?.trim() .toLowerCase() .replace(/[\s_-]+/g, "-") ?? "" ); } function findCursorSelectOptionValue( configOption: EffectAcpSchema.SessionConfigOption | undefined, matcher: (option: CursorSessionSelectOption) => boolean, ): string | undefined { return flattenSessionConfigSelectOptions(configOption).find(matcher)?.value; } function findCursorBooleanConfigValue( configOption: EffectAcpSchema.SessionConfigOption | undefined, requested: boolean, ): string | boolean | undefined { if (!configOption) { return undefined; } if (configOption.type === "boolean") { return requested; } return findCursorSelectOptionValue( configOption, (option) => normalizeCursorConfigOptionToken(option.value) === String(requested), ); } export function resolveCursorAcpBaseModelId(model: string | null | undefined): string { const trimmed = model?.trim(); const base = trimmed && trimmed.length > 0 ? trimmed : "default"; return base.includes("[") ? base.slice(0, base.indexOf("[")) : base; } export function resolveCursorAcpConfigUpdates( configOptions: ReadonlyArray<EffectAcpSchema.SessionConfigOption> | null | undefined, selections: ReadonlyArray<ProviderOptionSelection> | null | undefined, ): ReadonlyArray<{ readonly configId: string; readonly value: string | boolean }> { if (!configOptions || configOptions.length === 0) { return []; } const updates: Array<{ readonly configId: string; readonly value: string | boolean }> = []; const reasoningOption = findCursorEffortConfigOption(configOptions); const requestedReasoning = normalizeCursorReasoningValue( getProviderOptionStringSelectionValue(selections, "reasoning"), ); if (reasoningOption && requestedReasoning) { const value = findCursorSelectOptionValue(reasoningOption, (option) => { const normalizedValue = normalizeCursorReasoningValue(option.value); const normalizedName = normalizeCursorReasoningValue(option.name); return normalizedValue === requestedReasoning || normalizedName === requestedReasoning; });