- RMM Overshell (migration 077): admin page, dispatch UI, executor/worker, target resolver, script registry (AD/DHCP/DNS/event-log/services/software/network/loglift) - LogLift evidence pipeline (migration 078): upload webhook, B2 storage client, receiver/matcher, EventLogCollector PowerShell script - IT Glue audit + write-back (migrations 075, 076): asset-audit runner, ticket xrefs, applications/configurations browse pages + apply/revert/audit endpoints - Link-aware analyzer bundles (migration 073) + provider toggle (migration 074): link-discovery service, OpenRouter LLM provider, related-tickets/itglue-suggestion panels, analyze-bundle endpoint - Endpoint data model + device-link reconciliation (migrations 079, 080): conflicts admin page, reconciler service, resolve endpoints - Dashboard overhaul: integration-health service + alerts, overview/health endpoints - Permissions: add itglue + rmm scopes; middleware: public /api/rmm/loglift route Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75 lines
1.8 KiB
TypeScript
75 lines
1.8 KiB
TypeScript
'use client';
|
|
|
|
import { Sparkles, Zap } from 'lucide-react';
|
|
|
|
export type AnalyzerProvider = 'anthropic' | 'openrouter';
|
|
|
|
interface ProviderToggleProps {
|
|
value: AnalyzerProvider;
|
|
onChange: (next: AnalyzerProvider) => void;
|
|
disabled?: boolean;
|
|
size?: 'sm' | 'md';
|
|
}
|
|
|
|
const OPTIONS: Array<{
|
|
value: AnalyzerProvider;
|
|
label: string;
|
|
hint: string;
|
|
icon: typeof Sparkles;
|
|
}> = [
|
|
{
|
|
value: 'anthropic',
|
|
label: 'Claude',
|
|
hint: 'Haiku → Sonnet → Opus',
|
|
icon: Sparkles,
|
|
},
|
|
{
|
|
value: 'openrouter',
|
|
label: 'DeepSeek',
|
|
hint: 'V4 Flash → V4 Pro → R1',
|
|
icon: Zap,
|
|
},
|
|
];
|
|
|
|
export function ProviderToggle({
|
|
value,
|
|
onChange,
|
|
disabled = false,
|
|
size = 'md',
|
|
}: ProviderToggleProps) {
|
|
const padding = size === 'sm' ? 'px-2 py-1 text-xs' : 'px-3 py-1.5 text-sm';
|
|
return (
|
|
<div
|
|
className="inline-flex rounded-md border bg-muted/40 p-0.5"
|
|
role="radiogroup"
|
|
aria-label="LLM provider"
|
|
>
|
|
{OPTIONS.map((opt) => {
|
|
const Icon = opt.icon;
|
|
const active = opt.value === value;
|
|
return (
|
|
<button
|
|
key={opt.value}
|
|
type="button"
|
|
role="radio"
|
|
aria-checked={active}
|
|
disabled={disabled}
|
|
onClick={() => onChange(opt.value)}
|
|
title={opt.hint}
|
|
className={[
|
|
padding,
|
|
'rounded-sm flex items-center gap-1.5 transition-colors',
|
|
active
|
|
? 'bg-background shadow-sm font-medium'
|
|
: 'text-muted-foreground hover:text-foreground',
|
|
disabled ? 'opacity-50 cursor-not-allowed' : '',
|
|
].join(' ')}
|
|
>
|
|
<Icon className={size === 'sm' ? 'w-3 h-3' : 'w-3.5 h-3.5'} />
|
|
{opt.label}
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|