|
10 | 10 |
|
11 | 11 | (h/reset-components-before-test) |
12 | 12 |
|
13 | | -(defn ^:private rewrite! |
14 | | - "Helper to invoke rewrite/prompt with configurable mocks. |
15 | | - Returns {:resp <function-return> :finished? <promise>}" |
16 | | - [params {:keys [api-mock build-instructions-mock refine-file-context-mock |
17 | | - login-renew-mock default-model-mock] |
18 | | - :or {build-instructions-mock (constantly "INSTR") |
19 | | - refine-file-context-mock (constantly "FULL-CONTENT") |
20 | | - login-renew-mock (fn [& _] nil) |
21 | | - default-model-mock (constantly "anthropic/claude-dev")}}] |
22 | | - (let [finished? (promise) |
23 | | - resp (with-redefs [llm-api/sync-or-async-prompt! |
24 | | - (fn [opts] |
25 | | - (when api-mock |
26 | | - (api-mock (assoc opts :finished? finished?))) |
27 | | - nil) |
28 | | - f.prompt/build-rewrite-instructions build-instructions-mock |
29 | | - f.login/maybe-renew-auth-token! login-renew-mock |
30 | | - llm-api/refine-file-context refine-file-context-mock |
31 | | - llm-api/default-model default-model-mock] |
32 | | - ;; ensure test env config is set |
33 | | - (h/config! {:env "test"}) |
34 | | - (let [r (f.rewrite/prompt params (h/db*) (h/config) (h/messenger) (h/metrics))] |
35 | | - ;; Keep redefs in scope until async code runs |
36 | | - (deref finished? 2000 nil) |
37 | | - r))] |
38 | | - {:resp resp :finished? finished?})) |
39 | | - |
40 | 13 | (deftest prompt-basic-flow-test |
41 | 14 | (testing "Basic rewrite flow: started -> reasoning -> text -> finish" |
42 | 15 | (h/reset-components!) |
43 | 16 | (let [api-opts* (atom nil) |
44 | | - {:keys [resp finished?]} |
45 | | - (rewrite! |
46 | | - {:id "rw-1" |
47 | | - :prompt "Please improve the following" |
48 | | - :text "Original text" |
49 | | - :range {:start {:line 1 :character 0} |
50 | | - :end {:line 1 :character 14}}} |
51 | | - {:api-mock |
52 | | - (fn [{:keys [on-first-response-received on-reason on-message-received] :as opts}] |
53 | | - (reset! api-opts* opts) |
54 | | - ;; Emit the events in the expected order |
55 | | - (on-first-response-received {:type :text}) |
56 | | - (on-reason {:status :started}) |
57 | | - (on-reason {:status :thinking :text "..."}) |
58 | | - (on-message-received {:type :text :text "Hello"}) |
59 | | - (on-message-received {:type :text :text ", world!"}) |
60 | | - (on-message-received {:type :finish}) |
61 | | - (deliver (:finished? opts) true)) |
62 | | - :build-instructions-mock (constantly "INSTR")})] |
63 | | - ;; Wait for async future to publish the finish event |
64 | | - (is (true? (deref finished? 2000 false)) "Timed out waiting for finish event") |
65 | | - ;; Function return value |
66 | | - (is (= {:status "prompting" :model "anthropic/claude-dev"} resp)) |
| 17 | + resp (with-redefs [llm-api/sync-or-async-prompt! |
| 18 | + (fn [{:keys [on-first-response-received on-reason on-message-received] :as opts}] |
| 19 | + (reset! api-opts* opts) |
| 20 | + ;; Emit the events in the expected order |
| 21 | + (on-first-response-received {:type :text}) |
| 22 | + (on-reason {:status :started}) |
| 23 | + (on-reason {:status :thinking :text "..."}) |
| 24 | + (on-message-received {:type :text :text "Hello"}) |
| 25 | + (on-message-received {:type :text :text ", world!"}) |
| 26 | + (on-message-received {:type :finish})) |
| 27 | + f.prompt/build-rewrite-instructions (constantly "INSTR") |
| 28 | + f.login/maybe-renew-auth-token! (fn [& _] nil) |
| 29 | + llm-api/refine-file-context (constantly "FULL-CONTENT") |
| 30 | + llm-api/default-model (constantly "openai/gpt-4.1")] |
| 31 | + (h/config! {:env "test"}) |
| 32 | + (f.rewrite/prompt {:id "rw-1" |
| 33 | + :prompt "Please improve the following" |
| 34 | + :text "Original text" |
| 35 | + :range {:start {:line 1 :character 0} |
| 36 | + :end {:line 1 :character 14}}} |
| 37 | + (h/db*) (h/config) (h/messenger) (h/metrics)))] |
| 38 | + (is (= {:status "prompting" :model "openai/gpt-4.1"} resp)) |
67 | 39 | ;; Messenger events captured by TestMessenger |
68 | 40 | (let [msgs (get (h/messages) :rewrite-content-received)] |
69 | 41 | ;; Ensure order and content types |
|
82 | 54 | (swap! (h/db*) assoc :models {"openai/gpt-test" {:max-output-tokens 1024}}) |
83 | 55 | (let [captured-instr-args* (atom nil) |
84 | 56 | api-opts* (atom nil) |
85 | | - finished? (promise) |
86 | 57 | resp |
87 | 58 | (with-redefs [llm-api/sync-or-async-prompt! |
88 | 59 | (fn [opts] |
89 | 60 | (reset! api-opts* opts) |
90 | 61 | ((:on-first-response-received opts) {:type :text}) |
91 | | - ((:on-message-received opts) {:type :finish}) |
92 | | - (deliver finished? true)) |
| 62 | + ((:on-message-received opts) {:type :finish})) |
93 | 63 | f.prompt/build-rewrite-instructions |
94 | 64 | (fn [text path full-text range cfg] |
95 | 65 | (reset! captured-instr-args* {:text text :path path :full-text full-text :range range :config cfg}) |
96 | 66 | "MY-INSTR") |
97 | 67 | f.login/maybe-renew-auth-token! (fn [& _] nil) |
98 | 68 | llm-api/refine-file-context (fn [path _] (str "CTX:" path))] |
99 | 69 | (h/config! {:env "test" :rewrite {:model "openai/gpt-test"}}) |
100 | | - (let [r (f.rewrite/prompt {:id "rw-2" |
101 | | - :prompt "Do it" |
102 | | - :text "T" |
103 | | - :path (h/file-path "/tmp/file.txt") |
104 | | - :range {:start {:line 10 :character 2} |
105 | | - :end {:line 12 :character 5}}} |
106 | | - (h/db*) (h/config) (h/messenger) (h/metrics))] |
107 | | - (deref finished? 2000 nil) |
108 | | - r))] |
| 70 | + (f.rewrite/prompt {:id "rw-2" |
| 71 | + :prompt "Do it" |
| 72 | + :text "T" |
| 73 | + :path (h/file-path "/tmp/file.txt") |
| 74 | + :range {:start {:line 10 :character 2} |
| 75 | + :end {:line 12 :character 5}}} |
| 76 | + (h/db*) (h/config) (h/messenger) (h/metrics)))] |
109 | 77 | (is (= {:status "prompting" :model "openai/gpt-test"} resp)) |
110 | | - (is (true? (deref finished? 2000 false))) |
111 | 78 | ;; build-rewrite-instructions received expected args |
112 | 79 | (is (match? {:text "T" |
113 | 80 | :path (h/file-path "/tmp/file.txt") |
|
132 | 99 | (swap! (h/db*) assoc :models {"google/gemini-dev" {:reason? true}}) |
133 | 100 | (let [renew-called* (atom nil) |
134 | 101 | api-opts* (atom nil) |
135 | | - finished? (promise) |
136 | 102 | resp |
137 | 103 | (with-redefs [llm-api/sync-or-async-prompt! |
138 | 104 | (fn [opts] |
139 | 105 | (reset! api-opts* opts) |
140 | 106 | ((:on-first-response-received opts) {:type :text}) |
141 | | - ((:on-message-received opts) {:type :finish}) |
142 | | - (deliver finished? true)) |
| 107 | + ((:on-message-received opts) {:type :finish})) |
143 | 108 | f.prompt/build-rewrite-instructions (constantly "INSTR") |
144 | 109 | f.login/maybe-renew-auth-token! |
145 | 110 | (fn [{:keys [provider]} _ctx] |
146 | 111 | (reset! renew-called* provider)) |
147 | 112 | llm-api/default-model (constantly "google/gemini-dev")] |
148 | 113 | (h/config! {:env "test"}) |
149 | | - (let [r (f.rewrite/prompt {:id "rw-3" |
150 | | - :prompt "X" |
151 | | - :text "Y"} |
152 | | - (h/db*) (h/config) (h/messenger) (h/metrics))] |
153 | | - (deref finished? 2000 nil) |
154 | | - r))] |
| 114 | + (f.rewrite/prompt {:id "rw-3" |
| 115 | + :prompt "X" |
| 116 | + :text "Y"} |
| 117 | + (h/db*) (h/config) (h/messenger) (h/metrics)))] |
155 | 118 | (is (= {:status "prompting" :model "google/gemini-dev"} resp)) |
156 | | - (is (true? (deref finished? 2000 false))) |
157 | 119 | (is (= "google" @renew-called*)) |
158 | 120 | (is (= "google" (:provider @api-opts*))) |
159 | 121 | (is (= "gemini-dev" (:model @api-opts*))) |
|
0 commit comments