> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/moeru-ai/airi/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugin API Reference

> Complete API reference for plugin development

## Core Functions

### definePlugin()

Defines a plugin with metadata and setup function.

```typescript theme={null}
function definePlugin(
  name: string,
  version: string,
  setup: () => Promise<Plugin> | Plugin
): PluginDefinition
```

<ParamField path="name" type="string" required>
  Plugin name (used for module identification)
</ParamField>

<ParamField path="version" type="string" required>
  Plugin version (semver format recommended)
</ParamField>

<ParamField path="setup" type="() => Promise<Plugin> | Plugin" required>
  Function that returns the plugin implementation
</ParamField>

**Example:**

```typescript theme={null}
import { definePlugin } from '@proj-airi/plugin-sdk'

export default definePlugin('my-plugin', '1.0.0', () => ({
  async init(context) {
    return true
  },
  async setupModules(context) {
    // Setup logic
  }
}))
```

## Plugin Interface

### Plugin

The plugin implementation interface.

```typescript theme={null}
interface Plugin {
  init?: (context: ContextInit) => Promise<void | undefined | false>
  setupModules?: (context: ContextInit) => Promise<void | undefined>
}
```

<ParamField path="init" type="function" optional>
  Plugin initialization hook. Return `false` to abort initialization.
</ParamField>

<ParamField path="setupModules" type="function" optional>
  Module setup hook. Called after configuration is applied.
</ParamField>

### ContextInit

Context passed to plugin hooks.

```typescript theme={null}
interface ContextInit {
  channels: {
    host: ChannelHost
  }
  apis: PluginApis
}
```

<ParamField path="channels.host" type="ChannelHost" required>
  Event channel for communicating with the plugin host
</ParamField>

<ParamField path="apis" type="PluginApis" required>
  APIs for protocol and client operations
</ParamField>

## Plugin Host API

### PluginHost

Manages plugin lifecycle and orchestration.

```typescript theme={null}
class PluginHost {
  constructor(options?: PluginHostOptions)
  
  async load(manifest: ManifestV1, options?: PluginLoadOptions): Promise<PluginHostSession>
  async init(sessionId: string, options?: PluginStartOptions): Promise<PluginHostSession>
  async start(manifest: ManifestV1, options?: PluginStartOptions): Promise<PluginHostSession>
  
  async applyConfiguration(sessionId: string, config: ModuleConfigEnvelope): Promise<PluginHostSession>
  markConfigurationNeeded(sessionId: string, reason?: string): PluginHostSession
  
  announceCapability(key: string, metadata?: Record<string, unknown>): CapabilityDescriptor
  markCapabilityReady(key: string, metadata?: Record<string, unknown>): CapabilityDescriptor
  markCapabilityDegraded(key: string, metadata?: Record<string, unknown>): CapabilityDescriptor
  withdrawCapability(key: string, metadata?: Record<string, unknown>): CapabilityDescriptor
  
  async waitForCapability(key: string, timeoutMs?: number): Promise<CapabilityDescriptor>
  async waitForCapabilities(keys: string[], timeoutMs?: number): Promise<void>
  isCapabilityReady(key: string): boolean
  listCapabilities(): CapabilityDescriptor[]
  
  listSessions(): PluginHostSession[]
  getSession(sessionId: string): PluginHostSession | undefined
  stop(sessionId: string): PluginHostSession | undefined
  async reload(sessionId: string, options?: PluginStartOptions): Promise<PluginHostSession>
  
  setProvidersListResolver(resolver: () => Promise<Array<{ name: string }>> | Array<{ name: string }>): void
}
```

### PluginHostOptions

```typescript theme={null}
interface PluginHostOptions {
  runtime?: 'electron' | 'node' | 'web'
  transport?: PluginTransport
  protocolVersion?: string
  apiVersion?: string
  supportedProtocolVersions?: string[]
  supportedApiVersions?: string[]
}
```

<ParamField path="runtime" type="'electron' | 'node' | 'web'" optional>
  Runtime environment. Defaults to `'electron'`.
</ParamField>

<ParamField path="transport" type="PluginTransport" optional>
  Communication transport. Defaults to `{ kind: 'in-memory' }`.
</ParamField>

<ParamField path="protocolVersion" type="string" optional>
  Preferred protocol version. Defaults to `'v1'`.
</ParamField>

