# Wasot Plugin Architecture

This document describes the technical architecture for Wasot [plugins](./plugins.md). For a hands-on guide, see the [Rust plugin tutorial](./rust_plugin_tutorial.md).

## Overview

Wasot uses a **plugin architecture** where external tools are implemented as separate executables that communicate with the main Wasot process via **gRPC over Unix domain sockets** (see [socket communication](./plugin_socket_communication.md)). This design provides:

- **Language independence**: Plugins can be written in any language supporting gRPC
- **Process isolation**: Each plugin runs in its own process
- **Performance**: Unix sockets provide fast IPC with minimal overhead
- **Reliability**: Plugin crashes don't affect the main Wasot process

## Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                        Wasot Main Process                       │
│  ┌─────────────────┐    ┌─────────────────┐                     │
│  │ Document Parser │    │ Event Processor │                     │
│  └─────────────────┘    └─────────────────┘                     │
│           │                       │                             │
│           ▼                       ▼                             │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │            Plugin Manager & gRPC Client                     ││
│  └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
                                 │
                                 │ Unix Domain Socket
                                 │ (gRPC over UDS)
                                 │
┌────────────────────────────────▼─────────────────────────────────┐
│                        Plugin Process                            │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │              gRPC Server (GrpcLibrary)                      │ │
│  │  • GetTools() → Returns available tools                     │ │
│  │  • CallTool() → Processes events & updates context          │ │
│  └─────────────────────────────────────────────────────────────┘ │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │                    Tool Implementations                     │ │
│  │  • my_tool_1: Handles "paragraph" selector                  │ │
│  │  • my_tool_2: Handles ".section > .title" selector          │ │
│  │  • my_tool_3: Handles "code[lang=rust]" selector            │ │
│  └─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
```

## Communication Protocol

### 1. Plugin Startup
```bash
# Wasot starts plugin with socket path as argument
./my_plugin /tmp/wasot_plugin_12345.sock
```

### 2. Plugin Lifecycle
```
1. Plugin binary receives socket path as argv[1]
2. Plugin creates gRPC server listening on that socket
3. Wasot connects to the socket
4. Wasot calls GetTools() once to discover available tools
5. For each matching event, Wasot calls CallTool()
6. Plugin processes event and returns context changes
7. Repeat step 5-6 until processing is complete
8. Wasot terminates connection and plugin exits
```

### 3. gRPC Interface

The plugin must implement the `GrpcLibrary` service defined in `proto/tools.proto`:

```protobuf
service GrpcLibrary {
    // Called once after start to get available tools
    rpc GetTools (GetToolsRequest) returns (GetToolsResponse);
    // Called for every matching tool event
    rpc CallTool(CallToolRequest) returns (CallToolResponse);
}
```

## Tool Definition

Each tool is defined by:

```protobuf
message ToolDefinition {
    string name = 1;                        // Unique tool name
    string library = 2;                     // Library name (for organization)
    repeated string selectors = 3;          // CSS-like selectors
    repeated string optional_context_keys = 4;   // Optional context inputs
    repeated string required_context_keys = 5;   // Required context inputs
    repeated string maybe_produced_keys = 6;     // Possible context outputs
}
```

### Selector Examples

See the full [selectors documentation](./selectors.md) for syntax details.

- `"paragraph"` - Matches paragraph blocks
- `".section"` - Matches blocks with class "section"
- `"code[lang=rust]"` - Matches code blocks with lang=rust attribute
- `".chapter > .title"` - Matches title blocks inside chapter blocks

## Event Processing Flow

```
1. Wasot parses document and generates events
2. For each event:
   a. Check which tools have matching selectors
   b. For each matching tool:
      - Serialize event to JSON
      - Collect current context (scoped + global)
      - Call plugin's CallTool RPC
      - Apply returned context changes
```

## Context Management

Tools can read and modify two types of context. See [context and scoped variables](./context_and_scoped_variables.md) for more details.

### Scoped Context
- Available only within current block and its children
- Automatically cleaned up when block ends
- Good for temporary state

### Global Context  
- Available throughout entire document processing
- Persists until processing ends
- Good for document-wide state

Example context changes:
```json
{
  "context_changes": [
    {
      "target": "SCOPE",
      "key": "current_author", 
      "value": "John Doe"
    },
    {
      "target": "GLOBAL",
      "key": "word_count",
      "value": "1234"
    }
  ]
}
```

## Performance Considerations

### Socket-based Communication
- **Fast**: Unix domain sockets are faster than TCP for local communication
- **Efficient**: No network stack overhead
- **Reliable**: Built-in flow control and error handling

### Process Isolation Benefits
- Plugin crashes don't affect Wasot
- Memory leaks in plugins are contained
- Different plugins can use different language runtimes

### Caching (Future Enhancement)
The architecture supports future caching optimizations:
- Tools declare their context dependencies
- Wasot can cache results when dependencies haven't changed
- Parallel execution when tools don't conflict

## Plugin Discovery

Plugins are discovered through:

1. **Command line**: `wasot --plugin ./my_plugin file.wasot`
2. **Configuration file**: Listed in `wasot.toml`
3. **Directory scanning**: Auto-discover in `~/.wasot/plugins/`

## Error Handling

### Plugin Startup Failures
- Plugin binary not found or not executable
- Socket binding failures
- gRPC server startup issues

### Runtime Failures
- Tool call timeouts
- Invalid context changes
- Plugin process crashes

Wasot gracefully handles these failures by:
- Logging errors with context
- Continuing processing without the failed plugin
- Providing helpful error messages to users

## Security Model

### Process Isolation
- Each plugin runs in separate process
- Limited filesystem access via socket path only
- No direct access to Wasot internals

### Input Validation
- All events are serialized/validated before sending
- Context changes are validated before applying
- Malformed responses are rejected

### Resource Limits (Future)
- Memory limits per plugin process
- CPU time limits per tool call
- Maximum concurrent plugins

## Development Workflow

```bash
# 1. Create plugin project
cargo new my_wasot_plugin
cd my_wasot_plugin

# 2. Add dependencies and implement GrpcLibrary service
# (See tutorial for details)

# 3. Build plugin
cargo build --release

# 4. Test with Wasot
wasot --plugin ./target/release/my_wasot_plugin document.wasot
```

This architecture provides a robust foundation for extensible document processing while maintaining performance and reliability.