/* * agent_llm.h — OpenAI-compatible LLM HTTP client * * Sends chat-completions requests to an OpenAI-compatible endpoint * (OpenAI, OpenRouter, Ollama, LM Studio, Groq, etc.) using libsoup-3.0, * parses the JSON response, and returns the assistant's message (text * content + any tool_calls). * * The HTTP call is synchronous (soup_session_send_and_read) and is * intended to be called from a background thread — not the GTK main * thread. A fresh SoupSession is created per call so there are no * cross-thread sharing issues. */ #ifndef AGENT_LLM_H #define AGENT_LLM_H #include "cjson/cJSON.h" #ifdef __cplusplus extern "C" { #endif /* ── Response ──────────────────────────────────────────────────────── */ typedef struct { char *content; /* assistant text (may be NULL or empty) */ cJSON *tool_calls; /* JSON array of tool call objects, or NULL */ char *finish_reason; /* "stop", "tool_calls", "length", etc. */ } agent_llm_response_t; /* * Call an OpenAI-compatible chat completions endpoint. * * base_url — e.g. "https://api.openai.com/v1" or "http://localhost:11434/v1" * api_key — bearer token (may be NULL for local servers like Ollama) * model — model name, e.g. "gpt-4o", "llama3.1", etc. * messages — cJSON array of message objects (role/content/tool_calls/tool_call_id) * tools — cJSON array of tool definitions (OpenAI format), or NULL * * Returns a newly-allocated agent_llm_response_t. Caller must free with * agent_llm_response_free(). * * On error, returns NULL (caller should handle gracefully). */ agent_llm_response_t *agent_llm_chat(const char *base_url, const char *api_key, const char *model, cJSON *messages, cJSON *tools); /* * Free an agent_llm_response_t returned by agent_llm_chat(). * Safe to call with NULL. */ void agent_llm_response_free(agent_llm_response_t *resp); /* * Build the OpenAI-format "tools" array from the shared tool catalog * (agent_tool_catalog.h). Each entry is wrapped as: * * {"type":"function","function":{"name":...,"description":...,"parameters":{...}}} * * Returns a newly-allocated cJSON array. Caller frees with cJSON_Delete(). * Returns NULL if the catalog is empty or on allocation failure. */ cJSON *agent_llm_build_openai_tools(void); /* * Fetch the list of available models from an OpenAI-compatible API. * Calls GET {base_url}/models with the Authorization header. * * base_url — e.g. "https://api.ppq.ai" * api_key — bearer token (may be NULL for local servers) * * Returns a cJSON array of model ID strings (newly allocated), e.g.: * ["gpt-4o", "gpt-4o-mini", "llama3.1"] * Returns NULL on error. Caller must cJSON_Delete(). */ cJSON *agent_llm_list_models(const char *base_url, const char *api_key); #ifdef __cplusplus } #endif #endif /* AGENT_LLM_H */