/** * Settings Type Definitions * * Types for managing Crewly application settings including * runtime preferences, chat settings, and skill configurations. * * @module types/settings.types */ /** * Available AI runtime options */ export type AIRuntime = 'claude-code' | 'gemini-cli' | 'codex-cli' | 'opencode-cli' | 'antigravity-cli' | 'crewly-agent'; /** * Array of all valid AI runtimes */ export declare const AI_RUNTIMES: readonly AIRuntime[]; /** * General application settings */ export interface GeneralSettings { /** Default AI runtime for new agents */ defaultRuntime: AIRuntime; /** Whether to auto-start the orchestrator on application launch */ autoStartOrchestrator: boolean; /** * Whether the hung-session watchdog auto-restarts the orchestrator when its * session is hung (alive but claiming work without ever heartbeating). When * false, the hang is still detected + surfaced on `/health` but not recovered. */ autoRecoverHungOrchestrator: boolean; /** Agent check-in interval in minutes */ checkInIntervalMinutes: number; /** Maximum concurrent agents allowed */ maxConcurrentAgents: number; /** Enable verbose logging */ verboseLogging: boolean; /** Whether to auto-resume agent sessions on restart */ autoResumeOnRestart: boolean; /** Whether to post a "back online" message to the owner's channel after a restart */ announceOnBoot: boolean; /** * Keep this machine on the latest npm release automatically: install it in * a quiet window and restart gracefully (specs/auto-update.md). Only acts * on npm installs — never on a dev checkout. `CREWLY_AUTO_UPDATE=0` forces * it off regardless of this value. Optional so older settings files merge * to the default (on). */ autoUpdate?: boolean; /** * Start a fresh Claude Code conversation (with a saved handover) when a team * member gets a task unrelated to its previous one, instead of carrying the * whole history into every turn. Never applies to the orchestrator. * `CREWLY_FRESH_TASK_CONVERSATION=0` forces it off regardless of this value. * Optional so older settings files merge to the default (on). */ freshConversationPerTask?: boolean; /** Per-runtime CLI init commands. Key = runtime type, value = CLI command string */ runtimeCommands: Record; /** Minutes of inactivity before an agent is automatically suspended (0 = disabled) */ agentIdleTimeoutMinutes: number; /** Max concurrently running agents while the machine is under resource pressure (orchestrator exempt). Default 6. */ pressureMaxRunningAgents?: number; /** Idle timeout in minutes while under resource pressure (0 = use the normal timeout). Default 10. */ pressureIdleTimeoutMinutes?: number; /** Enable proactive context compaction based on cumulative terminal output volume */ enableProactiveCompact: boolean; /** * Enable threshold-driven context compaction at RED (85%) / CRITICAL (95%). * * When `false` (default), the wrapper does NOT trigger `/compact` based on * context-percent thresholds — the runtime (Claude Code, etc.) handles its * own internal compaction. The threshold path remains as opt-in safety net * for users who want wrapper-driven compaction on top of native compaction. * * Per spec 2026-05-05-compact-fix-AB-followup: aligns wrapper behavior with * Steve's user-position decision — "Claude Code self-compacts internally, * external compact is unnecessary". */ enableThresholdCompact: boolean; /** Enable Self Evolution mode — orchestrator monitors for errors and self-triages */ enableSelfEvolution: boolean; /** Enable token usage tracking for agent sessions */ tokenTracking: boolean; /** Enable the auditor agent (quality observer that monitors agents and writes audit reports). * When disabled, the auditor PTY session is not started and all audit scheduling is skipped. */ enableAuditor: boolean; /** * Cadence (in minutes) at which idle agents are scanned and auto-claimed * to the next available WorkItem. * * Spec 2026-05-06-task-management-v1-deprecation.md: V3 task-pool is * the operational backbone, and `AgentAutoClaimService` is the single * autonomy loop. The polling tick is a safety net on top of the * event-driven `agent:idle` trigger. * * - `0` disables polling entirely (events-only — instant on idle). * - `> 0` runs a periodic scan every N minutes. * - Default `5` (a reasonable balance between responsiveness and * token spend; the event path still fires immediately on idle). */ autonomyTickIntervalMinutes: number; } /** * Chat interface settings */ export interface ChatSettings { /** Show raw terminal output in chat messages */ showRawTerminalOutput: boolean; /** Enable typing indicator when agent is processing */ enableTypingIndicator: boolean; /** Maximum number of messages to keep in history */ maxMessageHistory: number; /** Auto-scroll to newest messages */ autoScrollToBottom: boolean; /** Show timestamps on messages */ showTimestamps: boolean; } /** * Skills system settings */ export interface SkillsSettings { /** Custom skills directory path */ skillsDirectory: string; /** Enable browser automation capabilities */ enableBrowserAutomation: boolean; /** Browser runtime profile used when generating MCP browser config */ browserProfile?: { headless: boolean; stealth: boolean; humanDelayMinMs: number; humanDelayMaxMs: number; }; /** Enable script execution */ enableScriptExecution: boolean; /** Timeout for skill execution in milliseconds */ skillExecutionTimeoutMs: number; } /** * Supported AI provider names for API key management. * * Note: 'deepseek' is served via the OpenAI-compatible endpoint at * https://api.deepseek.com/v1, but is configured as a distinct provider * so users can save a separate API key in Settings. See * services/agent/crewly-agent/model-manager.ts for the runtime wiring. */ export type ApiKeyProvider = 'gemini' | 'anthropic' | 'openai' | 'deepseek'; /** * Array of all valid API key providers */ export declare const API_KEY_PROVIDERS: readonly ApiKeyProvider[]; /** * Environment variable names for each provider's API key */ export declare const API_KEY_ENV_VARS: Record; /** * Configuration for an API key override at runtime or skill level */ export interface ApiKeyConfig { /** The actual API key value (encrypted at rest) */ key: string; /** Whether this uses the global key or a custom override */ source: 'global' | 'custom'; } /** * API Keys settings with global keys and per-level overrides * * Override resolution order: skill → runtime → global → env var fallback */ export interface ApiKeysSettings { /** Global API keys available system-wide */ global: { gemini?: string; anthropic?: string; openai?: string; deepseek?: string; }; /** Per-runtime API key overrides (e.g. "gemini-cli", "crewly-agent") */ runtimeOverrides?: { [runtimeType: string]: { gemini?: ApiKeyConfig; anthropic?: ApiKeyConfig; openai?: ApiKeyConfig; deepseek?: ApiKeyConfig; }; }; /** Per-skill API key overrides (e.g. "nano-banana-image") */ skillOverrides?: { [skillName: string]: { gemini?: ApiKeyConfig; anthropic?: ApiKeyConfig; openai?: ApiKeyConfig; deepseek?: ApiKeyConfig; }; }; } /** * Context for resolving an API key through the override chain */ export interface ApiKeyResolutionContext { /** Runtime type requesting the key (e.g. "gemini-cli", "crewly-agent") */ runtime?: string; /** Skill name requesting the key (e.g. "nano-banana-image") */ skill?: string; } /** * Complete Crewly settings */ export interface CrewlySettings { /** General application settings */ general: GeneralSettings; /** Chat interface settings */ chat: ChatSettings; /** Skills system settings */ skills: SkillsSettings; /** API key management settings */ apiKeys?: ApiKeysSettings; } /** * Partial settings for updates */ export interface UpdateSettingsInput { /** Partial general settings */ general?: Partial; /** Partial chat settings */ chat?: Partial; /** Partial skills settings */ skills?: Partial; /** Partial API keys settings */ apiKeys?: Partial; } /** * Settings validation result */ export interface SettingsValidationResult { /** Whether the settings are valid */ valid: boolean; /** Array of validation error messages */ errors: string[]; } /** * Minimum values for numeric settings */ export declare const SETTINGS_CONSTRAINTS: { readonly MIN_CHECK_IN_INTERVAL: 1; readonly MIN_MAX_CONCURRENT_AGENTS: 1; readonly MIN_MAX_MESSAGE_HISTORY: 10; readonly MIN_SKILL_EXECUTION_TIMEOUT: 1000; }; /** * Type guard to check if a string is a valid AI runtime * * @param value - The string to check * @returns True if the value is a valid AI runtime * * @example * ```typescript * if (isValidAIRuntime(input)) { * // input is typed as AIRuntime * } * ``` */ export declare function isValidAIRuntime(value: string): value is AIRuntime; /** * Get default settings with all sensible values * * @returns Complete Crewly settings with default values * * @example * ```typescript * const defaults = getDefaultSettings(); * console.log(defaults.general.defaultRuntime); // 'claude-code' * ``` */ export declare function getDefaultSettings(): CrewlySettings; /** * Validate settings and return validation result * * @param settings - The settings to validate * @returns Validation result with valid flag and any errors * * @example * ```typescript * const result = validateSettings(settings); * if (!result.valid) { * console.error('Validation errors:', result.errors); * } * ``` */ export declare function validateSettings(settings: CrewlySettings): SettingsValidationResult; /** * Deep merge settings with partial updates * * Creates a new settings object without modifying the originals. * * @param existing - The existing settings * @param updates - Partial updates to apply * @returns New settings object with updates applied * * @example * ```typescript * const updated = mergeSettings(current, { * general: { defaultRuntime: 'gemini-cli' }, * }); * ``` */ export declare function mergeSettings(existing: CrewlySettings, updates: UpdateSettingsInput): CrewlySettings; /** * Check if a partial settings object has any defined values * * @param settings - The partial settings to check * @returns True if any section has defined values */ export declare function hasSettingsUpdates(settings: UpdateSettingsInput): boolean; /** * Check if a string is a valid API key provider * * @param value - The string to check * @returns True if the value is a valid API key provider */ export declare function isValidApiKeyProvider(value: string): value is ApiKeyProvider; /** The character masked API keys are made of (see {@link maskApiKey}). */ export declare const API_KEY_MASK_CHAR = "\u2022"; /** * Whether a value is a masked API key as {@link maskApiKey} produces it, * not a real key. Real provider keys never start with `•`. * * @param value - Candidate key * @returns True for a mask * * @example * isMaskedApiKey('••••••••abcd') // true * isMaskedApiKey('sk-live-abcd') // false */ export declare function isMaskedApiKey(value: unknown): boolean; /** * Replace every masked key in an API-keys update with the stored key for * the same slot (global, runtime override, skill override). A masked value * with nothing stored behind it is dropped. The input is not modified. * * @param existing - Stored API keys * @param update - Incoming partial update * @returns The update with real keys only */ export declare function restoreMaskedApiKeys(existing: ApiKeysSettings, update: Partial): Partial; /** * Mask an API key for safe display, showing only the last 4 characters * * @param key - The API key to mask * @returns Masked key string (e.g. "••••••••abcd") */ export declare function maskApiKey(key: string): string; /** * Resolve an API key through the override chain: skill → runtime → global → env var * * @param provider - The API key provider * @param apiKeysSettings - The API keys settings * @param context - Resolution context with optional runtime and skill * @returns The resolved API key or undefined if not found */ export declare function resolveApiKey(provider: ApiKeyProvider, apiKeysSettings: ApiKeysSettings | undefined, context?: ApiKeyResolutionContext): string | undefined; /** * Create a masked copy of API keys settings for safe API responses * * @param apiKeys - The API keys settings to mask * @returns Masked copy safe for API responses */ export declare function maskApiKeysSettings(apiKeys: ApiKeysSettings): ApiKeysSettings; /** * Get the display name for an AI runtime * * @param runtime - The AI runtime * @returns Human-readable display name */ export declare function getAIRuntimeDisplayName(runtime: AIRuntime): string; //# sourceMappingURL=settings.types.d.ts.map