engine

package
v0.18.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 15 Imported by: 0

README ΒΆ

HotPlex Engine: The Control Plane

The engine package is the core orchestration layer of HotPlex. It transforms local AI CLI agents (like Claude Code) into high-availability, production-ready services by managing process lifecycles, security boundaries, and real-time event streaming.

πŸ› Architecture Overview

The Engine operates as a Stateful Multi-Session Controller. It manages a pool of persistent CLI processes to eliminate the overhead of repeated cold starts.

graph TD
    API[Application API / ChatApps] --> Engine[HotPlex Engine]
    
    subgraph EngineCore [Engine Control Plane]
        Manager[Session Manager / Pool]
        WAF[Danger Detector / Firewall]
        Telemetry[Stats & Metrics]
    end

    Engine --> Manager
    Engine --> WAF
    
    subgraph ProcessPool [Hot-Multiplexed Process Pool]
        S1[Session 1: Claude CLI]
        S2[Session 2: Claude CLI]
        Sn[Session N: Claude CLI]
    end

    Manager --> S1
    Manager --> S2
    Manager --> Sn
Key Architectural Concepts
  • Hot-Multiplexing: Instead of spawning a new process for every user message, the Engine keeps CLI processes alive in a "Busy/Ready" state. Subsequent turns are piped directly via stdin, reducing latency by 90%+.
  • Session Isolation: Each user session is bound to a unique working directory and a dedicated OS process group (PGID), ensuring that file operations and recursive tool executions are strictly sandboxed.
  • Regex Firewall (WAF): A pre-execution security layer that scans user prompts for dangerous patterns (e.g., recursive rm -rf /, credential exfiltration) before they reach the AI agent.
  • Event Bridge: Translates raw CLI stdout (often inconsistent JSON lines) into a strictly typed, normalized event stream.

πŸ›  Developer Guide

1. Initializing the Engine

The Engine is typically initialized as a singleton.

opts := engine.EngineOptions{
    Provider:         claudeProvider, // e.g. provider.NewClaudeCodeProvider
    Namespace:        "prod",
    Timeout:          10 * time.Minute,
    IdleTimeout:      30 * time.Minute,
    AllowedTools:     []string{"ls", "cat", "grep"},
    PermissionMode:  "auto", // auto-approve non-destructive tools
}

eng, err := engine.NewEngine(opts)
2. Executing a Task

To run a task, you provide a context, a session Config, the prompt, and a callback to receive real-time updates.

cfg := &types.Config{
    SessionID: "user-123-abc",
    WorkDir:   "/tmp/workspace/user-123",
}

err := eng.Execute(ctx, cfg, "Analyze this project structure", func(eventType string, data any) error {
    switch eventType {
    case "thinking":
        fmt.Printf("AI is thinking: %v\n", data)
    case "answer":
        fmt.Printf("Token: %v\n", data)
    case "session_stats":
        stats := data.(*event.SessionStatsData)
        fmt.Printf("Task completed. Tokens used: %d\n", stats.TotalTokens)
    }
    return nil
})
3. Session Lifecycle Management

The Engine provides several methods to control active sessions:

  • StopSession(sessionID, reason): Gracefully terminates a session and kills the underlying process group.
  • ResetSessionProvider(sessionID): Signals the engine to start a fresh AI context (clears conversation history) on the next execution.
  • GetSessionStats(sessionID): Retrieves real-time metrics (tokens used, tools called, duration breakdown).

πŸ›‘ Security Boundaries

The Engine enforces three layers of security:

  1. Input Filtering: Regex-based detection of malicious prompts.
  2. Runtime Constraints: AllowedTools and DisallowedTools whitelist/blacklist.
  3. OS Isolation: Each session runs in its own directory. Access outside WorkDir can be restricted via provider-specific flags.

πŸ“Š Observability

The SessionStats object provides high-fidelity tracking of AI performance:

  • Duration Breakdown: Thinking time vs. Tool execution time vs. Text generation time.
  • Token Accounting: Input, output, and cache (Read/Write) tokens.
  • Tool Audit: A complete list of all local tools successfully invoked during the session.

Package Path: github.com/hrygo/hotplex/engine
Core Components: Engine, SessionManager, Provider

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

