-module(claude). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/claude.gleam"). -export([version/0, new/1, from_env/0, run/3, run_with_config/2, message/2, text_content/1, result_text/1]). -export_type([env_error/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type env_error() :: env_var_not_set | env_var_empty. -file("src/claude.gleam", 22). ?DOC(" The current SDK version.\n"). -spec version() -> binary(). version() -> <<"1.0.0"/utf8>>. -file("src/claude.gleam", 38). ?DOC( " Create a new client configuration with the given API key.\n" "\n" " Uses sensible defaults:\n" " - base_url: \"https://api.anthropic.com\"\n" " - model: \"claude-sonnet-4-5-20250929\"\n" " - max_tokens: 4096\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let client = claude.new(\"sk-ant-...\")\n" " ```\n" ). -spec new(binary()) -> claude@client:config(). new(Api_key) -> claude@client:new(Api_key). -file("src/claude.gleam", 52). ?DOC( " Create a client configuration from the ANTHROPIC_API_KEY environment variable.\n" "\n" " Returns `Error(EnvVarNotSet)` if the environment variable is not set,\n" " or `Error(EnvVarEmpty)` if it is set but empty.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let assert Ok(client) = claude.from_env()\n" " ```\n" ). -spec from_env() -> {ok, claude@client:config()} | {error, env_error()}. from_env() -> case claude_ffi:get_env(<<"ANTHROPIC_API_KEY"/utf8>>) of {ok, Key} -> case gleam@string:is_empty(Key) of true -> {error, env_var_empty}; false -> {ok, claude@client:new(Key)} end; {error, _} -> {error, env_var_not_set} end. -file("src/claude.gleam", 86). ?DOC( " Run an agent loop with the given tool registry.\n" "\n" " This is the primary entry point for running an agentic workflow.\n" " The agent sends the prompt to the API, and if the model responds with\n" " tool calls, it executes them using the typed tools in the registry and\n" " feeds the results back. This continues until the model stops calling\n" " tools or the maximum number of iterations is reached.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let client = claude.new(\"sk-ant-...\")\n" " let tools = tool.registry()\n" " |> tool.register(weather_tool())\n" "\n" " case claude.run(client, \"What's the weather in SF?\", tools) {\n" " Ok(result) -> io.println(claude.result_text(result))\n" " Error(err) -> io.println(\"Error!\")\n" " }\n" " ```\n" ). -spec run(claude@client:config(), binary(), claude@types@tool:registry()) -> {ok, claude@agent:agent_result()} | {error, claude@agent:agent_error()}. run(Client, Prompt, Tools) -> Cfg = claude@agent@config:new(Client, Tools), claude@agent:run(Cfg, Prompt). -file("src/claude.gleam", 117). ?DOC( " Run an agent loop with a fully customized configuration.\n" "\n" " Use this when you need to set system prompts, custom models,\n" " thinking budgets, or other advanced options.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let tools = tool.registry()\n" " |> tool.register(weather_tool())\n" "\n" " let cfg =\n" " config.new(client: client, tools: tools)\n" " |> config.with_system(\"You are a helpful assistant.\")\n" " |> config.with_model(\"claude-opus-4-5-20250929\")\n" " |> config.with_max_iterations(5)\n" "\n" " case claude.run_with_config(cfg, \"Analyze this data\") {\n" " Ok(result) -> io.println(claude.result_text(result))\n" " Error(_) -> io.println(\"Error!\")\n" " }\n" " ```\n" ). -spec run_with_config(claude@agent@config:agent_config(), binary()) -> {ok, claude@agent:agent_result()} | {error, claude@agent:agent_error()}. run_with_config(Config, Prompt) -> claude@agent:run(Config, Prompt). -file("src/claude.gleam", 138). ?DOC( " Send a single message to the API without the agent loop.\n" "\n" " This is useful for simple one-shot interactions where tool use\n" " is not needed.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let client = claude.new(\"sk-ant-...\")\n" " case claude.message(client, \"What is 2 + 2?\") {\n" " Ok(msg) -> io.println(claude.text_content(msg))\n" " Error(_) -> io.println(\"API error\")\n" " }\n" " ```\n" ). -spec message(claude@client:config(), binary()) -> {ok, claude@types@message:message()} | {error, claude@types@error:api_error()}. message(Client, Prompt) -> claude@messages:create( {request_params, Client, none, none, [claude@types@message:new_user(Prompt)], claude@types@tool:registry(), none, none, none} ). -file("src/claude.gleam", 165). ?DOC( " Extract and concatenate all text content blocks from a message.\n" "\n" " Tool use blocks, thinking blocks, and other non-text blocks are ignored.\n" " Multiple text blocks are joined with newlines.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let assert Ok(msg) = claude.message(client, \"Hello!\")\n" " io.println(claude.text_content(msg))\n" " ```\n" ). -spec text_content(claude@types@message:message()) -> binary(). text_content(Msg) -> _pipe = erlang:element(4, Msg), _pipe@1 = gleam@list:filter_map(_pipe, fun(Block) -> case Block of {text, T, _} -> {ok, T}; _ -> {error, nil} end end), gleam@string:join(_pipe@1, <<"\n"/utf8>>). -file("src/claude.gleam", 187). ?DOC( " Extract the text content from an agent result's final message.\n" "\n" " This is a convenience function that applies `text_content` to the\n" " result's final message.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let assert Ok(result) = claude.run(client, \"Hello\", tools)\n" " io.println(claude.result_text(result))\n" " ```\n" ). -spec result_text(claude@agent:agent_result()) -> binary(). result_text(Result) -> text_content(erlang:element(3, Result)).