# OpenCode Process Manager

## Overview

This document explains the OpenCode Process Manager implementation, which optimizes resource usage by managing OpenCode sessions through a singleton instance manager.

## Problem Statement

Previously, the application spawned a **new OpenCode process for every message** sent by users. This meant:
- Multiple concurrent sessions resulted in dozens of separate OpenCode processes
- High memory and CPU overhead from process spawning
- No process reuse or pooling
- Inefficient resource utilization

## Solution

The `OpencodeProcessManager` class provides a singleton manager that:

1. **Tracks all OpenCode sessions** in a centralized location
2. **Monitors process execution** with detailed logging
3. **Prepares for future optimization** when OpenCode supports server/daemon mode
4. **Falls back gracefully** to per-message spawning when server mode is unavailable

## Current Implementation

### Architecture

```
┌─────────────────────────────────────┐
│   Multiple User Sessions            │
│  (Session A, B, C, D...)            │
└───────────┬─────────────────────────┘
            │
            ▼
┌─────────────────────────────────────┐
│  OpencodeProcessManager (Singleton) │
│  - Tracks all sessions              │
│  - Monitors execution               │
│  - Manages process lifecycle        │
└───────────┬─────────────────────────┘
            │
            ▼
┌─────────────────────────────────────┐
│  OpenCode CLI Execution             │
│  (Currently: per-message processes) │
│  (Future: single daemon instance)   │
└─────────────────────────────────────┘
```

### Key Features

1. **Singleton Pattern**: Only one `OpencodeProcessManager` instance exists across the entire application
2. **Session Tracking**: Maps session IDs to their workspace directories
3. **Process Monitoring**: Logs execution time, active processes, and resource usage
4. **Graceful Degradation**: Falls back to per-message spawning if server mode unavailable
5. **Lifecycle Management**: Properly initialized on startup and cleaned up on shutdown

### Code Locations

- **Manager Class**: Lines ~575-836 in [server.js](chat/server.js)
- **Singleton Instance**: Line ~838 in [server.js](chat/server.js) 
- **Integration**: Line ~6165 in [server.js](chat/server.js) (sendToOpencode function)
- **Initialization**: Lines ~11239-11246 in [server.js](chat/server.js) (bootstrap function)
- **Shutdown**: Line ~981 in [server.js](chat/server.js) (gracefulShutdown function)
- **Status Endpoint**: Lines ~9832-9867 in [server.js](chat/server.js)

## Current Behavior

### What Happens Now

Since OpenCode doesn't currently support a persistent server/daemon mode, the manager:

1. **Tracks each execution** with detailed logging
2. **Reports statistics** via the `/api/opencode/status` endpoint
3. **Routes through `executeStandalone`** which spawns per-message processes
4. **Logs process lifecycle** (start, duration, completion)

This provides:
- ✅ Better visibility into OpenCode usage
- ✅ Centralized execution management
- ✅ Foundation for future optimization
- ⚠️ Still spawns separate processes per message (but tracked)

## Future Optimization

### When OpenCode Adds Server Mode

If/when OpenCode supports a persistent server/daemon mode (e.g., `opencode serve` or `opencode daemon`):

1. **Update `getServerModeArgs()`** to return the correct command arguments
2. **The manager will automatically**:
   - Start a single OpenCode process on server startup
   - Route all sessions through this single instance
   - Maintain persistent connections
   - Dramatically reduce resource overhead

### Expected Benefits (Future)

When server mode is available:
- **90%+ reduction** in process spawning overhead
- **Faster response times** (no process startup delay)
- **Lower memory usage** (one process vs. many)
- **Better session continuity** (persistent state)

## Monitoring

### Status Endpoint

Check OpenCode manager status:
```bash
curl http://localhost:3000/api/opencode/status
```

Response includes:
```json
{
  "available": true,
  "version": "...",
  "runningProcesses": 3,
  "activeStreams": 2,
  "processManager": {
    "isRunning": false,
    "isReady": true,
    "pendingRequests": 0,
    "activeSessions": 5,
    "lastActivity": 1234567890,
    "idleTime": 1234,
    "mode": "per-session",
    "description": "Each message spawns separate OpenCode process"
  }
}
```

### Logging

The manager logs:
- Process execution start/end
- Duration of each command
- Active process count
- Session workspace mapping
- Errors and failures

