update docs
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
# Implementation Plan: YiemAgent Agent Framework
|
||||
|
||||
## 1. Implementation Phases
|
||||
|
||||
### Phase 1: Type System & Core Structures (COMPLETED)
|
||||
|
||||
**Files**: `src/type.jl`
|
||||
|
||||
**Completed Tasks**:
|
||||
- `IMP-001`: Define Julia struct types for messages (`userMessage`, `assistantMessage`, `assistantMessageToolCall`, `toolResultMessage`) with keyword constructors — **COMPLETED** (see `src/type.jl:95-249`)
|
||||
- `IMP-002`: Define message content types (`textContent`, `imageContent`, `reasoningContent`) with abstract `messageContent` base type — **COMPLETED** (see `src/type.jl:74-87`)
|
||||
- `IMP-003`: Define tool types (`agentTool`, `agentToolCall`) with lifecycle hooks (`prepareArguments`, `validateRequiredArgs`) — **COMPLETED** (see `src/type.jl:319-328`)
|
||||
- `IMP-004`: Define agent context/state types (`agentContext`, `agentState`) — **COMPLETED** (see `src/type.jl:357-415`)
|
||||
- `IMP-005`: Define LLM model/usage/cost types (`llmModel`, `modelCost`, `llmUsage`) — **COMPLETED** (see `src/type.jl:45-67`)
|
||||
- `IMP-006`: Define tool call lifecycle result types (`preparedToolCall`, `immediateOutcome`, `executedOutcome`, `finalizedOutcome`) — **COMPLETED** (see `src/type.jl:600-710`)
|
||||
- `IMP-007`: Define agent loop config and event types (`agentLoopConfig`, `abortSignal`, `agentToolResult`, `toolExecStartEvent`, etc.) — **COMPLETED** (see `src/type.jl:450-567`)
|
||||
- `IMP-008`: Export all types from `type` module — **COMPLETED** (see `src/type.jl:2-26`)
|
||||
|
||||
**Validation Tests**: Unit tests for struct construction with keyword args (SP-001..SP-008, SP-019..SP-022)
|
||||
|
||||
**Traceability**: FR-001, FR-002, FR-003, FR-004, FR-005, FR-006
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Utility & Formatting Functions (COMPLETED)
|
||||
|
||||
**Files**: `src/utils.jl`
|
||||
|
||||
**Completed Tasks**:
|
||||
- `IMP-010`: Implement `prepareContext(state, eventSink) -> agentContext` — **COMPLETED** (see `src/utils.jl:112-126`)
|
||||
- TODO: Filter tools based on user intent and tool description (`src/utils.jl:114`)
|
||||
- TODO: Inject system prompt context (e.g., time, session state) (`src/utils.jl:118`)
|
||||
- TODO: Prune/reorder messages (`src/utils.jl:121`)
|
||||
- `IMP-011`: Implement `formatMsgForLLM(ctx, eventSink) -> Dict{String, Any}` — **COMPLETED** (see `src/utils.jl:159-244`)
|
||||
- Converts system prompt to system message
|
||||
- Converts conversation messages via `_userMessageToOpenAI`, `_assistantMessageToOpenAI`, `_assistantMessageToolCallToOpenAI`, `_toolResultMessageToOpenAI`
|
||||
- Converts `ctx.tools` to OpenAI function tool format via `_toolsToOpenAI`
|
||||
- `IMP-012`: Implement message converters (`_userMessageToOpenAI`, `_assistantMessageToOpenAI`, `_assistantMessageToolCallToOpenAI`, `_toolResultMessageToOpenAI`) — **COMPLETED** (see `src/utils.jl:321-387`)
|
||||
- `IMP-013`: Implement `_messageContentToBlocks` — converts `textContent`/`imageContent` to OpenAI content blocks — **COMPLETED** (see `src/utils.jl:396-413`)
|
||||
- `IMP-014`: Implement `_toolsToOpenAI` — converts `OrderedDict{String, agentTool}` to OpenAI tools array — **COMPLETED** (see `src/utils.jl:429-447`)
|
||||
- `IMP-015`: Implement `beforeToolCall` hook default (returns `beforeToolCallResult(false, "N/A")`) — **COMPLETED** (see `src/utils.jl:278-284`)
|
||||
- `IMP-016`: Implement `afterToolCall` hook default (returns `nothing`) — **COMPLETED** (see `src/utils.jl:310-316`)
|
||||
- `IMP-017`: Implement `validateRequiredArgs(args, inputSchema)` — validates required fields in tool arguments — **COMPLETED** (see `src/utils.jl:479-497`)
|
||||
- `IMP-018`: Implement `validateToolArguments(tool, prepared)` — wrapper that calls tool-specific or default hook — **COMPLETED** (see `src/utils.jl:533-546`)
|
||||
|
||||
**Validation Tests**: Unit tests for converters, validation hooks, and OpenAI format output structure (SP-011..SP-016, SP-023, SP-024)
|
||||
|
||||
**Traceability**: FR-001, FR-002, FR-003, FR-004, FR-005, FR-006
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Tool Registry & MCP Integration (COMPLETED)
|
||||
|
||||
**Files**: `src/toolRegistry.jl`
|
||||
|
||||
**Completed Tasks**:
|
||||
- `IMP-020`: Implement `_extract_text_content(result)` — extracts text from MCP tool result content array — **COMPLETED** (see `src/toolRegistry.jl:19-33`)
|
||||
- `IMP-021`: Implement `_wrap_mcp_tool(mcpserver, tool_def)` — wraps MCP tool as `agentTool` with `execute` calling `mcpserver("tools/call", ...)` — **COMPLETED** (see `src/toolRegistry.jl:41-106`)
|
||||
- Handles MCP error responses (`haskey(response, "error")`)
|
||||
- Extracts text and `isError` from result
|
||||
- `IMP-022`: Implement `register_mcp_tools(tools, mcpserver)` — queries `tools/list` with pagination (`nextCursor`) — **COMPLETED** (see `src/toolRegistry.jl:118-186`)
|
||||
- Handles both `result.tools` and `result.error` response shapes
|
||||
- Skips already registered tools (idempotent)
|
||||
- `IMP-023`: Implement `registerTool(tools, tool)` — adds tool to OrderedDict — **COMPLETED** (see `src/toolRegistry.jl:200-205`)
|
||||
- `IMP-024`: Implement `listTool(tools, mcpserver)` — builtin tool that triggers runtime discovery and lists all tools — **COMPLETED** (see `src/toolRegistry.jl:235-271`)
|
||||
- `IMP-025`: Implement `registerAllTools(tools, mcpserver)` — discovers existing tools + registers `listTools` — **COMPLETED** (see `src/toolRegistry.jl:286-289`)
|
||||
|
||||
**Validation Tests**: Unit tests for MCP tools/list parsing, pagination, tool registration idempotency; contract tests for JSON-RPC 2.0 format (SP-009, SP-010)
|
||||
|
||||
**Traceability**: FR-002, FR-004
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Agent Core & Loop (COMPLETED)
|
||||
|
||||
**Files**: `src/agentCore.jl`
|
||||
|
||||
**Completed Tasks**:
|
||||
- `IMP-030`: Define `yiemAgent` struct with channels, callbacks, MCP server — **COMPLETED** (see `src/agentCore.jl:17-95`)
|
||||
- `IMP-031`: Implement `yiemAgent` constructor — creates channels, discovers MCP tools, spawns `_agentLoop` task — **COMPLETED** (see `src/agentCore.jl:126-199`)
|
||||
- `IMP-032`: Implement `_agentLoop(agent)` — background `@spawn` task managing `inputChannel`/`followUpChannel` priority dispatch — **COMPLETED** (see `src/agentCore.jl:225-364`)
|
||||
- Handles shutdown signal: drains all channels, breaks loop
|
||||
- On error: catches, calls `eventSink(errMsg)`, exits loop
|
||||
- `IMP-033`: Implement `_processMessage(...)` — drains input, calls `llmCall`, extracts tool calls, executes, loops until no tool calls — **COMPLETED** (see `src/agentCore.jl:394-544`)
|
||||
- `while true` loop: `llmCall()` → `_extractToolCalls()` → if `hasToolCalls && length > 0` execute → append results → repeat
|
||||
- On `toolResultBatch.terminate == true`: build final response and break
|
||||
- Catches all errors and calls `eventSink(err_msg)`
|
||||
- `IMP-034`: Implement `_extractToolCalls(response)` — handles **both** formats:
|
||||
- Format 1: `response["message"]["tool_calls"]` (LMStudio/vLLM style) — **COMPLETED** (see `src/agentCore.jl:671-683`)
|
||||
- Format 2: `response.content` blocks with `type => "tool_calls"` or `type => "tool_call"` (OpenAI API style) — **COMPLETED** (see `src/agentCore.jl:685-719`)
|
||||
- Extracts `reasoning_content`, `content` text blocks, `api`, `provider`, `model`, `usage`, `finish_reason` — **COMPLETED** (see `src/agentCore.jl:723-797`)
|
||||
- Returns `(hasToolCalls, toolCallList, assistant_message)` — **COMPLETED** (see `src/agentCore.jl:799-827`)
|
||||
- `IMP-035`: Implement `prepareToolCall(context, assistantMsg, toolCall, config, signal, eventSink)` — resolves tool, validates args, runs `beforeToolCall` hook, never throws — **COMPLETED** (see `src/agentCore.jl:974-1035`)
|
||||
- `IMP-036`: Implement `executePreparedToolCall(prep, signal, eventSink)` — calls `tool.execute(toolCallId, args, ...)` — **COMPLETED** (see `src/agentCore.jl:1078-1100`)
|
||||
- `IMP-037`: Implement `finalizeExecutedToolCall(context, msg, prep, executed, config, signal, eventSink)` — runs `afterToolCall` hook, catches errors — **COMPLETED** (see `src/agentCore.jl:1159-1198`)
|
||||
- `IMP-038`: Implement `prepareToolCallArguments(tool, toolCall)` — calls `tool.prepareArguments` if present — **COMPLETED** (see `src/agentCore.jl:908-917`)
|
||||
- `IMP-039`: Implement `createErrorToolResult(msg)` — builds `agentToolResult` with error content — **COMPLETED** (see `src/agentCore.jl:572-574`)
|
||||
- `IMP-040`: Implement `createToolResultMessage(f)` — builds `toolResultMessage` from `finalizedOutcome` — **COMPLETED** (see `src/agentCore.jl:606-612`)
|
||||
|
||||
**Note**: Sequential and parallel execution implementations continue beyond line 1207 of `src/agentCore.jl` — implementation incomplete, requires review to ensure execution methods properly call hooks and emit lifecycle events. See IMP-041.
|
||||
|
||||
**Validation Tests**: Integration tests for full agent loop with mocked LLM and MCP; contract tests for response format extraction (WT-001..WT-032, SP-017, SP-018)
|
||||
|
||||
**Traceability**: FR-001, FR-002, FR-003, FR-004, FR-005
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: Public API (COMPLETED)
|
||||
|
||||
**Files**: `src/api.jl`
|
||||
|
||||
**Completed Tasks**:
|
||||
- `IMP-050`: Implement `promptAgent(agent, msg::AbstractDict)` — put to `inputChannel`, returns agent for chaining — **COMPLETED** (see `src/api.jl:36-39`)
|
||||
- `IMP-051`: Implement `promptAgent(agent, text::String)` — wraps text as OpenAI `Dict` and put to `inputChannel` — **COMPLETED** (see `src/api.jl:41-44`)
|
||||
- `IMP-052`: Implement `takeResponse(agent)` — blocks on `outputChannel` `take!`, returns OpenAI dict response — **COMPLETED** (see `src/api.jl:66-68`)
|
||||
- `IMP-053`: Implement `followUp(agent, msg::AbstractDict)` — put to `followUpChannel`, returns agent — **COMPLETED** (see `src/api.jl:94-97`)
|
||||
- `IMP-054`: Implement `followUp(agent, text::String)` — wraps text as OpenAI `Dict` and put to `followUpChannel` — **COMPLETED** (see `src/api.jl:99-102`)
|
||||
- `IMP-055`: Implement `stopAgent(agent)` — puts `:shutdown`, `fetch(_agentLoop)`, closes all channels — **COMPLETED** (see `src/api.jl:126-139`)
|
||||
|
||||
**Validation Tests**: Integration tests for send/receive/stop lifecycle (WT-001..WT-005)
|
||||
|
||||
**Traceability**: FR-001, FR-006
|
||||
|
||||
---
|
||||
|
||||
## 2. Module Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── YiemAgent.jl # Parent module, includes submodules in dependency order
|
||||
├── type.jl # All Julia struct types (exports 30+ types)
|
||||
├── utils.jl # Formatting, validation, hooks (default implementations)
|
||||
├── toolRegistry.jl # MCP tool discovery, registration, listTools builtin
|
||||
├── agentCore.jl # yiemAgent struct, _agentLoop, _processMessage, extractToolCalls
|
||||
└── api.jl # Public: promptAgent, takeResponse, followUp, stopAgent
|
||||
```
|
||||
|
||||
**Include order** (per `src/YiemAgent.jl` lines 6-19):
|
||||
1. `type.jl` (no dependencies)
|
||||
2. `utils.jl` (depends on `type`)
|
||||
3. `toolRegistry.jl` (depends on `type`)
|
||||
4. `agentCore.jl` (depends on `type`, `utils`, `toolRegistry`)
|
||||
5. `api.jl` (depends on `type`, `utils`, `agentCore`, `toolRegistry`)
|
||||
|
||||
---
|
||||
|
||||
## 3. Task Dependencies
|
||||
|
||||
| Task ID | Title | Depends On | Status |
|
||||
|---------|-------|------------|--------|
|
||||
| IMP-001..IMP-008 | Type system | — | **COMPLETED** |
|
||||
| IMP-010..IMP-018 | Utils (formatMsgForLLM, converters, hooks) | IMP-001..IMP-008 | **COMPLETED** |
|
||||
| IMP-020..IMP-025 | Tool registry (MCP discovery) | IMP-003, IMP-017 | **COMPLETED** |
|
||||
| IMP-030..IMP-040 | Agent core (agent loop, tool call execution) | IMP-001..IMP-008, IMP-010..IMP-018, IMP-020..IMP-025 | **INCOMPLETE*** (see note) |
|
||||
| IMP-050..IMP-055 | Public API | IMP-030..IMP-040 | **COMPLETED** |
|
||||
|
||||
**NOTE on IMP-030..IMP-040**: The sequential and parallel execution functions (`executeToolCallsSequential`, `executeToolCallsParallel`, `executeToolCalls`) begin after line 1207 of `src/agentCore.jl` but the full implementation is truncated in file reads and requires review. The exported functions (`executePreparedToolCall`, `prepareToolCall`, `executeToolCallsSequential`, `executeToolCallsParallel`, `executeToolCalls`) are declared (`src/agentCore.jl:4-5`) but their full bodies may be incomplete. **Requires manual validation.**
|
||||
|
||||
**Traceability**: IMP-001..IMP-008 → SP-001..SP-008, IMP-020..IMP-025 → SP-009, SP-010; IMP-010..IMP-018 → SP-011..SP-016, SP-023, SP-024; IMP-030..IMP-040 → SP-017, SP-018, SP-019..SP-022
|
||||
|
||||
---
|
||||
|
||||
## 4. Remaining Work (TODOs)
|
||||
|
||||
| File | Line | Description | Priority |
|
||||
|------|------|-------------|----------|
|
||||
| `src/utils.jl` | 114 | Filter tools from `state.tools` based on user intent and tool description | High |
|
||||
| `src/utils.jl` | 118 | Add system prompt context: time, session state, user preferences | Medium |
|
||||
| `src/utils.jl` | 121 | Prune/reorder/conversation messages before sending to LLM | Medium |
|
||||
| `src/agentCore.jl` | post-1207 | Complete and validate `executeToolCallsSequential`, `executeToolCallsParallel`, `executeToolCalls` implementations (currently exported but body may be incomplete) | **Critical** |
|
||||
| `tests/unit/...` | — | Write unit tests for all struct types (IMP-001..IMP-008) and converters (SP-011..SP-016) | High |
|
||||
| `tests/unit/...` | — | Write unit tests for tool validation hooks (SP-023, SP-024) | High |
|
||||
| `tests/integration/...` | — | Write integration tests for agent loop with mocked LLM/MCP (WT-001..WT-032) | High |
|
||||
| `tests/contract/...` | — | Write contract tests for response formats (SP-017, SP-018) | Medium |
|
||||
| `tests/perf/...` | — | Write performance tests (NFR-101, NFR-102) | Medium |
|
||||
|
||||
---
|
||||
|
||||
## 5. Build & Deployment
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
cd /home/ton/docker-apps/sommpanion/YiemAgent
|
||||
julia --project=. -e 'using Pkg; Pkg.instantiate(); using Pkg; Pkg.precompile()'
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```bash
|
||||
julia --project=./tests -e 'using Pkg; Pkg.instantiate()'
|
||||
julia --project=./tests -e 'using Test; Test.@testset "Unit" begin include("tests/unit/run_tests.jl") end'
|
||||
julia --project=./tests -e 'using Test; Test.@testset "Integration" begin include("tests/integration/run_tests.jl") end'
|
||||
```
|
||||
|
||||
### CI/CD Preparation
|
||||
|
||||
- Add `.github/workflows/julia.yaml` referencing `ci/julia-pipeline.yaml` steps
|
||||
- Add `Project.toml` dependencies:
|
||||
```toml
|
||||
[deps]
|
||||
JSON = "682c8566-3430-5439-8f4e-b64832e8aaba"
|
||||
DataStructures = "892a3cad-33e6-51e5-808c-f3d90072be70"
|
||||
HTTP = "cd6eee30-4dd5-5329-8bad-3259ec48d0f4"
|
||||
# plus: UUIDs, Dates, PrettyPrinting, Serialization, DataFrames, NATS, LibPQ
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Risk Mitigation
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Line 1207+ of `agentCore.jl` (sequential/parallel execution) is incomplete or broken | Manually review and validate `executeToolCallsSequential`, `executeToolCallsParallel`, `executeToolCalls` against spec SP-021 (agentLoopConfig) and trace to test `test_tool_call_execution_sequence` |
|
||||
| `GeneralUtils` internal package unavailable in CI | Ensure `GeneralUtils` is installed as dependency (via `Pkg.develop` or registry) |
|
||||
| NATS `mcpServer` struct is abstract — no concrete implementation | Provide at least one mock `mcpServer` for tests that returns canned JSON responses |
|
||||
| Message history grows unbounded | Implement `prepareContext` pruning (TODO in code); add NFR-104 for max history tokens |
|
||||
Reference in New Issue
Block a user