diff --git a/src/yetibot/core/commands/agent.clj b/src/yetibot/core/commands/agent.clj index 16e6e5e9..51735b44 100644 --- a/src/yetibot/core/commands/agent.clj +++ b/src/yetibot/core/commands/agent.clj @@ -347,7 +347,12 @@ "code is not a request to audit CI.\n" "- If you can't tell what the request refers to, reply briefly asking for " "the missing detail. NEVER invent work or report an unrelated summary like " - "\"checked all repos, everything green\".\n\n" + "\"checked all repos, everything green\".\n" + "- If you need more background context than what is provided in the thread " + "context, you are highly encouraged to search the entire channel's history " + "using the `yetibot` tool with the `history` command (e.g., `history` or " + "`history | grep keyword`). It is your job as an autonomous agent to " + "perform this extra search when needed!\n\n" "The codebase (so you can go straight to the right place — don't rediscover " "it). The org is `yetibot`:\n" "- `yetibot/core` — the library: chat commands, adapters, and most logic.\n" @@ -573,14 +578,19 @@ whole thread lets a follow-up like \"retry\" resolve to the original ask." [channel-id] (try - (let [topic (try (:name @(discord/get-channel! (rest-conn) channel-id)) - (catch Exception _ nil)) - lines (->> (all-channel-messages channel-id) - (sort-by :timestamp) - (map (fn [m] (str (get-in m [:author :username]) ": " (:content m)))) - (remove string/blank?))] - (string/join "\n" (cond->> lines - (not (string/blank? topic)) (cons (str "[thread topic] " topic))))) + (let [channel @(discord/get-channel! (rest-conn) channel-id) + type (:type channel)] + (if (not (#{10 11 12} type)) + "" + (let [lines (->> (all-channel-messages channel-id) + (sort-by :timestamp) + (map (fn [m] (str (get-in m [:author :username]) ": " (:content m)))) + (remove string/blank?))] + (if (<= (count lines) 1) + "" + (let [topic (:name channel)] + (string/join "\n" (cond->> lines + (not (string/blank? topic)) (cons (str "[thread topic] " topic))))))))) (catch Exception e (debug "thread-context failed:" (.getMessage e)) ""))) ;; --------------------------------------------------------------------------- diff --git a/test/yetibot/core/test/commands/agent.clj b/test/yetibot/core/test/commands/agent.clj index a1d0ece1..8975e554 100644 --- a/test/yetibot/core/test/commands/agent.clj +++ b/test/yetibot/core/test/commands/agent.clj @@ -52,7 +52,9 @@ (fact "gives the bot an identity" (agent/build-agent-prompt "do x" nil nil) => (contains "Yetibot")) (fact "tells gemini to use yetibot tool to run yetibot commands" - (agent/build-agent-prompt "do x" nil nil) => (contains "yetibot"))) + (agent/build-agent-prompt "do x" nil nil) => (contains "yetibot")) + (fact "encourages searching entire channel if needed" + (agent/build-agent-prompt "do x" nil nil) => (contains "search the entire channel's history"))) (facts "about parse-json-response" (fact "pulls the response field" @@ -184,6 +186,28 @@ (fact "keeps the original request text" (agent/resume-request "add a bagif command") => (contains "add a bagif command"))) +(facts "about thread-context" + (fact "returns empty string if the channel is not a thread (type is not 10, 11, or 12)" + (#'agent/thread-context "channel-id-123") => "" + (provided + (#'agent/rest-conn) => "mock-conn" + (discljord.messaging/get-channel! "mock-conn" "channel-id-123") => (atom {:type 0 :name "general"}))) + + (fact "returns thread context if the channel is a thread (type 11) with multiple messages" + (#'agent/thread-context "thread-id-456") => "[thread topic] cool-thread\nalice: hello\nbob: world" + (provided + (#'agent/rest-conn) => "mock-conn" + (discljord.messaging/get-channel! "mock-conn" "thread-id-456") => (atom {:type 11 :name "cool-thread"}) + (#'agent/all-channel-messages "thread-id-456") => [{:author {:username "alice"} :content "hello" :timestamp 1} + {:author {:username "bob"} :content "world" :timestamp 2}])) + + (fact "returns empty string if the channel is a thread but has 1 or fewer messages (first message/prompt only)" + (#'agent/thread-context "thread-id-789") => "" + (provided + (#'agent/rest-conn) => "mock-conn" + (discljord.messaging/get-channel! "mock-conn" "thread-id-789") => (atom {:type 11 :name "cool-thread"}) + (#'agent/all-channel-messages "thread-id-789") => [{:author {:username "alice"} :content "hello" :timestamp 1}]))) + (facts "about agent subcommands" (fact "agent-list-commands-cmd returns available commands in JSON" (agent/agent-list-commands-cmd {}) => {:result/value "{\"commands\":[\"cmd1\",\"cmd2\"]}"}