summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bensima.com>2025-11-24 13:59:34 -0500
committerBen Sima <ben@bensima.com>2025-11-24 13:59:34 -0500
commitea466775a6b12dce67b789aa98d2c40a9c913a97 (patch)
treecf021707fc1afb974ae5d4ff582273ca5a0b1659
parent5ddaf58a46c832b2f937cebac1ec2a9368bd51e9 (diff)
Simplify agent command
I think the cd'ing and stuff was messing with the direnv assumptions.
-rw-r--r--.tasks/tasks.jsonl4
-rw-r--r--Omni/Agent.hs51
-rwxr-xr-xOmni/Agent/monitor.sh75
-rwxr-xr-xOmni/Agent/start-worker.sh69
4 files changed, 12 insertions, 187 deletions
diff --git a/.tasks/tasks.jsonl b/.tasks/tasks.jsonl
index 55e1b2b..87c4c62 100644
--- a/.tasks/tasks.jsonl
+++ b/.tasks/tasks.jsonl
@@ -215,9 +215,9 @@
{"taskCreatedAt":"2025-11-23T00:42:56.80437736Z","taskDependencies":[{"depId":"t-1o2c9wcq3go.1","depType":"Blocks"}],"taskDescription":"Implement Mailgun email sending in Biz/PodcastItLater/Mail.py. Use requests. Blocked by Setup Mailgun Infrastructure.","taskId":"t-1o2c9wcq3go.2","taskNamespace":"Biz/PodcastItLater.hs","taskParent":"t-1o2c9wcq3go","taskPriority":"P2","taskStatus":"Review","taskTitle":"Implement Mailgun Client","taskType":"WorkTask","taskUpdatedAt":"2025-11-24T16:49:48.009344483Z"}
{"taskCreatedAt":"2025-11-23T01:18:20.705021976Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbco62ly","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Build failed: Biz.nix - 1","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T03:32:59.957672612Z"}
{"taskCreatedAt":"2025-11-23T01:20:43.938765636Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbf1fzh2","taskNamespace":"Biz/PodcastItLater.hs","taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Build failed: Biz/PodcastItLater/Episode.py - 1","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T03:35:07.74267138Z"}
-{"taskCreatedAt":"2025-11-23T01:21:11.642226289Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbfhxu5e","taskNamespace":"Biz/PodcastItLater.hs","taskParent":null,"taskPriority":"P2","taskStatus":"InProgress","taskTitle":"Build failed: Biz/PodcastItLater/Test.py - 1","taskType":"WorkTask","taskUpdatedAt":"2025-11-24T17:28:04.518804886Z"}
+{"taskCreatedAt":"2025-11-23T01:21:11.642226289Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbfhxu5e","taskNamespace":"Biz/PodcastItLater.hs","taskParent":null,"taskPriority":"P2","taskStatus":"Review","taskTitle":"Build failed: Biz/PodcastItLater/Test.py - 1","taskType":"WorkTask","taskUpdatedAt":"2025-11-24T18:37:33.773584669Z"}
{"taskCreatedAt":"2025-11-23T01:21:53.713796565Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbg6zl25","taskNamespace":"Biz/PodcastItLater.hs","taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Build failed: Biz/PodcastItLater/UI.py - 1","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T03:35:26.517302875Z"}
{"taskCreatedAt":"2025-11-23T01:22:34.513743178Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbgva26h","taskNamespace":"Biz/PodcastItLater.hs","taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Build failed: Biz/PodcastItLater/Worker.py - 1","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T03:35:26.599046196Z"}
{"taskCreatedAt":"2025-11-23T01:32:43.559862931Z","taskDependencies":[],"taskDescription":null,"taskId":"t-1o2cbqxw13j","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Build failed: pyproject.toml - ","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T03:35:26.680640676Z"}
-{"taskCreatedAt":"2025-11-23T01:40:20.696284164Z","taskDependencies":[{"depId":"t-1o2cbco62ly","depType":"DiscoveredFrom"}],"taskDescription":null,"taskId":"t-1o2cbyi23kl","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"Open","taskTitle":"Investigate why bild uses different source than workspace","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T01:40:20.696284164Z"}
+{"taskCreatedAt":"2025-11-23T01:40:20.696284164Z","taskDependencies":[{"depId":"t-1o2cbco62ly","depType":"DiscoveredFrom"}],"taskDescription":null,"taskId":"t-1o2cbyi23kl","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"InProgress","taskTitle":"Investigate why bild uses different source than workspace","taskType":"WorkTask","taskUpdatedAt":"2025-11-24T18:37:38.639492336Z"}
{"taskCreatedAt":"2025-11-23T01:40:20.879380653Z","taskDependencies":[{"depId":"t-1o2cbco62ly","depType":"DiscoveredFrom"}],"taskDescription":null,"taskId":"t-1o2cbyi61hb","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"Open","taskTitle":"Fix ruff formatting consistency in build environment","taskType":"WorkTask","taskUpdatedAt":"2025-11-23T01:40:20.879380653Z"}
diff --git a/Omni/Agent.hs b/Omni/Agent.hs
index d94949c..070e3fb 100644
--- a/Omni/Agent.hs
+++ b/Omni/Agent.hs
@@ -21,7 +21,7 @@ import qualified System.Console.Docopt as Docopt
import qualified System.Directory as Directory
import qualified System.Environment as Env
import qualified System.Exit as Exit
-import System.FilePath ((</>))
+import System.FilePath (takeFileName)
import qualified System.IO as IO
import qualified System.IO.Temp as Temp
@@ -43,10 +43,9 @@ help =
agent
Usage:
- agent start <name> [--path=<path>]
+ agent start
agent harvest [--path=<path>]
agent merge-driver <ours> <theirs>
- agent setup <name>
agent test
agent --help
@@ -58,11 +57,12 @@ Options:
move :: Cli.Arguments -> IO ()
move args
| args `Cli.has` Cli.command "start" = do
- name <-
- Cli.getArg args (Cli.argument "name") |> \case
- Just n -> pure (Text.pack n)
- Nothing -> panic "Name required"
- let path = Cli.getArgWithDefault args "." (Cli.longOption "path")
+ -- Always run in current directory
+ let path = "."
+
+ -- Infer name from current directory
+ absPath <- Directory.getCurrentDirectory
+ let name = Text.pack (takeFileName absPath)
let worker =
Core.Worker
@@ -75,7 +75,6 @@ move args
Worker.start worker
| args `Cli.has` Cli.command "harvest" = harvest args
| args `Cli.has` Cli.command "merge-driver" = mergeDriver args
- | args `Cli.has` Cli.command "setup" = setup args
| otherwise = putStrLn (Cli.usage help)
getArgOrExit :: Cli.Arguments -> Docopt.Option -> IO String
@@ -135,31 +134,6 @@ mergeDriver args = do
TaskCore.importTasks theirs
Exit.exitSuccess
-setup :: Cli.Arguments -> IO ()
-setup args = do
- nameStr <- getArgOrExit args (Cli.argument "name")
- let name = Text.pack nameStr
- root <- Git.getRepoRoot "."
- let worktreePath = root <> "/../" <> nameStr
-
- putText <| "Creating worktree '" <> Text.pack worktreePath <> "' on branch '" <> name <> "' (from live)..."
-
- -- git worktree add -b <name> <path> live
- Git.runGit root ["worktree", "add", "-b", nameStr, worktreePath, "live"]
-
- -- Copy .envrc.local if exists
- let envrc = root </> ".envrc.local"
- exists <- Directory.doesFileExist envrc
- when exists <| do
- putText "Copying .envrc.local..."
- Directory.copyFile envrc (worktreePath </> ".envrc.local")
-
- -- Config git
- Git.runGit worktreePath ["config", "user.name", "Omni Worker"]
- Git.runGit worktreePath ["config", "user.email", "bot@omni.agent"]
-
- putText <| "Worker setup complete at " <> Text.pack worktreePath
-
test :: Test.Tree
test = Test.group "Omni.Agent" [unitTests, logTests]
@@ -178,7 +152,7 @@ unitTests =
Test.group
"Unit tests"
[ Test.unit "can parse start command" <| do
- let result = Docopt.parseArgs help ["start", "worker-1"]
+ let result = Docopt.parseArgs help ["start"]
case result of
Left err -> Test.assertFailure <| "Failed to parse 'start': " <> show err
Right args -> args `Cli.has` Cli.command "start" Test.@?= True,
@@ -186,10 +160,5 @@ unitTests =
let result = Docopt.parseArgs help ["harvest"]
case result of
Left err -> Test.assertFailure <| "Failed to parse 'harvest': " <> show err
- Right args -> args `Cli.has` Cli.command "harvest" Test.@?= True,
- Test.unit "can parse setup command" <| do
- let result = Docopt.parseArgs help ["setup", "worker-2"]
- case result of
- Left err -> Test.assertFailure <| "Failed to parse 'setup': " <> show err
- Right args -> args `Cli.has` Cli.command "setup" Test.@?= True
+ Right args -> args `Cli.has` Cli.command "harvest" Test.@?= True
]
diff --git a/Omni/Agent/monitor.sh b/Omni/Agent/monitor.sh
deleted file mode 100755
index e57611f..0000000
--- a/Omni/Agent/monitor.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env bash
-# Omni/Agent/monitor.sh
-# Monitor the logs of a worker agent
-# Usage: ./Omni/Agent/monitor.sh [--raw] [worker-name]
-
-set -e
-
-RAW_MODE=false
-WORKER="omni-worker-1"
-
-# Parse arguments
-while [[ "$#" -gt 0 ]]; do
- case $1 in
- --raw) RAW_MODE=true ;;
- *) WORKER="$1" ;;
- esac
- shift
-done
-
-REPO_ROOT="$(git rev-parse --show-toplevel)"
-WORKER_DIR="$REPO_ROOT/../$WORKER"
-LOG_FILE="$WORKER_DIR/_/llm/amp.log"
-
-if [ ! -d "$WORKER_DIR" ]; then
- echo "Error: Worker directory '$WORKER_DIR' not found."
- echo "Usage: $0 [--raw] [worker-name]"
- exit 1
-fi
-
-echo "Monitoring worker: $WORKER"
-echo "Watching log: $LOG_FILE"
-if [ "$RAW_MODE" = true ]; then
- echo "Mode: RAW output"
-else
- echo "Mode: FORMATTED output"
-fi
-echo "---------------------------------------------------"
-
-# Wait for log file to appear
-if [ ! -f "$LOG_FILE" ]; then
- echo "Waiting for log file at $LOG_FILE..."
- while [ ! -f "$LOG_FILE" ]; do
- sleep 1
- done
-fi
-
-if [ "$RAW_MODE" = true ]; then
- tail -f "$LOG_FILE"
-else
- # Tail the log and use jq to parse/filter relevant events
- 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
- '
-fi
diff --git a/Omni/Agent/start-worker.sh b/Omni/Agent/start-worker.sh
deleted file mode 100755
index 457c83c..0000000
--- a/Omni/Agent/start-worker.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-# Omni/Agent/start-worker.sh
-# Launches an Amp worker agent in the specified worktree in a loop.
-# Usage: ./Omni/Agent/start-worker.sh [worker-directory-name-or-path]
-# Example: ./Omni/Agent/start-worker.sh omni-worker-1
-
-TARGET="${1:-omni-worker-1}"
-
-# 1. Find the Main Repo (where node_modules lives)
-# The first worktree listed is always the main one
-MAIN_REPO="$(git worktree list --porcelain | grep '^worktree ' | head -n 1 | cut -d ' ' -f 2)"
-AMP_BIN="$MAIN_REPO/node_modules/.bin/amp"
-TASK_BIN="$MAIN_REPO/_/bin/task"
-
-# 2. Resolve Worker Path
-if [ -d "$TARGET" ]; then
- WORKER_PATH="$(realpath "$TARGET")"
-elif [ -d "$MAIN_REPO/../$TARGET" ]; then
- WORKER_PATH="$(realpath "$MAIN_REPO/../$TARGET")"
-else
- echo "Error: Worker directory for '$TARGET' not found."
- exit 1
-fi
-
-if [ ! -x "$AMP_BIN" ]; then
- echo "Error: Amp binary not found at '$AMP_BIN'."
- exit 1
-fi
-
-# Ensure task binary is built/available
-if [ ! -x "$TASK_BIN" ]; then
- echo "Warning: Task binary not found at '$TASK_BIN'. Assuming it's in path or build it first."
-fi
-
-# Ensure worker has local task and agent binaries
-mkdir -p "$WORKER_PATH/_/bin"
-
-echo "Syncing worker repo..."
-if ! (cd "$WORKER_PATH" && git sync); then
- echo "Error: Failed to run 'git sync' in worker directory."
- exit 1
-fi
-
-echo "Building 'task' in worker..."
-if ! (cd "$WORKER_PATH" && bild Omni/Task.hs); then
- echo "Error: Failed to build 'task' in worker directory."
- exit 1
-fi
-
-echo "Building 'agent' in worker..."
-if ! (cd "$WORKER_PATH" && bild Omni/Agent.hs); then
- echo "Error: Failed to build 'agent' in worker directory."
- exit 1
-fi
-
-echo "Starting Worker Agent (Haskell)"
-echo " Worker Path: $WORKER_PATH"
-echo " Agent Bin: $WORKER_PATH/_/bin/agent"
-echo " Log File: $WORKER_PATH/_/llm/amp.log"
-echo " Monitor: ./Omni/Agent/monitor.sh $TARGET"
-echo " Press Ctrl+C to stop."
-
-# Add amp to PATH so the agent can find it
-export PATH="$MAIN_REPO/node_modules/.bin:$PATH"
-
-# Run the agent
-"$WORKER_PATH/_/bin/agent" start "$TARGET" --path "$WORKER_PATH"