|
| 1 | +(ns eca.features.chat.lifecycle-test |
| 2 | + (:require |
| 3 | + [clojure.test :refer [deftest is testing]] |
| 4 | + [eca.features.chat.lifecycle :as lifecycle])) |
| 5 | + |
| 6 | +(set! *warn-on-reflection* true) |
| 7 | + |
| 8 | +(def ^:private chat-id "c1") |
| 9 | +(def ^:private agent-name :default) |
| 10 | +(def ^:private full-model "openai/test") |
| 11 | +(def ^:private config {:autoCompactPercentage 75}) |
| 12 | + |
| 13 | +(defn- db-with [usage model-caps] |
| 14 | + {:chats {chat-id {:usage usage}} |
| 15 | + :models {full-model model-caps}}) |
| 16 | + |
| 17 | +(deftest auto-compact?-does-not-crash-on-zero-or-missing-context-limit |
| 18 | + (testing "zero context limit (e.g. models.dev returning 0 for image-only models) is treated as unknown and returns falsy" |
| 19 | + (let [db (db-with {:last-input-tokens 100 :last-output-tokens 50} |
| 20 | + {:limit {:context 0 :output 0}})] |
| 21 | + (is (not (lifecycle/auto-compact? chat-id agent-name full-model config db))))) |
| 22 | + |
| 23 | + (testing "nil context limit returns falsy" |
| 24 | + (let [db (db-with {:last-input-tokens 100 :last-output-tokens 50} |
| 25 | + {:limit {:context nil :output nil}})] |
| 26 | + (is (not (lifecycle/auto-compact? chat-id agent-name full-model config db))))) |
| 27 | + |
| 28 | + (testing "missing :limit map returns falsy" |
| 29 | + (let [db (db-with {:last-input-tokens 100 :last-output-tokens 50} |
| 30 | + {})] |
| 31 | + (is (not (lifecycle/auto-compact? chat-id agent-name full-model config db))))) |
| 32 | + |
| 33 | + (testing "unknown model (no entry in :models) returns falsy" |
| 34 | + (let [db {:chats {chat-id {:usage {:last-input-tokens 100 :last-output-tokens 50}}}}] |
| 35 | + (is (not (lifecycle/auto-compact? chat-id agent-name full-model config db)))))) |
| 36 | + |
| 37 | +(deftest auto-compact?-with-positive-context-limit |
| 38 | + (testing "returns truthy when usage meets/exceeds the configured threshold" |
| 39 | + (let [db (db-with {:last-input-tokens 800 :last-output-tokens 0} |
| 40 | + {:limit {:context 1000 :output 1000}})] |
| 41 | + (is (lifecycle/auto-compact? chat-id agent-name full-model config db)))) |
| 42 | + |
| 43 | + (testing "returns false when usage is below the configured threshold" |
| 44 | + (let [db (db-with {:last-input-tokens 100 :last-output-tokens 0} |
| 45 | + {:limit {:context 1000 :output 1000}})] |
| 46 | + (is (false? (lifecycle/auto-compact? chat-id agent-name full-model config db))))) |
| 47 | + |
| 48 | + (testing "respects per-agent autoCompactPercentage override" |
| 49 | + (let [db (db-with {:last-input-tokens 500 :last-output-tokens 0} |
| 50 | + {:limit {:context 1000 :output 1000}})] |
| 51 | + (is (lifecycle/auto-compact? chat-id agent-name full-model |
| 52 | + {:agent {agent-name {:autoCompactPercentage 40}} |
| 53 | + :autoCompactPercentage 99} |
| 54 | + db))))) |
| 55 | + |
| 56 | +(deftest auto-compact?-respects-in-progress-flags |
| 57 | + (testing "returns nil when chat is already compacting" |
| 58 | + (let [db (-> (db-with {:last-input-tokens 800 :last-output-tokens 0} |
| 59 | + {:limit {:context 1000 :output 1000}}) |
| 60 | + (assoc-in [:chats chat-id :compacting?] true))] |
| 61 | + (is (nil? (lifecycle/auto-compact? chat-id agent-name full-model config db))))) |
| 62 | + |
| 63 | + (testing "returns nil when chat is already auto-compacting" |
| 64 | + (let [db (-> (db-with {:last-input-tokens 800 :last-output-tokens 0} |
| 65 | + {:limit {:context 1000 :output 1000}}) |
| 66 | + (assoc-in [:chats chat-id :auto-compacting?] true))] |
| 67 | + (is (nil? (lifecycle/auto-compact? chat-id agent-name full-model config db)))))) |
0 commit comments