§9 acceptance: grep-zero sweep — every internal x.ai/grok identifier renamed
The PRD's first acceptance gate now holds: grep -RinE '\bx\.ai\b|grok' crates/ --include='*.rs' → 0 matches (exempt: NOTICE and third-party license archives, README provenance, and the required 'Based on Grok Build Open Source' attribution, now sourced from version_attribution.txt). Wire-visible renames (both sides in this repo, changed in lockstep): - Auth method id 'grok.com' → 'kimi-code' (AuthMethodKind::KimiCode). - Every x.ai/* and _x.ai/* ACP ext method and meta key → kigi/* / _kigi/* (~200 names; grokShell → kigiShell). Session-file replay keeps a read-side alias for the legacy '_x.ai/session/update' method so existing updates.jsonl histories load; writes emit only the new name (both directions test-pinned). - Agent types grok-build* → kigi* with a documented legacy-prefix alias at resolution time so persisted sessions keep resolving. - ToolNamespace/BuiltinAgentName GrokBuild* → Kigi* (wire snake_case kigi/kigi_concise/kigi_hashline; schema regenerated); grok_build implementation dirs renamed to kigi*. - x-grok-* headers → x-kigi-*, __GROK_* sentinels → __KIGI_*, themes grokday/groknight → kigiday/kiginight (old persisted values fall back to the default theme), web_fetch allowlist xAI hosts → kimi.com + moonshot platforms, changelog CDN → this repo, grok-build changelog archives deleted. - BYOK default endpoint removed: [endpoints] api_base_url is now truly optional with NO default — consumers fail fast with the flag name when unset (no silent x.ai egress). Mock harnesses inject it explicitly. - System-prompt identity fixed: 'released by xAI' → 'an unofficial community CLI for Kimi' (template + regenerated encrypted form). Also repaired pre-existing grok-era test debt found by the sweep: the stale trace_classify default-model pin, the grok-pager UA label test, pty-harness stale-binary reuse and non-hermetic moonshot routing (a PTY test could previously reach the real api.moonshot.cn), and the outdated oauth fixture scope key. Gates: §9 grep 0; fmt clean; workspace check/clippy 0/0 (-D warnings); FULL cargo test --workspace: 234 suites, 21,961 passed, 0 failed; deny advisories ok.
This commit is contained in:
1 parent
86e3724310
commit
6f31415ed6
1056 files changed
+8410
-18307
No files matched your search
@@ -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<ToolKind> {
|
||||
kigi_tools::types::kind_for(name)
|
||||
@@ -55,7 +55,7 @@ pub struct AgentBuilder {
|
||||
notification_handle: ToolNotificationHandle,
|
||||
owner_session_id: Option<String>,
|
||||
parent_scheduler_handle:
|
||||
Option<kigi_tools::implementations::grok_build::scheduler::types::SchedulerHandle>,
|
||||
Option<kigi_tools::implementations::kigi::scheduler::types::SchedulerHandle>,
|
||||
/// The agent definition — set via from_definition() or built up
|
||||
/// via individual with_*() calls.
|
||||
definition: Option<AgentDefinition>,
|
||||
@@ -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<std::sync::Arc<dyn kigi_tools::implementations::lsp::LspBackend>>,
|
||||
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<String>) -> 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<String> =
|
||||
@@ -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<String>, disallowed: Vec<String>) -> 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<String> {
|
||||
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<String> = 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(),
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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<String, bool>) -> Vec<SubagentEntry> {
|
||||
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<AgentDefinition> {
|
||||
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<AgentDefinition> {
|
||||
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<AgentDefinition> {
|
||||
// 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<AgentDefinition> {
|
||||
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<String, bool>,
|
||||
plugins: Option<&crate::plugins::PluginRegistry>,
|
||||
) -> Vec<SubagentEntry> {
|
||||
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<AgentDefinition> {
|
||||
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());
|
||||
|
||||
@@ -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;
|
||||
@@ -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<String>,
|
||||
},
|
||||
/// 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<String>,
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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 <label>…`).
|
||||
/// Identity in the primary kigi system prompt (`You are <label>…`).
|
||||
/// Not the UI picker name. Defaults to [`DEFAULT_SYSTEM_PROMPT_LABEL`].
|
||||
#[serde(default = "default_system_prompt_label")]
|
||||
pub system_prompt_label: String,
|
||||
}
|
||||
/// Default identity on trim-tool-descriptions (`You are Grok released by xAI`).
|
||||
pub const DEFAULT_SYSTEM_PROMPT_LABEL: &str = "Grok";
|
||||
/// Default identity on trim-tool-descriptions (`You are Kigi released by xAI`).
|
||||
pub const DEFAULT_SYSTEM_PROMPT_LABEL: &str = "Kigi";
|
||||
fn default_system_prompt_label() -> String {
|
||||
DEFAULT_SYSTEM_PROMPT_LABEL.to_string()
|
||||
}
|
||||
@@ -427,9 +427,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_placeholders_system_prompt_label_override() {
|
||||
let mut ctx = test_context();
|
||||
ctx.system_prompt_label = "Grok Internal".into();
|
||||
ctx.system_prompt_label = "Kigi Internal".into();
|
||||
let p = ctx.placeholders();
|
||||
assert_eq!(p["system_prompt_label"], "Grok Internal");
|
||||
assert_eq!(p["system_prompt_label"], "Kigi Internal");
|
||||
}
|
||||
#[test]
|
||||
fn test_missing_system_prompt_label_deserializes_to_default() {
|
||||
@@ -1229,7 +1229,7 @@ mod tests {
|
||||
("plan", plan),
|
||||
] {
|
||||
assert!(
|
||||
!prompt.contains("You are a Grok Build agent"),
|
||||
!prompt.contains("You are a Kigi agent"),
|
||||
"{name} prompt should not duplicate base template identity"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// XOR-encrypted prompt templates (key = position-dependent seed).
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub(crate) const BASE_PROMPT_ENC: &[u8] = &[3, 52, 41, 125, 63, 45, 5, 65, 70, 24, 31, 69, 21, 30, 27, 29, 15, 6, 51, 29, 28, 0, 29, 1, 6, 44, 24, 20, 20, 18, 20, 89, 7, 6, 92, 15, 27, 19, 229, 224, 241, 230, 224, 165, 228, 254, 168, 241, 203, 194, 162, 173, 215, 224, 229, 177, 243, 225, 241, 181, 178, 236, 189, 180, 186, 242, 250, 189, 247, 236, 255, 207, 205, 205, 251, 204, 200, 211, 205, 219, 203, 200, 216, 196, 216, 202, 144, 148, 207, 147, 213, 219, 150, 214, 205, 205, 213, 213, 211, 208, 209, 202, 179, 225, 163, 164, 161, 171, 178, 231, 188, 161, 171, 191, 236, 174, 161, 162, 160, 189, 183, 167, 177, 166, 246, 164, 183, 191, 174, 172, 189, 175, 187, 255, 133, 143, 133, 138, 138, 128, 131, 149, 129, 135, 141, 203, 152, 140, 157, 132, 131, 223, 214, 136, 209, 216, 214, 146, 148, 138, 159, 219, 217, 128, 222, 158, 110, 33, 107, 109, 112, 96, 116, 102, 107, 125, 99, 125, 105, 45, 77, 67, 89, 49, 102, 124, 123, 121, 54, 99, 112, 120, 110, 59, 116, 120, 114, 111, 83, 1, 87, 80, 65, 87, 85, 7, 95, 64, 94, 67, 12, 94, 65, 73, 68, 70, 83, 65, 81, 21, 83, 89, 95, 80, 84, 94, 89, 79, 87, 81, 39, 97, 54, 34, 55, 46, 53, 105, 108, 50, 111, 102, 108, 40, 32, 43, 57, 55, 114, 118, 41, 117, 15, 56, 45, 43, 122, 54, 61, 52, 48, 127, 7, 14, 3, 15, 68, 12, 21, 71, 28, 6, 74, 8, 3, 0, 30, 3, 21, 5, 23, 83, 0, 29, 19, 87, 13, 10, 31, 9, 91, 14, 94, 13, 229, 240, 247, 230, 247, 241, 170, 167, 236, 236, 228, 228, 248, 232, 234, 175, 231, 248, 230, 251, 253, 251, 182, 227, 240, 252, 186, 167, 233, 238, 251, 237, 255, 208, 215, 198, 214, 220, 152, 135, 220, 200, 205, 133, 166, 167, 146, 206, 211, 197, 219, 220, 218, 234, 197, 214, 222, 220, 206, 194, 130, 183, 233, 218, 169, 166, 170, 227, 161, 164, 165, 175, 232, 168, 169, 191, 165, 162, 160, 239, 178, 168, 242, 187, 187, 162, 246, 178, 185, 170, 179, 183, 165, 253, 183, 171, 192, 130, 131, 141, 196, 135, 131, 199, 157, 135, 142, 132, 130, 136, 206, 142, 158, 149, 210, 155, 155, 130, 214, 145, 153, 139, 218, 146, 136, 142, 222, 154, 102, 103, 103, 96, 112, 118, 38, 117, 109, 104, 105, 99, 34, 45, 66, 96, 115, 112, 126, 63, 52, 103, 115, 97, 125, 107, 105, 114, 126, 113, 123, 63, 87, 78, 80, 72, 4, 86, 83, 68, 64, 9, 75, 88, 12, 72, 74, 70, 68, 88, 92, 84, 20, 83, 95, 91, 93, 74, 26, 90, 82, 89, 30, 77, 53, 47, 44, 42, 42, 34, 102, 51, 45, 58, 62, 56, 108, 36, 61, 111, 54, 56, 60, 54, 116, 33, 57, 119, 60, 54, 122, 61, 46, 56, 59, 51, 25, 79, 66, 33, 1, 3, 9, 21, 13, 73, 15, 19, 9, 14, 27, 27, 25, 31, 21, 83, 21, 27, 15, 87, 25, 26, 14, 18, 19, 19, 13, 95, 244, 233, 227, 247, 164, 228, 244, 226, 168, 225, 235, 249, 232, 173, 250, 224, 176, 227, 247, 229, 241, 231, 229, 242, 180, 185, 232, 254, 253, 254, 246, 191, 211, 201, 195, 209, 193, 193, 134, 194, 208, 221, 207, 217, 194, 204, 194, 143, 195, 200, 193, 199, 209, 216, 197, 155, 152, 214, 200, 155, 221, 207, 219, 159, 175, 181, 170, 166, 182, 178, 175, 180, 173, 233, 184, 162, 191, 166, 183, 239, 191, 163, 242, 183, 177, 166, 162, 165, 173, 186, 174, 178, 170, 184, 242, 255, 131, 137, 135, 128, 143, 197, 145, 142, 156, 129, 202, 159, 132, 136, 206, 154, 131, 148, 128, 211, 146, 156, 132, 132, 140, 215, 240, 241, 191, 146, 144, 153, 105, 115, 111, 106, 106, 98, 38, 110, 123, 41, 105, 99, 105, 108, 126, 52, 48, 112, 50, 126, 125, 102, 98, 118, 115, 124, 116, 59, 125, 126, 106, 118, 79, 79, 2, 74, 87, 5, 72, 72, 92, 9, 2, 88, 89, 78, 70, 15, 81, 66, 18, 95, 91, 70, 66, 23, 79, 86, 72, 80, 16, 29, 83, 90, 51, 50, 35, 36, 33, 54, 102, 62, 39, 60, 106, 40, 45, 35, 32, 32, 36, 113, 39, 61, 39, 48, 56, 51, 116, 121, 62, 62, 48, 56, 42, 58, 4, 65, 0, 17, 5, 11, 5, 15, 13, 26, 67, 69, 76, 43, 1, 29, 80, 5, 26, 28, 7, 16, 86, 20, 25, 10, 31, 8, 80, 93, 10, 30, 235, 228, 162, 247, 236, 224, 166, 228, 231, 231, 254, 238, 244, 249, 162, 175, 228, 249, 247, 179, 245, 246, 226, 254, 247, 247, 182, 187, 253, 243, 250, 191, 212, 201, 199, 131, 209, 214, 195, 213, 143, 218, 138, 194, 194, 222, 218, 221, 197, 210, 198, 218, 219, 219, 197, 151, 209, 215, 206, 212, 156, 220, 221, 220, 175, 180, 172, 183, 255, 229, 164, 190, 232, 173, 175, 173, 173, 184, 162, 187, 252, 241, 161, 178, 173, 245, 161, 191, 185, 173, 250, 162, 179, 168, 254, 175, 140, 128, 140, 195, 144, 138, 198, 131, 135, 201, 139, 133, 136, 205, 143, 156, 155, 209, 144, 150, 146, 154, 132, 146, 216, 157, 149, 146, 146, 154, 222, 150, 116, 47, 34, 86, 119, 96, 116, 116, 40, 106, 107, 101, 44, 98, 120, 106, 98, 99, 123, 119, 113, 53, 98, 127, 121, 109, 58, 127, 121, 123, 127, 106, 76, 85, 2, 193, 164, 177, 6, 78, 78, 9, 94, 67, 73, 84, 14, 74, 72, 65, 94, 90, 87, 92, 66, 91, 65, 25, 91, 72, 87, 29, 71, 80, 53, 97, 54, 44, 100, 36, 37, 51, 104, 36, 37, 57, 41, 109, 47, 58, 36, 62, 60, 60, 57, 58, 35, 36, 52, 32, 118, 123, 37, 50, 43, 127, 13, 0, 27, 67, 20, 23, 9, 4, 13, 12, 14, 75, 27, 4, 26, 7, 31, 4, 6, 83, 23, 26, 24, 17, 17, 11, 23, 26, 8, 20, 17, 17, 172, 161, 224, 246, 240, 165, 245, 243, 225, 229, 230, 171, 225, 228, 224, 235, 176, 227, 251, 224, 255, 230, 182, 246, 246, 253Line truncated
|
||||
pub(crate) const BASE_PROMPT_ENC: &[u8] = &[3, 52, 41, 125, 63, 45, 5, 65, 70, 24, 31, 69, 21, 30, 27, 29, 15, 6, 51, 29, 28, 0, 29, 1, 6, 44, 24, 20, 20, 18, 20, 89, 7, 6, 80, 93, 31, 17, 160, 244, 236, 236, 226, 227, 239, 228, 225, 232, 230, 171, 239, 226, 227, 226, 229, 255, 251, 231, 237, 181, 213, 219, 209, 185, 252, 244, 238, 189, 213, 246, 205, 200, 140, 131, 253, 202, 211, 135, 201, 219, 207, 139, 136, 214, 139, 130, 144, 216, 212, 147, 221, 198, 233, 217, 215, 215, 229, 210, 210, 201, 219, 205, 161, 162, 182, 170, 178, 160, 230, 226, 181, 233, 171, 165, 236, 172, 187, 187, 191, 191, 189, 190, 187, 160, 165, 247, 185, 190, 191, 181, 168, 253, 170, 183, 129, 149, 194, 128, 139, 136, 150, 139, 141, 157, 143, 152, 204, 158, 129, 137, 132, 134, 147, 129, 145, 213, 147, 153, 159, 144, 148, 158, 153, 143, 151, 145, 103, 33, 118, 98, 119, 110, 117, 41, 44, 114, 47, 38, 44, 104, 98, 124, 117, 49, 55, 110, 52, 116, 120, 55, 113, 119, 110, 126, 110, 124, 125, 107, 73, 87, 71, 3, 103, 105, 111, 7, 92, 70, 69, 71, 12, 89, 70, 78, 68, 17, 90, 86, 88, 69, 69, 23, 77, 74, 95, 73, 79, 29, 73, 86, 52, 41, 98, 48, 43, 35, 50, 48, 41, 59, 47, 107, 41, 35, 41, 38, 62, 52, 55, 33, 61, 59, 49, 119, 44, 56, 41, 48, 47, 115, 122, 36, 69, 76, 66, 6, 10, 1, 15, 1, 72, 76, 23, 75, 53, 2, 27, 29, 80, 28, 19, 26, 26, 85, 17, 24, 25, 21, 90, 18, 15, 93, 10, 16, 160, 226, 237, 238, 244, 233, 227, 243, 237, 169, 254, 227, 233, 173, 251, 252, 245, 227, 181, 224, 180, 231, 243, 230, 237, 252, 233, 239, 176, 189, 250, 250, 206, 206, 214, 198, 192, 133, 209, 206, 220, 193, 195, 197, 140, 217, 198, 202, 144, 141, 199, 192, 209, 199, 233, 198, 205, 220, 200, 194, 130, 157, 202, 222, 167, 239, 200, 201, 248, 164, 165, 179, 161, 166, 164, 148, 191, 172, 168, 170, 164, 168, 236, 217, 131, 176, 191, 176, 176, 249, 191, 186, 191, 181, 254, 190, 131, 149, 139, 140, 138, 197, 132, 158, 200, 129, 133, 156, 204, 136, 143, 156, 153, 157, 139, 211, 157, 129, 214, 148, 153, 151, 218, 153, 153, 221, 139, 145, 100, 110, 108, 102, 36, 100, 104, 99, 40, 97, 101, 124, 44, 107, 111, 125, 48, 120, 102, 96, 52, 112, 112, 113, 125, 122, 110, 104, 60, 111, 123, 126, 67, 73, 12, 3, 104, 74, 69, 70, 68, 5, 10, 89, 73, 91, 75, 93, 67, 88, 80, 95, 81, 21, 65, 88, 74, 82, 26, 72, 73, 94, 86, 31, 33, 50, 98, 38, 32, 44, 50, 46, 38, 46, 106, 45, 37, 33, 43, 60, 112, 48, 60, 55, 116, 39, 35, 57, 54, 48, 52, 60, 124, 41, 59, 44, 20, 18, 66, 10, 23, 69, 0, 14, 6, 12, 74, 31, 3, 77, 10, 0, 80, 23, 0, 22, 17, 25, 15, 89, 88, 59, 31, 29, 19, 15, 27, 95, 229, 249, 231, 224, 241, 241, 239, 233, 239, 169, 235, 229, 245, 173, 239, 236, 228, 248, 253, 253, 231, 181, 226, 255, 249, 237, 186, 250, 238, 248, 190, 247, 193, 211, 198, 131, 208, 202, 134, 213, 205, 223, 207, 217, 223, 200, 130, 143, 194, 212, 211, 208, 220, 149, 197, 223, 217, 203, 223, 223, 156, 216, 198, 203, 165, 179, 172, 162, 168, 229, 181, 190, 187, 189, 175, 166, 191, 225, 238, 160, 162, 241, 179, 161, 177, 245, 185, 163, 176, 188, 168, 172, 181, 174, 187, 255, 146, 136, 145, 136, 157, 197, 137, 149, 200, 141, 143, 152, 152, 159, 155, 140, 132, 152, 132, 150, 216, 213, 149, 159, 157, 154, 145, 219, 139, 148, 138, 151, 32, 117, 106, 102, 36, 112, 117, 98, 122, 41, 108, 98, 126, 126, 122, 33, 26, 27, 81, 124, 122, 115, 127, 101, 117, 112, 116, 124, 60, 116, 109, 63, 67, 73, 71, 66, 84, 30, 6, 70, 8, 68, 67, 88, 88, 76, 69, 74, 94, 17, 83, 80, 64, 92, 89, 89, 24, 80, 73, 27, 82, 82, 74, 31, 104, 50, 55, 32, 44, 101, 39, 52, 104, 37, 37, 56, 56, 109, 57, 32, 34, 58, 126, 115, 57, 48, 37, 36, 57, 62, 63, 40, 124, 36, 49, 42, 64, 2, 3, 13, 10, 10, 18, 71, 29, 7, 25, 14, 2, 9, 66, 79, 20, 20, 30, 22, 0, 16, 18, 87, 26, 11, 27, 21, 31, 21, 27, 12, 169, 175, 162, 197, 235, 247, 166, 243, 224, 230, 249, 238, 172, 238, 239, 252, 245, 226, 190, 179, 224, 244, 253, 242, 184, 237, 242, 254, 188, 254, 241, 241, 212, 196, 218, 215, 136, 133, 210, 207, 205, 137, 203, 200, 216, 196, 193, 193, 156, 145, 211, 221, 208, 149, 194, 223, 221, 153, 207, 200, 217, 207, 153, 204, 224, 168, 172, 176, 176, 183, 179, 164, 188, 160, 165, 165, 191, 237, 167, 161, 164, 190, 242, 178, 183, 182, 185, 162, 182, 173, 225, 251, 190, 164, 254, 187, 133, 135, 131, 150, 136, 145, 202, 199, 155, 136, 147, 203, 155, 133, 143, 155, 208, 136, 157, 134, 212, 133, 154, 150, 150, 217, 142, 148, 220, 153, 145, 223, 97, 111, 102, 35, 101, 118, 109, 39, 106, 108, 108, 100, 126, 104, 46, 107, 127, 120, 124, 116, 52, 124, 98, 57, 56, 76, 105, 126, 110, 110, 62, 124, 65, 79, 2, 76, 82, 64, 84, 85, 65, 77, 79, 11, 88, 69, 79, 91, 16, 85, 87, 85, 85, 64, 90, 67, 24, 219, 186, 175, 28, 84, 88, 31, 52, 41, 39, 58, 100, 32, 62, 55, 36, 32, 41, 34, 56, 33, 55, 111, 49, 34, 57, 115, 45, 58, 35, 119, 44, 54, 122, 58, 63, 41, 126, 50, 15, 19, 7, 67, 5, 16, 18, 8, 6, 6, 7, 4, 25, 30, 2, 22, 92, 81, 11, 28, 1, 85, 27, 22, 1, 89, 10, 9, 19, 30, 27, 26, 228, 161, 245, 234, 240, 237, 233, 242, 252, 169, 233, 228, 226, 235, 231, 253, 253, 240, 230, 250, 251, 251, 186, 183, 2Line truncated
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub(crate) const CODEX_PROMPT_ENC: &[u8] = &[34, 19, 8, 94, 30, 242, 228, 162, 226, 164, 230, 233, 227, 225, 231, 237, 171, 237, 234, 235, 225, 228, 177, 224, 230, 250, 251, 255, 249, 255, 185, 243, 245, 188, 233, 246, 250, 128, 234, 203, 196, 205, 133, 229, 235, 225, 133, 138, 202, 140, 217, 203, 221, 221, 216, 220, 210, 216, 152, 212, 214, 203, 220, 222, 155, 223, 210, 218, 214, 174, 166, 226, 162, 183, 182, 175, 180, 188, 168, 164, 191, 226, 237, 151, 160, 165, 241, 179, 161, 177, 245, 179, 175, 168, 188, 185, 175, 185, 185, 254, 171, 143, 193, 128, 134, 196, 149, 148, 130, 139, 128, 153, 142, 192, 205, 157, 142, 150, 148, 222, 211, 149, 155, 146, 215, 144, 156, 150, 139, 154, 136, 146, 209, 10, 11, 70, 108, 36, 107, 105, 115, 40, 123, 111, 123, 126, 98, 106, 122, 115, 116, 62, 51, 103, 96, 123, 122, 121, 107, 115, 97, 121, 49, 62, 111, 65, 83, 67, 83, 76, 87, 71, 84, 77, 5, 10, 68, 94, 13, 65, 91, 88, 84, 64, 68, 93, 70, 83, 23, 74, 92, 76, 94, 93, 81, 30, 75, 40, 36, 98, 32, 43, 43, 50, 34, 38, 61, 57, 107, 35, 43, 110, 59, 56, 56, 33, 115, 39, 44, 37, 35, 61, 52, 122, 43, 46, 50, 51, 47, 20, 65, 22, 12, 68, 17, 14, 2, 72, 28, 25, 14, 30, 65, 78, 10, 6, 20, 28, 83, 29, 19, 86, 22, 11, 18, 31, 31, 92, 25, 23, 13, 229, 226, 246, 239, 253, 171, 166, 206, 238, 169, 254, 227, 233, 173, 251, 252, 245, 227, 178, 242, 231, 254, 229, 183, 249, 251, 245, 238, 232, 189, 231, 240, 213, 211, 130, 202, 202, 214, 210, 213, 221, 202, 222, 194, 195, 195, 221, 131, 144, 195, 215, 192, 196, 218, 216, 211, 152, 205, 210, 218, 200, 157, 199, 208, 181, 225, 163, 177, 161, 229, 167, 231, 171, 166, 174, 162, 162, 170, 238, 174, 163, 162, 187, 160, 160, 180, 184, 163, 248, 184, 180, 191, 252, 175, 187, 187, 137, 147, 135, 128, 144, 197, 146, 136, 200, 157, 130, 142, 204, 153, 143, 156, 155, 209, 147, 135, 212, 157, 151, 153, 156, 215, 240, 241, 165, 146, 139, 141, 32, 98, 99, 115, 101, 103, 111, 107, 97, 125, 99, 110, 127, 55, 4, 5, 61, 49, 64, 118, 119, 112, 127, 97, 125, 57, 111, 104, 121, 111, 62, 111, 82, 78, 79, 83, 80, 86, 6, 70, 70, 77, 10, 68, 88, 69, 75, 93, 16, 82, 93, 93, 64, 80, 78, 67, 24, 73, 72, 84, 74, 84, 90, 90, 36, 97, 32, 58, 100, 49, 46, 34, 104, 33, 43, 57, 34, 40, 61, 60, 124, 113, 33, 38, 55, 61, 118, 54, 43, 121, 60, 50, 48, 56, 45, 127, 9, 15, 66, 23, 12, 0, 70, 16, 7, 27, 1, 24, 28, 12, 13, 10, 94, 123, 95, 83, 55, 26, 27, 26, 13, 23, 19, 24, 29, 9, 27, 95, 247, 232, 246, 235, 164, 241, 238, 226, 168, 252, 249, 238, 254, 173, 236, 246, 176, 226, 230, 225, 241, 244, 251, 254, 246, 254, 186, 239, 244, 244, 240, 244, 201, 207, 197, 131, 130, 133, 212, 194, 219, 217, 197, 197, 223, 200, 221, 131, 144, 208, 220, 215, 148, 215, 207, 151, 213, 216, 209, 210, 210, 218, 158, 153, 224, 180, 178, 167, 165, 177, 175, 169, 175, 233, 186, 167, 173, 163, 189, 225, 218, 252, 242, 150, 185, 188, 162, 247, 190, 172, 180, 184, 168, 180, 177, 177, 192, 130, 131, 143, 136, 150, 198, 147, 135, 201, 152, 158, 130, 205, 154, 138, 130, 156, 155, 157, 149, 153, 214, 148, 151, 148, 151, 154, 146, 153, 141, 223, 97, 111, 102, 35, 101, 117, 118, 107, 113, 41, 122, 106, 120, 110, 102, 106, 99, 63, 50, 87, 113, 101, 115, 121, 124, 112, 116, 124, 60, 114, 112, 63, 72, 78, 85, 3, 80, 77, 79, 84, 8, 90, 90, 78, 79, 68, 72, 70, 83, 17, 64, 70, 90, 21, 95, 68, 24, 90, 85, 85, 90, 84, 89, 74, 50, 36, 38, 111, 100, 60, 41, 50, 104, 42, 43, 37, 108, 63, 43, 62, 37, 52, 33, 39, 116, 33, 62, 54, 44, 121, 46, 51, 57, 46, 59, 127, 6, 20, 12, 0, 16, 12, 9, 9, 72, 10, 11, 7, 0, 30, 78, 13, 21, 81, 23, 0, 23, 20, 26, 22, 12, 28, 30, 91, 8, 18, 94, 11, 232, 228, 162, 246, 247, 224, 244, 167, 238, 230, 248, 171, 237, 253, 254, 253, 255, 231, 243, 255, 180, 247, 243, 241, 247, 235, 255, 187, 238, 232, 240, 241, 201, 207, 197, 141, 132, 232, 201, 213, 205, 137, 197, 197, 140, 217, 198, 198, 195, 145, 219, 221, 148, 193, 222, 210, 152, 155, 233, 218, 210, 217, 220, 208, 184, 225, 163, 173, 160, 229, 167, 183, 184, 187, 165, 189, 173, 161, 189, 237, 240, 162, 183, 176, 160, 188, 185, 185, 246, 211, 208, 209, 255, 253, 150, 176, 151, 193, 155, 140, 145, 197, 145, 136, 154, 130, 224, 225, 207, 206, 206, 191, 149, 131, 129, 156, 154, 148, 154, 158, 140, 128, 240, 241, 165, 146, 139, 141, 32, 101, 103, 101, 101, 112, 106, 115, 40, 121, 111, 121, 127, 98, 96, 110, 124, 120, 102, 106, 52, 116, 120, 115, 56, 109, 117, 117, 121, 61, 119, 108, 0, 66, 77, 77, 71, 76, 85, 66, 4, 9, 78, 66, 94, 72, 77, 91, 28, 17, 83, 93, 80, 21, 80, 69, 81, 92, 84, 95, 80, 68, 16, 31, 25, 46, 55, 99, 39, 42, 43, 42, 61, 39, 35, 40, 45, 57, 43, 111, 53, 55, 52, 58, 55, 60, 51, 57, 44, 53, 35, 119, 124, 60, 50, 40, 1, 24, 17, 67, 15, 0, 3, 23, 1, 7, 13, 75, 24, 5, 11, 79, 5, 2, 23, 1, 84, 22, 26, 18, 25, 11, 22, 2, 92, 20, 16, 25, 239, 243, 239, 230, 224, 165, 231, 229, 231, 252, 254, 171, 227, 227, 233, 224, 249, 255, 245, 179, 245, 246, 226, 254, 247, 247, 233, 187, 235, 244, 234, 247, 207, 212, 214, 131, 209, 203, 200, 194, 203, 204, 217, 216, 205, 223, 215, 143, 212, 212, 198Line truncated
|
||||
|
||||
@@ -832,12 +832,12 @@ mod tests {
|
||||
fn find_skill_paths_flat_layout() {
|
||||
// Traditional flat layout: skills/<name>/SKILL.md
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let grok_dir = tmp.path().join(".kigi");
|
||||
let kigi_dir = tmp.path().join(".kigi");
|
||||
|
||||
write_skill_md(&grok_dir.join("skills").join("alpha"), "alpha");
|
||||
write_skill_md(&grok_dir.join("skills").join("beta"), "beta");
|
||||
write_skill_md(&kigi_dir.join("skills").join("alpha"), "alpha");
|
||||
write_skill_md(&kigi_dir.join("skills").join("beta"), "beta");
|
||||
|
||||
let paths = find_skill_paths(&grok_dir);
|
||||
let paths = find_skill_paths(&kigi_dir);
|
||||
assert_eq!(paths.len(), 2);
|
||||
assert!(paths.iter().all(|p| p.file_name().unwrap() == "SKILL.md"));
|
||||
}
|
||||
@@ -846,13 +846,13 @@ mod tests {
|
||||
fn find_skill_paths_nested_layout() {
|
||||
// Nested: skills/team/infra/SKILL.md, skills/team/training/SKILL.md
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let grok_dir = tmp.path().join(".kigi");
|
||||
let skills = grok_dir.join("skills");
|
||||
let kigi_dir = tmp.path().join(".kigi");
|
||||
let skills = kigi_dir.join("skills");
|
||||
|
||||
write_skill_md(&skills.join("team").join("infra"), "infra");
|
||||
write_skill_md(&skills.join("team").join("training"), "training");
|
||||
|
||||
let paths = find_skill_paths(&grok_dir);
|
||||
let paths = find_skill_paths(&kigi_dir);
|
||||
assert_eq!(paths.len(), 2);
|
||||
|
||||
let path_strs: Vec<String> = paths.iter().map(|p| p.display().to_string()).collect();
|
||||
@@ -864,8 +864,8 @@ mod tests {
|
||||
fn find_skill_paths_mixed_flat_and_nested() {
|
||||
// Mix of flat and nested skills
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let grok_dir = tmp.path().join(".kigi");
|
||||
let skills = grok_dir.join("skills");
|
||||
let kigi_dir = tmp.path().join(".kigi");
|
||||
let skills = kigi_dir.join("skills");
|
||||
|
||||
// Flat
|
||||
write_skill_md(&skills.join("top-level"), "top-level");
|
||||
@@ -874,7 +874,7 @@ mod tests {
|
||||
// Nested 2 levels
|
||||
write_skill_md(&skills.join("org").join("team").join("deep"), "deep");
|
||||
|
||||
let paths = find_skill_paths(&grok_dir);
|
||||
let paths = find_skill_paths(&kigi_dir);
|
||||
assert_eq!(paths.len(), 3);
|
||||
}
|
||||
|
||||
@@ -882,8 +882,8 @@ mod tests {
|
||||
fn find_skill_paths_dir_without_skill_md_is_skipped() {
|
||||
// A subdirectory exists but has no SKILL.md — should not appear
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let grok_dir = tmp.path().join(".kigi");
|
||||
let skills = grok_dir.join("skills");
|
||||
let kigi_dir = tmp.path().join(".kigi");
|
||||
let skills = kigi_dir.join("skills");
|
||||
|
||||
write_skill_md(&skills.join("valid"), "valid");
|
||||
// Create a dir with no SKILL.md
|
||||
@@ -893,7 +893,7 @@ mod tests {
|
||||
fs::create_dir_all(&other).unwrap();
|
||||
fs::write(other.join("README.md"), "not a skill").unwrap();
|
||||
|
||||
let paths = find_skill_paths(&grok_dir);
|
||||
let paths = find_skill_paths(&kigi_dir);
|
||||
assert_eq!(paths.len(), 1);
|
||||
assert!(paths[0].display().to_string().contains("valid"));
|
||||
}
|
||||
@@ -902,10 +902,10 @@ mod tests {
|
||||
fn find_skill_paths_no_skills_dir() {
|
||||
// .kigi exists but no skills/ subdirectory
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let grok_dir = tmp.path().join(".kigi");
|
||||
fs::create_dir_all(&grok_dir).unwrap();
|
||||
let kigi_dir = tmp.path().join(".kigi");
|
||||
fs::create_dir_all(&kigi_dir).unwrap();
|
||||
|
||||
let paths = find_skill_paths(&grok_dir);
|
||||
let paths = find_skill_paths(&kigi_dir);
|
||||
assert!(paths.is_empty());
|
||||
}
|
||||
|
||||
@@ -944,15 +944,15 @@ mod tests {
|
||||
fn find_skill_paths_parent_and_child_both_have_skill_md() {
|
||||
// A directory has SKILL.md and also has subdirectories with SKILL.md
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let grok_dir = tmp.path().join(".kigi");
|
||||
let skills = grok_dir.join("skills");
|
||||
let kigi_dir = tmp.path().join(".kigi");
|
||||
let skills = kigi_dir.join("skills");
|
||||
|
||||
// Parent skill
|
||||
write_skill_md(&skills.join("parent"), "parent-skill");
|
||||
// Child skill inside parent
|
||||
write_skill_md(&skills.join("parent").join("child"), "child-skill");
|
||||
|
||||
let paths = find_skill_paths(&grok_dir);
|
||||
let paths = find_skill_paths(&kigi_dir);
|
||||
assert_eq!(paths.len(), 2);
|
||||
|
||||
let path_strs: Vec<String> = paths.iter().map(|p| p.display().to_string()).collect();
|
||||
@@ -1108,9 +1108,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_model_and_effort() {
|
||||
let content = "---\nname: my-skill\ndescription: test\nmodel: grok-3\neffort: high\n---\n";
|
||||
let content = "---\nname: my-skill\ndescription: test\nmodel: kigi-3\neffort: high\n---\n";
|
||||
let parsed = parse_skill_frontmatter(content, None).unwrap();
|
||||
assert_eq!(parsed.model.as_deref(), Some("grok-3"));
|
||||
assert_eq!(parsed.model.as_deref(), Some("kigi-3"));
|
||||
assert_eq!(parsed.effort.as_deref(), Some("high"));
|
||||
}
|
||||
|
||||
@@ -1251,7 +1251,7 @@ mod tests {
|
||||
#[test]
|
||||
fn parse_full_spec_plus_extensions() {
|
||||
// Mixed agentskills.io spec fields + our extensions — all must parse.
|
||||
let content = "---\nname: my-skill\ndescription: A full skill\nlicense: MIT\ncompatibility: Python 3.12+\nmetadata:\n author: test-org\n version: \"2.0\"\nallowed-tools:\n - bash\n - read_file\nargument-hint: file path\nmodel: grok-3\neffort: high\nuser-invocable: true\ndisable-model-invocation: false\n---\nBody content.\n";
|
||||
let content = "---\nname: my-skill\ndescription: A full skill\nlicense: MIT\ncompatibility: Python 3.12+\nmetadata:\n author: test-org\n version: \"2.0\"\nallowed-tools:\n - bash\n - read_file\nargument-hint: file path\nmodel: kigi-3\neffort: high\nuser-invocable: true\ndisable-model-invocation: false\n---\nBody content.\n";
|
||||
let parsed = parse_skill_frontmatter(content, None).unwrap();
|
||||
assert_eq!(parsed.name, "my-skill");
|
||||
assert_eq!(parsed.description, "A full skill");
|
||||
@@ -1263,7 +1263,7 @@ mod tests {
|
||||
Some(["bash".to_string(), "read_file".to_string()].as_slice())
|
||||
);
|
||||
assert_eq!(parsed.argument_hint.as_deref(), Some("file path"));
|
||||
assert_eq!(parsed.model.as_deref(), Some("grok-3"));
|
||||
assert_eq!(parsed.model.as_deref(), Some("kigi-3"));
|
||||
assert_eq!(parsed.effort.as_deref(), Some("high"));
|
||||
assert!(parsed.user_invocable);
|
||||
assert!(!parsed.disable_model_invocation);
|
||||
@@ -1575,7 +1575,7 @@ mod tests {
|
||||
root: root.clone(),
|
||||
canonical_root: root.clone(),
|
||||
scope: PluginScope::User,
|
||||
origin: crate::plugins::PluginOrigin::UserGrok,
|
||||
origin: crate::plugins::PluginOrigin::UserKigi,
|
||||
trusted: true,
|
||||
enabled: true,
|
||||
version: Some("1.0.0".to_string()),
|
||||
@@ -1653,7 +1653,7 @@ mod tests {
|
||||
root: root.to_path_buf(),
|
||||
canonical_root: root.to_path_buf(),
|
||||
scope: PluginScope::User,
|
||||
origin: crate::plugins::PluginOrigin::UserGrok,
|
||||
origin: crate::plugins::PluginOrigin::UserKigi,
|
||||
trusted: true,
|
||||
skill_dirs,
|
||||
command_dirs: vec![],
|
||||
@@ -2323,7 +2323,7 @@ mod tests {
|
||||
root: root.clone(),
|
||||
canonical_root: root,
|
||||
scope: PluginScope::Project,
|
||||
origin: crate::plugins::PluginOrigin::ProjectGrok,
|
||||
origin: crate::plugins::PluginOrigin::ProjectKigi,
|
||||
trusted: true,
|
||||
enabled: true,
|
||||
version: Some("1.0.0".to_string()),
|
||||
@@ -2458,7 +2458,7 @@ mod tests {
|
||||
"cursor must be gated off: {dirs:?}"
|
||||
);
|
||||
assert!(ends_with(&dirs, ".claude"), "claude must remain: {dirs:?}");
|
||||
assert!(ends_with(&dirs, ".kigi"), "grok must remain: {dirs:?}");
|
||||
assert!(ends_with(&dirs, ".kigi"), "kigi must remain: {dirs:?}");
|
||||
}
|
||||
|
||||
// ── Same-scope frontmatter-name collisions (copied skill dirs) ──────
|
||||
|
||||
@@ -32,7 +32,7 @@ pub(crate) fn base_template() -> Zeroizing<String> {
|
||||
decrypt(BASE_PROMPT_ENC, PROMPT_SEEDS[0])
|
||||
}
|
||||
|
||||
/// The base prompt template source, exposed for `grok prompt --section template`.
|
||||
/// The base prompt template source, exposed for `kigi prompt --section template`.
|
||||
pub fn base_template_source() -> Zeroizing<String> {
|
||||
base_template()
|
||||
}
|
||||
@@ -41,7 +41,7 @@ pub(crate) fn apply_patch_template() -> Zeroizing<String> {
|
||||
decrypt(CODEX_PROMPT_ENC, PROMPT_SEEDS[1])
|
||||
}
|
||||
|
||||
/// Apply-patch prompt template source, exposed for `grok prompt --section apply-patch-template`.
|
||||
/// Apply-patch prompt template source, exposed for `kigi prompt --section apply-patch-template`.
|
||||
pub fn apply_patch_template_source() -> Zeroizing<String> {
|
||||
apply_patch_template()
|
||||
}
|
||||
@@ -93,7 +93,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// Build a TemplateRenderer with the standard grok-build tool kinds.
|
||||
/// Build a TemplateRenderer with the standard kigi tool kinds.
|
||||
fn default_renderer() -> TemplateRenderer {
|
||||
let tools: HashMap<ToolKind, String> = [
|
||||
(ToolKind::Read, "read_file"),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! workspace overview, optional rules / skills / MCP listings).
|
||||
//!
|
||||
//! `UserMessageTemplate` selects the rendering strategy:
|
||||
//! - `Default` -- the legacy Grok Build prefix (built by the shell layer).
|
||||
//! - `Default` -- the legacy Kigi prefix (built by the shell layer).
|
||||
//! - `Custom` -- caller-supplied template string (MiniJinja, same delimiters
|
||||
//! as the system prompt templates).
|
||||
//!
|
||||
@@ -63,7 +63,7 @@ fn normalize_git_status(status: &str) -> Option<String> {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum UserMessageTemplate {
|
||||
/// Legacy Grok Build prefix: `<user_info>` + optional `<git_status>`.
|
||||
/// Legacy Kigi prefix: `<user_info>` + optional `<git_status>`.
|
||||
/// Built directly by the shell layer; this
|
||||
/// renderer returns `None` for `Default` and the caller falls back to
|
||||
/// its own legacy path.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const TARGET: &str = "xai_grok_instrumentation";
|
||||
const TARGET: &str = "xai_kigi_instrumentation";
|
||||
|
||||
pub struct TimingGuard {
|
||||
name: &'static str,
|
||||
|
||||
Reference in new issue
Block a user