Look for log entries with:
- `"OpenCode process manager..."`
- `"Executing OpenCode command (standalone)"`
- `"OpenCode command completed"`

## Implementation Details

### OpencodeProcessManager Class

#### Properties
- `process`: Reference to the persistent OpenCode process (when in server mode)
- `isReady`: Boolean indicating if the manager is ready to accept requests
- `pendingRequests`: Map of in-flight requests awaiting responses
- `sessionWorkspaces`: Map of session IDs to their workspace directories
- `lastActivity`: Timestamp of last activity (for idle detection)
- `heartbeatInterval`: Timer for keeping persistent connection alive

#### Methods

**`start()`**
- Initializes the manager
- Attempts to start OpenCode in server mode
- Falls back to per-session mode if unavailable

**`executeInSession(sessionId, workspaceDir, command, args, options)`**
- Main execution method
- Routes through persistent process (future) or standalone spawning (current)
- Tracks session -> workspace mapping

**`executeStandalone(workspaceDir, command, args, options)`**
- Current fallback implementation
- Spawns individual OpenCode process
- Logs execution metrics

**`stop()`**
- Gracefully shuts down manager
- Terminates persistent process if running
- Cleans up resources

**`getStats()`**
- Returns current manager statistics
- Used by monitoring endpoint

### Integration Points

1. **Bootstrap** (startup): Manager initialized after all state is loaded
2. **sendToOpencode**: Routes all OpenCode executions through manager
3. **gracefulShutdown**: Stops manager before server shutdown
4. **Status endpoint**: Exposes manager statistics

## Testing

### Verify Installation

1. Start the server:
   ```bash
   node chat/server.js
   ```

2. Check the logs for:
   ```
   Initializing OpenCode process manager...
   OpenCode does not support server mode, will use per-session approach
   OpenCode process manager initialized
   ```

3. Check status endpoint:
   ```bash
   curl http://localhost:3000/api/opencode/status | jq .
   ```

4. Send a message in a session and observe logs:
   ```
   Executing OpenCode command (standalone) { processId: '...', activeProcesses: 1 }
   OpenCode command completed { processId: '...', duration: 1234 }
   ```

### Multiple Concurrent Sessions

1. Open multiple builder sessions in different browser tabs
2. Send messages in each
3. Check `/api/opencode/status` to see `runningProcesses` count
4. Each process should be logged with start/end times

## Configuration

No configuration required. The manager automatically:
- Detects if OpenCode supports server mode
- Falls back to per-session spawning
- Adapts to available capabilities

## Performance Impact

### Current (Per-Session Mode)
- ✅ Better tracking and visibility
- ✅ Centralized management
- ✅ Foundation for future optimization
- ➖ No performance improvement yet (still spawns separate processes)

### Future (Server Mode)
- ✅ 90%+ reduction in process overhead
- ✅ Faster response times
- ✅ Lower memory usage
- ✅ Better resource utilization

## Migration Notes

This change is **backward compatible**:
- No changes to session management
- No changes to API endpoints (except enhanced status response)
- No changes to client behavior
- Existing sessions continue to work

## Troubleshooting

### Manager Not Starting
Check logs for: `"OpenCode process manager initialization failed"`
- This is expected if OpenCode doesn't support server mode
- Manager falls back to per-session spawning automatically

### Multiple Processes Still Running
This is **expected behavior** in current mode:
- Each message spawns a separate process
- This will change when OpenCode adds server mode support
- All processes are now tracked and logged

### Status Endpoint Not Responding
1. Verify server is running
2. Check that route is registered in `routeInternal()`
3. Look for initialization errors in logs

## Future Enhancements

1. **Add Server Mode Support**: Update `getServerModeArgs()` when available
2. **Request Batching**: Queue and batch multiple requests
3. **Connection Pooling**: Maintain pool of persistent connections
4. **Load Balancing**: Distribute across multiple OpenCode instances
5. **Health Checks**: Monitor and restart unresponsive instances

## Summary

The OpenCode Process Manager provides:
- ✅ Centralized session management
- ✅ Comprehensive execution tracking
- ✅ Foundation for future optimization
- ✅ Graceful fallback to current behavior
- ✅ Enhanced monitoring and debugging

While currently operating in per-session mode, it's ready to leverage OpenCode's server mode as soon as it becomes available, providing significant resource savings and performance improvements.
