diff --git a/chat.el b/chat.el index 3e7f903..c2e4a61 100644 --- a/chat.el +++ b/chat.el @@ -576,7 +576,7 @@ fn handle_chat_agentic(body: String) -> String { let system: String = identity + " You have access to tools: read files, write files, browse the web, search your memory, run commands. Use them when they add genuine value. Be direct.\n\n" + ctx let api_key: String = agentic_api_key() - let tools_json: String = agentic_tools_with_web() + let tools_json: String = agentic_tools_all() let safe_msg: String = json_safe(message) let safe_sys: String = json_safe(system) @@ -962,6 +962,7 @@ fn handle_dharma_room_turn(body: String) -> String { fn handle_dharma_room_turn_agentic(body: String) -> String { let transcript: String = json_get(body, "transcript") + let room_id: String = json_get(body, "room_id") let identity: String = state_get("soul_identity") let cgi_id: String = state_get("soul_cgi_id") let model: String = chat_default_model() @@ -974,93 +975,29 @@ fn handle_dharma_room_turn_agentic(body: String) -> String { let system: String = identity + " You have access to tools: read files, write files, browse the web, search your memory, run commands. Use them when they add genuine value. Be direct and stay in character.\n\n" + ctx let api_key: String = agentic_api_key() - let tools_json: String = agentic_tools_literal() + let tools_json: String = agentic_tools_all() let safe_transcript: String = json_safe(transcript) let safe_sys: String = json_safe(system) let messages: String = "[{\"role\":\"user\",\"content\":\"" + safe_transcript + "\"}]" - let api_url: String = "https://api.anthropic.com/v1/messages" let h: Map = {} map_set(h, "x-api-key", api_key) map_set(h, "anthropic-version", "2023-06-01") map_set(h, "content-type", "application/json") - let final_text: String = "" - let tools_log: String = "" - let iteration: Int = 0 - let keep_going: Bool = true + // Use dharma-prefixed session_id so bridge suspension works correctly per room. + let session_id: String = if str_eq(room_id, "") { "dharma:" + next_bridge_id() } else { "dharma:" + room_id } + let loop_result: String = agentic_loop(session_id, model, safe_sys, tools_json, messages, h, "") - while keep_going && iteration < 8 { - let req_body: String = "{\"model\":\"" + model + "\"" - + ",\"max_tokens\":4096" - + ",\"system\":\"" + safe_sys + "\"" - + ",\"tools\":" + tools_json - + ",\"messages\":" + messages - + "}" - - let raw_resp: String = http_post_with_headers(api_url, req_body, h) - - let is_error: Bool = str_starts_with(raw_resp, "{\"error\"") - || str_starts_with(raw_resp, "{\"type\":\"error\"") - || str_contains(raw_resp, "authentication_error") - if is_error { - return "{\"error\":\"llm unavailable\",\"response\":\"\",\"cgi_id\":\"" + cgi_id + "\"}" - } - - let stop_reason: String = json_get(raw_resp, "stop_reason") - let content_arr: String = json_get_raw(raw_resp, "content") - let eff_content: String = if str_eq(content_arr, "") { "[]" } else { content_arr } - - let text_out: String = "" - let has_tool: Bool = false - let tool_id: String = "" - let tool_name: String = "" - let tool_input: String = "" - let ci: Int = 0 - let c_total: Int = json_array_len(eff_content) - while ci < c_total { - let block: String = json_array_get(eff_content, ci) - let btype: String = json_get(block, "type") - let text_out = if str_eq(btype, "text") { text_out + json_get(block, "text") } else { text_out } - let is_new_tool: Bool = str_eq(btype, "tool_use") && !has_tool - let has_tool = if is_new_tool { true } else { has_tool } - let tool_id = if is_new_tool { json_get(block, "id") } else { tool_id } - let tool_name = if is_new_tool { json_get(block, "name") } else { tool_name } - let tool_input = if is_new_tool { json_get_raw(block, "input") } else { tool_input } - let ci = ci + 1 - } - - let tool_result_raw: String = if has_tool { dispatch_tool(tool_name, tool_input) } else { "" } - let tool_result: String = if str_len(tool_result_raw) > 6000 { - str_slice(tool_result_raw, 0, 6000) + "...[truncated]" - } else { tool_result_raw } - - let tool_msg: String = "{\"type\":\"tool_result\",\"tool_use_id\":\"" + tool_id + "\",\"content\":\"" + tool_result + "\"}" - - let tool_quoted: String = "\"" + tool_name + "\"" - let tools_log = if has_tool { - if str_eq(tools_log, "") { tool_quoted } else { tools_log + "," + tool_quoted } - } else { tools_log } - - let is_tool_turn: Bool = str_eq(stop_reason, "tool_use") && has_tool - let inner: String = str_slice(messages, 1, str_len(messages) - 1) - let messages = if is_tool_turn { - "[" + inner - + ",{\"role\":\"assistant\",\"content\":" + eff_content + "}" - + ",{\"role\":\"user\",\"content\":[" + tool_msg + "]}" - + "]" - } else { messages } - let final_text = if !is_tool_turn { text_out } else { final_text } - let keep_going = if !is_tool_turn { false } else { keep_going } - let iteration = iteration + 1 - } - - if str_eq(final_text, "") { - return "{\"error\":\"no response\",\"response\":\"\",\"cgi_id\":\"" + cgi_id + "\"}" + let result_error: String = json_get(loop_result, "error") + if !str_eq(result_error, "") { + return "{\"error\":\"" + result_error + "\",\"response\":\"\",\"cgi_id\":\"" + cgi_id + "\"}" } + let final_text: String = json_get(loop_result, "reply") + let tools_arr: String = json_get_raw(loop_result, "tools_used") + let eff_tools: String = if str_eq(tools_arr, "") { "[]" } else { tools_arr } let safe_text: String = json_safe(final_text) - let tools_arr: String = if str_eq(tools_log, "") { "[]" } else { "[" + tools_log + "]" } - return "{\"response\":\"" + safe_text + "\",\"cgi_id\":\"" + cgi_id + "\",\"tools_used\":" + tools_arr + "}" + return "{\"response\":\"" + safe_text + "\",\"cgi_id\":\"" + cgi_id + "\",\"tools_used\":" + eff_tools + "}" } fn auto_persist(req: String, resp: String) -> Void {