Spaces:
Runtime error
Runtime error
| //! Spec-Kit Init Tool | |
| //! | |
| //! Initializes a new spec-kit project. | |
| use anyhow::{Context, Result}; | |
| use async_trait::async_trait; | |
| use serde::{Deserialize, Serialize}; | |
| use serde_json::{json, Value}; | |
| use std::path::PathBuf; | |
| use crate::mcp::types::{ContentBlock, ToolDefinition, ToolResult}; | |
| use crate::speckit::SpecKitCli; | |
| use crate::tools::Tool; | |
| /// Parameters for the speckit_init tool | |
| pub struct InitParams { | |
| /// Project name | |
| project_name: String, | |
| /// Project path (defaults to current directory) | |
| project_path: PathBuf, | |
| } | |
| fn default_project_path() -> PathBuf { | |
| PathBuf::from(".") | |
| } | |
| /// Tool for initializing spec-kit projects | |
| pub struct InitTool { | |
| cli: SpecKitCli, | |
| } | |
| impl InitTool { | |
| /// Create a new init tool | |
| pub fn new(cli: SpecKitCli) -> Self { | |
| Self { cli } | |
| } | |
| } | |
| impl Tool for InitTool { | |
| fn definition(&self) -> ToolDefinition { | |
| ToolDefinition { | |
| name: "speckit_init".to_string(), | |
| description: "Initialize a new spec-kit project with proper directory structure and configuration files".to_string(), | |
| input_schema: json!({ | |
| "type": "object", | |
| "properties": { | |
| "project_name": { | |
| "type": "string", | |
| "description": "Name of the project to initialize" | |
| }, | |
| "project_path": { | |
| "type": "string", | |
| "description": "Path where the project should be created", | |
| "default": "." | |
| } | |
| }, | |
| "required": ["project_name"] | |
| }) | |
| } | |
| } | |
| async fn execute(&self, params: Value) -> Result<ToolResult> { | |
| let params: InitParams = | |
| serde_json::from_value(params).context("Failed to parse init parameters")?; | |
| tracing::info!( | |
| project_name = %params.project_name, | |
| project_path = %params.project_path.display(), | |
| "Initializing spec-kit project" | |
| ); | |
| // Execute spec-kit init command | |
| let result = self | |
| .cli | |
| .init(¶ms.project_name, ¶ms.project_path) | |
| .await?; | |
| if !result.is_success() { | |
| return Ok(ToolResult { | |
| content: vec![ContentBlock::text(format!( | |
| "Failed to initialize project: {}", | |
| result.stderr | |
| ))], | |
| is_error: Some(true), | |
| }); | |
| } | |
| let message = format!( | |
| "Successfully initialized spec-kit project '{}' at {}\n\n\ | |
| Next steps:\n\ | |
| 1. Navigate to the project: cd {}\n\ | |
| 2. Create constitution: Use speckit_constitution tool\n\ | |
| 3. Define requirements: Use speckit_specify tool\n\ | |
| 4. Create technical plan: Use speckit_plan tool\n\ | |
| 5. Generate tasks: Use speckit_tasks tool\n\ | |
| 6. Implement: Use speckit_implement tool", | |
| params.project_name, | |
| params.project_path.display(), | |
| params.project_path.display() | |
| ); | |
| Ok(ToolResult { | |
| content: vec![ContentBlock::text(message)], | |
| is_error: None, | |
| }) | |
| } | |
| } | |
| mod tests { | |
| use super::*; | |
| use tempfile::tempdir; | |
| async fn test_init_tool_definition() { | |
| let cli = SpecKitCli::new(); | |
| let tool = InitTool::new(cli); | |
| let def = tool.definition(); | |
| assert_eq!(def.name, "speckit_init"); | |
| assert!(!def.description.is_empty()); | |
| } | |
| async fn test_init_tool_execute() { | |
| let cli = SpecKitCli::new_test_mode(); | |
| let tool = InitTool::new(cli); | |
| let dir = tempdir().unwrap(); | |
| let params = json!({ | |
| "project_name": "test-project", | |
| "project_path": dir.path().to_str().unwrap() | |
| }); | |
| let result = tool.execute(params).await.unwrap(); | |
| assert!(result.is_error.is_none() || !result.is_error.unwrap()); | |
| } | |
| } | |