feat: full tool call support (OpenAI + Gemini endpoints)

- store.rs: Add tool context storage (active tools, tool config, pending
  tool results, call_id mapping, last function calls for history rewrite)
- types.rs: Add tools/tool_choice fields to ResponsesRequest, add
  build_function_call_output helper for OpenAI function_call output items
- modify.rs: Replace hardcoded get_weather with dynamic ToolContext
  injection. Add openai_tools_to_gemini and openai_tool_choice_to_gemini
  converters. Add conversation history rewriting for tool result turns
  (replaces fake 'Tool call completed' model turn with real functionCall,
  injects functionResponse before last user turn)
- proxy.rs: Build ToolContext from MitmStore before calling modify_request.
  Save last_function_calls for history rewriting on subsequent turns
- responses.rs: Store client tools in MitmStore before LS call. Detect
  function_call_output in input array for tool result submission. Return
  captured functionCalls as OpenAI function_call output items with
  generated call_ids and stringified arguments
- gemini.rs: New Gemini-native endpoint (POST /v1/gemini) with zero
  format translation. Accepts functionDeclarations directly, returns
  functionCall in Gemini format directly
- mod.rs: Wire /v1/gemini route, bump version to 3.3.0
This commit is contained in:
Nikketryhard
2026-02-14 22:56:44 -06:00
parent 8455aa674f
commit 786987116b
8 changed files with 989 additions and 51 deletions

View File

@@ -32,6 +32,12 @@ pub(crate) struct ResponsesRequest {
pub metadata: Option<serde_json::Value>,
#[serde(default)]
pub user: Option<String>,
/// Tool definitions (OpenAI format).
#[serde(default)]
pub tools: Option<Vec<serde_json::Value>>,
/// Tool choice: "auto", "required", "none", or {"type":"function","function":{"name":"X"}}.
#[serde(default)]
pub tool_choice: Option<serde_json::Value>,
}
/// Chat Completions request (OpenAI-compatible).
@@ -220,6 +226,18 @@ pub fn build_message_output_in_progress(msg_id: &str) -> serde_json::Value {
})
}
/// Build a function_call output item (OpenAI Responses API format).
pub fn build_function_call_output(call_id: &str, name: &str, arguments: &str) -> serde_json::Value {
serde_json::json!({
"type": "function_call",
"id": call_id,
"call_id": call_id,
"name": name,
"arguments": arguments,
"status": "completed",
})
}
// ─── Helpers ─────────────────────────────────────────────────────────────────
/// Serialize Option<u64> as either the number or JSON null (not omitted).