huskies: merge 585_bug_bot_not_aware_of_actual_running_port_defaults_to_3001
This commit is contained in:
@@ -349,13 +349,14 @@ pub(super) fn tool_dump_crdt(args: &Value) -> Result<String, String> {
|
|||||||
.map_err(|e| format!("Serialization error: {e}"))
|
.map_err(|e| format!("Serialization error: {e}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MCP tool: return the server version and build hash.
|
/// MCP tool: return the server version, build hash, and running port.
|
||||||
pub(super) fn tool_get_version() -> Result<String, String> {
|
pub(super) fn tool_get_version(ctx: &AppContext) -> Result<String, String> {
|
||||||
let build_hash =
|
let build_hash =
|
||||||
std::fs::read_to_string(".huskies/build_hash").unwrap_or_else(|_| "unknown".to_string());
|
std::fs::read_to_string(".huskies/build_hash").unwrap_or_else(|_| "unknown".to_string());
|
||||||
serde_json::to_string_pretty(&json!({
|
serde_json::to_string_pretty(&json!({
|
||||||
"version": env!("CARGO_PKG_VERSION"),
|
"version": env!("CARGO_PKG_VERSION"),
|
||||||
"build_hash": build_hash.trim(),
|
"build_hash": build_hash.trim(),
|
||||||
|
"port": ctx.agents.port(),
|
||||||
}))
|
}))
|
||||||
.map_err(|e| format!("Serialization error: {e}"))
|
.map_err(|e| format!("Serialization error: {e}"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -897,7 +897,7 @@ fn handle_tools_list(id: Option<Value>) -> JsonRpcResponse {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "get_version",
|
"name": "get_version",
|
||||||
"description": "Return the server version and build hash.",
|
"description": "Return the server version, build hash, and running port.",
|
||||||
"inputSchema": {
|
"inputSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {}
|
"properties": {}
|
||||||
@@ -1330,7 +1330,7 @@ async fn handle_tools_call(id: Option<Value>, params: &Value, ctx: &AppContext)
|
|||||||
"get_pipeline_status" => story_tools::tool_get_pipeline_status(ctx),
|
"get_pipeline_status" => story_tools::tool_get_pipeline_status(ctx),
|
||||||
// Diagnostics
|
// Diagnostics
|
||||||
"get_server_logs" => diagnostics::tool_get_server_logs(&args),
|
"get_server_logs" => diagnostics::tool_get_server_logs(&args),
|
||||||
"get_version" => diagnostics::tool_get_version(),
|
"get_version" => diagnostics::tool_get_version(ctx),
|
||||||
// Server lifecycle
|
// Server lifecycle
|
||||||
"rebuild_and_restart" => diagnostics::tool_rebuild_and_restart(ctx).await,
|
"rebuild_and_restart" => diagnostics::tool_rebuild_and_restart(ctx).await,
|
||||||
// Permission bridge (Claude Code → frontend dialog)
|
// Permission bridge (Claude Code → frontend dialog)
|
||||||
|
|||||||
+21
-11
@@ -37,6 +37,13 @@ pub(crate) async fn ensure_project_root_with_story_kit(
|
|||||||
if !path.join(".huskies").is_dir() {
|
if !path.join(".huskies").is_dir() {
|
||||||
scaffold_story_kit(&path, port)?;
|
scaffold_story_kit(&path, port)?;
|
||||||
}
|
}
|
||||||
|
// Always update .mcp.json with the current port so the bot connects to
|
||||||
|
// the right endpoint even when HUSKIES_PORT changes between restarts.
|
||||||
|
let mcp_content = format!(
|
||||||
|
"{{\n \"mcpServers\": {{\n \"huskies\": {{\n \"type\": \"http\",\n \"url\": \"http://localhost:{port}/mcp\"\n }}\n }}\n}}\n"
|
||||||
|
);
|
||||||
|
fs::write(path.join(".mcp.json"), mcp_content)
|
||||||
|
.map_err(|e| format!("Failed to write .mcp.json: {}", e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@@ -194,16 +201,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn open_project_does_not_overwrite_existing_mcp_json() {
|
async fn open_project_updates_mcp_json_with_current_port() {
|
||||||
// scaffold must NOT overwrite .mcp.json when it already exists — QA
|
// .mcp.json must always be updated with the actual running port so the
|
||||||
// test servers share the real project root, and re-writing would
|
// bot connects to the right MCP endpoint even when HUSKIES_PORT changes.
|
||||||
// clobber the file with the wrong port.
|
|
||||||
let dir = tempdir().unwrap();
|
let dir = tempdir().unwrap();
|
||||||
let project_dir = dir.path().join("myproject");
|
let project_dir = dir.path().join("myproject");
|
||||||
fs::create_dir_all(&project_dir).unwrap();
|
fs::create_dir_all(&project_dir).unwrap();
|
||||||
// Pre-write .mcp.json with a different port to simulate an already-configured project.
|
// Pre-write .mcp.json with a different port to simulate a stale file.
|
||||||
let mcp_path = project_dir.join(".mcp.json");
|
let mcp_path = project_dir.join(".mcp.json");
|
||||||
fs::write(&mcp_path, "{\"existing\": true}").unwrap();
|
fs::write(&mcp_path, "{\"stale\": true}").unwrap();
|
||||||
let store = make_store(&dir);
|
let store = make_store(&dir);
|
||||||
let state = SessionState::default();
|
let state = SessionState::default();
|
||||||
|
|
||||||
@@ -211,15 +217,19 @@ mod tests {
|
|||||||
project_dir.to_string_lossy().to_string(),
|
project_dir.to_string_lossy().to_string(),
|
||||||
&state,
|
&state,
|
||||||
&store,
|
&store,
|
||||||
3001,
|
3002,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
let content = fs::read_to_string(&mcp_path).unwrap();
|
||||||
fs::read_to_string(&mcp_path).unwrap(),
|
assert!(
|
||||||
"{\"existing\": true}",
|
content.contains("3002"),
|
||||||
"open_project must not overwrite an existing .mcp.json"
|
"open_project must update .mcp.json with the actual running port"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
content.contains("localhost"),
|
||||||
|
"mcp.json must reference localhost"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user