<ParamField path="apiVersion" type="string" optional>
  Preferred API version. Defaults to `'v1'`.
</ParamField>

### PluginStartOptions

```typescript theme={null}
interface PluginStartOptions {
  cwd?: string
  runtime?: 'electron' | 'node' | 'web'
  requireConfiguration?: boolean
  compatibility?: Omit<ModuleCompatibilityRequest, 'protocolVersion' | 'apiVersion'>
  requiredCapabilities?: string[]
  capabilityWaitTimeoutMs?: number
}
```

<ParamField path="cwd" type="string" optional>
  Working directory for loading plugin files
</ParamField>

<ParamField path="requireConfiguration" type="boolean" optional>
  Stop at configuration-needed phase. Defaults to `false`.
</ParamField>

<ParamField path="requiredCapabilities" type="string[]" optional>
  Capabilities that must be ready before initialization
</ParamField>

<ParamField path="capabilityWaitTimeoutMs" type="number" optional>
  Timeout for waiting on capabilities. Defaults to `15000`ms.
</ParamField>

### PluginHostSession

```typescript theme={null}
interface PluginHostSession {
  manifest: ManifestV1
  plugin: Plugin
  id: string
  index: number
  cwd: string
  identity: ModuleIdentity
  phase: PluginSessionPhase
  lifecycle: ActorRefFrom<typeof pluginLifecycleMachine>
  transport: PluginTransport
  runtime: PluginRuntime
  channels: {
    host: ReturnType<typeof createPluginContext>
  }
  apis: PluginApis
}
```

## APIs

### Protocol APIs

APIs for plugin-host protocol communication.

#### capabilities

```typescript theme={null}
interface CapabilityApis {
  wait(key: string, timeoutMs?: number): Promise<CapabilityDescriptor>
  snapshot(): Promise<CapabilityDescriptor[]>
}
```

**wait()**

Wait for a capability to become ready.

```typescript theme={null}
const capability = await apis.protocol.capabilities.wait('llm:openai', 15000)
```

<ParamField path="key" type="string" required>
  Capability key to wait for
</ParamField>

<ParamField path="timeoutMs" type="number" optional>
  Timeout in milliseconds. Defaults to `15000`.
</ParamField>

<ResponseField name="capability" type="CapabilityDescriptor">
  The capability descriptor when ready
</ResponseField>

**snapshot()**

Get current snapshot of all capabilities.

```typescript theme={null}
const capabilities = await apis.protocol.capabilities.snapshot()
```

<ResponseField name="capabilities" type="CapabilityDescriptor[]">
  Array of all capability descriptors
</ResponseField>

#### resources.providers

```typescript theme={null}
interface ProviderApis {
  list(): Promise<Array<{ name: string }>>
}
```

**list()**

List available resource providers.

```typescript theme={null}
const providers = await apis.protocol.resources.providers.list()
```

<ResponseField name="providers" type="Array<{ name: string }>">
  Array of provider names
</ResponseField>

### Client APIs

APIs for client-side functionality.

#### resources.providers

```typescript theme={null}
interface ClientProviderApis {
  list(): Promise<Array<{ name: string }>>
}
```

**list()**

List available providers from client perspective.

```typescript theme={null}
const providers = await apis.client.resources.providers.list()
```

## Types

### ManifestV1

Plugin manifest structure.

```typescript theme={null}
interface ManifestV1 {
  apiVersion: 'v1'
  kind: 'manifest.plugin.airi.moeru.ai'
  name: string
  entrypoints: {
    default?: string
    electron?: string
    node?: string
    web?: string
  }
}
```

<ParamField path="apiVersion" type="'v1'" required>
  Manifest API version
</ParamField>

<ParamField path="kind" type="'manifest.plugin.airi.moeru.ai'" required>
  Manifest kind identifier
</ParamField>

<ParamField path="name" type="string" required>
  Plugin name
</ParamField>

<ParamField path="entrypoints" type="object" required>
  Runtime-specific entrypoint paths
</ParamField>

### ModuleIdentity

```typescript theme={null}
interface ModuleIdentity {
  id: string
  kind: 'plugin'
  plugin: {
    id: string
    labels?: Record<string, string>
  }
  labels?: Record<string, string>
}
```

### CapabilityDescriptor

