The great storkit name conversion

This commit is contained in:
Dave
2026-03-20 12:26:02 +00:00
parent 51d878e117
commit c4e45b2841
25 changed files with 1522 additions and 1333 deletions

View File

@@ -160,8 +160,7 @@ struct AllTokenUsageResponse {
pub fn story_is_archived(project_root: &path::Path, story_id: &str) -> bool {
let work = project_root.join(".storkit").join("work");
let filename = format!("{story_id}.md");
work.join("5_done").join(&filename).exists()
|| work.join("6_archived").join(&filename).exists()
work.join("5_done").join(&filename).exists() || work.join("6_archived").join(&filename).exists()
}
pub struct AgentsApi {
@@ -215,11 +214,7 @@ impl AgentsApi {
self.ctx
.agents
.stop_agent(
&project_root,
&payload.0.story_id,
&payload.0.agent_name,
)
.stop_agent(&project_root, &payload.0.story_id, &payload.0.agent_name)
.await
.map_err(bad_request)?;
@@ -258,9 +253,7 @@ impl AgentsApi {
/// Get the configured agent roster from project.toml.
#[oai(path = "/agents/config", method = "get")]
async fn get_agent_config(
&self,
) -> OpenApiResult<Json<Vec<AgentConfigInfoResponse>>> {
async fn get_agent_config(&self) -> OpenApiResult<Json<Vec<AgentConfigInfoResponse>>> {
let project_root = self
.ctx
.agents
@@ -288,9 +281,7 @@ impl AgentsApi {
/// Reload project config and return the updated agent roster.
#[oai(path = "/agents/config/reload", method = "post")]
async fn reload_config(
&self,
) -> OpenApiResult<Json<Vec<AgentConfigInfoResponse>>> {
async fn reload_config(&self) -> OpenApiResult<Json<Vec<AgentConfigInfoResponse>>> {
let project_root = self
.ctx
.agents
@@ -440,10 +431,8 @@ impl AgentsApi {
.get_project_root(&self.ctx.state)
.map_err(bad_request)?;
let file_results = crate::http::workflow::read_test_results_from_story_file(
&project_root,
&story_id.0,
);
let file_results =
crate::http::workflow::read_test_results_from_story_file(&project_root, &story_id.0);
Ok(Json(
file_results.map(|r| TestResultsResponse::from_story_results(&r)),
@@ -467,8 +456,7 @@ impl AgentsApi {
.get_project_root(&self.ctx.state)
.map_err(bad_request)?;
let log_path =
crate::agent_log::find_latest_log(&project_root, &story_id.0, &agent_name.0);
let log_path = crate::agent_log::find_latest_log(&project_root, &story_id.0, &agent_name.0);
let Some(path) = log_path else {
return Ok(Json(AgentOutputResponse {
@@ -480,10 +468,13 @@ impl AgentsApi {
let output: String = entries
.iter()
.filter(|e| {
e.event.get("type").and_then(|t| t.as_str()) == Some("output")
.filter(|e| e.event.get("type").and_then(|t| t.as_str()) == Some("output"))
.filter_map(|e| {
e.event
.get("text")
.and_then(|t| t.as_str())
.map(str::to_owned)
})
.filter_map(|e| e.event.get("text").and_then(|t| t.as_str()).map(str::to_owned))
.collect();
Ok(Json(AgentOutputResponse { output }))
@@ -562,9 +553,7 @@ impl AgentsApi {
///
/// Returns the full history from the persistent token_usage.jsonl log.
#[oai(path = "/token-usage", method = "get")]
async fn get_all_token_usage(
&self,
) -> OpenApiResult<Json<AllTokenUsageResponse>> {
async fn get_all_token_usage(&self) -> OpenApiResult<Json<AllTokenUsageResponse>> {
let project_root = self
.ctx
.agents
@@ -659,9 +648,7 @@ mod tests {
ctx.agents
.inject_test_agent("80_story_active", "coder-1", AgentStatus::Running);
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.list_agents().await.unwrap().0;
// Archived story's agent should not appear
@@ -686,9 +673,7 @@ mod tests {
ctx.agents
.inject_test_agent("42_story_whatever", "coder-1", AgentStatus::Completed);
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.list_agents().await.unwrap().0;
assert!(result.iter().any(|a| a.story_id == "42_story_whatever"));
}
@@ -705,9 +690,7 @@ mod tests {
async fn get_agent_config_returns_default_when_no_toml() {
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.get_agent_config().await.unwrap().0;
// Default config has one agent named "default"
assert_eq!(result.len(), 1);
@@ -734,9 +717,7 @@ model = "haiku"
"#,
);
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.get_agent_config().await.unwrap().0;
assert_eq!(result.len(), 2);
assert_eq!(result[0].name, "coder-1");
@@ -753,9 +734,7 @@ model = "haiku"
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.get_agent_config().await;
assert!(result.is_err());
}
@@ -766,9 +745,7 @@ model = "haiku"
async fn reload_config_returns_default_when_no_toml() {
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.reload_config().await.unwrap().0;
assert_eq!(result.len(), 1);
assert_eq!(result[0].name, "default");
@@ -788,9 +765,7 @@ allowed_tools = ["Read", "Bash"]
"#,
);
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.reload_config().await.unwrap().0;
assert_eq!(result.len(), 1);
assert_eq!(result[0].name, "supervisor");
@@ -807,9 +782,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.reload_config().await;
assert!(result.is_err());
}
@@ -820,9 +793,7 @@ allowed_tools = ["Read", "Bash"]
async fn list_worktrees_returns_empty_when_no_worktree_dir() {
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.list_worktrees().await.unwrap().0;
assert!(result.is_empty());
}
@@ -835,9 +806,7 @@ allowed_tools = ["Read", "Bash"]
std::fs::create_dir_all(worktrees_dir.join("43_story_bar")).unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let mut result = api.list_worktrees().await.unwrap().0;
result.sort_by(|a, b| a.story_id.cmp(&b.story_id));
@@ -851,9 +820,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.list_worktrees().await;
assert!(result.is_err());
}
@@ -865,9 +832,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.stop_agent(Json(StopAgentPayload {
story_id: "42_story_foo".to_string(),
@@ -881,9 +846,7 @@ allowed_tools = ["Read", "Bash"]
async fn stop_agent_returns_error_when_agent_not_found() {
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.stop_agent(Json(StopAgentPayload {
story_id: "nonexistent_story".to_string(),
@@ -899,9 +862,7 @@ allowed_tools = ["Read", "Bash"]
let ctx = AppContext::new_test(tmp.path().to_path_buf());
ctx.agents
.inject_test_agent("42_story_foo", "coder-1", AgentStatus::Running);
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.stop_agent(Json(StopAgentPayload {
story_id: "42_story_foo".to_string(),
@@ -920,9 +881,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.start_agent(Json(StartAgentPayload {
story_id: "42_story_foo".to_string(),
@@ -949,9 +908,7 @@ allowed_tools = ["Read", "Bash"]
)
.unwrap();
let ctx = AppContext::new_test(root.to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_work_item_content(Path("42_story_foo".to_string()))
.await
@@ -973,9 +930,7 @@ allowed_tools = ["Read", "Bash"]
)
.unwrap();
let ctx = AppContext::new_test(root.to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_work_item_content(Path("43_story_bar".to_string()))
.await
@@ -989,9 +944,7 @@ allowed_tools = ["Read", "Bash"]
async fn get_work_item_content_returns_not_found_when_absent() {
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_work_item_content(Path("99_story_nonexistent".to_string()))
.await;
@@ -1003,9 +956,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_work_item_content(Path("42_story_foo".to_string()))
.await;
@@ -1018,9 +969,7 @@ allowed_tools = ["Read", "Bash"]
async fn get_agent_output_returns_empty_when_no_log_exists() {
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_agent_output(
Path("42_story_foo".to_string()),
@@ -1040,8 +989,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let root = tmp.path();
let mut writer =
AgentLogWriter::new(root, "42_story_foo", "coder-1", "sess-test").unwrap();
let mut writer = AgentLogWriter::new(root, "42_story_foo", "coder-1", "sess-test").unwrap();
writer
.write_event(&AgentEvent::Status {
@@ -1073,9 +1021,7 @@ allowed_tools = ["Read", "Bash"]
.unwrap();
let ctx = AppContext::new_test(root.to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_agent_output(
Path("42_story_foo".to_string()),
@@ -1094,9 +1040,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_agent_output(
Path("42_story_foo".to_string()),
@@ -1113,9 +1057,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.create_worktree(Json(CreateWorktreePayload {
story_id: "42_story_foo".to_string(),
@@ -1129,9 +1071,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
// project_root is set but has no git repo — git worktree add will fail
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.create_worktree(Json(CreateWorktreePayload {
story_id: "42_story_foo".to_string(),
@@ -1147,12 +1087,8 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let ctx = AppContext::new_test(tmp.path().to_path_buf());
*ctx.state.project_root.lock().unwrap() = None;
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let result = api
.remove_worktree(Path("42_story_foo".to_string()))
.await;
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api.remove_worktree(Path("42_story_foo".to_string())).await;
assert!(result.is_err());
}
@@ -1161,9 +1097,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
// project_root is set but no worktree exists for this story_id
let ctx = AppContext::new_test(tmp.path().to_path_buf());
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.remove_worktree(Path("nonexistent_story".to_string()))
.await;
@@ -1177,9 +1111,7 @@ allowed_tools = ["Read", "Bash"]
let tmp = TempDir::new().unwrap();
let root = make_work_dirs(&tmp);
let ctx = AppContext::new_test(root);
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_test_results(Path("42_story_foo".to_string()))
.await
@@ -1214,9 +1146,7 @@ allowed_tools = ["Read", "Bash"]
.unwrap();
}
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_test_results(Path("42_story_foo".to_string()))
.await
@@ -1255,7 +1185,7 @@ name: "Test story"
## Test Results
<!-- story-kit-test-results: {"unit":[{"name":"from_file","status":"pass","details":null}],"integration":[]} -->
<!-- storkit-test-results: {"unit":[{"name":"from_file","status":"pass","details":null}],"integration":[]} -->
"#;
std::fs::write(
root.join(".storkit/work/2_current/42_story_foo.md"),
@@ -1264,9 +1194,7 @@ name: "Test story"
.unwrap();
let ctx = AppContext::new_test(root);
let api = AgentsApi {
ctx: Arc::new(ctx),
};
let api = AgentsApi { ctx: Arc::new(ctx) };
let result = api
.get_test_results(Path("42_story_foo".to_string()))
.await