import type { ClaudeSettings, ClaudeModelSelection, ModelCapabilities, ServerProvider, ServerProviderModel, ServerProviderAuth, ServerProviderSlashCommand, ServerProviderState,} from "@t3tools/contracts";import { Cache, Duration, Effect, Equal, Layer, Option, Result, Schema, Stream } from "effect";import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";import { decodeJsonResult } from "@t3tools/shared/schemaJson";import { createModelCapabilities, getModelSelectionStringOptionValue, getProviderOptionCurrentValue, getProviderOptionDescriptors,} from "@t3tools/shared/model";import { query as claudeQuery, type SlashCommand as ClaudeSlashCommand, type SDKUserMessage,} from "@anthropic-ai/claude-agent-sdk"; import { buildBooleanOptionDescriptor, buildSelectOptionDescriptor, buildServerProvider, AUTH_PROBE_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, detailFromResult, extractAuthBoolean, isCommandMissingCause, parseGenericCliVersion, providerModelsFromSettings, spawnAndCollect, type CommandResult,} from "../providerSnapshot.ts";import { compareCliVersions } from "../cliVersion.ts";import { makeManagedServerProvider } from "../makeManagedServerProvider.ts";import { ClaudeProvider } from "../Services/ClaudeProvider.ts";import { ServerSettingsService } from "../../serverSettings.ts";import { ServerSettingsError } from "@t3tools/contracts"; const DEFAULT_CLAUDE_MODEL_CAPABILITIES: ModelCapabilities = createModelCapabilities({ optionDescriptors: [],}); const PROVIDER = "claudeAgent" as const;const CLAUDE_PRESENTATION = { displayName: "Claude", showInteractionModeToggle: true,} as const;const MINIMUM_CLAUDE_OPUS_4_7_VERSION = "2.1.111";const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ { slug: "claude-opus-4-7", name: "Claude Opus 4.7", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High" }, { value: "xhigh", label: "Extra High", isDefault: true }, { value: "max", label: "Max" }, { value: "ultrathink", label: "Ultrathink" }, ], promptInjectedValues: ["ultrathink"], }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", options: [ { value: "200k", label: "200k", isDefault: true }, { value: "1m", label: "1M" }, ], }), ], }), }, { slug: "claude-opus-4-6", name: "Claude Opus 4.6", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "max", label: "Max" }, { value: "ultrathink", label: "Ultrathink" }, ], promptInjectedValues: ["ultrathink"], }), buildBooleanOptionDescriptor({ id: "fastMode", label: "Fast Mode", }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", options: [ { value: "200k", label: "200k", isDefault: true }, { value: "1m", label: "1M" }, ], }), ], }), }, { slug: "claude-opus-4-5", name: "Claude Opus 4.5", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "max", label: "Max" }, ], }), buildBooleanOptionDescriptor({ id: "fastMode", label: "Fast Mode", }), ], }), }, { slug: "claude-sonnet-4-6", name: "Claude Sonnet 4.6", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "ultrathink", label: "Ultrathink" }, ], promptInjectedValues: ["ultrathink"], }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", options: [ { value: "200k", label: "200k", isDefault: true }, { value: "1m", label: "1M" }, ], }), ], }), }, { slug: "claude-haiku-4-5", name: "Claude Haiku 4.5", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildBooleanOptionDescriptor({ id: "thinking", label: "Thinking", }), ], }), },]; function supportsClaudeOpus47(version: string | null | undefined): boolean { return version ? compareCliVersions(version, MINIMUM_CLAUDE_OPUS_4_7_VERSION) >= 0 : false;} function getBuiltInClaudeModelsForVersion( version: string | null | undefined,): ReadonlyArray<ServerProviderModel> { if (supportsClaudeOpus47(version)) { return BUILT_IN_MODELS; } return BUILT_IN_MODELS.filter((model) => model.slug !== "claude-opus-4-7");} function formatClaudeOpus47UpgradeMessage(version: string | null): string { const versionLabel = version ? `v${version}` : "the installed version"; return `Claude Code ${versionLabel} is too old for Claude Opus 4.7. Upgrade to v${MINIMUM_CLAUDE_OPUS_4_7_VERSION} or newer to access it.`;} export function getClaudeModelCapabilities(model: string | null | undefined): ModelCapabilities { const slug = model?.trim(); return ( BUILT_IN_MODELS.find((candidate) => candidate.slug === slug)?.capabilities ?? DEFAULT_CLAUDE_MODEL_CAPABILITIES );} export function resolveClaudeEffort( caps: ModelCapabilities, raw: string | null | undefined,): string | undefined { const descriptors = getProviderOptionDescriptors({ caps, ...(raw ? { selections: [{ id: "effort", value: raw }] } : {}), }); const effortDescriptor = descriptors.find((descriptor) => descriptor.id === "effort"); const value = getProviderOptionCurrentValue(effortDescriptor); return typeof value === "string" ? value : undefined;} /** * Normalize a resolved Claude effort value into one suitable for the Claude * CLI's `--effort` flag. * * Mirrors the mapping used when invoking the Claude Agent SDK * ({@link getEffectiveClaudeAgentEffort} in ClaudeAdapter): the Opus 4.7 * capability `"xhigh"` is rewritten to the accepted CLI value `"max"`, and * `"ultrathink"` is filtered out because it is a prompt-prefix mode rather * than a CLI-effort value. Returns `undefined` when no flag should be passed. */export function normalizeClaudeCliEffort(effort: string | null | undefined): string | undefined { if (!effort || effort === "ultrathink") { return undefined; } if (effort === "xhigh") { return "max"; } return effort;} export function resolveClaudeApiModelId(modelSelection: ClaudeModelSelection): string { switch (getModelSelectionStringOptionValue(modelSelection, "contextWindow")) { case "1m": return `${modelSelection.model}[1m]`; default: return modelSelection.model; }}export function parseClaudeAuthStatusFromOutput(result: CommandResult): { readonly status: Exclude<ServerProviderState, "disabled">; readonly auth: Pick<ServerProviderAuth, "status">; readonly message?: string;} { const lowerOutput = `${result.stdout}\n${result.stderr}`.toLowerCase(); if ( lowerOutput.includes("unknown command") || lowerOutput.includes("unrecognized command") || lowerOutput.includes("unexpected argument") ) { return { status: "warning", auth: { status: "unknown" }, message: "Claude Agent authentication status command is unavailable in this version of Claude.", }; } if ( lowerOutput.includes("not logged in") || lowerOutput.includes("login required") || lowerOutput.includes("authentication required") || lowerOutput.includes("run `claude login`") || lowerOutput.includes("run claude login") ) { return { status: "error", auth: { status: "unauthenticated" }, message: "Claude is not authenticated. Run `claude auth login` and try again.", }; } const parsedAuth = (() => { const trimmed = result.stdout.trim(); if (!trimmed || (!trimmed.startsWith("{") && !trimmed.startsWith("["))) { return { attemptedJsonParse: false as const, auth: undefined as boolean | undefined }; } try { return { attemptedJsonParse: true as const, auth: extractAuthBoolean(JSON.parse(trimmed)), }; } catch { return { attemptedJsonParse: false as const, auth: undefined as boolean | undefined }; } })(); if (parsedAuth.auth === true) { return { status: "ready", auth: { status: "authenticated" } }; } if (parsedAuth.auth === false) { return { status: "error", auth: { status: "unauthenticated" }, message: "Claude is not authenticated. Run `claude auth login` and try again.", }; } if (parsedAuth.attemptedJsonParse) { return { status: "warning", auth: { status: "unknown" }, message: "Could not verify Claude authentication status from JSON output (missing auth marker).", }; } if (result.code === 0) { return { status: "ready", auth: { status: "authenticated" } }; } const detail = detailFromResult(result); return { status: "warning", auth: { status: "unknown" }, message: detail ? `Could not verify Claude authentication status. ${detail}` : "Could not verify Claude authentication status.", };} // ── Subscription type detection ─────────────────────────────────────//// The SDK probe returns typed `AccountInfo.subscriptionType` directly.// This walker is a best-effort fallback for the `claude auth status`// JSON output whose shape is not guaranteed. /** Keys that directly hold a subscription/plan identifier. */const SUBSCRIPTION_TYPE_KEYS = [ "subscriptionType", "subscription_type", "plan", "tier", "planType", "plan_type",] as const; /** Keys whose value may be a nested object containing subscription info. */const SUBSCRIPTION_CONTAINER_KEYS = ["account", "subscription", "user", "billing"] as const;const AUTH_METHOD_KEYS = ["authMethod", "auth_method"] as const;const AUTH_METHOD_CONTAINER_KEYS = ["auth", "account", "session"] as const; /** Lift an unknown value into `Option<string>` if it is a non-empty string. */const asNonEmptyString = (v: unknown): Option.Option<string> => typeof v === "string" && v.length > 0 ? Option.some(v) : Option.none(); /** Lift an unknown value into `Option<Record>` if it is a plain object. */const asRecord = (v: unknown): Option.Option<Record<string, unknown>> => typeof v === "object" && v !== null && !globalThis.Array.isArray(v) ? Option.some(v as Record<string, unknown>) : Option.none(); /** * Walk an unknown parsed JSON value looking for a subscription/plan * identifier, returning the first match as an `Option`. */function findSubscriptionType(value: unknown): Option.Option<string> { if (globalThis.Array.isArray(value)) { return Option.firstSomeOf(value.map(findSubscriptionType)); } return asRecord(value).pipe( Option.flatMap((record) => { const direct = Option.firstSomeOf( SUBSCRIPTION_TYPE_KEYS.map((key) => asNonEmptyString(record[key])), ); if (Option.isSome(direct)) return direct; return Option.firstSomeOf( SUBSCRIPTION_CONTAINER_KEYS.map((key) => asRecord(record[key]).pipe(Option.flatMap(findSubscriptionType)), ), ); }), );} function findAuthMethod(value: unknown): Option.Option<string> { if (globalThis.Array.isArray(value)) { return Option.firstSomeOf(value.map(findAuthMethod)); } return asRecord(value).pipe( Option.flatMap((record) => { const direct = Option.firstSomeOf( AUTH_METHOD_KEYS.map((key) => asNonEmptyString(record[key])), ); if (Option.isSome(direct)) return direct; return Option.firstSomeOf( AUTH_METHOD_CONTAINER_KEYS.map((key) => asRecord(record[key]).pipe(Option.flatMap(findAuthMethod)), ), ); }), );} /** * Try to extract a subscription type from the `claude auth status` JSON * output. This is a zero-cost operation on data we already have. */const decodeUnknownJson = decodeJsonResult(Schema.Unknown); function extractSubscriptionTypeFromOutput(result: CommandResult): string | undefined { const parsed = decodeUnknownJson(result.stdout.trim()); if (Result.isFailure(parsed)) return undefined; return Option.getOrUndefined(findSubscriptionType(parsed.success));} function extractClaudeAuthMethodFromOutput(result: CommandResult): string | undefined { const parsed = decodeUnknownJson(result.stdout.trim()); if (Result.isFailure(parsed)) return undefined; return Option.getOrUndefined(findAuthMethod(parsed.success));} function toTitleCaseWords(value: string): string { return value .split(/[\s_-]+/g) .filter(Boolean) .map((part) => part[0]!.toUpperCase() + part.slice(1).toLowerCase()) .join(" ");} function claudeSubscriptionLabel(subscriptionType: string | undefined): string | undefined { const normalized = subscriptionType?.toLowerCase().replace(/[\s_-]+/g, ""); if (!normalized) return undefined; switch (normalized) { case "max": case "maxplan": case "max5": case "max20": return "Max"; case "enterprise": return "Enterprise"; case "team": return "Team"; case "pro": return "Pro"; case "free": return "Free"; default: return toTitleCaseWords(subscriptionType!); }} function normalizeClaudeAuthMethod(authMethod: string | undefined): string | undefined { const normalized = authMethod?.toLowerCase().replace(/[\s_-]+/g, ""); if (!normalized) return undefined; if (normalized === "apikey") return "apiKey"; return undefined;} function claudeAuthMetadata(input: { readonly subscriptionType: string | undefined; readonly authMethod: string | undefined;}): { readonly type: string; readonly label: string } | undefined { if (normalizeClaudeAuthMethod(input.authMethod) === "apiKey") { return { type: "apiKey", label: "Claude API Key", }; } if (input.subscriptionType) { const subscriptionLabel = claudeSubscriptionLabel(input.subscriptionType); return { type: input.subscriptionType, label: `Claude ${subscriptionLabel ?? toTitleCaseWords(input.subscriptionType)} Subscription`, }; } return undefined;} // ── SDK capability probe ──────────────────────────────────────────── const CAPABILITIES_PROBE_TIMEOUT_MS = 8_000; function nonEmptyProbeString(value: string): string | undefined { const candidate = value.trim(); return candidate ? candidate : undefined;} function parseClaudeInitializationCommands( commands: ReadonlyArray<ClaudeSlashCommand> | undefined,): ReadonlyArray<ServerProviderSlashCommand> {Lines 1–500 of 929. Load more
import type { ClaudeSettings, ClaudeModelSelection, ModelCapabilities, ServerProvider, ServerProviderModel, ServerProviderAuth, ServerProviderSlashCommand, ServerProviderState, } from "@t3tools/contracts"; import { Cache, Duration, Effect, Equal, Layer, Option, Result, Schema, Stream } from "effect"; import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; import { decodeJsonResult } from "@t3tools/shared/schemaJson"; import { createModelCapabilities, getModelSelectionStringOptionValue, getProviderOptionCurrentValue, getProviderOptionDescriptors, } from "@t3tools/shared/model"; import { query as claudeQuery, type SlashCommand as ClaudeSlashCommand, type SDKUserMessage, } from "@anthropic-ai/claude-agent-sdk"; import { buildBooleanOptionDescriptor, buildSelectOptionDescriptor, buildServerProvider, AUTH_PROBE_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, detailFromResult, extractAuthBoolean, isCommandMissingCause, parseGenericCliVersion, providerModelsFromSettings, spawnAndCollect, type CommandResult, } from "../providerSnapshot.ts"; import { compareCliVersions } from "../cliVersion.ts"; import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; import { ClaudeProvider } from "../Services/ClaudeProvider.ts"; import { ServerSettingsService } from "../../serverSettings.ts"; import { ServerSettingsError } from "@t3tools/contracts"; const DEFAULT_CLAUDE_MODEL_CAPABILITIES: ModelCapabilities = createModelCapabilities({ optionDescriptors: [], }); const PROVIDER = "claudeAgent" as const; const CLAUDE_PRESENTATION = { displayName: "Claude", showInteractionModeToggle: true, } as const; const MINIMUM_CLAUDE_OPUS_4_7_VERSION = "2.1.111"; const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ { slug: "claude-opus-4-7", name: "Claude Opus 4.7", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High" }, { value: "xhigh", label: "Extra High", isDefault: true }, { value: "max", label: "Max" }, { value: "ultrathink", label: "Ultrathink" }, ], promptInjectedValues: ["ultrathink"], }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", options: [ { value: "200k", label: "200k", isDefault: true }, { value: "1m", label: "1M" }, ], }), ], }), }, { slug: "claude-opus-4-6", name: "Claude Opus 4.6", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "max", label: "Max" }, { value: "ultrathink", label: "Ultrathink" }, ], promptInjectedValues: ["ultrathink"], }), buildBooleanOptionDescriptor({ id: "fastMode", label: "Fast Mode", }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", options: [ { value: "200k", label: "200k", isDefault: true }, { value: "1m", label: "1M" }, ], }), ], }), }, { slug: "claude-opus-4-5", name: "Claude Opus 4.5", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "max", label: "Max" }, ], }), buildBooleanOptionDescriptor({ id: "fastMode", label: "Fast Mode", }), ], }), }, { slug: "claude-sonnet-4-6", name: "Claude Sonnet 4.6", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", options: [ { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "ultrathink", label: "Ultrathink" }, ], promptInjectedValues: ["ultrathink"], }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", options: [ { value: "200k", label: "200k", isDefault: true }, { value: "1m", label: "1M" }, ], }), ], }), }, { slug: "claude-haiku-4-5", name: "Claude Haiku 4.5", isCustom: false, capabilities: createModelCapabilities({ optionDescriptors: [ buildBooleanOptionDescriptor({ id: "thinking", label: "Thinking", }), ], }), }, ]; function supportsClaudeOpus47(version: string | null | undefined): boolean { return version ? compareCliVersions(version, MINIMUM_CLAUDE_OPUS_4_7_VERSION) >= 0 : false; } function getBuiltInClaudeModelsForVersion( version: string | null | undefined, ): ReadonlyArray<ServerProviderModel> { if (supportsClaudeOpus47(version)) { return BUILT_IN_MODELS; } return BUILT_IN_MODELS.filter((model) => model.slug !== "claude-opus-4-7"); } function formatClaudeOpus47UpgradeMessage(version: string | null): string { const versionLabel = version ? `v${version}` : "the installed version"; return `Claude Code ${versionLabel} is too old for Claude Opus 4.7. Upgrade to v${MINIMUM_CLAUDE_OPUS_4_7_VERSION} or newer to access it.`; } export function getClaudeModelCapabilities(model: string | null | undefined): ModelCapabilities { const slug = model?.trim(); return ( BUILT_IN_MODELS.find((candidate) => candidate.slug === slug)?.capabilities ?? DEFAULT_CLAUDE_MODEL_CAPABILITIES ); } export function resolveClaudeEffort( caps: ModelCapabilities, raw: string | null | undefined, ): string | undefined { const descriptors = getProviderOptionDescriptors({ caps, ...(raw ? { selections: [{ id: "effort", value: raw }] } : {}), }); const effortDescriptor = descriptors.find((descriptor) => descriptor.id === "effort"); const value = getProviderOptionCurrentValue(effortDescriptor); return typeof value === "string" ? value : undefined; } /** * Normalize a resolved Claude effort value into one suitable for the Claude * CLI's `--effort` flag. * * Mirrors the mapping used when invoking the Claude Agent SDK * ({@link getEffectiveClaudeAgentEffort} in ClaudeAdapter): the Opus 4.7 * capability `"xhigh"` is rewritten to the accepted CLI value `"max"`, and * `"ultrathink"` is filtered out because it is a prompt-prefix mode rather * than a CLI-effort value. Returns `undefined` when no flag should be passed. */ export function normalizeClaudeCliEffort(effort: string | null | undefined): string | undefined { if (!effort || effort === "ultrathink") { return undefined; } if (effort === "xhigh") { return "max"; } return effort; } export function resolveClaudeApiModelId(modelSelection: ClaudeModelSelection): string { switch (getModelSelectionStringOptionValue(modelSelection, "contextWindow")) { case "1m": return `${modelSelection.model}[1m]`; default: return modelSelection.model; } } export function parseClaudeAuthStatusFromOutput(result: CommandResult): { readonly status: Exclude<ServerProviderState, "disabled">; readonly auth: Pick<ServerProviderAuth, "status">; readonly message?: string; } { const lowerOutput = `${result.stdout}\n${result.stderr}`.toLowerCase(); if ( lowerOutput.includes("unknown command") || lowerOutput.includes("unrecognized command") || lowerOutput.includes("unexpected argument") ) { return { status: "warning", auth: { status: "unknown" }, message: "Claude Agent authentication status command is unavailable in this version of Claude.", }; } if ( lowerOutput.includes("not logged in") || lowerOutput.includes("login required") || lowerOutput.includes("authentication required") || lowerOutput.includes("run `claude login`") || lowerOutput.includes("run claude login") ) { return { status: "error", auth: { status: "unauthenticated" }, message: "Claude is not authenticated. Run `claude auth login` and try again.", }; } const parsedAuth = (() => { const trimmed = result.stdout.trim(); if (!trimmed || (!trimmed.startsWith("{") && !trimmed.startsWith("["))) { return { attemptedJsonParse: false as const, auth: undefined as boolean | undefined }; } try { return { attemptedJsonParse: true as const, auth: extractAuthBoolean(JSON.parse(trimmed)), }; } catch { return { attemptedJsonParse: false as const, auth: undefined as boolean | undefined }; } })(); if (parsedAuth.auth === true) { return { status: "ready", auth: { status: "authenticated" } }; } if (parsedAuth.auth === false) { return { status: "error", auth: { status: "unauthenticated" }, message: "Claude is not authenticated. Run `claude auth login` and try again.", }; } if (parsedAuth.attemptedJsonParse) { return { status: "warning", auth: { status: "unknown" }, message: "Could not verify Claude authentication status from JSON output (missing auth marker).", }; } if (result.code === 0) { return { status: "ready", auth: { status: "authenticated" } }; } const detail = detailFromResult(result); return { status: "warning", auth: { status: "unknown" }, message: detail ? `Could not verify Claude authentication status. ${detail}` : "Could not verify Claude authentication status.", }; } // ── Subscription type detection ───────────────────────────────────── // // The SDK probe returns typed `AccountInfo.subscriptionType` directly. // This walker is a best-effort fallback for the `claude auth status` // JSON output whose shape is not guaranteed. /** Keys that directly hold a subscription/plan identifier. */ const SUBSCRIPTION_TYPE_KEYS = [ "subscriptionType", "subscription_type", "plan", "tier", "planType", "plan_type", ] as const; /** Keys whose value may be a nested object containing subscription info. */ const SUBSCRIPTION_CONTAINER_KEYS = ["account", "subscription", "user", "billing"] as const; const AUTH_METHOD_KEYS = ["authMethod", "auth_method"] as const; const AUTH_METHOD_CONTAINER_KEYS = ["auth", "account", "session"] as const; /** Lift an unknown value into `Option<string>` if it is a non-empty string. */ const asNonEmptyString = (v: unknown): Option.Option<string> => typeof v === "string" && v.length > 0 ? Option.some(v) : Option.none(); /** Lift an unknown value into `Option<Record>` if it is a plain object. */ const asRecord = (v: unknown): Option.Option<Record<string, unknown>> => typeof v === "object" && v !== null && !globalThis.Array.isArray(v) ? Option.some(v as Record<string, unknown>) : Option.none(); /** * Walk an unknown parsed JSON value looking for a subscription/plan * identifier, returning the first match as an `Option`. */ function findSubscriptionType(value: unknown): Option.Option<string> { if (globalThis.Array.isArray(value)) { return Option.firstSomeOf(value.map(findSubscriptionType)); } return asRecord(value).pipe( Option.flatMap((record) => { const direct = Option.firstSomeOf( SUBSCRIPTION_TYPE_KEYS.map((key) => asNonEmptyString(record[key])), ); if (Option.isSome(direct)) return direct; return Option.firstSomeOf( SUBSCRIPTION_CONTAINER_KEYS.map((key) => asRecord(record[key]).pipe(Option.flatMap(findSubscriptionType)), ), ); }), ); } function findAuthMethod(value: unknown): Option.Option<string> { if (globalThis.Array.isArray(value)) { return Option.firstSomeOf(value.map(findAuthMethod)); } return asRecord(value).pipe( Option.flatMap((record) => { const direct = Option.firstSomeOf( AUTH_METHOD_KEYS.map((key) => asNonEmptyString(record[key])), ); if (Option.isSome(direct)) return direct; return Option.firstSomeOf( AUTH_METHOD_CONTAINER_KEYS.map((key) => asRecord(record[key]).pipe(Option.flatMap(findAuthMethod)), ), ); }), ); } /** * Try to extract a subscription type from the `claude auth status` JSON * output. This is a zero-cost operation on data we already have. */ const decodeUnknownJson = decodeJsonResult(Schema.Unknown); function extractSubscriptionTypeFromOutput(result: CommandResult): string | undefined { const parsed = decodeUnknownJson(result.stdout.trim()); if (Result.isFailure(parsed)) return undefined; return Option.getOrUndefined(findSubscriptionType(parsed.success)); } function extractClaudeAuthMethodFromOutput(result: CommandResult): string | undefined { const parsed = decodeUnknownJson(result.stdout.trim()); if (Result.isFailure(parsed)) return undefined; return Option.getOrUndefined(findAuthMethod(parsed.success)); } function toTitleCaseWords(value: string): string { return value .split(/[\s_-]+/g) .filter(Boolean) .map((part) => part[0]!.toUpperCase() + part.slice(1).toLowerCase()) .join(" "); } function claudeSubscriptionLabel(subscriptionType: string | undefined): string | undefined { const normalized = subscriptionType?.toLowerCase().replace(/[\s_-]+/g, ""); if (!normalized) return undefined; switch (normalized) { case "max": case "maxplan": case "max5": case "max20": return "Max"; case "enterprise": return "Enterprise"; case "team": return "Team"; case "pro": return "Pro"; case "free": return "Free"; default: return toTitleCaseWords(subscriptionType!); } } function normalizeClaudeAuthMethod(authMethod: string | undefined): string | undefined { const normalized = authMethod?.toLowerCase().replace(/[\s_-]+/g, ""); if (!normalized) return undefined; if (normalized === "apikey") return "apiKey"; return undefined; } function claudeAuthMetadata(input: { readonly subscriptionType: string | undefined; readonly authMethod: string | undefined; }): { readonly type: string; readonly label: string } | undefined { if (normalizeClaudeAuthMethod(input.authMethod) === "apiKey") { return { type: "apiKey", label: "Claude API Key", }; } if (input.subscriptionType) { const subscriptionLabel = claudeSubscriptionLabel(input.subscriptionType); return { type: input.subscriptionType, label: `Claude ${subscriptionLabel ?? toTitleCaseWords(input.subscriptionType)} Subscription`, }; } return undefined; } // ── SDK capability probe ──────────────────────────────────────────── const CAPABILITIES_PROBE_TIMEOUT_MS = 8_000; function nonEmptyProbeString(value: string): string | undefined { const candidate = value.trim(); return candidate ? candidate : undefined; } function parseClaudeInitializationCommands( commands: ReadonlyArray<ClaudeSlashCommand> | undefined, ): ReadonlyArray<ServerProviderSlashCommand> {