|
3 | 3 | [cheshire.core :as json] |
4 | 4 | [clojure.set :as set] |
5 | 5 | [clojure.string :as string] |
| 6 | + [eca.features.commands :as f.commands] |
6 | 7 | [eca.features.context :as f.context] |
7 | 8 | [eca.features.index :as f.index] |
8 | 9 | [eca.features.prompt :as f.prompt] |
|
12 | 13 | [eca.llm-api :as llm-api] |
13 | 14 | [eca.logger :as logger] |
14 | 15 | [eca.messenger :as messenger] |
15 | | - [eca.shared :as shared :refer [assoc-some multi-str]])) |
| 16 | + [eca.shared :as shared :refer [assoc-some]])) |
16 | 17 |
|
17 | 18 | (set! *warn-on-reflection* true) |
18 | 19 |
|
|
45 | 46 | (defn ^:private tool-name->origin [name all-tools] |
46 | 47 | (:origin (first (filter #(= name (:name %)) all-tools)))) |
47 | 48 |
|
48 | | -(defn ^:private tokens->cost [input-tokens input-cache-creation-tokens input-cache-read-tokens output-tokens model db] |
49 | | - (let [normalized-model (if (string/includes? model "/") |
50 | | - (last (string/split model #"/")) |
51 | | - model) |
52 | | - {:keys [input-token-cost output-token-cost |
53 | | - input-cache-creation-token-cost input-cache-read-token-cost]} (get-in db [:models normalized-model]) |
54 | | - input-cost (* input-tokens input-token-cost) |
55 | | - input-cost (if input-cache-creation-tokens |
56 | | - (+ input-cost (* input-cache-creation-tokens input-cache-creation-token-cost)) |
57 | | - input-cost) |
58 | | - input-cost (if input-cache-read-tokens |
59 | | - (+ input-cost (* input-cache-read-tokens input-cache-read-token-cost)) |
60 | | - input-cost)] |
61 | | - (when (and input-token-cost output-token-cost) |
62 | | - (format "%.2f" (+ input-cost |
63 | | - (* output-tokens output-token-cost)))))) |
64 | | - |
65 | 49 | (defn ^:private usage-msg->usage |
66 | 50 | [{:keys [input-tokens output-tokens |
67 | 51 | input-cache-creation-tokens input-cache-read-tokens]} |
|
84 | 68 | (assoc-some {:message-output-tokens output-tokens |
85 | 69 | :message-input-tokens (+ input-tokens message-input-cache-tokens) |
86 | 70 | :session-tokens (+ total-input-tokens total-input-cache-tokens total-output-tokens)} |
87 | | - :message-cost (tokens->cost input-tokens input-cache-creation-tokens input-cache-read-tokens output-tokens model db) |
88 | | - :session-cost (tokens->cost total-input-tokens total-input-cache-creation-tokens total-input-cache-read-tokens total-output-tokens model db))))) |
| 71 | + :message-cost (shared/tokens->cost input-tokens input-cache-creation-tokens input-cache-read-tokens output-tokens model db) |
| 72 | + :session-cost (shared/tokens->cost total-input-tokens total-input-cache-creation-tokens total-input-cache-read-tokens total-output-tokens model db))))) |
89 | 73 |
|
90 | 74 | (defn ^:private message->decision [message] |
91 | 75 | (let [slash? (string/starts-with? message "/") |
|
98 | 82 | {:type :mcp-prompt |
99 | 83 | :server server |
100 | 84 | :prompt (second (string/split (first parts) #":")) |
101 | | - :args (if (seq parts) |
102 | | - (vec (rest parts)) |
103 | | - [])}) |
| 85 | + :args (vec (rest parts))}) |
104 | 86 |
|
105 | 87 | slash? |
106 | | - {:type :eca-command |
107 | | - :command (subs message 1)} |
| 88 | + (let [command (subs message 1) |
| 89 | + parts (string/split command #" ")] |
| 90 | + {:type :eca-command |
| 91 | + :command (first parts) |
| 92 | + :args (vec (rest parts))}) |
108 | 93 |
|
109 | 94 | :else |
110 | 95 | {:type :prompt-message |
|
276 | 261 | :text error-message}) |
277 | 262 | (prompt-messages! messages false chat-ctx)))) |
278 | 263 |
|
279 | | -(defn ^:private handle-command! [{:keys [command]} {:keys [chat-id db* model] :as chat-ctx}] |
280 | | - (let [db @db*] |
281 | | - (case command |
282 | | - "costs" (let [total-input-tokens (get-in db [:chats chat-id :total-input-tokens] 0) |
283 | | - total-input-cache-creation-tokens (get-in db [:chats chat-id :total-input-cache-creation-tokens] nil) |
284 | | - total-input-cache-read-tokens (get-in db [:chats chat-id :total-input-cache-read-tokens] nil) |
285 | | - total-output-tokens (get-in db [:chats chat-id :total-output-tokens] 0) |
286 | | - text (multi-str (str "Total input tokens: " total-input-tokens) |
287 | | - (when total-input-cache-creation-tokens |
288 | | - (str "Total input cache creation tokens: " total-input-cache-creation-tokens)) |
289 | | - (when total-input-cache-read-tokens |
290 | | - (str "Total input cache read tokens: " total-input-cache-read-tokens)) |
291 | | - (str "Total output tokens: " total-output-tokens) |
292 | | - (str "Total cost: $" (tokens->cost total-input-tokens total-input-cache-creation-tokens total-input-cache-read-tokens total-output-tokens model db)))] |
293 | | - (send-content! chat-ctx :system {:type :text |
294 | | - :text text})) |
295 | | - "repo-map-show" (send-content! chat-ctx :system {:type :text |
296 | | - :text (f.index/repo-map db {:as-string? true})}) |
297 | | - (send-content! chat-ctx :system {:type :text |
298 | | - :text (str "Unknown command: " command)}))) |
299 | | - (finish-chat-prompt! :idle chat-ctx)) |
| 264 | +(defn ^:private handle-command! [{:keys [command args]} {:keys [chat-id db* config model] :as chat-ctx}] |
| 265 | + (let [{:keys [type] :as result} (f.commands/handle-command! command args chat-id model config db*)] |
| 266 | + (case type |
| 267 | + :text (do (send-content! chat-ctx :system {:type :text :text (:text result)}) |
| 268 | + (finish-chat-prompt! :idle chat-ctx)) |
| 269 | + :send-prompt (prompt-messages! [{:role "user" :content (:prompt result)}] true chat-ctx) |
| 270 | + nil))) |
300 | 271 |
|
301 | 272 | (defn prompt |
302 | 273 | [{:keys [message model behavior contexts chat-id request-id]} |
|
346 | 317 |
|
347 | 318 | (defn query-commands |
348 | 319 | [{:keys [query chat-id]} |
349 | | - db*] |
| 320 | + db* |
| 321 | + config] |
350 | 322 | (let [query (string/lower-case query) |
351 | | - mcp-prompts (->> (f.mcp/all-prompts @db*) |
352 | | - (mapv #(-> % |
353 | | - (assoc :name (str (:server %) ":" (:name %)) |
354 | | - :type :mcpPrompt) |
355 | | - (dissoc :server)))) |
356 | | - eca-commands [{:name "costs" |
357 | | - :type :native |
358 | | - :description "Show the total costs of the current chat session." |
359 | | - :arguments []} |
360 | | - {:name "repo-map-show" |
361 | | - :type :native |
362 | | - :description "Show the actual repoMap of current session." |
363 | | - :arguments []}] |
364 | | - commands (concat mcp-prompts |
365 | | - eca-commands) |
| 323 | + commands (f.commands/all-commands @db* config) |
366 | 324 | commands (if (string/blank? query) |
367 | 325 | commands |
368 | 326 | (filter #(or (string/includes? (string/lower-case (:name %)) query) |
|
0 commit comments