From ba466ffdba886d1a30b8fd7c6727ad69a6d40f2c Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Fri, 19 Dec 2025 22:59:34 -0500 Subject: Omni/Agent/Subagent/Coder: improve token efficiency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrote system prompt with TOKEN EFFICIENCY section - Reduced defaults: timeout 600s, maxCost 50ยข, maxTokens 100k - Added output truncation (8000 char cap) to all tools - Tightened search limits (30 results, 5 context lines) --- Omni/Agent/Tools.hs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'Omni/Agent/Tools.hs') diff --git a/Omni/Agent/Tools.hs b/Omni/Agent/Tools.hs index 22cc8a1..0bd394f 100644 --- a/Omni/Agent/Tools.hs +++ b/Omni/Agent/Tools.hs @@ -210,8 +210,22 @@ instance Aeson.FromJSON ToolResult where <*> (v .:? "output" .!= "") <*> (v .:? "error") +-- | Maximum characters for tool output to prevent token explosion +maxOutputChars :: Int +maxOutputChars = 8000 + +-- | Truncate output if too long, adding a notice +truncateOutput :: Text -> Text +truncateOutput output + | Text.length output <= maxOutputChars = output + | otherwise = + Text.take maxOutputChars output + <> "\n\n[OUTPUT TRUNCATED - " + <> tshow (Text.length output - maxOutputChars) + <> " chars omitted. Use line ranges or more specific searches.]" + mkSuccess :: Text -> Aeson.Value -mkSuccess output = Aeson.toJSON <| ToolResult True output Nothing +mkSuccess output = Aeson.toJSON <| ToolResult True (truncateOutput output) Nothing mkError :: Text -> Aeson.Value mkError err = Aeson.toJSON <| ToolResult False "" (Just err) @@ -244,7 +258,7 @@ readFileTool :: Engine.Tool readFileTool = Engine.Tool { Engine.toolName = "read_file", - Engine.toolDescription = "Read the contents of a file. Can optionally read a specific line range.", + Engine.toolDescription = "Read file contents. PREFER using start_line/end_line to read only what you need. Large files will be truncated.", Engine.toolJsonSchema = Aeson.object [ "type" .= ("object" :: Text), @@ -588,7 +602,7 @@ executeSearchCodebase v = Aeson.Error e -> pure <| mkError (Text.pack e) Aeson.Success args -> do let pat = Text.unpack (searchPattern args) - maxRes = fromMaybe 100 (searchMaxResults args) + maxRes = min 50 (fromMaybe 30 (searchMaxResults args)) caseSensitive = fromMaybe False (searchCaseSensitive args) baseArgs = ["--line-number", "--no-heading", "--max-count=" <> show maxRes, pat] @@ -660,13 +674,13 @@ executeSearchAndRead v = Aeson.Error e -> pure <| mkError (Text.pack e) Aeson.Success args -> do let pat = Text.unpack (sarPattern args) - ctx = fromMaybe 10 (sarContextLines args) + ctx = min 15 (fromMaybe 5 (sarContextLines args)) pathArg = maybe ["."] (\p -> [Text.unpack p]) (sarPath args) rgArgs = [ "--line-number", "--no-heading", "--context=" <> show ctx, - "--max-count=20", + "--max-count=10", "--ignore-case", pat ] -- cgit v1.2.3