// Request builder to construct Anthropic Message API requests // Ported from old_repo/services/api/claude.ts import "dart:io"; import "api_types.dart"; // builds a message api request with all the standard options class MessageRequestBuilder { final String model; final int maxTokens; final List> messages; String? _systemPrompt; double? _temperature; List>? _tools; String? _toolChoice; Map? _metadata; MessageRequestBuilder({ required this.model, required this.maxTokens, required this.messages, }); MessageRequestBuilder withSystem(String system) { _systemPrompt = system; return this; } MessageRequestBuilder withTemperature(double temp) { _temperature = temp; return this; } MessageRequestBuilder withTools(List> tools) { _tools = tools; return this; } MessageRequestBuilder withToolChoice(String choice) { _toolChoice = choice; return this; } MessageRequestBuilder withMetadata(Map metadata) { _metadata = metadata; return this; } MessageRequest build() { return MessageRequest( model: model, maxTokens: maxTokens, messages: messages, systemPrompt: _systemPrompt, temperature: _temperature, tools: _tools, toolChoice: _toolChoice, metadata: _metadata, ); } } // helpers to add headers for API requests class HeaderBuilder { final Map _headers = {}; HeaderBuilder() { _initializeDefaultHeaders(); } void _initializeDefaultHeaders() { // Add standard headers for API requests final env = Platform.environment; // Session tracking if (env.containsKey("CLAUDE_CODE_SESSION_ID")) { _headers["X-Claude-Code-Session-Id"] = env["CLAUDE_CODE_SESSION_ID"]!; } // Remote tracking (if in a container) if (env.containsKey("CLAUDE_CODE_CONTAINER_ID")) { _headers["x-claude-remote-container-id"] = env["CLAUDE_CODE_CONTAINER_ID"]!; } if (env.containsKey("CLAUDE_CODE_REMOTE_SESSION_ID")) { _headers["x-claude-remote-session-id"] = env["CLAUDE_CODE_REMOTE_SESSION_ID"]!; } // App identifier _headers["x-app"] = "cli"; // User agent from utils would go here (TODO when http client created) _headers["User-Agent"] = "clawd_code/0.1.0"; } void addCustomHeader(String name, String value) { _headers[name] = value; } void addAuthHeader(String apiKey) { _headers["Authorization"] = "Bearer $apiKey"; } void addOpenRouterHeaders() { _headers["HTTP-Referer"] = "clawd_code"; _headers["X-Title"] = "clawd_code"; } // parse custom headers from env var (newline or semicolon separated) void addCustomHeadersFromEnv() { final env = Platform.environment; final customHeadersEnv = env["ANTHROPIC_CUSTOM_HEADERS"]; if (customHeadersEnv == null || customHeadersEnv.isEmpty) return; final headerStrings = customHeadersEnv.split(RegExp(r"\n|\r\n")); for (final headerString in headerStrings) { if (headerString.trim().isEmpty) continue; // parse "Name: Value" format, split on first colon final colonIdx = headerString.indexOf(":"); if (colonIdx == -1) continue; final name = headerString.substring(0, colonIdx).trim(); final value = headerString.substring(colonIdx + 1).trim(); if (name.isNotEmpty) { _headers[name] = value; } } } Map build() { return Map.unmodifiable(_headers); } } // builds user and assistant message objects for the API class MessageBuilder { // create a user message static Map createUserMessage(String content) { return { "role": "user", "content": content, }; } // create a user message with mixed content (text + tool results) static Map createUserMessageWithContent( List> contentBlocks, ) { return { "role": "user", "content": contentBlocks, }; } // create assistant message with text content static Map createAssistantMessage(String content) { return { "role": "assistant", "content": [ { "type": "text", "text": content, } ], }; } // create assistant message with tool use static Map createAssistantMessageWithToolUse( String toolId, String toolName, Map toolInput, ) { return { "role": "assistant", "content": [ { "type": "tool_use", "id": toolId, "name": toolName, "input": toolInput, } ], }; } // add tool result to existing user message static Map createToolResultContent( String toolUseId, String content, ) { return { "type": "tool_result", "tool_use_id": toolUseId, "content": content, }; } } // normalize message content for sending to API List> normalizeMessagesForApi( List> messages, ) { // basic validation and normalization // in real implementation would handle various message formats return messages; } // normalize content from api response dynamic normalizeContentFromApi(dynamic content) { if (content is! List) return content; // ensure all blocks have proper types return List.from(content); }