kya-validator 0.2.3

Rust core KYA (Know Your Agent) validator with Python bindings, TEE support, and blockchain integration
Documentation
/**
 * ScenarioSelector - Component for selecting and configuring negotiation scenarios.
 */
import { useState, useEffect } from 'react';
import { useDemoStore } from '../../store/demoStore';

// Scenario types
export type ScenarioType = 'desperate_buyer' | 'price_negotiation' | 'custom';

export interface ScenarioConfig {
  type: ScenarioType;
  name: string;
  description: string;
  parameters: ScenarioParameter[];
}

export interface ScenarioParameter {
  name: string;
  type: 'string' | 'number' | 'enum';
  defaultValue: unknown;
  description?: string;
  enumValues?: string[];
}

// Pre-defined scenarios
const SCENARIOS: Record<ScenarioType, ScenarioConfig> = {
  desperate_buyer: {
    type: 'desperate_buyer',
    name: 'Desperate JIT Buyer',
    description: 'A desperate buyer willing to pay list price for immediate delivery. Focus on availability and speed.',
    parameters: [
      {
        name: 'urgency_level',
        type: 'enum',
        defaultValue: 'critical',
        description: 'Level of urgency for procurement',
        enumValues: ['low', 'medium', 'high', 'critical'],
      },
      {
        name: 'price_sensitivity',
        type: 'enum',
        defaultValue: 'flexible',
        description: 'Price negotiation stance',
        enumValues: ['flexible', 'moderate', 'strict'],
      },
      {
        name: 'negotiation_strategy',
        type: 'enum',
        defaultValue: 'accommodating',
        description: 'How to handle pricing negotiations',
        enumValues: ['accommodating', 'firm', 'competitive'],
      },
    ],
  },
  price_negotiation: {
    type: 'price_negotiation',
    name: 'Price Negotiation',
    description: 'JIT procurement with configurable price negotiation parameters.',
    parameters: [
      {
        name: 'expected_price',
        type: 'number',
        defaultValue: 2000,
        description: 'Your target price (lower than storefront)',
      },
      {
        name: 'competition',
        type: 'enum',
        defaultValue: 'moderate',
        description: 'Market competition level',
        enumValues: ['none', 'low', 'medium', 'high'],
      },
      {
        name: 'desperation',
        type: 'enum',
        defaultValue: 'medium',
        description: 'Time pressure level',
        enumValues: ['none', 'low', 'medium', 'high'],
      },
    ],
  },
  custom: {
    type: 'custom',
    name: 'Custom Scenario',
    description: 'Configure your own custom negotiation scenario parameters.',
    parameters: [
      {
        name: 'custom_parameters',
        type: 'string',
        defaultValue: '',
        description: 'Custom scenario configuration (JSON)',
      },
    ],
  },
};

interface ScenarioSelectorProps {
  onScenarioApply?: (scenario: ScenarioType, parameters: Record<string, unknown>) => void;
}

export default function ScenarioSelector({ onScenarioApply }: ScenarioSelectorProps) {
  const { currentScenario, scenarioParameters, setScenario, setScenarioParameters } = useDemoStore();
  const [selectedScenarioType, setSelectedScenarioType] = useState<ScenarioType>('desperate_buyer');
  const [localParameters, setLocalParameters] = useState<Record<string, unknown>>({});

  // Initialize local parameters when scenario changes
  useEffect(() => {
    const scenario = SCENARIOS[selectedScenarioType];
    const defaultParams: Record<string, unknown> = {};
    scenario.parameters.forEach((param) => {
      defaultParams[param.name] = param.defaultValue;
    });
    setLocalParameters(defaultParams);
  }, [selectedScenarioType]);

  // Sync with store when current scenario changes
  useEffect(() => {
    if (currentScenario) {
      setSelectedScenarioType(currentScenario);
      setLocalParameters(scenarioParameters);
    }
  }, [currentScenario, scenarioParameters]);

  const handleScenarioChange = (type: ScenarioType) => {
    setSelectedScenarioType(type);
    const scenario = SCENARIOS[type];
    const defaultParams: Record<string, unknown> = {};
    scenario.parameters.forEach((param) => {
      defaultParams[param.name] = param.defaultValue;
    });
    setLocalParameters(defaultParams);
  };

  const handleParameterChange = (paramName: string, value: unknown) => {
    setLocalParameters((prev) => ({
      ...prev,
      [paramName]: value,
    }));
  };

  const handleApplyScenario = () => {
    setScenario(selectedScenarioType);
    setScenarioParameters(localParameters);
    
    if (onScenarioApply) {
      onScenarioApply(selectedScenarioType, localParameters);
    }
  };

  const selectedScenario = SCENARIOS[selectedScenarioType];

  return (
    <div className="bg-slate-700/50 rounded-lg p-4 space-y-4">
      <div>
        <label className="block text-sm font-medium text-slate-300 mb-2">
          Select Negotiation Scenario
        </label>
        <select
          value={selectedScenarioType}
          onChange={(e) => handleScenarioChange(e.target.value as ScenarioType)}
          className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:ring-2 focus:ring-cyan-500"
        >
          {Object.entries(SCENARIOS).map(([type, config]) => (
            <option key={type} value={type}>
              {config.name}
            </option>
          ))}
        </select>
      </div>

      {/* Scenario Description */}
      <div className="bg-slate-600/50 rounded-lg p-3">
        <h4 className="text-sm font-semibold text-cyan-400 mb-1">
          {selectedScenario.name}
        </h4>
        <p className="text-xs text-slate-300">{selectedScenario.description}</p>
      </div>

      {/* Scenario Parameters */}
      <div className="space-y-3">
        <h4 className="text-sm font-medium text-slate-300">Scenario Parameters</h4>
        {selectedScenario.parameters.map((param) => (
          <div key={param.name}>
            <label className="block text-xs text-slate-400 mb-1">
              {param.name.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase())}
              {param.description && ` - ${param.description}`}
            </label>
            {param.type === 'enum' && param.enumValues ? (
              <select
                value={localParameters[param.name] as string}
                onChange={(e) => handleParameterChange(param.name, e.target.value)}
                className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:ring-2 focus:ring-cyan-500"
              >
                {param.enumValues.map((value) => (
                  <option key={value} value={value}>
                    {value}
                  </option>
                ))}
              </select>
            ) : param.type === 'number' ? (
              <input
                type="number"
                value={localParameters[param.name] as number}
                onChange={(e) => handleParameterChange(param.name, Number(e.target.value))}
                className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:ring-2 focus:ring-cyan-500"
              />
            ) : (
              <input
                type="text"
                value={localParameters[param.name] as string}
                onChange={(e) => handleParameterChange(param.name, e.target.value)}
                className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:ring-2 focus:ring-cyan-500"
              />
            )}
          </div>
        ))}
      </div>

      {/* Apply Scenario Button */}
      <button
        onClick={handleApplyScenario}
        className="w-full bg-gradient-to-r from-cyan-500 to-blue-600 hover:from-cyan-600 hover:to-blue-700 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 flex items-center justify-center gap-2"
      >
        <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
          />
        </svg>
        Apply Scenario
      </button>
    </div>
  );
}