This section is empty.

Types ΒΆ

type Engine ΒΆ

type Engine struct {
	// contains filtered or unexported fields
}

Engine is the core Control Plane for AI CLI agent integration. Configured as a long-lived Singleton, it transforms local CLI tools into production-ready services by managing a hot-multiplexed process pool, enforcing security WAF rules, and providing a unified event-driven SDK for application integration.

func NewEngine ΒΆ

func NewEngine(options EngineOptions) (*Engine, error)

NewEngine creates a new HotPlex Engine instance.

func (*Engine) CheckDanger ΒΆ added in v0.18.0

func (r *Engine) CheckDanger(prompt string) (blocked bool, operation, reason string)

CheckDanger exposes the WAF danger detector to the chatapps layer. Returns blocked=true if the prompt matches dangerous patterns. chatapps uses this for pre-flight WAF checks before calling Execute.

func (*Engine) CleanupSessionFiles ΒΆ added in v0.17.0

func (r *Engine) CleanupSessionFiles(sessionID string) error

CleanupSessionFiles deletes all session files associated with the provider session. This handles the complete removal of context on disk for commands like /reset.

func (*Engine) Close ΒΆ

func (r *Engine) Close() error

Close terminates all active sessions managed by this runner and cleans up resources. It triggers Graceful Shutdown by cascading termination signals down to the SessionManager, which drops the entire process group (PGID) to prevent zombie processes.

func (*Engine) Execute ΒΆ

func (r *Engine) Execute(ctx context.Context, cfg *types.Config, prompt string, callback event.Callback) error

Execute runs Claude Code CLI with the given configuration and streams

func (*Engine) GetAllowedTools ΒΆ added in v0.11.0

func (r *Engine) GetAllowedTools() []string

GetAllowedTools returns the current allowed tools list. Thread-safe: uses internal mutex.

func (*Engine) GetCLIVersion ΒΆ

func (r *Engine) GetCLIVersion() (string, error)

GetCLIVersion returns the Claude Code CLI version.

func (*Engine) GetDisallowedTools ΒΆ added in v0.11.0

func (r *Engine) GetDisallowedTools() []string

GetDisallowedTools returns the current disallowed tools list. Thread-safe: uses internal mutex.

func (*Engine) GetSession ΒΆ added in v0.12.0

func (r *Engine) GetSession(sessionID string) (*intengine.Session, bool)

GetSession retrieves an active session by sessionID. Returns the session and true if found, or nil and false if not found.

func (*Engine) GetSessionStats ΒΆ

func (r *Engine) GetSessionStats(sessionID string) *SessionStats

GetSessionStats returns a copy of the accumulated session stats.

func (*Engine) ResetSessionProvider ΒΆ added in v0.13.0

func (r *Engine) ResetSessionProvider(sessionID string)

ResetSessionProvider marks a session to get a new ProviderSessionID on restart. This is used for /clear command to force a fresh session with new context.

func (*Engine) SetAllowedTools ΒΆ added in v0.11.0

func (r *Engine) SetAllowedTools(tools []string)

SetAllowedTools sets the allowed tools for the engine. This affects new sessions created after the call. Thread-safe: uses internal mutex.

func (*Engine) SetDangerAllowPaths ΒΆ

func (r *Engine) SetDangerAllowPaths(paths []string)

SetDangerAllowPaths sets the allowed safe paths for the danger detector.

func (*Engine) SetDangerBypassEnabled ΒΆ

func (r *Engine) SetDangerBypassEnabled(token string, enabled bool) error

SetDangerBypassEnabled enables or disables danger detection bypass. WARNING: Only use for Evolution mode (admin only).

func (*Engine) SetDisallowedTools ΒΆ added in v0.11.0

func (r *Engine) SetDisallowedTools(tools []string)

SetDisallowedTools sets the disallowed tools for the engine. This affects new sessions created after the call. Thread-safe: uses internal mutex.

func (*Engine) StopSession ΒΆ

func (r *Engine) StopSession(sessionID string, reason string) error

StopSession terminates a running session by session ID. This is the implementation for session.stop from the spec.

func (*Engine) ValidateConfig ΒΆ

