-
Notifications
You must be signed in to change notification settings - Fork 2
Permalink
Choose a base ref
{{ refName }}
default
Choose a head ref
{{ refName }}
default
Comparing changes
Choose two branches to see what’s changed or to start a new pull request.
If you need to, you can also or
learn more about diff comparisons.
Open a pull request
Create a new pull request by comparing changes across two branches. If you need to, you can also .
Learn more about diff comparisons here.
base repository: inference-gateway/cli
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.99.1
Could not load branches
Nothing to show
Loading
Could not load tags
Nothing to show
{{ refName }}
default
Loading
...
head repository: inference-gateway/cli
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.99.2
Could not load branches
Nothing to show
Loading
Could not load tags
Nothing to show
{{ refName }}
default
Loading
- 2 commits
- 125 files changed
- 2 contributors
Commits on Jan 25, 2026
-
refactor: Replace agent loop with event-driven state machine (#379)
## Overview This PR completes the agent state machine refactoring by extracting all state handlers into separate, maintainable files following the **State Design Pattern**. This improves code organization, readability, and scalability. ## Problem Statement The previous implementation had all state handlers in a single 1400+ line file (`agent_event_driven.go`), making it: - **Hard to navigate**: Finding specific state logic required scrolling through unrelated code - **Difficult to maintain**: Changes to one state risked affecting others - **Complex to review**: PR reviews had to parse through the entire event-driven agent implementation - **Not scalable**: Adding new states or modifying existing ones became increasingly difficult ## Solution Refactored the agent state machine to follow the [State Design Pattern](https://refactoring.guru/design-patterns/state): ### Architecture Changes **Before:** ``` internal/services/ ├── agent.go (1400+ lines - monolithic) ├── agent_event_driven.go └── tools/ ``` **After:** ``` internal/agent/ ├── agent.go (1200 lines) - core service ├── agent_event_driven.go (400 lines) - event coordinator ├── agent_state_machine.go - state transitions ├── agent_streaming.go - LLM streaming ├── agent_tools.go - tool execution ├── agent_utils.go - helpers └── states/ (12 files, ~50-100 lines each) ├── idle.go ├── checking_queue.go ├── streaming_llm.go ├── post_stream.go ├── evaluating_tools.go ├── approving_tools.go ├── executing_tools.go ├── post_tool_execution.go ├── completing.go ├── error.go ├── cancelled.go └── stopped.go ``` ### Key Components 1. **State Handler Interface** (`state_handler.go`) - Defines `Handle(event)` method all states must implement - `StateContext` provides access to agent dependencies 2. **Concrete States** (`states/*.go`) - Each state in its own file - Implements the `StateHandler` interface - Processes events relevant to that state 3. **Event-Driven Agent** (`agent_event_driven.go`) - Simplified to ~400 lines (from 1400+) - Maintains state handler registry - Delegates events to appropriate state handlers ## Changes Made ### Phase 1: Infrastructure - ✅ Created `StateHandler` interface and `StateContext` struct - ✅ Created `states/` package for state implementations ### Phase 2: State Extraction Extracted all 12 states into separate files: 1. ✅ `idle.go` - Initial state, transitions to CheckingQueue 2. ✅ `error.go` - Terminal state for errors 3. ✅ `cancelled.go` - Terminal state for user cancellation 4. ✅ `stopped.go` - Terminal state for stops 5. ✅ `completing.go` - Finalization and cleanup 6. ✅ `evaluating_tools.go` - Tool approval evaluation 7. ✅ `streaming_llm.go` - LLM streaming coordination 8. ✅ `post_stream.go` - Post-streaming transitions 9. ✅ `executing_tools.go` - Tool execution coordination 10. ✅ `checking_queue.go` - Queue processing and completion logic 11. ✅ `approving_tools.go` - User approval workflow 12. ✅ `post_tool_execution.go` - Post-tool transitions ### Phase 3: Event-Driven Agent Refactoring - ✅ Added state handler registry (`stateHandlers` map) - ✅ Implemented `registerStateHandlers()` method - ✅ Simplified `handleEvent()` to dispatch pattern - ✅ Removed all `handle*State()` methods (~1000 lines deleted) ### Phase 4: Testing & Cleanup - ✅ Updated tests to match new architecture - ✅ Fixed test expectations for improved message storage timing - ✅ Removed outdated comments - ✅ All tests passing - ✅ Linter clean (0 issues) ## Benefits ### Code Organization - **Before**: 1400+ line file with 12 state handlers - **After**: 12 focused files, each 30-100 lines - Clear separation: one state = one file - Easy to locate and modify state-specific logic ### Maintainability - Each state is isolated (LSP compliance) - PR reviews focus on specific state files - New states just add a new file + registration line - Reduced merge conflicts (different files) ### Testability - Each state tested in isolation with its own test file - Easy to mock `StateContext` for state-specific tests - Test failures clearly indicate problematic state ### Scalability - 12 states = 12 files × 50-100 lines (manageable) - Adding states doesn't increase file complexity - Clear pattern for new state implementations ## Design Patterns Applied 1. **State Design Pattern** - Context delegates to state handlers 2. **Single Responsibility Principle** - One file handles one state's events 3. **Open/Closed Principle** - Open for extension, closed for modification 4. **Dependency Inversion** - States depend on `StateContext` interface ## Testing - ✅ All unit tests passing - ✅ Integration tests passing - ✅ No race conditions (`go test -race`) - ✅ Code coverage maintained - ✅ Manual testing confirms normal operation ## Migration Impact - **Lines Removed**: ~1000 (state handlers extracted) - **Lines Added**: ~800 (12 new state files + infrastructure) - **Net Reduction**: ~200 lines - **Complexity Reduction**: Significant (from one 1400-line file to 12 focused files) ## Verification ```bash # Build task build ✅ Success # Tests task test ✅ All tests passing (internal/agent: 1.212s) # Linter task lint ✅ 0 issues ``` ## Breaking Changes None. This is a pure refactoring with no API or behavior changes. ## References - [State Design Pattern - Refactoring Guru](https://refactoring.guru/design-patterns/state) - [State Pattern in Go](https://refactoring.guru/design-patterns/state/go/example) - [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
Configuration menu - View commit details
-
Copy full SHA for 536fdc6 - Browse repository at this point
Copy the full SHA 536fdc6View commit details -
chore(release): 0.99.2 [skip ci]
## [0.99.2](v0.99.1...v0.99.2) (2026-01-25) ### ♻️ Code Refactoring * Replace agent loop with event-driven state machine ([#379](#379)) ([536fdc6](536fdc6))
Configuration menu - View commit details
-
Copy full SHA for da90102 - Browse repository at this point
Copy the full SHA da90102View commit details
Loading
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v0.99.1...v0.99.2