arial
GitHub

Adapter System

The adapter system provides a pluggable interface for AI backends, allowing Arial to work with different AI providers while maintaining a consistent internal API.

Overview

Adapters abstract the details of communicating with AI backends. Currently, Arial includes a Claude adapter, but the architecture supports adding other providers.

Core Interface

interface Adapter {
  id: string
  name: string
  capabilities: AdapterCapability[]

  hasCapabilities(required: AdapterCapability[]): boolean
  createExecutionRunner(options: ExecutionRunnerOptions): AgentRunner
  runPlanningAgent(options: PlanningAgentOptions): Promise<AgentRunResult>
  runSpecReviewAgent(options: AgentRunOptions): Promise<AgentRunResult>
  runConflictAgent(options: AgentRunOptions): Promise<AgentRunResult>
}

Capabilities

Adapters declare their capabilities:

CapabilityDescription
`file_read`Read files from the filesystem
`file_write`Write/edit files
`file_search`Search for files by pattern
`bash_execute`Execute shell commands
`web_search`Search the web
`web_fetch`Fetch web content
`code_analysis`Analyze code structure
`git_operations`Perform Git operations

Specs can require specific capabilities via frontmatter:

---
requiredCapabilities:
  - bash_execute
  - file_write
---

Adapter Registry

The registry (adapters/registry.ts) manages adapter instantiation:

Loading Configuration

function loadAdapterConfig(): AdapterConfig

Loads configuration from environment variables:

  • ANTHROPIC_API_KEY - API key for Claude
  • CLAUDE_LOCAL_CREDENTIALS - Use local Claude credentials

Creating Adapters

function createAdapter(config: AdapterConfig): Adapter

Factory function that instantiates the appropriate adapter based on configuration.

Validating Capabilities

function validateCapabilities(
  adapter: Adapter,
  required: AdapterCapability[]
): Result<void, string>

Ensures an adapter meets the requirements for a workstream.

Claude Adapter

Located in adapters/claude/, the Claude adapter implements:

Structure

adapters/claude/
├── index.ts       # Adapter implementation
├── agent.ts       # Single-call agent execution
├── runner.ts      # Long-running execution runner
└── permissions.ts # Dangerous command detection

Agent Types

Single-Call Agents (agent.ts):

  • Planning agent - Analyzes specs and suggests workstream organization
  • Spec review agent - Evaluates spec completeness
  • Conflict agent - Resolves merge conflicts

Execution Runner (runner.ts):

  • Long-running agent for workstream execution
  • Async with polling for status updates
  • Streams tool execution events

Permission System

The Claude adapter includes dangerous command detection (permissions.ts):

  • Fork bombs (:(){:|:&};:)
  • Recursive deletion (rm -rf /, rm -rf ~)
  • Filesystem formatting (mkfs, dd to /dev/)
  • Pipe to shell (curl | sh)
  • Permission bypasses (chmod 777 /)

Adding a New Adapter

To add a new AI provider:

Agent Runner Interface

The AgentRunner interface for long-running execution:

interface AgentRunner {
  start(): Promise<void>
  stop(): void
  isRunning(): boolean
  wait(): Promise<AgentRunResult>

  on(event: 'tool_start', handler: (tool: string) => void): void
  on(event: 'tool_end', handler: (tool: string) => void): void
  on(event: 'output', handler: (line: string) => void): void
}

This abstraction allows different backends to implement execution in their own way while providing a consistent interface to the orchestrator.