func (r *Engine) ValidateConfig(cfg *types.Config) error

ValidateConfig validates the Config.

type EngineOptions ΒΆ

type EngineOptions = intengine.EngineOptions

EngineOptions defines the configuration parameters for initializing a new HotPlex Engine. It allows customization of timeouts, logging, and foundational security boundaries that apply to all sessions managed by this engine instance.

type SessionStats ΒΆ

type SessionStats struct {
	SessionID            string          `json:"session_id"`
	StartTime            time.Time       `json:"-"` // Internal use only, use ToSummary() for JSON
	TotalDurationMs      int64           `json:"total_duration_ms"`
	ThinkingDurationMs   int64           `json:"thinking_duration_ms"`
	ToolDurationMs       int64           `json:"tool_duration_ms"`
	GenerationDurationMs int64           `json:"generation_duration_ms"`
	InputTokens          int32           `json:"input_tokens"`
	OutputTokens         int32           `json:"output_tokens"`
	CacheWriteTokens     int32           `json:"cache_write_tokens"`
	CacheReadTokens      int32           `json:"cache_read_tokens"`
	ToolCallCount        int32           `json:"tool_call_count"`
	ToolsUsed            map[string]bool `json:"-"` // Internal set, use ToSummary() for array
	FilesModified        int32           `json:"files_modified"`
	FilePaths            []string        `json:"file_paths"`
	// contains filtered or unexported fields
}

SessionStats collects session-level statistics for Geek/Evolution modes.

func (*SessionStats) EndGeneration ΒΆ

func (s *SessionStats) EndGeneration()

EndGeneration marks the end of the generation phase and records its duration.

func (*SessionStats) EndThinking ΒΆ

func (s *SessionStats) EndThinking()

EndThinking marks the end of the thinking phase and records its duration.

func (*SessionStats) FinalizeDuration ΒΆ

func (s *SessionStats) FinalizeDuration() *SessionStats

FinalizeDuration finalizes any ongoing phase tracking and returns the final stats.

func (*SessionStats) GetCurrentToolID ΒΆ added in v0.13.0

func (s *SessionStats) GetCurrentToolID() string

GetCurrentToolID returns the current tool ID being tracked. Returns empty string if no tool is currently being tracked.

func (*SessionStats) GetCurrentToolName ΒΆ added in v0.13.0

func (s *SessionStats) GetCurrentToolName() string

GetCurrentToolName returns the current tool name being tracked. Returns empty string if no tool is currently being tracked.

func (*SessionStats) GetToolNameByToolID ΒΆ added in v0.15.0

func (s *SessionStats) GetToolNameByToolID(toolID string) string

GetToolNameByToolID returns the tool name for a given tool ID. This is useful when tool_result events don't include tool_name. Returns empty string if tool ID is not found.

func (*SessionStats) RecordFileModification ΒΆ

func (s *SessionStats) RecordFileModification(filePath string)

RecordFileModification records that a file was modified. Uses O(1) map lookup for deduplication instead of O(n) linear scan.

func (*SessionStats) RecordTokens ΒΆ

func (s *SessionStats) RecordTokens(input, output, cacheWrite, cacheRead int32)

RecordTokens records token usage.

func (*SessionStats) RecordToolResult ΒΆ

func (s *SessionStats) RecordToolResult(toolID string) (durationMs int64, toolName string)

RecordToolResult records the end of a tool call. If RecordToolUse was not called (e.g., Claude Code didn't send tool_use event), this will record a minimal duration (1ms) to indicate the tool completed.

func (*SessionStats) RecordToolUse ΒΆ

func (s *SessionStats) RecordToolUse(toolName, toolID string)

RecordToolUse records the start of a tool call.

func (*SessionStats) StartGeneration ΒΆ

func (s *SessionStats) StartGeneration()

StartGeneration marks the start of the generation phase.

func (*SessionStats) StartThinking ΒΆ

func (s *SessionStats) StartThinking()

StartThinking marks the start of the thinking phase.

func (*SessionStats) ToSummary ΒΆ

func (s *SessionStats) ToSummary() map[string]interface{}

ToSummary converts stats to a summary map for JSON serialization.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL