diff options
Diffstat (limited to 'Omni/Agent')
| -rw-r--r-- | Omni/Agent/DESIGN.md | 104 | ||||
| -rwxr-xr-x | Omni/Agent/monitor-worker.sh | 47 | ||||
| -rwxr-xr-x | Omni/Agent/start-worker.sh | 2 |
3 files changed, 152 insertions, 1 deletions
diff --git a/Omni/Agent/DESIGN.md b/Omni/Agent/DESIGN.md new file mode 100644 index 0000000..c3fa792 --- /dev/null +++ b/Omni/Agent/DESIGN.md @@ -0,0 +1,104 @@ +# Multi-Agent System 2.0 Design + +**Goal:** Replace the current bash-script based worker system (`start-worker.sh`, etc.) with a robust, type-safe Haskell application `Omni/Agent.hs`. + +## 1. CLI Interface + +The `agent` command (compiled from `Omni/Agent.hs`) will provide a unified interface for managing workers. + +```bash +agent start <name> [--background] # Start a worker (foreground by default, background with flag) +agent stop <name> # Stop a background worker +agent status # List all workers and their status +agent log <name> [-f] # View/tail worker logs +agent harvest # Harvest task updates from all workers +agent sync # Sync local state with live (helper) +``` + +## 2. Module Structure (`Omni/Agent/`) + +We will refactor the bash logic into Haskell modules: + +- **Omni.Agent** (`Omni/Agent.hs`): Main entry point and CLI parsing (Docopt). +- **Omni.Agent.Core**: Core data types and state management. +- **Omni.Agent.Worker**: The worker loop logic (sync, claim, work, submit). +- **Omni.Agent.Git**: Git operations (worktree, branch, merge, commit). +- **Omni.Agent.Process**: Process management (PID files, signals). +- **Omni.Agent.Log**: Log streaming and filtering (the "monitor" logic). + +## 3. Data Types + +```haskell +data WorkerStatus + = Idle + | Syncing + | Working TaskId + | Submitting TaskId + | Error Text + deriving (Show, Eq, Generic) + +data Worker = Worker + { workerName :: Text + , workerPid :: Maybe Int + , workerStatus :: WorkerStatus + , workerPath :: FilePath + } +``` + +## 4. Implementation Details + +### 4.1 Worker Loop (`agent start`) +The Haskell implementation should replicate the logic of `start-worker.sh` but with better error handling and logging. + +1. **Setup**: Ensure worktree exists (or create it). +2. **Loop**: + - `Git.syncWithLive` + - `Task.sync` + - `task <- Task.findReady` + - If `task`: + - `Task.claim task` + - `Git.checkoutTaskBranch task` + - `Amp.execute prompt` + - `Git.commit` + - `Git.checkoutBase` + - `Task.submitReview task` + - Else: `sleep 60` + +### 4.2 Process Management +- Store PIDs in `.tasks/workers/<name>.pid`. +- `agent stop` sends SIGTERM to the PID. +- `agent status` checks if PID is alive. + +### 4.3 Logging +- Continue writing raw Amp logs to `_/llm/amp.log` in the worker directory. +- `agent log` reads this file and applies the filtering logic (currently in `monitor-worker.sh` jq script) using Haskell (Aeson). +- **Requirement:** Output must include timestamps for every event. Extract the `timestamp` field from the JSON log and format it (e.g., `[HH:MM:ss] 🤖 THOUGHT: ...`). + +### 4.4 Harvesting +- Iterate over `.tasks/workers/` or `git worktree list`. +- For each worker, extract `.tasks/tasks.jsonl` via `git show`. +- Run `Task.import`. + +## 5. Migration Strategy + +1. **Parallel Existence**: Keep bash scripts while developing Haskell version. +2. **Feature Parity**: Ensure `agent start` works exactly like `start-worker.sh`. +3. **Cutover**: Update `WORKER_AGENT_GUIDE.md` to use `agent` command. +4. **Cleanup**: Delete bash scripts. + +## 6. Testing Plan + +### 6.1 Unit Tests (`Omni/Agent/Test.hs`) +- Test `Git` module commands (mocked). +- Test `Log` filtering logic. +- Test CLI argument parsing. + +### 6.2 Integration Tests +- Create a temporary test repo. +- Spawn a worker. +- Mock `amp` binary (simple script that `echo "done"`). +- Verify task moves from Open -> InProgress -> Review. + +## 7. References +- `Omni/Agent/start-worker.sh` (Current implementation) +- `Omni/Task.hs` (Task manager integration) diff --git a/Omni/Agent/monitor-worker.sh b/Omni/Agent/monitor-worker.sh new file mode 100755 index 0000000..2638e2d --- /dev/null +++ b/Omni/Agent/monitor-worker.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -e + +# Omni/Agent/monitor-worker.sh +# Monitors the worker agent's activity by filtering the debug log. +# Usage: ./Omni/Agent/monitor-worker.sh [worker-directory-name] + +WORKER_NAME="${1:-omni-worker-1}" +REPO_ROOT="$(git rev-parse --show-toplevel)" +WORKER_PATH="$REPO_ROOT/../$WORKER_NAME" +LOG_FILE="$WORKER_PATH/_/llm/amp.log" + +if [ ! -f "$LOG_FILE" ]; then + echo "Waiting for log file at $LOG_FILE..." + while [ ! -f "$LOG_FILE" ]; do sleep 1; done +fi + +echo "Monitoring Worker Agent in '$WORKER_PATH'..." +echo "Press Ctrl+C to stop." +echo "------------------------------------------------" + +# Tail the log and use jq to parse/filter relevant events +# We handle JSON parse errors gracefully (in case of partial writes) +tail -f "$LOG_FILE" | grep --line-buffered "^{" | jq -R -r ' +try ( + fromjson | + if .message == "executing 1 tools in 1 batch(es)" then + "🤖 THOUGHT: Planning tool execution (" + (.batches[0][0] // "unknown") + ")" + elif .message == "Tool Bash - checking permissions" then + empty + elif .message == "Tool Bash permitted - action: allow" then + "🔧 TOOL: Bash command executed" + elif .toolName != null and .message == "Processing tool completion for ledger" then + "✅ TOOL: " + .toolName + " completed" + elif .message == "ide-fs" and .method == "readFile" then + "📂 READ: " + .path + elif .message == "System prompt build complete (no changes)" then + "🧠 THINKING..." + elif .message == "System prompt build complete (first build)" then + "🚀 STARTING new task context" + elif .level == "error" then + "❌ ERROR: " + .message + else + empty + end +) catch empty +' diff --git a/Omni/Agent/start-worker.sh b/Omni/Agent/start-worker.sh index d005156..25f325c 100755 --- a/Omni/Agent/start-worker.sh +++ b/Omni/Agent/start-worker.sh @@ -117,7 +117,7 @@ Context: " mkdir -p _/llm - "$AMP_BIN" --log-file "_/llm/amp.log" --dangerously-allow-all -x "$PROMPT" + "$AMP_BIN" --log-level debug --log-file "_/llm/amp.log" --dangerously-allow-all -x "$PROMPT" AGENT_EXIT_CODE=$? |
