From b13c42cc5566aa7365118fddc7f327b4c774a910 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Wed, 26 Nov 2025 09:38:21 -0500 Subject: Improve worker prompt and fix output interleaving - More explicit prompt: MUST run bild --test, fix hlint issues - Add workerQuiet flag to disable ANSI status bar in loop mode - Loop mode uses simple putText, manual jr work keeps status bar --- Omni/Agent/Core.hs | 3 +- Omni/Agent/Worker.hs | 93 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 37 deletions(-) (limited to 'Omni/Agent') diff --git a/Omni/Agent/Core.hs b/Omni/Agent/Core.hs index a2594d6..88f7237 100644 --- a/Omni/Agent/Core.hs +++ b/Omni/Agent/Core.hs @@ -27,7 +27,8 @@ data Worker = Worker { workerName :: Text, workerPid :: Maybe Int, workerStatus :: WorkerStatus, - workerPath :: FilePath + workerPath :: FilePath, + workerQuiet :: Bool -- Disable ANSI status bar (for loop mode) } deriving (Show, Eq, Generic) diff --git a/Omni/Agent/Worker.hs b/Omni/Agent/Worker.hs index e2c1635..0bf7519 100644 --- a/Omni/Agent/Worker.hs +++ b/Omni/Agent/Worker.hs @@ -17,13 +17,23 @@ import qualified System.Process as Process start :: Core.Worker -> Maybe Text -> IO () start worker maybeTaskId = do - AgentLog.init (Core.workerName worker) - AgentLog.log ("[worker] Starting for " <> Core.workerName worker) + if Core.workerQuiet worker + then putText ("[worker] Starting for " <> Core.workerName worker) + else do + AgentLog.init (Core.workerName worker) + AgentLog.log ("[worker] Starting for " <> Core.workerName worker) case maybeTaskId of - Just tid -> AgentLog.log ("[worker] Target task: " <> tid) - Nothing -> AgentLog.log "[worker] No specific task, will pick from ready queue" + Just tid -> logMsg worker ("[worker] Target task: " <> tid) + Nothing -> logMsg worker "[worker] No specific task, will pick from ready queue" runOnce worker maybeTaskId +-- | Log message respecting quiet mode +logMsg :: Core.Worker -> Text -> IO () +logMsg worker msg = + if Core.workerQuiet worker + then putText msg + else AgentLog.log msg + runOnce :: Core.Worker -> Maybe Text -> IO () runOnce worker maybeTaskId = do -- Find work @@ -40,11 +50,11 @@ runOnce worker maybeTaskId = do Nothing -> do case maybeTaskId of Just tid -> do - AgentLog.updateActivity ("Task " <> tid <> " not found.") - AgentLog.log ("[worker] Task " <> tid <> " not found.") + unless (Core.workerQuiet worker) <| AgentLog.updateActivity ("Task " <> tid <> " not found.") + logMsg worker ("[worker] Task " <> tid <> " not found.") Nothing -> do - AgentLog.updateActivity "No work found." - AgentLog.log "[worker] No ready tasks found." + unless (Core.workerQuiet worker) <| AgentLog.updateActivity "No work found." + logMsg worker "[worker] No ready tasks found." Just task -> do processTask worker task @@ -52,32 +62,34 @@ processTask :: Core.Worker -> TaskCore.Task -> IO () processTask worker task = do let repo = Core.workerPath worker let tid = TaskCore.taskId task + let quiet = Core.workerQuiet worker + let say = logMsg worker - AgentLog.update (\s -> s {AgentLog.statusTask = Just tid}) - AgentLog.log ("[worker] Claiming task " <> tid) + unless quiet <| AgentLog.update (\s -> s {AgentLog.statusTask = Just tid}) + say ("[worker] Claiming task " <> tid) -- Claim task TaskCore.updateTaskStatus tid TaskCore.InProgress [] - AgentLog.log "[worker] Status -> InProgress" + say "[worker] Status -> InProgress" -- Run Amp - AgentLog.log "[worker] Starting amp..." + say "[worker] Starting amp..." (exitCode, output) <- runAmp repo task - AgentLog.log ("[worker] Amp exited with: " <> tshow exitCode) + say ("[worker] Amp exited with: " <> tshow exitCode) case exitCode of Exit.ExitSuccess -> do - AgentLog.log "[worker] Running formatters..." + say "[worker] Running formatters..." _ <- runFormatters repo -- Try to commit (this runs git hooks which may fail) let commitMsg = formatCommitMessage task output - AgentLog.log "[worker] Attempting commit..." + say "[worker] Attempting commit..." commitResult <- tryCommit repo commitMsg case commitResult of CommitFailed commitErr -> do - AgentLog.log ("[worker] Commit failed: " <> commitErr) + say ("[worker] Commit failed: " <> commitErr) -- Save failure context and reopen task for retry maybeCtx <- TaskCore.getRetryContext tid @@ -85,7 +97,7 @@ processTask worker task = do if attempt > 3 then do - AgentLog.log "[worker] Task failed 3 times, needs human intervention" + say "[worker] Task failed 3 times, needs human intervention" TaskCore.updateTaskStatus tid TaskCore.Open [] else do TaskCore.setRetryContext @@ -97,23 +109,23 @@ processTask worker task = do TaskCore.retryReason = "commit_failed: " <> commitErr } TaskCore.updateTaskStatus tid TaskCore.Open [] - AgentLog.log ("[worker] Task reopened (attempt " <> tshow attempt <> "/3)") + say ("[worker] Task reopened (attempt " <> tshow attempt <> "/3)") NoChanges -> do -- No changes = task already implemented, mark as Done - AgentLog.log "[worker] No changes to commit - task already done" + say "[worker] No changes to commit - task already done" TaskCore.clearRetryContext tid TaskCore.updateTaskStatus tid TaskCore.Done [] - AgentLog.log ("[worker] ✓ Task " <> tid <> " -> Done (no changes)") - AgentLog.update (\s -> s {AgentLog.statusTask = Nothing}) + say ("[worker] ✓ Task " <> tid <> " -> Done (no changes)") + unless quiet <| AgentLog.update (\s -> s {AgentLog.statusTask = Nothing}) CommitSuccess -> do -- Commit succeeded, set to Review TaskCore.updateTaskStatus tid TaskCore.Review [] - AgentLog.log ("[worker] ✓ Task " <> tid <> " -> Review") - AgentLog.update (\s -> s {AgentLog.statusTask = Nothing}) + say ("[worker] ✓ Task " <> tid <> " -> Review") + unless quiet <| AgentLog.update (\s -> s {AgentLog.statusTask = Nothing}) Exit.ExitFailure code -> do - AgentLog.log ("[worker] Amp failed with code " <> tshow code) + say ("[worker] Amp failed with code " <> tshow code) -- Don't set back to Open here - leave in InProgress for debugging - AgentLog.log "[worker] Task left in InProgress (amp failure)" + say "[worker] Task left in InProgress (amp failure)" -- | Run lint --fix to format and fix lint issues runFormatters :: FilePath -> IO (Either Text ()) @@ -155,24 +167,33 @@ runAmp repo task = do -- Check for retry context maybeRetry <- TaskCore.getRetryContext (TaskCore.taskId task) + let ns = fromMaybe "." (TaskCore.taskNamespace task) let basePrompt = "You are a Worker Agent.\n" <> "Your goal is to implement the following task:\n\n" <> formatTask task - <> "\n\nINSTRUCTIONS:\n" - <> "1. Analyze the codebase (use finder/Grep) to understand where to make changes.\n" + <> "\n\nCRITICAL INSTRUCTIONS:\n" + <> "1. Analyze the codebase to understand where to make changes.\n" <> "2. Implement the changes by editing files.\n" - <> "3. Run tests to verify your work (e.g., 'bild --test Omni/Namespace').\n" - <> "4. Fix any errors found during testing.\n" - <> "5. Do NOT update the task status or manage git branches.\n" - <> "6. When finished and tested, exit.\n\n" + <> "3. BEFORE finishing, you MUST run: bild --test " + <> ns + <> "\n" + <> "4. Fix ALL errors from bild --test (including hlint suggestions).\n" + <> "5. Keep running bild --test until it passes with no errors.\n" + <> "6. Do NOT update task status or manage git.\n" + <> "7. Only exit after bild --test passes.\n\n" + <> "IMPORTANT: The git commit will fail if hlint finds issues.\n" + <> "You must fix hlint suggestions like:\n" + <> "- 'Use list comprehension' -> use [x | cond] instead of if/else\n" + <> "- 'Avoid lambda' -> use function composition\n" + <> "- 'Redundant bracket' -> remove unnecessary parens\n\n" <> "Context:\n" - <> "- You are working in '" + <> "- Working directory: " <> Text.pack repo - <> "'.\n" - <> "- The task is in namespace '" - <> fromMaybe "root" (TaskCore.taskNamespace task) - <> "'.\n" + <> "\n" + <> "- Namespace: " + <> ns + <> "\n" -- Add retry context if present let retryPrompt = case maybeRetry of -- cgit v1.2.3