Files
opencode-krates-connector/design/shell-logs.md
Hermes Agent 89bc5e8c15 docs: Finalize all design documents
Signed-off-by: Hermes Agent <hermes@nosuchhost>
2026-06-16 09:00:33 -04:00

233 lines
5.1 KiB
Markdown

# Design Document: Shell & Logs Feature Specification
## Overview
Shell and Logs are real-time terminal and streaming views for Kubernetes resources. These features enable users to interact with running pods and monitor application behavior.
## Shell Terminal (kubectl exec)
### Requirements
- **Implementation**: xterm.js on client
- **Backend**: WebSocket → kubectl exec
- **Protocol**: Bidirectional terminal protocol
### Terminal Configuration
```typescript
{
rows: 24,
cols: 80,
fontFamily: 'IBM Plex Mono',
fontSize: 12,
lineHeight: 1.5,
cursorBlink: true,
theme: {
background: '#1a1e26',
foreground: '#b9c6d8',
}
}
```
### Connection Flow
1. User opens shell view
2. Extract pod name and namespace
3. Connect WebSocket to `/ws/shell?pod=X&ns=Y`
4. Backend:
- Extract query params
- Connect to k8s exec API
- Create execstream
- Proxy bidirectionally
5. Frontend:
- Initialize xterm
- Attach to WebSocket
- Handle resize events
- Route keypresses
### Key Routing
- **Shell focused + type**: Route to terminal
- **Canvas shortcuts disabled** when shell has focus
- **Space key**: Goes to terminal (not spotlight)
- **Ctrl/⌘+scroll**: Zoom canvas (not terminal zoom)
### Resize Handling
- **Client**: term.resize(cols, rows)
- **Server**: Send resize message via WebSocket
- **Backend**: Update k8s exec term size
- **Debounce**: 100ms for resize events
### State Management
```typescript
interface ShellState {
connected: boolean;
connectedAt: number;
lastActive: number;
buffer: string[];
cols: number;
rows: number;
}
```
### Error States
- Connection failed: Show error message
- Disconnected: Show "Disconnected" + reconnect button
- Permission denied: Show clear error
- Pod not found: Show error message
## Logs Viewer (kubectl logs)
### Requirements
- **Implementation**: WebSocket streaming
- **Auto-scroll**: To bottom by default
- **Color coding**: ERROR/WARN/INFO
### Connection Flow
1. User opens logs view
2. Connect to `/ws/logs?pod=X&ns=Y`
3. Backend:
- Start kubectl logs stream
- Forward to WebSocket
4. Frontend:
- Append lines to buffer
- Auto-scroll if at bottom
- Colorize based on level
### Log Parsing
Each log line should include:
- Timestamp
- Log level (ERROR/WARN/INFO/DEBUG)
- Message
Format:
```typescript
interface LogLine {
timestamp: string; // ISO 8601
level: 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
message: string;
}
```
### Color Coding
- **ERROR**: `#ef6f6f`
- **WARN**: `#e8b54a`
- **INFO**: `#b9c6d8`
- **DEBUG**: `#6b7280`
### Auto-Scroll Logic
- **Track scroll position**: Store `scrollTop`
- **At bottom**: Auto-scroll on new log
- **Scrolled up**: Don't auto-scroll
- **Threshold**: Within 20px of bottom = "at bottom"
### User Controls
- **Click auto-scroll toggle**: Switch between auto and manual scroll
- **Clear logs**: Button to clear buffer
- **Copy log line**: Right-click menu
- **Filter**: Simple filtering (show/hide levels)
### State Management
```typescript
interface LogsState {
connected: boolean;
autoScroll: boolean;
logLines: LogLine[];
scrollPosition: number;
filterLevels: Set<LogLevel>;
}
```
### Streaming Considerations
- **Backpressure**: Buffer if client slow
- **Rate limiting**: Server can throttle logs
- **Keep-alive**: Ping every 30s
- **Reconnect**: Exponential backoff on disconnect
### Performance Optimization
- **Virtualization**: Only render visible lines
- **Batching**: Flush logs in batches if high volume
- **Throttling**: 16ms throttle for updates
- **Cleanup**: Remove old logs (keep last 1000 lines)
## Shared Features
### View State
- Both views persist state in krate.window.state
- reconnect: Auto reconnect on disconnect
- timestamps: Show/hide timestamps
- wrap: Word wrap toggle
### Tab Switching
- Shell tab: Enabled for pods only
- Logs tab: Enabled for pods/workloads
- Empty state: Show helpful message for unsupported resources
### Close Behavior
- Shell: Keep buffer, show "Disconnnected"
- Logs: Stop streaming, keep buffer
- Cleanup: Close WebSocket, cancel watchers
## WebSocket Protocol
### Shell
```
// Client → Server
{
type: 'shell:input',
data: string // Key press data
}
{
type: 'shell:resize',
cols: number,
rows: number
}
// Server → Client
{
type: 'shell:output',
data: string // stdout/stderr
}
{
type: 'shell:status',
connected: boolean,
message?: string
}
```
### Logs
```
// Client → Server
{
type: 'logs:subscribe',
pod: string,
namespace: string,
follow: boolean,
timestamps: boolean
}
{
type: 'logs:filter',
levels: string[]
}
// Server → Client
{
type: 'log',
log: LogLine
}
{
type: 'status',
connected: boolean,
message?: string
}
```
## Gotchas
1. **Space key**: Must distinguish between canvas pan and shell input
2. **Focus routing**: Route keys based on hovered window
3. **Scroll management**: Track scroll position for logs
4. **Terminal resize**: Debounce resize events
5. **Reconnection**: Handle WebSocket disconnects gracefully
6. **Memory**: Clean up old logs/shell buffers
7. **Authentication**: Validate user on WebSocket upgrade
8. **Permissions**: Enforce namespace RBAC on backend