9.9 KiB
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:
- Tracks all OpenCode sessions in a centralized location
- Monitors process execution with detailed logging
- Prepares for future optimization when OpenCode supports server/daemon mode
- 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
- Singleton Pattern: Only one
OpencodeProcessManagerinstance exists across the entire application - Session Tracking: Maps session IDs to their workspace directories
- Process Monitoring: Logs execution time, active processes, and resource usage
- Graceful Degradation: Falls back to per-message spawning if server mode unavailable
- Lifecycle Management: Properly initialized on startup and cleaned up on shutdown
Code Locations
- Manager Class: Lines ~575-836 in server.js
- Singleton Instance: Line ~838 in server.js
- Integration: Line ~6165 in server.js (sendToOpencode function)
- Initialization: Lines ~11239-11246 in server.js (bootstrap function)
- Shutdown: Line ~981 in server.js (gracefulShutdown function)
- Status Endpoint: Lines ~9832-9867 in server.js
Current Behavior
What Happens Now
Since OpenCode doesn't currently support a persistent server/daemon mode, the manager:
- Tracks each execution with detailed logging
- Reports statistics via the
/api/opencode/statusendpoint - Routes through
executeStandalonewhich spawns per-message processes - 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):
- Update
getServerModeArgs()to return the correct command arguments - 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:
curl http://localhost:3000/api/opencode/status
Response includes:
{
"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 requestspendingRequests: Map of in-flight requests awaiting responsessessionWorkspaces: Map of session IDs to their workspace directorieslastActivity: 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
- Bootstrap (startup): Manager initialized after all state is loaded
- sendToOpencode: Routes all OpenCode executions through manager
- gracefulShutdown: Stops manager before server shutdown
- Status endpoint: Exposes manager statistics
Testing
Verify Installation
-
Start the server:
node chat/server.js -
Check the logs for:
Initializing OpenCode process manager... OpenCode does not support server mode, will use per-session approach OpenCode process manager initialized -
Check status endpoint:
curl http://localhost:3000/api/opencode/status | jq . -
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
- Open multiple builder sessions in different browser tabs
- Send messages in each
- Check
/api/opencode/statusto seerunningProcessescount - 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
- Verify server is running
- Check that route is registered in
routeInternal() - Look for initialization errors in logs
Future Enhancements
- Add Server Mode Support: Update
getServerModeArgs()when available - Request Batching: Queue and batch multiple requests
- Connection Pooling: Maintain pool of persistent connections
- Load Balancing: Distribute across multiple OpenCode instances
- 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.