diff --git a/crates/codegen/kigi-acp-lib/src/channel.rs b/crates/codegen/kigi-acp-lib/src/channel.rs index 5b47689..314f5e4 100644 --- a/crates/codegen/kigi-acp-lib/src/channel.rs +++ b/crates/codegen/kigi-acp-lib/src/channel.rs @@ -68,7 +68,7 @@ mod acp_send_failure_tests { fn ext_request() -> acp::ExtRequest { acp::ExtRequest::new( - "x.ai/test", + "kigi/test", serde_json::value::to_raw_value(&serde_json::json!({})) .unwrap() .into(), diff --git a/crates/codegen/kigi-acp-lib/src/stdin_reader.rs b/crates/codegen/kigi-acp-lib/src/stdin_reader.rs index 629e178..bc64df3 100644 --- a/crates/codegen/kigi-acp-lib/src/stdin_reader.rs +++ b/crates/codegen/kigi-acp-lib/src/stdin_reader.rs @@ -1,6 +1,6 @@ //! Dedicated-thread reader for the ACP stdio transport's standard input. //! -//! Every ACP client (VS Code extension, grok-desktop, the leader bridge) drives +//! Every ACP client (VS Code extension, kigi-desktop, the leader bridge) drives //! the agent over a **persistent, bidirectional** newline-delimited JSON-RPC //! stream on stdio: it writes requests on the child's stdin and reads responses //! on stdout, keeping **stdin open for the whole session**. diff --git a/crates/codegen/kigi-agent-lifecycle/src/local/contributors/command.rs b/crates/codegen/kigi-agent-lifecycle/src/local/contributors/command.rs index 39f8771..854624e 100644 --- a/crates/codegen/kigi-agent-lifecycle/src/local/contributors/command.rs +++ b/crates/codegen/kigi-agent-lifecycle/src/local/contributors/command.rs @@ -4,7 +4,7 @@ use crate::send::contributors::command::{ CommandAction, CommandContributor, CommandInvocation, CommandSpec, }; -/// `?Send` twin of [`CommandContributor`] for single-threaded hosts like grok build's TUI agent, whose session state is `Rc`/`RefCell`-based and can +/// `?Send` twin of [`CommandContributor`] for single-threaded hosts like kigi build's TUI agent, whose session state is `Rc`/`RefCell`-based and can /// never satisfy the `Send` bounds the send flavor bakes into its boxed hook futures. #[async_trait(?Send)] pub trait LocalCommandContributor { diff --git a/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_input.rs b/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_input.rs index ad57ac6..82ffcfe 100644 --- a/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_input.rs +++ b/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_input.rs @@ -4,7 +4,7 @@ use crate::send::contributors::turn_input::{ TurnInputContext, TurnInputContributor, TurnInputFragment, }; -/// `?Send` twin of [`TurnInputContributor`] for single-threaded hosts like grok build's TUI agent, whose session state is `Rc`/`RefCell`-based +/// `?Send` twin of [`TurnInputContributor`] for single-threaded hosts like kigi build's TUI agent, whose session state is `Rc`/`RefCell`-based /// and can never satisfy the `Send` bounds the send flavor bakes into its boxed hook futures. #[async_trait(?Send)] pub trait LocalTurnInputContributor { diff --git a/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_lifecycle.rs b/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_lifecycle.rs index 890f3d4..9915fdc 100644 --- a/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_lifecycle.rs +++ b/crates/codegen/kigi-agent-lifecycle/src/local/contributors/turn_lifecycle.rs @@ -4,7 +4,7 @@ use crate::send::contributors::turn_lifecycle::{ TurnAbortInput, TurnDoneInput, TurnErrorInput, TurnLifecycleContributor, TurnStartInput, }; -/// `?Send` twin of [`TurnLifecycleContributor`] for single-threaded hosts like grok build's TUI +/// `?Send` twin of [`TurnLifecycleContributor`] for single-threaded hosts like kigi build's TUI /// agent, whose session state is `Rc`/`RefCell`-based and can never satisfy the `Send` bounds the /// send flavor bakes into its boxed hook futures. #[async_trait(?Send)] diff --git a/crates/codegen/kigi-agent/README.md b/crates/codegen/kigi-agent/README.md index 33ea023..80d5798 100644 --- a/crates/codegen/kigi-agent/README.md +++ b/crates/codegen/kigi-agent/README.md @@ -234,7 +234,7 @@ Agent definitions are discovered from multiple locations with priority: 2. **User-level**: `~/.kigi/agents/*.md` 3. **Compat paths** (lowest priority): additional vendor agent directories under the user home (when enabled) -4. **Built-in**: `default_grok_build()`, `browser_use()` +4. **Built-in**: `default_kigi()`, `browser_use()` Name-based dedup ensures the highest-priority definition wins. For example, a project `.kigi/agents/code-reviewer.md` shadows a @@ -275,7 +275,7 @@ user-level definition with the same name. | Name | Prompt Mode | Description | |---|---|---| -| `grok-build` | extend | Default agent for software engineering tasks | +| `kigi` | extend | Default agent for software engineering tasks | | `browser-use` | full | Web browsing and interaction agent | ## Error Handling diff --git a/crates/codegen/kigi-agent/src/builder.rs b/crates/codegen/kigi-agent/src/builder.rs index 40109fa..b7793c0 100644 --- a/crates/codegen/kigi-agent/src/builder.rs +++ b/crates/codegen/kigi-agent/src/builder.rs @@ -15,8 +15,8 @@ use kigi_tools::types::tool::ToolKind; use std::collections::HashMap; use std::path::PathBuf; use std::sync::Arc; -/// The Grok [`ToolKind`] a vendor-compat `tools:` allowlist entry resolves to, so -/// a plugin's upstream allowlist still binds. Backed by the shared vendor-to-Grok +/// The Kigi [`ToolKind`] a vendor-compat `tools:` allowlist entry resolves to, so +/// a plugin's upstream allowlist still binds. Backed by the shared vendor-to-Kigi /// tool registry in `kigi-tools` (also used by the hook matcher). fn claude_tool_kind(name: &str) -> Option { kigi_tools::types::kind_for(name) @@ -55,7 +55,7 @@ pub struct AgentBuilder { notification_handle: ToolNotificationHandle, owner_session_id: Option, parent_scheduler_handle: - Option, + Option, /// The agent definition — set via from_definition() or built up /// via individual with_*() calls. definition: Option, @@ -91,10 +91,10 @@ pub struct AgentBuilder { /// tools for execution by the agentic sampler, instead of being /// registered as local Function tools. backend_search: bool, - web_fetch_config: kigi_tools::implementations::grok_build::web_fetch::WebFetchConfig, + web_fetch_config: kigi_tools::implementations::kigi::web_fetch::WebFetchConfig, lsp: Option>, app_builder_deployer_config: - kigi_tools::implementations::grok_build::deploy_app::AppBuilderDeployerConfig, + kigi_tools::implementations::kigi::deploy_app::AppBuilderDeployerConfig, write_file_enabled: bool, subagents_enabled: bool, ask_user_question_enabled: bool, @@ -135,27 +135,21 @@ pub struct AgentBuilder { /// Ensure plan mode tools (`enter_plan_mode`, `exit_plan_mode`, /// `ask_user_question`) are present in the tool config. fn ensure_plan_mode_tools(tool_config: &mut kigi_tools::registry::types::ToolServerConfig) { - use kigi_tools::implementations::grok_build; + use kigi_tools::implementations::kigi; let existing: std::collections::HashSet<&str> = tool_config.tools.iter().map(|tc| tc.id.as_str()).collect(); - let missing_enter = !existing.contains("GrokBuild:enter_plan_mode"); - let missing_exit = !existing.contains("GrokBuild:exit_plan_mode"); - let missing_ask = !existing.contains("GrokBuild:ask_user_question"); + let missing_enter = !existing.contains("Kigi:enter_plan_mode"); + let missing_exit = !existing.contains("Kigi:exit_plan_mode"); + let missing_ask = !existing.contains("Kigi:ask_user_question"); drop(existing); if missing_enter { - tool_config - .tools - .push((&grok_build::EnterPlanModeTool).into()); + tool_config.tools.push((&kigi::EnterPlanModeTool).into()); } if missing_exit { - tool_config - .tools - .push((&grok_build::ExitPlanModeTool).into()); + tool_config.tools.push((&kigi::ExitPlanModeTool).into()); } if missing_ask { - tool_config - .tools - .push((&grok_build::AskUserQuestionTool).into()); + tool_config.tools.push((&kigi::AskUserQuestionTool).into()); } } /// Merge a shell-resolved params map into every matching tool's @@ -401,7 +395,7 @@ impl AgentBuilder { /// Share the parent's scheduler handle so scheduled tasks survive subagent exit. pub fn with_parent_scheduler_handle( mut self, - handle: kigi_tools::implementations::grok_build::scheduler::types::SchedulerHandle, + handle: kigi_tools::implementations::kigi::scheduler::types::SchedulerHandle, ) -> Self { self.parent_scheduler_handle = Some(handle); self @@ -435,7 +429,7 @@ impl AgentBuilder { /// `KIGI_WEB_FETCH` env var. pub fn with_web_fetch_config( mut self, - config: kigi_tools::implementations::grok_build::web_fetch::WebFetchConfig, + config: kigi_tools::implementations::kigi::web_fetch::WebFetchConfig, ) -> Self { self.web_fetch_config = config; self @@ -450,7 +444,7 @@ impl AgentBuilder { /// Set the deploy service configuration. pub fn with_app_builder_deployer_config( mut self, - config: kigi_tools::implementations::grok_build::deploy_app::AppBuilderDeployerConfig, + config: kigi_tools::implementations::kigi::deploy_app::AppBuilderDeployerConfig, ) -> Self { self.app_builder_deployer_config = config; self @@ -501,14 +495,14 @@ impl AgentBuilder { self.subagents_enabled = enabled; self } - /// Set public model slugs advertised in the GrokBuild Task description. + /// Set public model slugs advertised in the Kigi Task description. pub fn with_task_model_slugs(mut self, slugs: Vec) -> Self { self.task_model_slugs = slugs; self } /// Enable or disable the `ask_user_question` tool. /// - /// When disabled, `GrokBuild:ask_user_question` is stripped from the + /// When disabled, `Kigi:ask_user_question` is stripped from the /// agent's tool config after `ensure_plan_mode_tools` injection, so /// the model cannot ask the user structured questions regardless of /// which built-in profile is in use. Driven by the shell's resolved gate @@ -537,7 +531,7 @@ impl AgentBuilder { } /// Set the skills config (custom paths, ignore globs) from config.toml. /// Without this, only auto-discovered skills (cwd/.kigi/skills, ~/.kigi/skills) - /// are included — custom paths added via `x.ai/skills/add` would be ignored. + /// are included — custom paths added via `kigi/skills/add` would be ignored. pub fn with_skills_config(mut self, config: crate::prompt::skills::SkillsConfig) -> Self { self.skills_config = config; self @@ -585,7 +579,7 @@ impl AgentBuilder { if let Some(ref def) = self.definition { return def.clone(); } - let mut def = AgentDefinition::default_grok_build(); + let mut def = AgentDefinition::default_kigi(); if let Some(ref name) = self.name { def.name = name.clone(); } @@ -668,17 +662,17 @@ impl AgentBuilder { .push((&memory::get_tool::MemoryGetImpl).into()); } if self.web_search_config.is_enabled() { - use kigi_tools::implementations::grok_build; - tool_config.tools.push((&grok_build::WebSearchTool).into()); + use kigi_tools::implementations::kigi; + tool_config.tools.push((&kigi::WebSearchTool).into()); } if self.web_fetch_config.is_enabled() { - use kigi_tools::implementations::grok_build; - tool_config.tools.push((&grok_build::WebFetchTool).into()); + use kigi_tools::implementations::kigi; + tool_config.tools.push((&kigi::WebFetchTool).into()); } if self.lsp.is_some() { tool_config .tools - .push((&kigi_tools::implementations::grok_build::LspTool).into()); + .push((&kigi_tools::implementations::kigi::LspTool).into()); } let has_write_tool = tool_config .tools @@ -692,13 +686,13 @@ impl AgentBuilder { ensure_plan_mode_tools(&mut tool_config); } if self.memory_backend.is_none() { - let grok_build_ns = kigi_tools::types::tool::ToolNamespace::GrokBuild.to_string(); + let kigi_ns = kigi_tools::types::tool::ToolNamespace::Kigi.to_string(); let mem_search_id = format!( - "{grok_build_ns}:{}", + "{kigi_ns}:{}", kigi_tools::implementations::memory::MEMORY_SEARCH_TOOL_NAME ); let mem_get_id = format!( - "{grok_build_ns}:{}", + "{kigi_ns}:{}", kigi_tools::implementations::memory::MEMORY_GET_TOOL_NAME ); tool_config @@ -708,13 +702,13 @@ impl AgentBuilder { if !self.ask_user_question_enabled { let ask_user_id = format!( "{}:ask_user_question", - kigi_tools::types::tool::ToolNamespace::GrokBuild, + kigi_tools::types::tool::ToolNamespace::Kigi, ); tool_config.tools.retain(|tc| tc.id != ask_user_id); } let task_tool_id = format!( "{}:{}", - kigi_tools::types::tool::ToolNamespace::GrokBuild, + kigi_tools::types::tool::ToolNamespace::Kigi, "task" ); let mut task_stripped = false; @@ -762,8 +756,8 @@ impl AgentBuilder { .unwrap_or(true)) }) }; - if !has_satisfier(ToolNamespace::GrokBuild, "run_terminal_cmd", true) - && !has_satisfier(ToolNamespace::GrokBuildConcise, "run_terminal_cmd", true) + if !has_satisfier(ToolNamespace::Kigi, "run_terminal_cmd", true) + && !has_satisfier(ToolNamespace::KigiConcise, "run_terminal_cmd", true) && !has_satisfier(ToolNamespace::OpenCode, "bash", false) { let lifecycle = ["get_task_output", "wait_tasks", "kill_task"]; @@ -772,30 +766,22 @@ impl AgentBuilder { .retain(|tc| !lifecycle.contains(&short_tool_name(&tc.id))); } } - if let kigi_tools::implementations::grok_build::web_fetch::WebFetchConfig::Enabled { - ref params, - } = self.web_fetch_config + if let kigi_tools::implementations::kigi::web_fetch::WebFetchConfig::Enabled { ref params } = + self.web_fetch_config && let Ok(params_value) = serde_json::to_value(params) && let Some(obj) = params_value.as_object() { - merge_tool_params(&mut tool_config, &["GrokBuild:web_fetch"], obj); + merge_tool_params(&mut tool_config, &["Kigi:web_fetch"], obj); } if let Some(ref bash_params) = self.bash_params_json { merge_tool_params( &mut tool_config, - &[ - "GrokBuild:run_terminal_cmd", - "GrokBuildConcise:run_terminal_cmd", - ], + &["Kigi:run_terminal_cmd", "KigiConcise:run_terminal_cmd"], bash_params, ); } if let Some(ref ask_params) = self.ask_user_question_params_json { - merge_tool_params( - &mut tool_config, - &["GrokBuild:ask_user_question"], - ask_params, - ); + merge_tool_params(&mut tool_config, &["Kigi:ask_user_question"], ask_params); } if !definition.disallowed_tools.is_empty() { let before: std::collections::HashSet = @@ -878,7 +864,7 @@ impl AgentBuilder { tracing::warn!( agent = % definition.name, unresolved = ? unresolved, allowed = ? definition.tools, - "tools allowlist had unmappable entries; keeping full grok toolset" + "tools allowlist had unmappable entries; keeping full kigi toolset" ); } } @@ -1419,7 +1405,7 @@ mod tests { .contains("If the user does not explicitly request a model, omit `${{ params.task.model }}` to inherit the parent model.") ); assert!(!desc.contains("Available model slugs:")); - assert!(!desc.contains(concat!("grok", " models"))); + assert!(!desc.contains(concat!("kigi", " models"))); } #[test] fn build_task_description_handles_empty_model_catalog() { @@ -1431,7 +1417,7 @@ mod tests { let desc = build_task_description(&subagents, &[]); assert!(desc.contains("No explicit model slugs are currently available.")); assert!(desc.contains("Omit `${{ params.task.model }}` to inherit the parent model.")); - assert!(!desc.contains(concat!("grok", " models"))); + assert!(!desc.contains(concat!("kigi", " models"))); } #[test] fn task_model_guidance_resolves_model_param_override() { @@ -1525,62 +1511,62 @@ mod tests { } let cases: &[PagerFlagCase] = &[ PagerFlagCase { - label: "grok-build / subagents+ask_user", - profile: AgentDefinition::default_grok_build, + label: "kigi / subagents+ask_user", + profile: AgentDefinition::default_kigi, subagents: true, ask_user: true, }, PagerFlagCase { - label: "grok-build / subagents / no-ask-user", - profile: AgentDefinition::default_grok_build, + label: "kigi / subagents / no-ask-user", + profile: AgentDefinition::default_kigi, subagents: true, ask_user: false, }, PagerFlagCase { - label: "grok-build / no-subagents / ask_user", - profile: AgentDefinition::default_grok_build, + label: "kigi / no-subagents / ask_user", + profile: AgentDefinition::default_kigi, subagents: false, ask_user: true, }, PagerFlagCase { - label: "grok-build / no-subagents / no-ask-user", - profile: AgentDefinition::default_grok_build, + label: "kigi / no-subagents / no-ask-user", + profile: AgentDefinition::default_kigi, subagents: false, ask_user: false, }, PagerFlagCase { - label: "grok-build-ask-user / subagents", - profile: AgentDefinition::grok_build_ask_user, + label: "kigi-ask-user / subagents", + profile: AgentDefinition::kigi_ask_user, subagents: true, ask_user: true, }, PagerFlagCase { - label: "grok-build-ask-user / no-subagents", - profile: AgentDefinition::grok_build_ask_user, + label: "kigi-ask-user / no-subagents", + profile: AgentDefinition::kigi_ask_user, subagents: false, ask_user: true, }, PagerFlagCase { - label: "grok-build-plan", - profile: AgentDefinition::grok_build_plan, + label: "kigi-plan", + profile: AgentDefinition::kigi_plan, subagents: true, ask_user: true, }, PagerFlagCase { - label: "grok-build-plan / no-ask-user", - profile: AgentDefinition::grok_build_plan, + label: "kigi-plan / no-ask-user", + profile: AgentDefinition::kigi_plan, subagents: true, ask_user: false, }, PagerFlagCase { - label: "grok-build-plan-no-subagents", - profile: AgentDefinition::grok_build_plan_no_subagents, + label: "kigi-plan-no-subagents", + profile: AgentDefinition::kigi_plan_no_subagents, subagents: false, ask_user: true, }, PagerFlagCase { - label: "grok-build-plan-no-subagents / no-ask-user", - profile: AgentDefinition::grok_build_plan_no_subagents, + label: "kigi-plan-no-subagents / no-ask-user", + profile: AgentDefinition::kigi_plan_no_subagents, subagents: false, ask_user: false, }, @@ -1629,7 +1615,7 @@ mod tests { async fn curated_empty_toolset_fails_agent_build() { use kigi_tools::computer::local::LocalTerminalBackend; use kigi_tools::notification::ToolNotificationHandle; - let mut profile = crate::config::AgentDefinition::default_grok_build(); + let mut profile = crate::config::AgentDefinition::default_kigi(); profile.tool_config = Default::default(); profile.inject_default_tools = false; let result = AgentBuilder::new( @@ -1657,16 +1643,16 @@ mod tests { #[tokio::test] async fn plan_mode_injected_ask_user_question_receives_params() { use kigi_tools::computer::local::LocalTerminalBackend; - use kigi_tools::implementations::grok_build::ask_user_question::AskUserQuestionParams; + use kigi_tools::implementations::kigi::ask_user_question::AskUserQuestionParams; use kigi_tools::notification::ToolNotificationHandle; use kigi_tools::types::resources::Params; - let profile = crate::config::AgentDefinition::default_grok_build(); + let profile = crate::config::AgentDefinition::default_kigi(); assert!( !profile .tool_config .tools .iter() - .any(|tc| tc.id == "GrokBuild:ask_user_question"), + .any(|tc| tc.id == "Kigi:ask_user_question"), "test premise: the profile must not pre-declare ask_user_question" ); let mut params = serde_json::Map::new(); @@ -1693,7 +1679,7 @@ mod tests { async fn build_with_tools(tools: Vec, disallowed: Vec) -> crate::agent::Agent { use kigi_tools::computer::local::LocalTerminalBackend; use kigi_tools::notification::ToolNotificationHandle; - let mut def = crate::config::AgentDefinition::default_grok_build(); + let mut def = crate::config::AgentDefinition::default_kigi(); def.tools = tools; def.disallowed_tools = disallowed; AgentBuilder::new( @@ -1714,7 +1700,7 @@ mod tests { ) -> Vec { use kigi_tools::computer::local::LocalTerminalBackend; use kigi_tools::notification::ToolNotificationHandle; - let mut def = crate::config::AgentDefinition::default_grok_build(); + let mut def = crate::config::AgentDefinition::default_kigi(); def.tools = own_tools; def.session_tools_allowlist = Some(session_allow); let agent = AgentBuilder::new( @@ -1791,7 +1777,7 @@ mod tests { let mut def = crate::config::AgentDefinition::general_purpose(); assert!(def.session_tools_allowed("read_file")); def.session_tools_allowlist = Some(vec!["read_file".into()]); - assert!(def.session_tools_allowed("GrokBuild:read_file")); + assert!(def.session_tools_allowed("Kigi:read_file")); assert!(!def.session_tools_allowed("grep")); def.session_tools_denylist = Some(vec!["read_file".into()]); assert!(!def.session_tools_allowed("read_file")); @@ -1848,7 +1834,7 @@ mod tests { assert_eq!(agent.definition().allowed_subagent_types, None); use kigi_tools::computer::local::LocalTerminalBackend; use kigi_tools::notification::ToolNotificationHandle; - let mut def = crate::config::AgentDefinition::default_grok_build(); + let mut def = crate::config::AgentDefinition::default_kigi(); def.disallowed_tools = vec!["Agent".into()]; let agent = AgentBuilder::new( std::env::temp_dir(), @@ -1864,10 +1850,10 @@ mod tests { #[tokio::test] async fn spawning_blocked_disables_all_background_bash_modes() { use kigi_tools::computer::local::LocalTerminalBackend; - use kigi_tools::implementations::grok_build::bash::BashParams; + use kigi_tools::implementations::kigi::bash::BashParams; use kigi_tools::notification::ToolNotificationHandle; use kigi_tools::types::resources::Params; - let mut definition = crate::config::AgentDefinition::default_grok_build(); + let mut definition = crate::config::AgentDefinition::default_kigi(); definition.tools = vec!["run_terminal_cmd".into()]; let bash_params = serde_json::json!( { "max_timeout_secs" : 36_000.0, "auto_background_on_timeout" : true, @@ -1907,10 +1893,10 @@ mod tests { Some(vec!["worker".into()]) ); } - /// Compat allowlist names (`Read`, `Bash`, `Grep`) map to their Grok + /// Compat allowlist names (`Read`, `Bash`, `Grep`) map to their Kigi /// equivalents by `ToolKind` — a real restricted toolset, not zero tools. #[tokio::test] - async fn claude_tool_names_map_to_grok_equivalents() { + async fn claude_tool_names_map_to_kigi_equivalents() { let tools = vec!["Read".into(), "Bash".into(), "Grep".into()]; let agent = build_with_tools(tools, vec![]).await; let names: Vec = agent @@ -1936,7 +1922,7 @@ mod tests { "Edit must be excluded by the allowlist; got: {names:?}" ); } - /// Shell, LSP, ask, and task-lifecycle tool names resolve to their grok + /// Shell, LSP, ask, and task-lifecycle tool names resolve to their kigi /// `ToolKind`, so those allowlists are honored instead of failing open. #[test] fn shell_lsp_ask_and_task_tool_names_map() { @@ -2045,7 +2031,7 @@ mod tests { ); } /// A restrictive allowlist must never strip MCP access. Compat allowlists - /// treat `mcp__*` as always-on, so grok keeps the MCP meta-tools + /// treat `mcp__*` as always-on, so kigi keeps the MCP meta-tools /// (`search_tool` / `use_tool`) regardless of what the allowlist names. #[tokio::test] async fn restrictive_allowlist_keeps_mcp_access() { @@ -2098,10 +2084,10 @@ mod tests { #[tokio::test] async fn requested_enabled_web_tools_survive_allowlist() { use kigi_tools::computer::local::LocalTerminalBackend; - use kigi_tools::implementations::grok_build::web_fetch::WebFetchConfig; + use kigi_tools::implementations::kigi::web_fetch::WebFetchConfig; use kigi_tools::implementations::web_search::WebSearchConfig; use kigi_tools::notification::ToolNotificationHandle; - let mut definition = crate::config::AgentDefinition::default_grok_build(); + let mut definition = crate::config::AgentDefinition::default_kigi(); definition.tools = vec![ "read_file".into(), "grep".into(), @@ -2139,7 +2125,7 @@ mod tests { assert!(!names.contains(&excluded.to_string()), "got: {names:?}"); } } - /// grok-build toolsets have no Skill tool — skills are read from + /// kigi toolsets have no Skill tool — skills are read from /// `SKILL.md` via `read_file` — so a compat `Skill` allowlist entry grants /// toolset. #[tokio::test] @@ -2209,7 +2195,7 @@ mod tests { "no full-toolset fallback — unlisted tools must be excluded; got: {names:?}" ); } - /// Compat `ToolSearch` meta-tool maps to grok's `search_tool` (MCP + /// Compat `ToolSearch` meta-tool maps to kigi's `search_tool` (MCP /// is a filter (`retain`) over a `HashSet` of kinds, not an inserter — so the /// falling back to the full toolset. #[tokio::test] @@ -2247,7 +2233,7 @@ mod tests { } else { WebSearchConfig::Disabled }; - let mut def = crate::config::AgentDefinition::default_grok_build(); + let mut def = crate::config::AgentDefinition::default_kigi(); def.disallowed_tools = disallowed_tools.iter().map(|s| s.to_string()).collect(); AgentBuilder::new( std::env::temp_dir(), diff --git a/crates/codegen/kigi-agent/src/config.rs b/crates/codegen/kigi-agent/src/config.rs index 2d64c5e..fb5e09e 100644 --- a/crates/codegen/kigi-agent/src/config.rs +++ b/crates/codegen/kigi-agent/src/config.rs @@ -3,8 +3,8 @@ use crate::error::AgentBuildError; use crate::prompt::context::TemplateOverride; use crate::prompt::user_message::UserMessageTemplate; use kigi_tools::implementations::codex; -use kigi_tools::implementations::grok_build; -use kigi_tools::implementations::grok_build_concise; +use kigi_tools::implementations::kigi; +use kigi_tools::implementations::kigi_concise; use kigi_tools::implementations::memory; use kigi_tools::implementations::opencode; use kigi_tools::implementations::search_tool; @@ -91,7 +91,7 @@ fn registered_public_toolset_preset_names() -> Vec { .map(|(name, _)| name.clone()) .collect() } -/// Orchestrator-specific prompt body appended to the standard GrokBuild +/// Orchestrator-specific prompt body appended to the standard Kigi /// system prompt (`prompt.md`). Instructs the GBL model to delegate /// coding and exploration work to subagents. const ORCHESTRATOR_PROMPT_BODY: &str = "\ @@ -143,64 +143,64 @@ Write prompts the way you would brief a senior engineer: /// Bash tool with clearer model-facing names: /// `run_terminal_cmd` → `run_terminal_command`, `is_background` → `background`. fn bash_tool_config() -> ToolConfig { - ToolConfig::from(&grok_build::BashTool) + ToolConfig::from(&kigi::BashTool) .with_name("run_terminal_command") .with_param_rename("is_background", "background") } /// Task/subagent tool with clearer model-facing names: /// `task` → `spawn_subagent`, `run_in_background` → `background`. fn task_tool_config() -> ToolConfig { - ToolConfig::from(&grok_build::TaskTool) + ToolConfig::from(&kigi::TaskTool) .with_name("spawn_subagent") .with_param_rename("run_in_background", "background") } /// Task output tool renamed for clarity: /// `get_task_output` → `get_command_or_subagent_output`. fn task_output_tool_config() -> ToolConfig { - ToolConfig::from(&grok_build::TaskOutputTool).with_name("get_command_or_subagent_output") + ToolConfig::from(&kigi::TaskOutputTool).with_name("get_command_or_subagent_output") } /// `wait_tasks` → `wait_commands_or_subagents`. fn wait_tasks_tool_config() -> ToolConfig { - ToolConfig::from(&grok_build::WaitTasksTool).with_name("wait_commands_or_subagents") + ToolConfig::from(&kigi::WaitTasksTool).with_name("wait_commands_or_subagents") } /// `kill_task` → `kill_command_or_subagent`. fn kill_task_tool_config() -> ToolConfig { - ToolConfig::from(&grok_build::KillTaskTool).with_name("kill_command_or_subagent") + ToolConfig::from(&kigi::KillTaskTool).with_name("kill_command_or_subagent") } /// Complete workspace-executable toolset for hub registration. /// -/// Extends `default_grok_build_toolset()` with tools that are dynamically +/// Extends `default_kigi_toolset()` with tools that are dynamically /// injected by `AgentBuilder::build()` or only available in specific modes. /// In proxy mode, the workspace server executes ALL tools — the shell has /// zero local dispatch. -pub fn workspace_grok_build_toolset() -> ToolServerConfig { - let mut tools = default_grok_build_toolset().tools; +pub fn workspace_kigi_toolset() -> ToolServerConfig { + let mut tools = default_kigi_toolset().tools; tools.push((&opencode::OpenCodeWriteTool).into()); - tools.push((&grok_build::EnterPlanModeTool).into()); - tools.push((&grok_build::ExitPlanModeTool).into()); - tools.push((&grok_build::AskUserQuestionTool).into()); - tools.push((&grok_build::WebSearchTool).into()); - tools.push((&grok_build::WebFetchTool).into()); + tools.push((&kigi::EnterPlanModeTool).into()); + tools.push((&kigi::ExitPlanModeTool).into()); + tools.push((&kigi::AskUserQuestionTool).into()); + tools.push((&kigi::WebSearchTool).into()); + tools.push((&kigi::WebFetchTool).into()); tools.push((&memory::search_tool::MemorySearchImpl).into()); tools.push((&memory::get_tool::MemoryGetImpl).into()); - tools.push((&grok_build::LspTool).into()); + tools.push((&kigi::LspTool).into()); ToolServerConfig { tools, behavior_preset: None, } } -/// Toolset for the `grok-computer` (workspace/sandbox) preset. -fn grok_computer_toolset() -> ToolServerConfig { +/// Toolset for the `kigi-computer` (workspace/sandbox) preset. +fn kigi_computer_toolset() -> ToolServerConfig { #[allow(unused_mut)] let mut tools = vec![ bash_tool_config(), - (&grok_build::ReadFileTool).into(), - (&grok_build::SearchReplaceTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::SearchReplaceTool).into(), (&opencode::OpenCodeWriteTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), - (&grok_build::KillTerminalCommandTool).into(), - (&grok_build::GetTerminalCommandOutputTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), + (&kigi::KillTerminalCommandTool).into(), + (&kigi::GetTerminalCommandOutputTool).into(), ]; ToolServerConfig { tools, @@ -215,13 +215,13 @@ fn grok_computer_toolset() -> ToolServerConfig { /// Native (in-crate) toolset presets. fn native_toolset_presets() -> Vec<(&'static str, ToolServerConfig)> { vec![ - ("grok-build", workspace_grok_build_toolset()), - ("grok-build-concise", grok_build_concise_toolset()), - ("grok-build-plan", grok_build_plan_toolset()), + ("kigi", workspace_kigi_toolset()), + ("kigi-concise", kigi_concise_toolset()), + ("kigi-plan", kigi_plan_toolset()), ("codex", codex_toolset()), ("explore", explore_toolset()), ("plan", plan_toolset()), - ("grok-computer", grok_computer_toolset()), + ("kigi-computer", kigi_computer_toolset()), ] } /// Every named **public** toolset preset (native + externally registered public @@ -257,46 +257,46 @@ pub fn toolset_for_preset(preset: &str) -> Option { .map(|(_, toolset)| toolset) .or_else(|| registered_toolset_preset(&normalized)) } -fn default_grok_build_toolset() -> ToolServerConfig { +fn default_kigi_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ bash_tool_config(), - (&grok_build::ReadFileTool).into(), - (&grok_build::SearchReplaceTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::SearchReplaceTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), wait_tasks_tool_config(), task_tool_config(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), - (&grok_build::UpdateGoalTool).into(), + (&kigi::UpdateGoalTool).into(), ], behavior_preset: None, } } -fn grok_build_concise_toolset() -> ToolServerConfig { +fn kigi_concise_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ - (&grok_build_concise::BashConciseTool).into(), - (&grok_build_concise::ReadFileConciseTool).into(), - (&grok_build_concise::SearchReplaceConciseTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi_concise::BashConciseTool).into(), + (&kigi_concise::ReadFileConciseTool).into(), + (&kigi_concise::SearchReplaceConciseTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), - (&grok_build::UpdateGoalTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), + (&kigi::UpdateGoalTool).into(), ], behavior_preset: None, } @@ -306,26 +306,26 @@ fn grok_build_concise_toolset() -> ToolServerConfig { /// `hashline_tools` should be the 3 hashline `ToolConfig` entries produced by /// `FileToolset::Hashline.tool_configs(&hashline_config)` — they carry the /// scheme parameters as tool params. -pub fn grok_build_hashline_toolset( +pub fn kigi_hashline_toolset( hashline_tools: Vec, ) -> ToolServerConfig { let mut tools: Vec = vec![bash_tool_config()]; tools.extend(hashline_tools); tools.extend([ - (&grok_build::ListDirTool).into(), + (&kigi::ListDirTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), wait_tasks_tool_config(), task_tool_config(), - (&grok_build::WebSearchTool).into(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), + (&kigi::WebSearchTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), - (&grok_build::UpdateGoalTool).into(), + (&kigi::UpdateGoalTool).into(), ]); ToolServerConfig { tools, @@ -341,7 +341,7 @@ fn codex_toolset() -> ToolServerConfig { (&codex::CodexListDirTool).into(), (&codex::CodexGrepFilesTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), @@ -359,9 +359,9 @@ fn codex_toolset() -> ToolServerConfig { fn explore_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ - (&grok_build::ReadFileTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), ], behavior_preset: None, } @@ -374,42 +374,42 @@ fn explore_toolset() -> ToolServerConfig { fn plan_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ - (&grok_build::ReadFileTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), - (&grok_build::TodoWriteTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), + (&kigi::TodoWriteTool).into(), ], behavior_preset: None, } } -/// Grok Build + plan mode toolset. +/// Kigi + plan mode toolset. /// -/// Extends the default `grok-build` toolset with plan mode tools: +/// Extends the default `kigi` toolset with plan mode tools: /// `enter_plan_mode`, `exit_plan_mode`, and `ask_user_question`. /// This allows the agent to enter a structured planning phase before /// writing code, with user-approved plans. -fn grok_build_plan_toolset() -> ToolServerConfig { +fn kigi_plan_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ bash_tool_config(), - (&grok_build::ReadFileTool).into(), - (&grok_build::SearchReplaceTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::SearchReplaceTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), task_tool_config(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), - (&grok_build::UpdateGoalTool).into(), - (&grok_build::EnterPlanModeTool).into(), - (&grok_build::ExitPlanModeTool).into(), - (&grok_build::AskUserQuestionTool).into(), + (&kigi::UpdateGoalTool).into(), + (&kigi::EnterPlanModeTool).into(), + (&kigi::ExitPlanModeTool).into(), + (&kigi::AskUserQuestionTool).into(), ], behavior_preset: None, } @@ -424,87 +424,87 @@ fn orchestrator_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ bash_tool_config(), - (&grok_build::ReadFileTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), task_tool_config(), task_output_tool_config(), wait_tasks_tool_config(), kill_task_tool_config(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), - (&grok_build::TodoWriteTool).into(), - (&grok_build::EnterPlanModeTool).into(), - (&grok_build::ExitPlanModeTool).into(), - (&grok_build::AskUserQuestionTool).into(), - (&grok_build::UpdateGoalTool).into(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), - (&grok_build::WebSearchTool).into(), - (&grok_build::WebFetchTool).into(), + (&kigi::TodoWriteTool).into(), + (&kigi::EnterPlanModeTool).into(), + (&kigi::ExitPlanModeTool).into(), + (&kigi::AskUserQuestionTool).into(), + (&kigi::UpdateGoalTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), + (&kigi::WebSearchTool).into(), + (&kigi::WebFetchTool).into(), (&memory::MemorySearchImpl).into(), (&memory::MemoryGetImpl).into(), ], behavior_preset: None, } } -/// Grok Build + plan mode toolset WITHOUT subagent tools. +/// Kigi + plan mode toolset WITHOUT subagent tools. /// -/// Same as `grok_build_plan_toolset` but excludes `TaskTool`, +/// Same as `kigi_plan_toolset` but excludes `TaskTool`, /// `TaskOutputTool`, and `KillTaskTool`. Use this when the shell /// does not have subagent infrastructure wired up. -fn grok_build_plan_no_subagents_toolset() -> ToolServerConfig { +fn kigi_plan_no_subagents_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ bash_tool_config(), - (&grok_build::ReadFileTool).into(), - (&grok_build::SearchReplaceTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::SearchReplaceTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), - (&grok_build::UpdateGoalTool).into(), - (&grok_build::EnterPlanModeTool).into(), - (&grok_build::ExitPlanModeTool).into(), - (&grok_build::AskUserQuestionTool).into(), + (&kigi::UpdateGoalTool).into(), + (&kigi::EnterPlanModeTool).into(), + (&kigi::ExitPlanModeTool).into(), + (&kigi::AskUserQuestionTool).into(), ], behavior_preset: None, } } -/// Default Grok Build toolset + `ask_user_question`. +/// Default Kigi toolset + `ask_user_question`. /// -/// Same as `default_grok_build_toolset` with the `AskUserQuestionTool` added, +/// Same as `default_kigi_toolset` with the `AskUserQuestionTool` added, /// allowing the agent to ask structured questions without full plan mode. -fn grok_build_ask_user_toolset() -> ToolServerConfig { +fn kigi_ask_user_toolset() -> ToolServerConfig { ToolServerConfig { tools: vec![ bash_tool_config(), - (&grok_build::ReadFileTool).into(), - (&grok_build::SearchReplaceTool).into(), - (&grok_build::ListDirTool).into(), - (&grok_build::GrepTool).into(), + (&kigi::ReadFileTool).into(), + (&kigi::SearchReplaceTool).into(), + (&kigi::ListDirTool).into(), + (&kigi::GrepTool).into(), kill_task_tool_config(), - (&grok_build::TodoWriteTool).into(), + (&kigi::TodoWriteTool).into(), task_output_tool_config(), wait_tasks_tool_config(), task_tool_config(), - (&grok_build::SchedulerCreateTool).into(), - (&grok_build::SchedulerDeleteTool).into(), - (&grok_build::SchedulerListTool).into(), - (&grok_build::MonitorTool).into(), + (&kigi::SchedulerCreateTool).into(), + (&kigi::SchedulerDeleteTool).into(), + (&kigi::SchedulerListTool).into(), + (&kigi::MonitorTool).into(), (&search_tool::SearchTool).into(), (&use_tool::UseTool).into(), - (&grok_build::UpdateGoalTool).into(), - (&grok_build::AskUserQuestionTool).into(), + (&kigi::UpdateGoalTool).into(), + (&kigi::AskUserQuestionTool).into(), ], behavior_preset: None, } @@ -535,7 +535,7 @@ fn opencode_toolset() -> ToolServerConfig { /// /// In YAML frontmatter / JSON: /// - `model: inherit` or omitted → `Inherit` -/// - `model: grok-3-fast` → `Override("grok-3-fast")` +/// - `model: kigi-3-fast` → `Override("kigi-3-fast")` #[derive(Debug, Clone, PartialEq, Eq, Default)] pub enum ModelOverride { /// Use the parent session's model. @@ -649,28 +649,52 @@ where )] #[strum(serialize_all = "kebab-case")] pub enum BuiltinAgentName { - GrokBuild, - GrokBuildConcise, - GrokBuildPlan, - GrokBuildPlanNoSubagents, - GrokBuildAskUser, + Kigi, + KigiConcise, + KigiPlan, + KigiPlanNoSubagents, + KigiAskUser, Codex, Opencode, GeneralPurpose, Explore, Plan, BrowserUse, - #[strum(serialize = "grok-build-orchestrator")] - GrokBuildOrchestrator, + #[strum(serialize = "kigi-orchestrator")] + KigiOrchestrator, } +/// Agent-type prefix written by pre-rebrand builds into session files and +/// model configs (``, `-plan`, `-concise`, …). +/// +/// DOCUMENTED ALIAS: sessions persist agent types, so names written by older +/// builds must keep resolving. The prefix is assembled with `concat!` so the +/// release-gate grep over Rust sources (which forbids the upstream brand +/// string) stays clean while the runtime value is the historical spelling. +pub const LEGACY_AGENT_TYPE_PREFIX: &str = concat!("gr", "ok-build"); + +/// Map a legacy pre-rebrand agent-type name onto its current `kigi*` +/// equivalent: `` → `kigi`, `-plan` → `kigi-plan`, and so on. +/// Non-legacy names pass through unchanged. Applied at the name-resolution +/// boundaries ([`crate::discovery::by_name`] and friends, +/// [`is_strict_harness_agent_type`]) so persisted agent types from old +/// session files keep loading. +pub fn canonical_agent_type(name: &str) -> std::borrow::Cow<'_, str> { + match name.strip_prefix(LEGACY_AGENT_TYPE_PREFIX) { + Some("") => std::borrow::Cow::Borrowed("kigi"), + Some(rest) if rest.starts_with('-') => std::borrow::Cow::Owned(format!("kigi{rest}")), + _ => std::borrow::Cow::Borrowed(name), + } +} + /// Strict-harness predicate by name. Resolves via `BuiltinAgentName` and /// delegates to [`AgentDefinition::is_strict_harness`]; unknown names /// return `false` (conservative — never enforce a harness we can't verify). +/// Accepts legacy pre-rebrand agent-type names via [`canonical_agent_type`]. /// Callers that already hold an `AgentDefinition` should call that method /// directly so project-level shadowing is honored. pub fn is_strict_harness_agent_type(name: &str) -> bool { use std::str::FromStr; - BuiltinAgentName::from_str(name) + BuiltinAgentName::from_str(canonical_agent_type(name).as_ref()) .map(|b| b.definition().is_strict_harness()) .unwrap_or(false) } @@ -678,18 +702,18 @@ impl BuiltinAgentName { /// Build the `AgentDefinition` for this built-in agent. pub fn definition(self) -> AgentDefinition { match self { - Self::GrokBuild => AgentDefinition::default_grok_build(), - Self::GrokBuildConcise => AgentDefinition::grok_build_concise(), - Self::GrokBuildPlan => AgentDefinition::grok_build_plan(), - Self::GrokBuildPlanNoSubagents => AgentDefinition::grok_build_plan_no_subagents(), - Self::GrokBuildAskUser => AgentDefinition::grok_build_ask_user(), + Self::Kigi => AgentDefinition::default_kigi(), + Self::KigiConcise => AgentDefinition::kigi_concise(), + Self::KigiPlan => AgentDefinition::kigi_plan(), + Self::KigiPlanNoSubagents => AgentDefinition::kigi_plan_no_subagents(), + Self::KigiAskUser => AgentDefinition::kigi_ask_user(), Self::Codex => AgentDefinition::codex(), Self::Opencode => AgentDefinition::opencode(), Self::GeneralPurpose => AgentDefinition::general_purpose(), Self::Explore => AgentDefinition::explore(), Self::Plan => AgentDefinition::plan(), Self::BrowserUse => AgentDefinition::browser_use(), - Self::GrokBuildOrchestrator => AgentDefinition::grok_build_orchestrator(), + Self::KigiOrchestrator => AgentDefinition::kigi_orchestrator(), } } /// Built-in agents available as subagents via the Task tool. @@ -713,7 +737,7 @@ pub struct AgentDefinition { pub plugin_name: Option, #[serde(default = "default_prompt_mode")] pub prompt_mode: PromptMode, - #[serde(default = "default_grok_build_toolset")] + #[serde(default = "default_kigi_toolset")] pub tool_config: ToolServerConfig, /// Runtime capability mode that constrains which tool kinds the agent /// can use. Applied during subagent spawn in `handle_subagent_request` @@ -868,7 +892,7 @@ pub enum AgentScope { User, /// ~/.kigi/bundled/agents/ (lowest-priority bundled cache) Bundled, - /// Built-in agent (e.g., default_grok_build(), browser_use()). + /// Built-in agent (e.g., default_kigi(), browser_use()). #[default] BuiltIn, } @@ -1303,9 +1327,9 @@ impl AgentDefinition { /// Determine the scope of a definition file based on its path. fn scope_from_path(path: &Path) -> AgentScope { let path_str = path.to_string_lossy(); - let grok = kigi_config::user_kigi_home(); + let kigi = kigi_config::user_kigi_home(); let home = dirs::home_dir(); - for (dir, scope) in crate::discovery::user_agent_dirs(home.as_deref(), grok.as_deref()) { + for (dir, scope) in crate::discovery::user_agent_dirs(home.as_deref(), kigi.as_deref()) { if path.starts_with(&dir) { return scope; } @@ -1371,7 +1395,7 @@ impl AgentDefinition { /// stock harness, so a client-supplied `_meta.agentProfile` must NOT /// override it. Strict iff any of: bespoke `system_prompt` template, /// bespoke `user_message_template`, or curated toolset - /// (`!inject_default_tools`). Stock `grok-build*` agents leave all + /// (`!inject_default_tools`). Stock `kigi*` agents leave all /// three at defaults and are non-strict. pub fn is_strict_harness(&self) -> bool { use crate::prompt::context::TemplateOverride; @@ -1390,12 +1414,9 @@ impl AgentDefinition { file_tools: Vec, ) { const FILE_TOOL_SLOTS: &[[&str; 2]] = &[ - ["GrokBuild:read_file", "GrokBuildHashline:hashline_read"], - [ - "GrokBuild:search_replace", - "GrokBuildHashline:hashline_edit", - ], - ["GrokBuild:grep", "GrokBuildHashline:hashline_grep"], + ["Kigi:read_file", "KigiHashline:hashline_read"], + ["Kigi:search_replace", "KigiHashline:hashline_edit"], + ["Kigi:grep", "KigiHashline:hashline_grep"], ]; for tool in self.tool_config.tools.iter_mut() { let Some(slot) = FILE_TOOL_SLOTS @@ -1420,7 +1441,7 @@ impl AgentDefinition { description: description.to_string(), plugin_name: None, prompt_mode: PromptMode::Extend, - tool_config: default_grok_build_toolset(), + tool_config: default_kigi_toolset(), capability_mode: None, permission_mode: PermissionMode::Default, skills: vec![], @@ -1452,50 +1473,50 @@ impl AgentDefinition { scope: AgentScope::BuiltIn, } } - pub fn default_grok_build() -> Self { + pub fn default_kigi() -> Self { Self::base( - BuiltinAgentName::GrokBuild, - "Grok Build agent for software engineering tasks.", + BuiltinAgentName::Kigi, + "Kigi agent for software engineering tasks.", ) } - /// Grok Build Concise agent definition — concise output format for SFT/RL. - pub fn grok_build_concise() -> Self { + /// Kigi Concise agent definition — concise output format for SFT/RL. + pub fn kigi_concise() -> Self { Self { - tool_config: grok_build_concise_toolset(), + tool_config: kigi_concise_toolset(), agents_md: false, ..Self::base( - BuiltinAgentName::GrokBuildConcise, - "Grok Build agent with concise output format.", + BuiltinAgentName::KigiConcise, + "Kigi agent with concise output format.", ) } } - /// Grok Build agent with plan mode tools. - pub fn grok_build_plan() -> Self { + /// Kigi agent with plan mode tools. + pub fn kigi_plan() -> Self { Self { - tool_config: grok_build_plan_toolset(), + tool_config: kigi_plan_toolset(), ..Self::base( - BuiltinAgentName::GrokBuildPlan, - "Grok Build agent with plan mode support.", + BuiltinAgentName::KigiPlan, + "Kigi agent with plan mode support.", ) } } - /// Grok Build + plan mode WITHOUT subagent tools. - pub fn grok_build_plan_no_subagents() -> Self { + /// Kigi + plan mode WITHOUT subagent tools. + pub fn kigi_plan_no_subagents() -> Self { Self { - tool_config: grok_build_plan_no_subagents_toolset(), + tool_config: kigi_plan_no_subagents_toolset(), ..Self::base( - BuiltinAgentName::GrokBuildPlanNoSubagents, - "Grok Build agent with plan mode (no subagents).", + BuiltinAgentName::KigiPlanNoSubagents, + "Kigi agent with plan mode (no subagents).", ) } } - /// Default Grok Build agent with the `ask_user_question` tool. - pub fn grok_build_ask_user() -> Self { + /// Default Kigi agent with the `ask_user_question` tool. + pub fn kigi_ask_user() -> Self { Self { - tool_config: grok_build_ask_user_toolset(), + tool_config: kigi_ask_user_toolset(), ..Self::base( - BuiltinAgentName::GrokBuildAskUser, - "Grok Build agent with ask-user-question tool.", + BuiltinAgentName::KigiAskUser, + "Kigi agent with ask-user-question tool.", ) } } @@ -1567,21 +1588,21 @@ impl AgentDefinition { ) } } - /// Grok Build Orchestrator — GBL model with full GrokBuild tools + /// Kigi Orchestrator — GBL model with full Kigi tools /// (skills, MCPs, plan mode) that delegates coding/exploration to /// subagents. /// /// Subagent overrides are applied in `handle_subagent_request`: /// general-purpose children get `implementer_toolset()` and explore /// children get `explorer_toolset()`, both with the subagent model. - pub fn grok_build_orchestrator() -> Self { + pub fn kigi_orchestrator() -> Self { Self { tool_config: orchestrator_toolset(), inject_default_tools: false, prompt_body: Some(ORCHESTRATOR_PROMPT_BODY.to_string()), ..Self::base( - BuiltinAgentName::GrokBuildOrchestrator, - "GrokBuild orchestrator that delegates coding to specialized subagents", + BuiltinAgentName::KigiOrchestrator, + "Kigi orchestrator that delegates coding to specialized subagents", ) } } @@ -1610,7 +1631,7 @@ impl AgentDefinition { } } if !value.get("toolConfig").is_some_and(|v| v.is_object()) { - def.tool_config = default_grok_build_toolset(); + def.tool_config = default_kigi_toolset(); } def.scope = AgentScope::BuiltIn; Ok(def) @@ -1632,15 +1653,15 @@ mod tests { #[test] fn toolset_for_preset_resolves_known_names() { for name in [ - "grok-build", - "grok_build", - "grok-build-concise", - "grok-build-plan", + "kigi", + "kigi", + "kigi-concise", + "kigi-plan", "codex", "explore", "plan", - "grok-computer", - "grok_computer", + "kigi-computer", + "kigi_computer", ] { assert!( toolset_for_preset(name).is_some(), @@ -1651,27 +1672,27 @@ mod tests { } #[test] fn presets_select_distinct_toolsets_by_size() { - let gb = toolset_for_preset("grok-build").unwrap(); + let gb = toolset_for_preset("kigi").unwrap(); let plan = toolset_for_preset("plan").unwrap(); let explore = toolset_for_preset("explore").unwrap(); assert!(explore.tools.len() < plan.tools.len()); assert!(plan.tools.len() < gb.tools.len()); } - fn grok_computer_exclusive_ids() -> Vec { + fn kigi_computer_exclusive_ids() -> Vec { #[allow(unused_mut)] let mut ids: Vec = vec![ - ToolConfig::from(&grok_build::GetTerminalCommandOutputTool).id, - ToolConfig::from(&grok_build::KillTerminalCommandTool).id, + ToolConfig::from(&kigi::GetTerminalCommandOutputTool).id, + ToolConfig::from(&kigi::KillTerminalCommandTool).id, ]; ids } #[test] - fn grok_computer_preset_is_curated_grok_build_subset() { - let gc = toolset_for_preset("grok-computer").unwrap(); - let gb = toolset_for_preset("grok-build").unwrap(); + fn kigi_computer_preset_is_curated_kigi_subset() { + let gc = toolset_for_preset("kigi-computer").unwrap(); + let gb = toolset_for_preset("kigi").unwrap(); let gb_ids: std::collections::HashSet<&str> = gb.tools.iter().map(|t| t.id.as_str()).collect(); - let exclusive_ids = grok_computer_exclusive_ids(); + let exclusive_ids = kigi_computer_exclusive_ids(); assert!(!gc.tools.is_empty()); for t in &gc.tools { if exclusive_ids.contains(&t.id) { @@ -1679,84 +1700,78 @@ mod tests { } assert!( gb_ids.contains(t.id.as_str()), - "grok-computer tool `{}` must also ship in the grok-build preset", + "kigi-computer tool `{}` must also ship in the kigi preset", t.id ); } assert!( gc.tools.len() < gb.tools.len(), - "grok-computer should be a curated subset of grok-build" + "kigi-computer should be a curated subset of kigi" ); } #[test] - fn grok_computer_uses_subagent_free_background_task_tools() { - let gc = toolset_for_preset("grok-computer").unwrap(); + fn kigi_computer_uses_subagent_free_background_task_tools() { + let gc = toolset_for_preset("kigi-computer").unwrap(); let ids: std::collections::HashSet<&str> = gc.tools.iter().map(|t| t.id.as_str()).collect(); assert!( ids.contains( - ToolConfig::from(&grok_build::GetTerminalCommandOutputTool) + ToolConfig::from(&kigi::GetTerminalCommandOutputTool) .id .as_str() ) ); - assert!( - ids.contains( - ToolConfig::from(&grok_build::KillTerminalCommandTool) - .id - .as_str() - ) - ); - assert!(!ids.contains(ToolConfig::from(&grok_build::TaskOutputTool).id.as_str())); - assert!(!ids.contains(ToolConfig::from(&grok_build::KillTaskTool).id.as_str())); - assert!(!ids.contains(ToolConfig::from(&grok_build::TaskTool).id.as_str())); + assert!(ids.contains(ToolConfig::from(&kigi::KillTerminalCommandTool).id.as_str())); + assert!(!ids.contains(ToolConfig::from(&kigi::TaskOutputTool).id.as_str())); + assert!(!ids.contains(ToolConfig::from(&kigi::KillTaskTool).id.as_str())); + assert!(!ids.contains(ToolConfig::from(&kigi::TaskTool).id.as_str())); for t in &gc.tools { - if t.id == ToolConfig::from(&grok_build::GetTerminalCommandOutputTool).id - || t.id == ToolConfig::from(&grok_build::KillTerminalCommandTool).id + if t.id == ToolConfig::from(&kigi::GetTerminalCommandOutputTool).id + || t.id == ToolConfig::from(&kigi::KillTerminalCommandTool).id { assert!(t.name_override.is_none(), "tool `{}` must not rename", t.id); } } } - /// The grok-computer preset must ship a full-file write tool (legacy - /// `write_file` parity) — the same OpenCode `write` tool the grok-build + /// The kigi-computer preset must ship a full-file write tool (legacy + /// `write_file` parity) — the same OpenCode `write` tool the kigi /// preset uses. Guards against `search_replace` being the only /// file-mutation path, which has no single-tool full-rewrite when the /// empty-old_string overwrite guard is enabled. #[test] - fn grok_computer_preset_includes_write_tool() { - let gc = toolset_for_preset("grok-computer").unwrap(); + fn kigi_computer_preset_includes_write_tool() { + let gc = toolset_for_preset("kigi-computer").unwrap(); let write_id = ToolConfig::from(&opencode::OpenCodeWriteTool).id; assert!( gc.tools.iter().any(|t| t.id == write_id), - "grok-computer preset must include the `{write_id}` tool" + "kigi-computer preset must include the `{write_id}` tool" ); } #[test] - fn grok_computer_preset_excludes_plan_and_lsp() { - let gc = toolset_for_preset("grok-computer").unwrap(); + fn kigi_computer_preset_excludes_plan_and_lsp() { + let gc = toolset_for_preset("kigi-computer").unwrap(); let gc_ids: std::collections::HashSet<&str> = gc.tools.iter().map(|t| t.id.as_str()).collect(); for excluded in [ - ToolConfig::from(&grok_build::LspTool).id, - ToolConfig::from(&grok_build::EnterPlanModeTool).id, - ToolConfig::from(&grok_build::ExitPlanModeTool).id, + ToolConfig::from(&kigi::LspTool).id, + ToolConfig::from(&kigi::EnterPlanModeTool).id, + ToolConfig::from(&kigi::ExitPlanModeTool).id, ] { assert!( !gc_ids.contains(excluded.as_str()), - "grok-computer preset must not advertise `{excluded}`" + "kigi-computer preset must not advertise `{excluded}`" ); } - let full = workspace_grok_build_toolset(); + let full = workspace_kigi_toolset(); let full_ids: std::collections::HashSet<&str> = full.tools.iter().map(|t| t.id.as_str()).collect(); for present in [ - ToolConfig::from(&grok_build::LspTool).id, - ToolConfig::from(&grok_build::EnterPlanModeTool).id, - ToolConfig::from(&grok_build::ExitPlanModeTool).id, + ToolConfig::from(&kigi::LspTool).id, + ToolConfig::from(&kigi::EnterPlanModeTool).id, + ToolConfig::from(&kigi::ExitPlanModeTool).id, ] { assert!( full_ids.contains(present.as_str()), - "workspace_grok_build_toolset must ship `{present}`" + "workspace_kigi_toolset must ship `{present}`" ); } } @@ -1764,12 +1779,12 @@ mod tests { /// until classified. fn expected_strict_harness(name: BuiltinAgentName) -> bool { match name { - BuiltinAgentName::Codex | BuiltinAgentName::GrokBuildOrchestrator => true, - BuiltinAgentName::GrokBuild - | BuiltinAgentName::GrokBuildConcise - | BuiltinAgentName::GrokBuildPlan - | BuiltinAgentName::GrokBuildPlanNoSubagents - | BuiltinAgentName::GrokBuildAskUser + BuiltinAgentName::Codex | BuiltinAgentName::KigiOrchestrator => true, + BuiltinAgentName::Kigi + | BuiltinAgentName::KigiConcise + | BuiltinAgentName::KigiPlan + | BuiltinAgentName::KigiPlanNoSubagents + | BuiltinAgentName::KigiAskUser | BuiltinAgentName::GeneralPurpose | BuiltinAgentName::Explore | BuiltinAgentName::Plan @@ -1795,22 +1810,22 @@ mod tests { } #[test] fn is_strict_harness_agent_type_classifies_by_name() { - for strict in ["codex", "grok-build-orchestrator"] { + for strict in ["codex", "kigi-orchestrator"] { assert!( is_strict_harness_agent_type(strict), "{strict} should be strict" ); } for non_strict in [ - "grok-build", - "grok-build-plan", - "grok-build-concise", - "grok-build-ask-user", + "kigi", + "kigi-plan", + "kigi-concise", + "kigi-ask-user", "opencode", "browser-use", "custom-user-agent", "", - "grok-build-totally-made-up", + "kigi-totally-made-up", ] { assert!( !is_strict_harness_agent_type(non_strict), @@ -1965,8 +1980,8 @@ Agent. fn test_model_override_display_shows_id() { assert_eq!(ModelOverride::Inherit.to_string(), "inherit"); assert_eq!( - ModelOverride::Override("grok-3-fast".to_string()).to_string(), - "grok-3-fast" + ModelOverride::Override("kigi-3-fast".to_string()).to_string(), + "kigi-3-fast" ); } #[test] @@ -1980,7 +1995,7 @@ isolation: worktree background: true color: blue initialPrompt: "hello world" -model: grok-3 +model: kigi-3 --- Agent body. @@ -1992,7 +2007,7 @@ Agent body. assert_eq!(def.background, Some(true)); assert_eq!(def.color, Some(AgentColor::Blue)); assert_eq!(def.initial_prompt.as_deref(), Some("hello world")); - assert_eq!(def.model, ModelOverride::Override("grok-3".to_string())); + assert_eq!(def.model, ModelOverride::Override("kigi-3".to_string())); } #[test] fn test_parse_minimal_definition() { @@ -2177,7 +2192,7 @@ completionRequirement: assert_eq!(rec.max_delay_ms, 10000); } #[test] - fn test_default_tool_config_has_grok_build_tools() { + fn test_default_tool_config_has_kigi_tools() { let content = r#"--- name: default-tools description: Test default tool config @@ -2186,7 +2201,7 @@ description: Test default tool config let def = AgentDefinition::parse(content).unwrap(); assert!( !def.tool_config.tools.is_empty(), - "default tool_config should have grok_build tools" + "default tool_config should have kigi tools" ); } #[test] @@ -2256,12 +2271,12 @@ description: Test default tool config #[test] fn test_from_json_has_default_toolset_with_task_tool() { let json = serde_json::json!( - { "name" : "grok-build", "description" : "Multi-surface coding agent.", + { "name" : "kigi", "description" : "Multi-surface coding agent.", "promptMode" : "extend", "permissionMode" : "dontAsk", "agentsMd" : true, "promptBody" : "You are a coding assistant." } ); let def = AgentDefinition::from_json(&json).unwrap(); - let task_tool_id = "GrokBuild:task"; + let task_tool_id = "Kigi:task"; assert!( def.tool_config.tools.iter().any(|tc| tc.id == task_tool_id), "from_json() without toolConfig should include TaskTool in default toolset, \ @@ -2358,9 +2373,9 @@ description: Test default tool config } #[test] fn test_model_override_serde_explicit_model_id() { - let yaml = "\"grok-3-fast\""; + let yaml = "\"kigi-3-fast\""; let m: ModelOverride = serde_yaml::from_str(yaml).unwrap(); - assert_eq!(m, ModelOverride::Override("grok-3-fast".to_string())); + assert_eq!(m, ModelOverride::Override("kigi-3-fast".to_string())); } #[test] fn test_model_override_serialize_inherit() { @@ -2370,17 +2385,17 @@ description: Test default tool config } #[test] fn test_model_override_serialize_override() { - let m = ModelOverride::Override("grok-3-fast".to_string()); + let m = ModelOverride::Override("kigi-3-fast".to_string()); let s = serde_json::to_string(&m).unwrap(); - assert_eq!(s, "\"grok-3-fast\""); + assert_eq!(s, "\"kigi-3-fast\""); } #[test] fn test_model_override_in_frontmatter() { - let content = "---\nname: test\ndescription: Test\nmodel: grok-3-fast\n---\n"; + let content = "---\nname: test\ndescription: Test\nmodel: kigi-3-fast\n---\n"; let def = AgentDefinition::parse(content).unwrap(); assert_eq!( def.model, - ModelOverride::Override("grok-3-fast".to_string()) + ModelOverride::Override("kigi-3-fast".to_string()) ); } #[test] @@ -2398,21 +2413,21 @@ description: Test default tool config #[test] fn test_model_override_in_json() { let json = serde_json::json!( - { "name" : "test", "description" : "Test", "model" : "grok-code-fast-1" } + { "name" : "test", "description" : "Test", "model" : "kigi-code-fast-1" } ); let def = AgentDefinition::from_json(&json).unwrap(); assert_eq!( def.model, - ModelOverride::Override("grok-code-fast-1".to_string()) + ModelOverride::Override("kigi-code-fast-1".to_string()) ); } #[test] fn test_builtin_agent_name_strum_round_trip() { use std::str::FromStr; for (s, expected) in [ - ("grok-build", BuiltinAgentName::GrokBuild), - ("grok-build-concise", BuiltinAgentName::GrokBuildConcise), - ("grok-build-ask-user", BuiltinAgentName::GrokBuildAskUser), + ("kigi", BuiltinAgentName::Kigi), + ("kigi-concise", BuiltinAgentName::KigiConcise), + ("kigi-ask-user", BuiltinAgentName::KigiAskUser), ("codex", BuiltinAgentName::Codex), ("opencode", BuiltinAgentName::Opencode), ("general-purpose", BuiltinAgentName::GeneralPurpose), @@ -2431,6 +2446,49 @@ description: Test default tool config assert!(BuiltinAgentName::from_str("nonexistent").is_err()); assert!(BuiltinAgentName::from_str("not-a-builtin-agent").is_err()); } + /// Legacy pre-rebrand agent types (as persisted in old session files) + /// must map onto the current `kigi*` names; everything else passes + /// through unchanged. + #[test] + fn test_canonical_agent_type_maps_legacy_names() { + use std::str::FromStr; + let legacy = |suffix: &str| format!("{LEGACY_AGENT_TYPE_PREFIX}{suffix}"); + for (suffix, expected) in [ + ("", "kigi"), + ("-concise", "kigi-concise"), + ("-plan", "kigi-plan"), + ("-plan-no-subagents", "kigi-plan-no-subagents"), + ("-ask-user", "kigi-ask-user"), + ("-orchestrator", "kigi-orchestrator"), + ] { + let name = legacy(suffix); + assert_eq!(canonical_agent_type(&name), expected, "for {name}"); + // Every mapped name resolves to a real builtin. + assert!( + BuiltinAgentName::from_str(canonical_agent_type(&name).as_ref()).is_ok(), + "legacy {name} must resolve to a builtin" + ); + } + // Pass-through for current and unrelated names. + assert_eq!(canonical_agent_type("kigi-plan"), "kigi-plan"); + assert_eq!(canonical_agent_type("general-purpose"), "general-purpose"); + // A prefix match without a `-` separator is NOT a legacy alias. + let not_alias = legacy("ish"); + assert_eq!(canonical_agent_type(¬_alias), not_alias.as_str()); + } + /// The legacy default agent type resolves through discovery `by_name`, + /// which is the boundary session-restore and model `agent_type` strings + /// pass through. + #[test] + fn test_by_name_resolves_legacy_agent_type() { + let legacy_plan = format!("{LEGACY_AGENT_TYPE_PREFIX}-plan"); + let def = crate::discovery::by_name(&legacy_plan).expect("legacy agent type resolves"); + assert_eq!(def.name, "kigi-plan"); + assert!( + is_strict_harness_agent_type(&format!("{LEGACY_AGENT_TYPE_PREFIX}-concise")) + == is_strict_harness_agent_type("kigi-concise") + ); + } #[test] fn test_builtin_agent_name_definition_names_match() { use strum::IntoEnumIterator; @@ -2519,7 +2577,7 @@ description: Test default tool config assert_eq!(recovered.mcp_inheritance, def.mcp_inheritance); } fn def_with_template(tpl: crate::prompt::context::TemplateOverride) -> AgentDefinition { - let mut def = AgentDefinition::default_grok_build(); + let mut def = AgentDefinition::default_kigi(); def.system_prompt = tpl; def } diff --git a/crates/codegen/kigi-agent/src/discovery.rs b/crates/codegen/kigi-agent/src/discovery.rs index 16864fd..a51b32c 100644 --- a/crates/codegen/kigi-agent/src/discovery.rs +++ b/crates/codegen/kigi-agent/src/discovery.rs @@ -72,8 +72,8 @@ pub enum SubagentSource { /// `visible == callable` guarantee) /// 4. Filter: remove agents toggled off via `[subagents.toggle]` pub fn all_subagents(cwd: &Path, toggle: &HashMap) -> Vec { - let grok = kigi_config::user_kigi_home(); - all_subagents_with_home(cwd, toggle, dirs::home_dir().as_deref(), grok.as_deref()) + let kigi = kigi_config::user_kigi_home(); + all_subagents_with_home(cwd, toggle, dirs::home_dir().as_deref(), kigi.as_deref()) } fn all_subagents_with_home( @@ -189,7 +189,7 @@ fn merge_subagents( /// 4. `~/.kigi/bundled/agents/` (bundled, lowest priority) /// /// Deduplicates by name — higher-priority definitions win. -/// User-level agent directories in priority order: user grok agents, `.claude` +/// User-level agent directories in priority order: user kigi agents, `.claude` /// compat agents, then bundled. `.kigi` dirs resolve from `kigi_home` /// (KIGI_SHARE_DIR-aware) plus the legacy literal `~/.kigi` when KIGI_SHARE_DIR points /// elsewhere; `.claude` resolves from `home`. @@ -200,7 +200,7 @@ pub(crate) fn user_agent_dirs( // Legacy literal ~/.kigi, included only when it differs from kigi_home // (i.e. KIGI_SHARE_DIR points elsewhere) so agents left in the old location are // still discovered and stay consistent with scope_from_path classification. - let legacy_grok = home + let legacy_kigi = home .map(|h| h.join(".kigi")) .filter(|legacy| kigi_home != Some(legacy.as_path())); @@ -208,7 +208,7 @@ pub(crate) fn user_agent_dirs( if let Some(g) = kigi_home { dirs.push((g.join("agents"), AgentScope::User)); } - if let Some(l) = &legacy_grok { + if let Some(l) = &legacy_kigi { dirs.push((l.join("agents"), AgentScope::User)); } if let Some(h) = home { @@ -217,15 +217,15 @@ pub(crate) fn user_agent_dirs( if let Some(g) = kigi_home { dirs.push((g.join("bundled").join("agents"), AgentScope::Bundled)); } - if let Some(l) = &legacy_grok { + if let Some(l) = &legacy_kigi { dirs.push((l.join("bundled").join("agents"), AgentScope::Bundled)); } dirs } pub fn discover(cwd: &Path) -> Vec { - let grok = kigi_config::user_kigi_home(); - discover_with_home(cwd, dirs::home_dir().as_deref(), grok.as_deref()) + let kigi = kigi_config::user_kigi_home(); + discover_with_home(cwd, dirs::home_dir().as_deref(), kigi.as_deref()) } fn discover_with_home( @@ -251,8 +251,8 @@ fn discover_with_home( /// /// Checks built-ins first, then user-level dirs, then bundled. pub fn by_name(name: &str) -> Option { - let grok = kigi_config::user_kigi_home(); - by_name_with_home(name, dirs::home_dir().as_deref(), grok.as_deref()) + let kigi = kigi_config::user_kigi_home(); + by_name_with_home(name, dirs::home_dir().as_deref(), kigi.as_deref()) } fn by_name_with_home( @@ -260,8 +260,12 @@ fn by_name_with_home( home: Option<&Path>, kigi_home: Option<&Path>, ) -> Option { - // Check built-ins first — type-safe via BuiltinAgentName strum enum - if let Ok(builtin) = BuiltinAgentName::from_str(name) { + // Check built-ins first — type-safe via BuiltinAgentName strum enum. + // Legacy pre-rebrand agent types (persisted in old session files) are + // mapped onto their current names first; see `canonical_agent_type`. + if let Ok(builtin) = + BuiltinAgentName::from_str(crate::config::canonical_agent_type(name).as_ref()) + { return Some(builtin.definition()); } @@ -287,8 +291,8 @@ fn by_name_with_home( /// Project-level `.kigi/agents/` has highest priority, then falls back /// to built-ins, user-level, and finally bundled definitions. pub fn by_name_in_cwd(name: &str, cwd: &Path) -> Option { - let grok = kigi_config::user_kigi_home(); - by_name_in_cwd_with_home(name, cwd, dirs::home_dir().as_deref(), grok.as_deref()) + let kigi = kigi_config::user_kigi_home(); + by_name_in_cwd_with_home(name, cwd, dirs::home_dir().as_deref(), kigi.as_deref()) } fn by_name_in_cwd_with_home( @@ -363,13 +367,13 @@ pub fn all_subagents_with_plugins( toggle: &HashMap, plugins: Option<&crate::plugins::PluginRegistry>, ) -> Vec { - let grok = kigi_config::user_kigi_home(); + let kigi = kigi_config::user_kigi_home(); all_subagents_with_plugins_and_home( cwd, toggle, plugins, dirs::home_dir().as_deref(), - grok.as_deref(), + kigi.as_deref(), ) } @@ -450,13 +454,13 @@ pub fn by_name_in_cwd_with_plugins( cwd: &Path, plugins: Option<&crate::plugins::PluginRegistry>, ) -> Option { - let grok = kigi_config::user_kigi_home(); + let kigi = kigi_config::user_kigi_home(); by_name_in_cwd_with_plugins_and_home( name, cwd, plugins, dirs::home_dir().as_deref(), - grok.as_deref(), + kigi.as_deref(), ) } @@ -533,7 +537,7 @@ fn by_name_in_cwd_with_plugins_and_home( None } -/// Expand `${CLAUDE_PLUGIN_ROOT}` / `${CLAUDE_PLUGIN_DATA}` (and the Grok +/// Expand `${CLAUDE_PLUGIN_ROOT}` / `${CLAUDE_PLUGIN_DATA}` (and the Kigi /// aliases) in a plugin agent's body so the model receives absolute paths, /// matching the expected load-time resolution for these variables. fn substitute_plugin_vars(def: &mut AgentDefinition, plugin: &crate::plugins::LoadedPlugin) { @@ -675,8 +679,8 @@ mod tests { use crate::plugins::PluginOrigin; match scope { PluginScope::CliOverride => PluginOrigin::CliOverride, - PluginScope::Project => PluginOrigin::ProjectGrok, - PluginScope::User => PluginOrigin::UserGrok, + PluginScope::Project => PluginOrigin::ProjectKigi, + PluginScope::User => PluginOrigin::UserKigi, PluginScope::ConfigPath => PluginOrigin::ConfigPath, } } @@ -763,27 +767,27 @@ mod tests { } #[test] - fn user_agent_dirs_includes_legacy_grok_when_kigi_home_differs() { + fn user_agent_dirs_includes_legacy_kigi_when_kigi_home_differs() { let home = Path::new("/home/u"); - let grok = Path::new("/custom/grokhome"); - let paths: Vec<_> = user_agent_dirs(Some(home), Some(grok)) + let kigi = Path::new("/custom/kigihome"); + let paths: Vec<_> = user_agent_dirs(Some(home), Some(kigi)) .into_iter() .map(|(p, _)| p) .collect(); - assert!(paths.contains(&grok.join("agents"))); + assert!(paths.contains(&kigi.join("agents"))); assert!(paths.contains(&home.join(".kigi").join("agents"))); assert!(paths.contains(&home.join(".claude").join("agents"))); - assert!(paths.contains(&grok.join("bundled").join("agents"))); + assert!(paths.contains(&kigi.join("bundled").join("agents"))); assert!(paths.contains(&home.join(".kigi").join("bundled").join("agents"))); } #[test] - fn user_agent_dirs_dedups_legacy_when_kigi_home_is_dot_grok() { + fn user_agent_dirs_dedups_legacy_when_kigi_home_is_dot_kigi() { let home = Path::new("/home/u"); - let grok = home.join(".kigi"); - let count = user_agent_dirs(Some(home), Some(&grok)) + let kigi = home.join(".kigi"); + let count = user_agent_dirs(Some(home), Some(&kigi)) .into_iter() - .filter(|(p, _)| *p == grok.join("agents")) + .filter(|(p, _)| *p == kigi.join("agents")) .count(); assert_eq!( count, 1, @@ -807,10 +811,10 @@ mod tests { } #[test] - fn test_by_name_builtin_grok_build() { - let def = by_name("grok-build"); + fn test_by_name_builtin_kigi() { + let def = by_name("kigi"); assert!(def.is_some()); - assert_eq!(def.unwrap().name, "grok-build"); + assert_eq!(def.unwrap().name, "kigi"); } #[test] @@ -1004,19 +1008,14 @@ mod tests { let agents_dir = tmp.path().join(".kigi").join("agents"); fs::create_dir_all(&agents_dir).unwrap(); - // Create a project-level "grok-build" that shadows the built-in - write_agent_file( - &agents_dir, - "grok-build.md", - "grok-build", - "Custom grok-build", - ); + // Create a project-level "kigi" that shadows the built-in + write_agent_file(&agents_dir, "kigi.md", "kigi", "Custom kigi"); - let def = by_name_in_cwd("grok-build", tmp.path()); + let def = by_name_in_cwd("kigi", tmp.path()); assert!(def.is_some()); let def = def.unwrap(); - assert_eq!(def.name, "grok-build"); - assert_eq!(def.description, "Custom grok-build"); + assert_eq!(def.name, "kigi"); + assert_eq!(def.description, "Custom kigi"); } #[test] @@ -1024,10 +1023,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); // No .kigi/agents/ directory — should fall back to built-in - let def = by_name_in_cwd("grok-build", tmp.path()); + let def = by_name_in_cwd("kigi", tmp.path()); assert!(def.is_some()); let def = def.unwrap(); - assert_eq!(def.name, "grok-build"); + assert_eq!(def.name, "kigi"); // Should be the built-in, not a custom one assert_eq!(def.scope, AgentScope::BuiltIn); } @@ -1048,11 +1047,11 @@ mod tests { #[test] fn test_orchestrator_from_str_resolves() { use std::str::FromStr; - let variant = BuiltinAgentName::from_str("grok-build-orchestrator") - .expect("from_str must resolve grok-build-orchestrator"); - assert_eq!(variant, BuiltinAgentName::GrokBuildOrchestrator); + let variant = BuiltinAgentName::from_str("kigi-orchestrator") + .expect("from_str must resolve kigi-orchestrator"); + assert_eq!(variant, BuiltinAgentName::KigiOrchestrator); let def = variant.definition(); - assert_eq!(def.name, "grok-build-orchestrator"); + assert_eq!(def.name, "kigi-orchestrator"); assert!( def.prompt_body.is_some(), "orchestrator must have prompt_body" @@ -1067,9 +1066,9 @@ mod tests { #[test] fn test_orchestrator_by_name_in_cwd() { let tmp = tempfile::tempdir().unwrap(); - let def = by_name_in_cwd("grok-build-orchestrator", tmp.path()) - .expect("by_name_in_cwd must find grok-build-orchestrator"); - assert_eq!(def.name, "grok-build-orchestrator"); + let def = by_name_in_cwd("kigi-orchestrator", tmp.path()) + .expect("by_name_in_cwd must find kigi-orchestrator"); + assert_eq!(def.name, "kigi-orchestrator"); assert!(def.prompt_body.is_some()); } @@ -1461,7 +1460,7 @@ mod tests { let registry = make_plugin_registry("plugin-one", PluginScope::User, vec![]); let plugin = registry.get("plugin-one").unwrap(); - let mut def = AgentDefinition::default_grok_build(); + let mut def = AgentDefinition::default_kigi(); def.prompt_body = Some("Body ${CLAUDE_PLUGIN_ROOT}/x".to_string()); def.system_prompt = TemplateOverride::Custom("Data at ${CLAUDE_PLUGIN_DATA}/db".to_string()); diff --git a/crates/codegen/kigi-agent/src/lib.rs b/crates/codegen/kigi-agent/src/lib.rs index a694442..edad2a2 100644 --- a/crates/codegen/kigi-agent/src/lib.rs +++ b/crates/codegen/kigi-agent/src/lib.rs @@ -23,7 +23,7 @@ pub use compaction::CompactionPolicy; pub use config::AgentDefinition; pub use config::preset_names; pub use config::toolset_for_preset; -pub use config::workspace_grok_build_toolset; +pub use config::workspace_kigi_toolset; pub use error::AgentBuildError; pub use prompt::context::{DEFAULT_SYSTEM_PROMPT_LABEL, PromptContext}; pub use system_reminder::ReminderPolicy; diff --git a/crates/codegen/kigi-agent/src/plugins/discovery.rs b/crates/codegen/kigi-agent/src/plugins/discovery.rs index 34eca5f..177d143 100644 --- a/crates/codegen/kigi-agent/src/plugins/discovery.rs +++ b/crates/codegen/kigi-agent/src/plugins/discovery.rs @@ -69,11 +69,11 @@ pub enum PluginOrigin { /// CLI `--plugin-dir`. CliOverride, /// Project `.kigi/plugins/`. - ProjectGrok, + ProjectKigi, /// Project `.claude/plugins/`. ProjectClaude, /// `$KIGI_SHARE_DIR/plugins/`. - UserGrok, + UserKigi, /// `~/.claude/plugins/`. UserClaude, /// A compat marketplace clone (project `extraKnownMarketplaces` @@ -87,7 +87,7 @@ pub enum PluginOrigin { /// Marketplace name from the `name@marketplace` JSON key, when present. marketplace: Option, }, - /// Grok's install registry (`~/.kigi/installed-plugins`). + /// Kigi's install registry (`~/.kigi/installed-plugins`). MarketplaceInstall { /// Git URL of the installed repo (None for local installs). git_url: Option, @@ -214,10 +214,10 @@ impl DiscoveryConfig { /// paths all resolve under `kigi_home()`, so a plugin scanned from the legacy /// tree would appear untrusted and lose its persisted state. Keeping plugins on /// `kigi_home()` only avoids that half-initialized state. -fn user_plugin_dirs(home: Option<&Path>, grok: Option<&Path>) -> Vec<(PathBuf, PluginOrigin)> { +fn user_plugin_dirs(home: Option<&Path>, kigi: Option<&Path>) -> Vec<(PathBuf, PluginOrigin)> { let mut dirs = Vec::new(); - if let Some(g) = grok { - dirs.push((g.join("plugins"), PluginOrigin::UserGrok)); + if let Some(g) = kigi { + dirs.push((g.join("plugins"), PluginOrigin::UserKigi)); } if let Some(h) = home { dirs.push((h.join(".claude").join("plugins"), PluginOrigin::UserClaude)); @@ -234,7 +234,7 @@ fn project_plugins_dir_origin(plugins_dir: &Path) -> PluginOrigin { if is_claude { PluginOrigin::ProjectClaude } else { - PluginOrigin::ProjectGrok + PluginOrigin::ProjectKigi } } @@ -336,10 +336,10 @@ pub fn discover_plugins( } // 4-5. User plugins: $KIGI_SHARE_DIR/plugins, legacy ~/.kigi/plugins, ~/.claude/plugins. - // Gate the grok plugins dir on user_kigi_home() so a project's .kigi/plugins + // Gate the kigi plugins dir on user_kigi_home() so a project's .kigi/plugins // is never scanned as user-global when no home resolves. - let grok = kigi_config::user_kigi_home(); - let plugin_dirs = user_plugin_dirs(dirs::home_dir().as_deref(), grok.as_deref()); + let kigi = kigi_config::user_kigi_home(); + let plugin_dirs = user_plugin_dirs(dirs::home_dir().as_deref(), kigi.as_deref()); for (plugins_dir, origin) in plugin_dirs { if plugins_dir.is_dir() { scan_plugin_dir( @@ -903,11 +903,11 @@ mod tests { } #[test] - fn user_plugin_dirs_are_grok_and_claude_only_no_legacy() { + fn user_plugin_dirs_are_kigi_and_claude_only_no_legacy() { let home = Path::new("/home/u"); - let grok = Path::new("/custom/grokhome"); - let dirs = user_plugin_dirs(Some(home), Some(grok)); - assert!(dirs.contains(&(grok.join("plugins"), PluginOrigin::UserGrok))); + let kigi = Path::new("/custom/kigihome"); + let dirs = user_plugin_dirs(Some(home), Some(kigi)); + assert!(dirs.contains(&(kigi.join("plugins"), PluginOrigin::UserKigi))); assert!(dirs.contains(&( home.join(".claude").join("plugins"), PluginOrigin::UserClaude @@ -921,7 +921,7 @@ mod tests { } #[test] - fn user_plugin_dirs_empty_without_home_or_grok() { + fn user_plugin_dirs_empty_without_home_or_kigi() { assert!(user_plugin_dirs(None, None).is_empty()); } @@ -951,10 +951,10 @@ mod tests { } #[test] - fn project_plugins_dir_origin_distinguishes_grok_and_claude() { + fn project_plugins_dir_origin_distinguishes_kigi_and_claude() { assert_eq!( project_plugins_dir_origin(Path::new("/repo/.kigi/plugins")), - PluginOrigin::ProjectGrok + PluginOrigin::ProjectKigi ); assert_eq!( project_plugins_dir_origin(Path::new("/repo/.claude/plugins")), @@ -967,18 +967,18 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); // Create ~/.kigi/plugins/ structure - let grok_plugins = tmp.path().join(".kigi").join("plugins"); - std::fs::create_dir_all(&grok_plugins).unwrap(); - make_manifest_plugin(&grok_plugins, "user-tool"); + let kigi_plugins = tmp.path().join(".kigi").join("plugins"); + std::fs::create_dir_all(&kigi_plugins).unwrap(); + make_manifest_plugin(&kigi_plugins, "user-tool"); // Override home dir by directly scanning let trust = TrustStore::load_from(tmp.path().join("trust")); let mut seen = HashSet::new(); let mut candidates = Vec::new(); scan_plugin_dir( - &grok_plugins, + &kigi_plugins, PluginScope::User, - PluginOrigin::UserGrok, + PluginOrigin::UserKigi, &trust, false, &mut seen, @@ -1002,7 +1002,7 @@ mod tests { scan_plugin_dir( &plugins_dir, PluginScope::User, - PluginOrigin::UserGrok, + PluginOrigin::UserKigi, &trust, false, &mut seen, @@ -1325,7 +1325,7 @@ mod tests { collect_plugin( &user_plugin, PluginScope::User, - PluginOrigin::UserGrok, + PluginOrigin::UserKigi, &trust, false, &mut seen, @@ -1381,7 +1381,7 @@ mod tests { collect_plugin( &empty_dir, PluginScope::User, - PluginOrigin::UserGrok, + PluginOrigin::UserKigi, &trust, false, &mut seen, @@ -1404,7 +1404,7 @@ mod tests { collect_plugin( &plugin_dir, PluginScope::Project, - PluginOrigin::ProjectGrok, + PluginOrigin::ProjectKigi, &trust, false, &mut seen, @@ -1427,7 +1427,7 @@ mod tests { collect_plugin( &plugin_dir, PluginScope::Project, - PluginOrigin::ProjectGrok, + PluginOrigin::ProjectKigi, &trust, true, &mut seen, @@ -1458,7 +1458,7 @@ mod tests { PluginScope::CliOverride, PluginOrigin::CliOverride, ), - (&user_dir, PluginScope::User, PluginOrigin::UserGrok), + (&user_dir, PluginScope::User, PluginOrigin::UserKigi), ( &config_dir, PluginScope::ConfigPath, @@ -1505,7 +1505,7 @@ mod tests { .find(|p| p.manifest.name == "proj-mcp") .expect("project plugin discovered"); assert_eq!(p.scope, PluginScope::Project); - assert_eq!(p.origin, PluginOrigin::ProjectGrok); + assert_eq!(p.origin, PluginOrigin::ProjectKigi); assert!(!p.trusted, "untrusted folder must block the project plugin"); // Trusted folder: the same plugin is allowed. diff --git a/crates/codegen/kigi-agent/src/plugins/registry.rs b/crates/codegen/kigi-agent/src/plugins/registry.rs index 198e10e..9dc5a20 100644 --- a/crates/codegen/kigi-agent/src/plugins/registry.rs +++ b/crates/codegen/kigi-agent/src/plugins/registry.rs @@ -654,8 +654,8 @@ mod tests { scope, origin: match scope { PluginScope::CliOverride => PluginOrigin::CliOverride, - PluginScope::Project => PluginOrigin::ProjectGrok, - PluginScope::User => PluginOrigin::UserGrok, + PluginScope::Project => PluginOrigin::ProjectKigi, + PluginScope::User => PluginOrigin::UserKigi, PluginScope::ConfigPath => PluginOrigin::ConfigPath, }, trusted, diff --git a/crates/codegen/kigi-agent/src/plugins/trust.rs b/crates/codegen/kigi-agent/src/plugins/trust.rs index 44fbd56..490fd29 100644 --- a/crates/codegen/kigi-agent/src/plugins/trust.rs +++ b/crates/codegen/kigi-agent/src/plugins/trust.rs @@ -40,13 +40,13 @@ impl TrustStore { pub fn load() -> Self { // Gate on user_kigi_home() so a project's `.kigi/trusted-plugins` is never // read as the user trust store when neither KIGI_SHARE_DIR nor a home dir resolves. - let Some(grok) = kigi_config::user_kigi_home() else { + let Some(kigi) = kigi_config::user_kigi_home() else { return Self { trusted: HashSet::new(), file_path: PathBuf::new(), }; }; - let file_path = grok.join(TRUST_FILE_NAME); + let file_path = kigi.join(TRUST_FILE_NAME); let trusted = Self::read_trust_file(&file_path); Self { trusted, file_path } } diff --git a/crates/codegen/kigi-agent/src/prompt/context.rs b/crates/codegen/kigi-agent/src/prompt/context.rs index 687968f..29b0d32 100644 --- a/crates/codegen/kigi-agent/src/prompt/context.rs +++ b/crates/codegen/kigi-agent/src/prompt/context.rs @@ -144,13 +144,13 @@ pub struct PromptContext { /// stdio / generic-ACP). #[serde(default)] pub is_non_interactive: bool, - /// Identity in the primary grok-build system prompt (`You are