huskies: merge 1032

This commit is contained in:
dave
2026-05-14 14:41:45 +00:00
parent bc99821274
commit 960b4f4d1d
9 changed files with 606 additions and 44 deletions
+3 -8
View File
@@ -66,14 +66,9 @@ pub(crate) async fn tool_rebuild_and_restart(ctx: &AppContext) -> Result<String,
/// WebSocket session, which presents a dialog to the user. Blocks until the
/// user approves or denies (with a 5-minute timeout).
pub(crate) fn tool_move_story(args: &Value, _ctx: &AppContext) -> Result<String, String> {
let story_id = args
.get("story_id")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: story_id")?;
let target_stage = args
.get("target_stage")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: target_stage")?;
let req = crate::validation::MoveStoryRequest::from_json(args)?;
let story_id = req.story_id.as_str();
let target_stage = req.target_stage.as_str();
let (from_stage, to_stage) = move_story_to_stage(story_id, target_stage)?;
@@ -435,7 +435,7 @@ mod tests {
&ctx,
);
assert!(result.is_err());
assert!(result.unwrap_err().contains("Invalid target_stage"));
assert!(result.unwrap_err().contains("InvalidValue"));
}
#[test]
+3 -8
View File
@@ -142,14 +142,9 @@ pub(super) async fn tool_move_story_to_merge(
args: &Value,
ctx: &AppContext,
) -> Result<String, String> {
let story_id = args
.get("story_id")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: story_id")?;
let agent_name = args
.get("agent_name")
.and_then(|v| v.as_str())
.unwrap_or("mergemaster");
let req = crate::validation::MoveStoryToMergeRequest::from_json(args)?;
let story_id = req.story_id.as_str();
let agent_name = req.resolved_agent_name();
let project_root = ctx.services.agents.get_project_root(&ctx.state)?;
@@ -9,10 +9,8 @@ use serde_json::Value;
/// Accepts a `story_id` (full filename stem, e.g. `"42_story_foo"`) and
/// delegates to [`service::work_item::freeze::freeze`].
pub(crate) fn tool_freeze_story(args: &Value, _ctx: &AppContext) -> Result<String, String> {
let story_id = args
.get("story_id")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: story_id")?;
let req = crate::validation::FreezeStoryRequest::from_json(args)?;
let story_id = req.story_id.as_str();
match crate::service::work_item::freeze::freeze(story_id)? {
FreezeStatus::AlreadyFrozen => Ok(format!("Story '{story_id}' is already frozen.")),
@@ -27,10 +25,8 @@ pub(crate) fn tool_freeze_story(args: &Value, _ctx: &AppContext) -> Result<Strin
/// Accepts a `story_id` (full filename stem, e.g. `"42_story_foo"`) and
/// delegates to [`service::work_item::freeze::unfreeze`].
pub(crate) fn tool_unfreeze_story(args: &Value, _ctx: &AppContext) -> Result<String, String> {
let story_id = args
.get("story_id")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: story_id")?;
let req = crate::validation::FreezeStoryRequest::from_json(args)?;
let story_id = req.story_id.as_str();
match crate::service::work_item::freeze::unfreeze(story_id)? {
UnfreezeStatus::NotFrozen => Ok(format!(
@@ -218,23 +218,11 @@ pub(crate) fn tool_update_story(args: &Value, ctx: &AppContext) -> Result<String
}
pub(crate) fn tool_unblock_story(args: &Value, ctx: &AppContext) -> Result<String, String> {
let story_id = args
.get("story_id")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: story_id")?;
let req = crate::validation::UnblockStoryRequest::from_json(args)?;
let root = ctx.state.get_project_root()?;
// Extract the numeric prefix (e.g. "42" from "42" or from legacy "42_story_foo").
let story_number = story_id
.split('_')
.next()
.filter(|s| !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()))
.ok_or_else(|| {
format!("Invalid story_id format: '{story_id}'. Expected a numeric ID (e.g. '42').")
})?;
let result = crate::chat::commands::unblock::unblock_by_number(&root, story_number);
let result =
crate::chat::commands::unblock::unblock_by_number(&root, req.story_id.numeric_prefix());
if result.contains("not blocked")
|| result.contains("not found")
|| result.contains("Error")