syncable-cli 0.37.1

A Rust-based CLI that analyzes code repositories and generates Infrastructure as Code configurations
Documentation
/**
 * Agent Settings Context
 *
 * Provides provider, model, and API key configuration for the agent.
 * Settings are persisted to localStorage.
 */
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';

export type Provider = 'openai' | 'anthropic' | 'bedrock';

export interface AgentSettings {
  provider: Provider;
  model: string;
  apiKey: string;
  awsRegion?: string;
}

interface AgentSettingsContextType {
  settings: AgentSettings;
  setProvider: (provider: Provider) => void;
  setModel: (model: string) => void;
  setApiKey: (apiKey: string) => void;
  setAwsRegion: (region: string) => void;
  availableModels: { id: string; name: string }[];
}

const STORAGE_KEY = 'syncable-agent-settings';

const DEFAULT_SETTINGS: AgentSettings = {
  provider: 'openai',
  model: 'gpt-5.2',
  apiKey: '',
  awsRegion: 'us-east-1',
};

const MODELS_BY_PROVIDER: Record<Provider, { id: string; name: string }[]> = {
  openai: [
    { id: 'gpt-5.2', name: 'GPT-5.2 - Latest reasoning model (Dec 2025)' },
    { id: 'gpt-5.2-mini', name: 'GPT-5.2 Mini - Fast and affordable' },
    { id: 'gpt-4o', name: 'GPT-4o - Multimodal workhorse' },
    { id: 'o1-preview', name: 'o1-preview - Advanced reasoning' },
  ],
  anthropic: [
    { id: 'claude-opus-4-5-20251101', name: 'Claude Opus 4.5 - Most capable (Nov 2025)' },
    { id: 'claude-sonnet-4-5-20250929', name: 'Claude Sonnet 4.5 - Balanced (Sep 2025)' },
    { id: 'claude-haiku-4-5-20251001', name: 'Claude Haiku 4.5 - Fast (Oct 2025)' },
    { id: 'claude-sonnet-4-20250514', name: 'Claude Sonnet 4 - Previous gen' },
  ],
  bedrock: [
    { id: 'global.anthropic.claude-opus-4-5-20251101-v1:0', name: 'Claude Opus 4.5 - Most capable (Nov 2025)' },
    { id: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0', name: 'Claude Sonnet 4.5 - Balanced (Sep 2025)' },
    { id: 'global.anthropic.claude-haiku-4-5-20251001-v1:0', name: 'Claude Haiku 4.5 - Fast (Oct 2025)' },
    { id: 'global.anthropic.claude-sonnet-4-20250514-v1:0', name: 'Claude Sonnet 4 - Previous gen' },
  ],
};

const AgentSettingsContext = createContext<AgentSettingsContextType | null>(null);

export function AgentSettingsProvider({ children }: { children: ReactNode }) {
  const [settings, setSettings] = useState<AgentSettings>(DEFAULT_SETTINGS);

  // Load from localStorage on mount
  useEffect(() => {
    try {
      const stored = localStorage.getItem(STORAGE_KEY);
      if (stored) {
        const parsed = JSON.parse(stored);
        setSettings({ ...DEFAULT_SETTINGS, ...parsed });
      }
    } catch (e) {
      console.error('Failed to load agent settings:', e);
    }
  }, []);

  // Save to localStorage on change
  useEffect(() => {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
    } catch (e) {
      console.error('Failed to save agent settings:', e);
    }
  }, [settings]);

  const setProvider = (provider: Provider) => {
    setSettings(prev => ({
      ...prev,
      provider,
      model: MODELS_BY_PROVIDER[provider][0].id, // Reset to first model
    }));
  };

  const setModel = (model: string) => {
    setSettings(prev => ({ ...prev, model }));
  };

  const setApiKey = (apiKey: string) => {
    setSettings(prev => ({ ...prev, apiKey }));
  };

  const setAwsRegion = (awsRegion: string) => {
    setSettings(prev => ({ ...prev, awsRegion }));
  };

  const availableModels = MODELS_BY_PROVIDER[settings.provider];

  return (
    <AgentSettingsContext.Provider
      value={{
        settings,
        setProvider,
        setModel,
        setApiKey,
        setAwsRegion,
        availableModels,
      }}
    >
      {children}
    </AgentSettingsContext.Provider>
  );
}

export function useAgentSettings() {
  const context = useContext(AgentSettingsContext);
  if (!context) {
    throw new Error('useAgentSettings must be used within AgentSettingsProvider');
  }
  return context;
}