#ifndef LLSH_TOOLS_H #define LLSH_TOOLS_H #include #include "config.h" #include "util.h" #include "dotagents.h" /* Mirrors tools.rs: the built-in tools the agent can call. * Each tool returns an owned string on success, or NULL with an owned * error message in **err (caller frees whichever was returned). */ char *tool_read_file(const char *path, unsigned long offset, unsigned long limit, char **err); char *tool_write_file(const char *path, const char *content, char **err); char *tool_run_shell(const char *command, char **err); char *tool_run_shell_timed(const char *command, unsigned long timeout_secs, char **err); /* `dot` is the caller's loaded .agents snapshot (borrowed); NULL means "no * skills/memories". */ char *tool_use_skill(const dotagents *dot, const char *id, char **err); char *tool_search_memories(const dotagents *dot, const char *query, char **err); /* Embedding tool. The `default` preset of `.agents/models.json` supplies * the connection; preset fields fall back to the top-level values. */ typedef struct { char *model; /* owned */ char *base_url; /* owned */ char *api_key; /* owned */ } embed_target; void embed_target_free(embed_target *t); /* Resolve the configured embedding connection. 0 + *out filled, or -1 with * *err owned. */ int tool_embed_resolve(const config *cfg, const dotagents *dot, embed_target *out, char **err); /* Pure helpers (no network; unit-testable). */ char *tool_embed_request(const char *model, const char *text, char **err); char *tool_embed_url(const char *base_url); /* `body` -> the `data[0].embedding` array as a JSON array string. 0 + * *vector_json owned, or -1 with *err owned. */ int tool_embed_parse(const char *body, char **vector_json, char **err); /* Full tool: resolve + POST {base}/embeddings + parse. Returns owned * `{"dimensions":N,"vector":[...]}` or NULL with *err owned. */ char *tool_embed(const char *text, const config *cfg, const dotagents *dot, char **err); /* LLM call tool: a one-shot completion through the session's provider * (OpenAI-compatible, Anthropic, or Ollama). `prompt` is the single user * message. The remaining fields are optional generation parameters, each * with an "unset" value (temperature < 0, max_tokens / thinking_budget 0, * pointers NULL); `embed` true routes the prompt to the embeddings * endpoint instead. All strings borrowed for the call's lifetime. */ typedef struct { const char *prompt; /* required */ const char *model; /* optional override; NULL = session model */ double temperature; /* < 0 = unset */ unsigned long max_tokens; /* 0 = unset */ const char *reasoning_effort; /* "low" / "medium" / "high"; NULL = unset */ unsigned long thinking_budget; /* 0 = unset (tokens) */ const char *response_schema; /* JSON Schema text; NULL = unset */ bool embed; /* true = embed the prompt instead */ } llm_tool_call; /* Full tool: one-shot completion (or embed when `call->embed`). Returns * owned result text, or NULL with *err owned. */ char *tool_llm(const llm_tool_call *call, const config *cfg, const dotagents *dot, char **err); /* Pure helpers (mirroring the tested functions in tools.rs). */ char *tool_truncate_output(const char *text); void tool_tokenize(const char *query, strlist *out); bool tool_is_subsequence(const char *needle, const char *haystack); double tool_field_match_strength(const char *field, const char *term); double tool_memory_relevance(const memory *m, const strlist *terms); /* Static registry for /tools display. Returns the entry count and sets * *out to a static array valid for the process lifetime. */ typedef struct { const char *name; const char *desc; } tool_entry; size_t tool_list_entries(const tool_entry **out); /* ------------------------------------------------------------------ */ /* Display vtable: per-tool transcript rendering */ /* ------------------------------------------------------------------ */ /* * Presentation hooks for the built-in tools. A tool may supply a * `render_call` that renders the one-line transcript display for an * invocation from its raw args JSON (freshly allocated; return NULL to * fall back to the generic `# name ` line). Tools without an * entry (e.g. MCP tools) always use the generic line. `dim_result` * marks the tool's result as shell-style (the UI renders it muted). */ typedef char *(*tool_render_call)(const char *args_json); typedef struct { const char *name; tool_render_call render_call; /* NULL -> generic display */ bool dim_result; } tool_display; /* The vtable entry for a built-in tool (borrowed; valid for the * process lifetime), or NULL when `name` is not a built-in tool. */ const tool_display *tool_display_for(const char *name); /* Built-in tool registry (single source of truth; llm.h builds the * provider tool schemas and the default preamble from it). */ size_t tool_builtin_count(void); const char *tool_builtin_name(size_t i); const char *tool_desc(const char *name); /* schema description; "" if unknown */ cJSON *tool_params_json(const char *name); /* fresh object; caller frees */ char *tool_preamble_list(void); /* "Available tools:" section; caller frees */ #endif