import * as nodeOs from "node:os"; import type { CursorSettings, ModelCapabilities, ProviderOptionSelection, ServerProvider, ServerProviderAuth, ServerProviderModel, ServerProviderState,} from "@t3tools/contracts";import { ProviderDriverKind } from "@t3tools/contracts";import type * as EffectAcpSchema from "effect-acp/schema";import { Cause, Effect, Exit, FileSystem, Layer, Option, Path, Result } from "effect";import { HttpClient } from "effect/unstable/http";import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";import { createModelCapabilities, getProviderOptionBooleanSelectionValue, getProviderOptionStringSelectionValue,} from "@t3tools/shared/model"; import { buildBooleanOptionDescriptor, buildSelectOptionDescriptor, buildServerProvider, collectStreamAsString, isCommandMissingCause, providerModelsFromSettings, type CommandResult, type ServerProviderDraft,} from "../providerSnapshot.ts";import { enrichProviderSnapshotWithVersionAdvisory, type ProviderMaintenanceCapabilities,} from "../providerMaintenance.ts";import { AcpSessionRuntime } from "../acp/AcpSessionRuntime.ts"; const PROVIDER = ProviderDriverKind.make("cursor");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_ACP_MODEL_CAPABILITY_TIMEOUT = "4 seconds";const CURSOR_ACP_MODEL_DISCOVERY_CONCURRENCY = 4;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"]>; export function buildInitialCursorProviderSnapshot( cursorSettings: CursorSettings,): ServerProviderDraft { const checkedAt = new Date().toISOString(); const models = getCursorFallbackModels(cursorSettings); if (!cursorSettings.enabled) { return buildServerProvider({ 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({ 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, })), );} const makeCursorAcpProbeRuntime = ( cursorSettings: CursorSettings, environment: NodeJS.ProcessEnv = process.env,) => 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(), env: environment, }, 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>, environment: NodeJS.ProcessEnv = process.env,) => makeCursorAcpProbeRuntime(cursorSettings, environment).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; }); if (value) {Lines 1–500 of 1287. Load more
import * as nodeOs from "node:os"; import type { CursorSettings, ModelCapabilities, ProviderOptionSelection, ServerProvider, ServerProviderAuth, ServerProviderModel, ServerProviderState, } from "@t3tools/contracts"; import { ProviderDriverKind } from "@t3tools/contracts"; import type * as EffectAcpSchema from "effect-acp/schema"; import { Cause, Effect, Exit, FileSystem, Layer, Option, Path, Result } from "effect"; import { HttpClient } from "effect/unstable/http"; import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; import { createModelCapabilities, getProviderOptionBooleanSelectionValue, getProviderOptionStringSelectionValue, } from "@t3tools/shared/model"; import { buildBooleanOptionDescriptor, buildSelectOptionDescriptor, buildServerProvider, collectStreamAsString, isCommandMissingCause, providerModelsFromSettings, type CommandResult, type ServerProviderDraft, } from "../providerSnapshot.ts"; import { enrichProviderSnapshotWithVersionAdvisory, type ProviderMaintenanceCapabilities, } from "../providerMaintenance.ts"; import { AcpSessionRuntime } from "../acp/AcpSessionRuntime.ts"; const PROVIDER = ProviderDriverKind.make("cursor"); 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_ACP_MODEL_CAPABILITY_TIMEOUT = "4 seconds"; const CURSOR_ACP_MODEL_DISCOVERY_CONCURRENCY = 4; 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"]>; export function buildInitialCursorProviderSnapshot( cursorSettings: CursorSettings, ): ServerProviderDraft { const checkedAt = new Date().toISOString(); const models = getCursorFallbackModels(cursorSettings); if (!cursorSettings.enabled) { return buildServerProvider({ 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({ 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, })), ); } const makeCursorAcpProbeRuntime = ( cursorSettings: CursorSettings, environment: NodeJS.ProcessEnv = process.env, ) => 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(), env: environment, }, 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>, environment: NodeJS.ProcessEnv = process.env, ) => makeCursorAcpProbeRuntime(cursorSettings, environment).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; }); if (value) {