diff --git a/CHANGELOG.md b/CHANGELOG.md index 27daa2717..fd70ea14d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Fix subagent spawning being rejected by reserved server-managed chat ids. + ## 0.133.1 - Support client-generated chat ids: clients may now create the `chatId` themselves and send it on the first `chat/prompt`. eca-emacs#231. diff --git a/src/eca/features/chat.clj b/src/eca/features/chat.clj index f47dd7d0a..a031af0e5 100644 --- a/src/eca/features/chat.clj +++ b/src/eca/features/chat.clj @@ -1246,6 +1246,12 @@ (def ^:private max-client-chat-id-length 256) +(defn ^:private server-managed-subagent-chat-id? + [db chat-id] + (and (string? chat-id) + (string/starts-with? chat-id "subagent-") + (some? (get-in db [:chats chat-id :subagent])))) + (defn validate-client-chat-id "Validates a client-supplied chat id. Returns nil when valid, otherwise an error message string. @@ -1275,7 +1281,8 @@ (defn prompt [{:keys [message agent behavior chat-id contexts variant trust] :as params} db* messenger config metrics] (let [provided-chat-id chat-id - invalid-id-reason (when (some? provided-chat-id) + invalid-id-reason (when (and (some? provided-chat-id) + (not (server-managed-subagent-chat-id? @db* provided-chat-id))) (validate-client-chat-id provided-chat-id))] (if invalid-id-reason (do (logger/warn logger-tag "Rejected chat/prompt with invalid chat-id" diff --git a/test/eca/features/chat_test.clj b/test/eca/features/chat_test.clj index 04a56d5b3..c450fdc7b 100644 --- a/test/eca/features/chat_test.clj +++ b/test/eca/features/chat_test.clj @@ -1403,6 +1403,19 @@ (is (match? {:chat-id "subagent-foo" :status :error} resp)) (is (= {} (:chats (h/db)))) (is (nil? (:chat-opened (h/messages)))))) + (testing "Server-managed subagent chat-id is accepted" + (h/reset-components!) + (let [chat-id "subagent-foo"] + (swap! (h/db*) assoc-in [:chats chat-id] {:id chat-id :subagent {:mode "subagent"}}) + (is (= {:chat-id chat-id} + (prompt! + {:message "hi" :chat-id chat-id} + {:all-tools-mock (constantly []) + :api-mock + (fn [{:keys [on-first-response-received on-message-received]}] + (on-first-response-received {:type :text :text "ok"}) + (on-message-received {:type :text :text "ok"}) + (on-message-received {:type :finish}))}))))) (testing "Excessively long chat-id is rejected" (h/reset-components!) (let [too-long (apply str (repeat 257 "a"))