```typescript theme={null}
interface CapabilityDescriptor {
  key: string
  state: 'announced' | 'ready' | 'degraded' | 'withdrawn'
  metadata?: Record<string, unknown>
  updatedAt: number
}
```

<ParamField path="key" type="string" required>
  Unique capability identifier
</ParamField>

<ParamField path="state" type="'announced' | 'ready' | 'degraded' | 'withdrawn'" required>
  Current capability state
</ParamField>

<ParamField path="metadata" type="Record<string, unknown>" optional>
  Additional capability metadata
</ParamField>

<ParamField path="updatedAt" type="number" required>
  Unix timestamp of last update
</ParamField>

### PluginSessionPhase

Plugin lifecycle phases.

```typescript theme={null}
type PluginSessionPhase =
  | 'loading'
  | 'loaded'
  | 'authenticating'
  | 'authenticated'
  | 'announced'
  | 'preparing'
  | 'waiting-deps'
  | 'prepared'
  | 'configuration-needed'
  | 'configured'
  | 'ready'
  | 'failed'
  | 'stopped'
```

### ModuleConfigEnvelope

Configuration envelope structure.

```typescript theme={null}
interface ModuleConfigEnvelope<C = Record<string, unknown>> {
  configId: string
  revision: number
  schemaVersion: number
  full: C
}
```

<ParamField path="configId" type="string" required>
  Unique configuration identifier
</ParamField>

<ParamField path="revision" type="number" required>
  Configuration revision number
</ParamField>

<ParamField path="schemaVersion" type="number" required>
  Configuration schema version
</ParamField>

<ParamField path="full" type="C" required>
  Complete configuration object
</ParamField>

## Protocol Events

Standard protocol events emitted by the plugin host.

### module:authenticate

Request authentication with token.

```typescript theme={null}
{
  type: 'module:authenticate',
  payload: {
    token: string
  }
}
```

### module:authenticated

Authentication result.

```typescript theme={null}
{
  type: 'module:authenticated',
  payload: {
    authenticated: boolean
  }
}
```

### module:announce

Announce module to registry.

```typescript theme={null}
{
  type: 'module:announce',
  payload: {
    name: string
    identity: ModuleIdentity
    possibleEvents: string[]
  }
}
```

### module:prepared

Module is prepared and ready for configuration.

```typescript theme={null}
{
  type: 'module:prepared',
  payload: {
    identity: ModuleIdentity
  }
}
```

### module:configuration:needed

Module requires configuration.

```typescript theme={null}
{
  type: 'module:configuration:needed',
  payload: {
    identity: ModuleIdentity
    reason?: string
  }
}
```

### module:configuration:configured

Configuration has been applied.

```typescript theme={null}
{
  type: 'module:configuration:configured',
  payload: {
    identity: ModuleIdentity
    config: ModuleConfigEnvelope
  }
}
```

### module:configure

Apply configuration to module.

```typescript theme={null}
{
  type: 'module:configure',
  payload: {
    config: Record<string, unknown>
  }
}
```

### module:status

Module status update.

```typescript theme={null}
{
  type: 'module:status',
  payload: {
    identity: ModuleIdentity
    phase: PluginSessionPhase
    reason?: string
    details?: Record<string, unknown>
  }
}
```

### registry:modules:sync

Sync module registry.

```typescript theme={null}
{
  type: 'registry:modules:sync',
  payload: {
    modules: Array<{
      name: string
      index?: number
      identity: ModuleIdentity
    }>
  }
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Type your configuration">
    Always define TypeScript interfaces for your plugin configuration to catch errors early.
  </Accordion>

  <Accordion title="Validate inputs">
    Validate all configuration and event payloads before using them.
  </Accordion>

  <Accordion title="Handle async errors">
    Wrap async operations in try-catch blocks and emit appropriate status events.
  </Accordion>

  <Accordion title="Use descriptive capability keys">
    Use namespaced capability keys like `'tool:weather'` or `'llm:provider:openai'`.
  </Accordion>

  <Accordion title="Clean up resources">
    Listen for stop events and clean up timers, connections, and other resources.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Creating Plugins" icon="code" href="/api/plugin-sdk/creating-plugins">
    Learn how to build plugins step-by-step
  </Card>

  <Card title="Plugin SDK Overview" icon="puzzle" href="/api/plugin-sdk/overview">
    Understand plugin architecture and concepts
  </Card>
</CardGroup>
