Files
Netcatty/components/ui/spinner.tsx
T
bincxzandClaude Opus 4.6 72887c35b5 feat: add AI chat panel with Vercel AI SDK integration
Add a comprehensive AI assistant feature to netcatty, enabling AI-powered
terminal automation and multi-host orchestration.

Core features:
- AI chat side panel (Zed-style) with agent selector, session history,
  conversation export (Markdown/JSON/TXT), and streaming responses
- Catty Agent: built-in terminal assistant with 9 tools (terminal exec,
  SFTP read/write, multi-host orchestration) using zod schemas
- BYOK provider support: OpenAI, Anthropic, Google, Ollama, OpenRouter,
  and custom OpenAI-compatible endpoints
- Three-tier permission model: Observer / Confirm / Autonomous
- Command safety: blocklist patterns, doom loop detection, abort support
- External agent support: ACP protocol (JSON-RPC over stdio) for
  Claude Agent, Codex CLI, Gemini CLI, and custom agents

Tech stack:
- Vercel AI SDK (ai, @ai-sdk/openai, @ai-sdk/anthropic, @ai-sdk/google)
  with streamText + fullStream for streaming tool-call loops
- AI Elements: adapted conversation (use-stick-to-bottom), message
  (streamdown markdown), prompt-input (InputGroup) components
- Custom bridge fetch adapter routing all API calls through Electron
  main process IPC to avoid CORS
- zod for tool parameter schemas

UI components:
- AIChatSidePanel, AgentSelector, ChatInput, ChatMessageList
- PermissionDialog, ExecutionPlan, ConversationExport
- AI Elements: conversation, message, tool-call, prompt-input
- New UI primitives: InputGroup, Spinner
- Settings AI tab for BYOK configuration and safety settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 14:22:28 +08:00

10 lines
345 B
TypeScript

import { cn } from '../../lib/utils';
import { Loader2 } from 'lucide-react';
import type { ComponentProps } from 'react';
export type SpinnerProps = ComponentProps<typeof Loader2>;
export const Spinner = ({ className, size = 16, ...props }: SpinnerProps) => (
<Loader2 className={cn('animate-spin', className)} size={size} {...props} />
);