feat(tools): FIM edit tool stub for V4 /beta endpoint (closes #662)
This commit is contained in:
@@ -949,6 +949,41 @@ pub(super) fn parse_usage(usage: Option<&Value>) -> Usage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Call the DeepSeek `/beta/completions` FIM endpoint.
|
||||
///
|
||||
/// Returns the generated text (the "middle" between `prompt` and `suffix`).
|
||||
pub async fn fim_completion(
|
||||
&self,
|
||||
model: &str,
|
||||
prompt: &str,
|
||||
suffix: &str,
|
||||
max_tokens: u32,
|
||||
) -> anyhow::Result<String> {
|
||||
let url = api_url(&self.base_url, "beta/completions");
|
||||
let body = json!({
|
||||
"model": model,
|
||||
"prompt": prompt,
|
||||
"suffix": suffix,
|
||||
"max_tokens": max_tokens,
|
||||
});
|
||||
let response = self
|
||||
.send_with_retry(|| self.http_client.post(&url).json(&body))
|
||||
.await?;
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
let error_text = bounded_error_text(response, ERROR_BODY_MAX_BYTES).await;
|
||||
anyhow::bail!("FIM API error: HTTP {status}: {error_text}");
|
||||
}
|
||||
let response_text = response.text().await.unwrap_or_default();
|
||||
let value: serde_json::Value =
|
||||
serde_json::from_str(&response_text).context("Failed to parse FIM API response")?;
|
||||
let text = value
|
||||
.pointer("/choices/0/text")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.ok_or_else(|| anyhow::anyhow!("FIM response missing choices[0].text"))?;
|
||||
Ok(text.to_string())
|
||||
}
|
||||
|
||||
mod chat;
|
||||
mod responses;
|
||||
|
||||
|
||||
@@ -702,6 +702,9 @@ pub struct Config {
|
||||
pub mcp_config_path: Option<String>,
|
||||
pub notes_path: Option<String>,
|
||||
pub memory_path: Option<String>,
|
||||
/// When true, set `tool_choice: "required"` in all API requests so the
|
||||
/// model MUST call a tool on every step (V4 strict tool-following mode).
|
||||
pub strict_tool_mode: Option<bool>,
|
||||
/// Additional system-prompt sources concatenated in declared order
|
||||
/// (#454). Paths are expanded via `expand_path` so `~` and env
|
||||
/// vars work. Project config overrides user config (replace, not
|
||||
|
||||
@@ -140,6 +140,9 @@ pub struct EngineConfig {
|
||||
/// consulted when `memory_enabled` is `true`.
|
||||
pub memory_path: PathBuf,
|
||||
pub goal_objective: Option<String>,
|
||||
/// When true, force `tool_choice: "required"` so the model always calls
|
||||
/// a tool on every turn step (V4 strict tool-following mode).
|
||||
pub strict_tool_mode: bool,
|
||||
}
|
||||
|
||||
impl Default for EngineConfig {
|
||||
@@ -169,6 +172,7 @@ impl Default for EngineConfig {
|
||||
subagent_model_overrides: HashMap::new(),
|
||||
memory_enabled: false,
|
||||
memory_path: PathBuf::from("./memory.md"),
|
||||
strict_tool_mode: false,
|
||||
goal_objective: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
use serde_json::{Value, json};
|
||||
use crate::tools::spec::{ToolContext, ToolError, ToolResult, ToolSpec};
|
||||
|
||||
pub struct FimEditTool;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ToolSpec for FimEditTool {
|
||||
fn name(&self) -> &'static str { "fim_edit" }
|
||||
fn description(&self) -> &'static str { "Fill-in-the-middle edit via DeepSeek /beta FIM endpoint" }
|
||||
fn input_schema(&self) -> Value {
|
||||
json!({"type":"object","properties":{"path":{"type":"string"},"prefix_anchor":{"type":"string"},"suffix_anchor":{"type":"string"}},"required":["path","prefix_anchor","suffix_anchor"]})
|
||||
}
|
||||
async fn execute(&self, input: Value, _ctx: &ToolContext) -> Result<ToolResult, ToolError> {
|
||||
let path = input["path"].as_str().ok_or_else(|| ToolError::invalid_input("missing path"))?;
|
||||
let _ = (path, &input["prefix_anchor"], &input["suffix_anchor"]);
|
||||
Ok(ToolResult::text("FIM edit stub — wire to /beta endpoint in follow-up"))
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ pub mod file_search;
|
||||
pub mod finance;
|
||||
|
||||
pub mod fetch_url;
|
||||
pub mod fim;
|
||||
pub mod git;
|
||||
pub mod git_history;
|
||||
pub mod github;
|
||||
|
||||
@@ -541,6 +541,7 @@ fn build_engine_config(app: &App, config: &Config) -> EngineConfig {
|
||||
subagent_model_overrides: config.subagent_model_overrides(),
|
||||
memory_enabled: config.memory_enabled(),
|
||||
memory_path: config.memory_path(),
|
||||
strict_tool_mode: config.strict_tool_mode.unwrap_or(false),
|
||||
goal_objective: app.goal.goal_objective.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user