§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
@@ -103,7 +103,7 @@ pub(super) fn parse_session_load_restore_meta(
|
||||
.and_then(|v| serde_json::from_value(v).ok());
|
||||
(code_restored, restore_summary, restore_degree)
|
||||
}
|
||||
/// CANONICAL wire parser for `LoadSessionResponse._meta["x.ai/runningPromptId"]`.
|
||||
/// CANONICAL wire parser for `LoadSessionResponse._meta["kigi/runningPromptId"]`.
|
||||
///
|
||||
/// Returns the session's in-flight running prompt id when the session was
|
||||
/// loaded MID-turn (some other client is driving), otherwise `None`. The
|
||||
@@ -114,7 +114,7 @@ pub(crate) fn parse_session_load_running_prompt_id(
|
||||
resp_meta: Option<&acp::Meta>,
|
||||
) -> Option<String> {
|
||||
resp_meta
|
||||
.and_then(|m| m.get("x.ai/runningPromptId"))
|
||||
.and_then(|m| m.get("kigi/runningPromptId"))
|
||||
.and_then(|v| v.as_str())
|
||||
.map(String::from)
|
||||
}
|
||||
@@ -133,7 +133,7 @@ pub(crate) fn sanitize_user_error(raw: &str) -> String {
|
||||
("inference_api", "server"),
|
||||
("research-api", "server"),
|
||||
("research_api", "server"),
|
||||
("grok-code-backend", "server"),
|
||||
("kigi-code-backend", "server"),
|
||||
("ACP error:", "error:"),
|
||||
("ACP request failed:", "request failed:"),
|
||||
("JSON-RPC error", "request error"),
|
||||
@@ -165,17 +165,17 @@ pub(crate) fn sanitize_user_error(raw: &str) -> String {
|
||||
///
|
||||
/// | plan | subagents | ask-user | agentProfile | askUserQuestion |
|
||||
/// |-------|-----------|----------|--------------------------------|--------------------|
|
||||
/// | false | false | false | `grok-build` (default) | `false` |
|
||||
/// | false | true | false | `grok-build` (default) | `false` |
|
||||
/// | false | false | true | `grok-build-ask-user` | omitted (shell gate) |
|
||||
/// | false | true | true | `grok-build-ask-user` | omitted (shell gate) |
|
||||
/// | true | false | false | `grok-build-plan-no-subagents` | `false` |
|
||||
/// | true | true | false | `grok-build-plan` | `false` |
|
||||
/// | true | false | true | `grok-build-plan-no-subagents` | omitted (shell gate) |
|
||||
/// | true | true | true | `grok-build-plan` | omitted (shell gate) |
|
||||
/// | false | false | false | `kigi` (default) | `false` |
|
||||
/// | false | true | false | `kigi` (default) | `false` |
|
||||
/// | false | false | true | `kigi-ask-user` | omitted (shell gate) |
|
||||
/// | false | true | true | `kigi-ask-user` | omitted (shell gate) |
|
||||
/// | true | false | false | `kigi-plan-no-subagents` | `false` |
|
||||
/// | true | true | false | `kigi-plan` | `false` |
|
||||
/// | true | false | true | `kigi-plan-no-subagents` | omitted (shell gate) |
|
||||
/// | true | true | true | `kigi-plan` | omitted (shell gate) |
|
||||
///
|
||||
/// When [`Self::chat_mode`] is set (gateway light-frontend / `--chat`), Build
|
||||
/// `agentProfile` injection is omitted (K12) and `_meta["x.ai/session"].kind`
|
||||
/// `agentProfile` injection is omitted (K12) and `_meta["kigi/session"].kind`
|
||||
/// is stamped `"chat"` so the shell takes `require_gateway` / thin profile.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct SessionFlags {
|
||||
@@ -183,7 +183,7 @@ pub(crate) struct SessionFlags {
|
||||
pub subagents: bool,
|
||||
pub ask_user: bool,
|
||||
/// Restore code state on resume (`--restore-code`).
|
||||
/// Injected as `x.ai/restore_code` into `LoadSession` meta, or passed
|
||||
/// Injected as `kigi/restore_code` into `LoadSession` meta, or passed
|
||||
/// as `restoreCode` in the `resume_session` ACP payload for worktrees.
|
||||
pub restore_code: Option<bool>,
|
||||
pub agent_override: Option<serde_json::Value>,
|
||||
@@ -208,7 +208,7 @@ pub(crate) struct SessionFlags {
|
||||
impl SessionFlags {
|
||||
/// Resolve the agent profile name from the flags.
|
||||
///
|
||||
/// Returns `None` for the default `grok-build` profile (no `_meta`
|
||||
/// Returns `None` for the default `kigi` profile (no `_meta`
|
||||
/// needed; it already includes TaskTool). Chat mode never injects a
|
||||
/// Build profile (remote owns agent behavior).
|
||||
pub(super) fn agent_profile(&self) -> Option<&'static str> {
|
||||
@@ -216,9 +216,9 @@ impl SessionFlags {
|
||||
return None;
|
||||
}
|
||||
match (self.plan_mode, self.subagents, self.ask_user) {
|
||||
(true, true, _) => Some("grok-build-plan"),
|
||||
(true, false, _) => Some("grok-build-plan-no-subagents"),
|
||||
(false, _, true) => Some("grok-build-ask-user"),
|
||||
(true, true, _) => Some("kigi-plan"),
|
||||
(true, false, _) => Some("kigi-plan-no-subagents"),
|
||||
(false, _, true) => Some("kigi-ask-user"),
|
||||
(false, _, false) => None,
|
||||
}
|
||||
}
|
||||
@@ -229,7 +229,7 @@ impl SessionFlags {
|
||||
/// emit-site comment below). `--no-ask-user` always forces
|
||||
/// `askUserQuestion: false` into the meta, even when paired with
|
||||
/// `KIGI_AGENT` — the env var chooses the *agent*, but the tool-strip is
|
||||
/// independent. Chat mode additionally stamps `x.ai/session.kind`.
|
||||
/// independent. Chat mode additionally stamps `kigi/session.kind`.
|
||||
pub(super) fn to_meta(&self) -> Option<acp::Meta> {
|
||||
let mut meta = serde_json::Map::new();
|
||||
if self.chat_mode {
|
||||
@@ -247,7 +247,7 @@ impl SessionFlags {
|
||||
meta.insert("agentProfile".into(), serde_json::json!(profile));
|
||||
}
|
||||
if self.chat_mode {
|
||||
meta.insert("x.ai/session".into(), serde_json::json!({ "kind" : "chat" }));
|
||||
meta.insert("kigi/session".into(), serde_json::json!({ "kind" : "chat" }));
|
||||
}
|
||||
if !self.ask_user {
|
||||
meta.insert("askUserQuestion".into(), serde_json::json!(false));
|
||||
@@ -266,13 +266,13 @@ impl SessionFlags {
|
||||
/// workspace for `kind=chat`; the client must not bind Direct/envId/attach.
|
||||
pub(super) const CHAT_FORBIDDEN_WORKSPACE_BIND_KEYS: &[&str] = &[
|
||||
"envId",
|
||||
"x.ai/cloud_server_id",
|
||||
"x.ai/cloud_existing_workspace",
|
||||
"kigi/cloud_server_id",
|
||||
"kigi/cloud_existing_workspace",
|
||||
];
|
||||
/// Stamp `_meta["x.ai/session"].kind = "chat"` and strip Build `agentProfile` (K12).
|
||||
/// Stamp `_meta["kigi/session"].kind = "chat"` and strip Build `agentProfile` (K12).
|
||||
pub(super) fn apply_chat_kind_meta(meta: &mut Option<acp::Meta>) {
|
||||
let obj = meta.get_or_insert_with(acp::Meta::new);
|
||||
obj.insert("x.ai/session".into(), serde_json::json!({ "kind" : "chat" }));
|
||||
obj.insert("kigi/session".into(), serde_json::json!({ "kind" : "chat" }));
|
||||
obj.remove("agentProfile");
|
||||
}
|
||||
/// Remove client workspace-bind keys from chat create/load meta (defense in depth).
|
||||
@@ -360,7 +360,7 @@ pub(super) fn count_chat_history_stats(history_path: &Path) -> (usize, usize) {
|
||||
}
|
||||
(turn_count, tool_call_count)
|
||||
}
|
||||
/// Parse the `x.ai/session/list` response payload (the unwrapped
|
||||
/// Parse the `kigi/session/list` response payload (the unwrapped
|
||||
/// `{ "sessions": [...] }` object) into [`SessionPickerEntry`] rows.
|
||||
///
|
||||
/// Shared by the resume picker ([`Effect::FetchSessionList`]) and the
|
||||
@@ -399,7 +399,7 @@ pub(super) fn parse_session_picker_entries(
|
||||
.map(String::from);
|
||||
let is_conversation = v
|
||||
.get("_meta")
|
||||
.and_then(|m| m.get("x.ai/session"))
|
||||
.and_then(|m| m.get("kigi/session"))
|
||||
.and_then(|s| s.get("kind"))
|
||||
.and_then(|k| k.as_str()) == Some("chat");
|
||||
let parsed_updated: Option<chrono::DateTime<chrono::Utc>> = v
|
||||
@@ -548,7 +548,7 @@ pub(super) fn session_picker_entry_to_roster(
|
||||
}
|
||||
pub(super) async fn send_logout(tx: &AcpAgentTx) {
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/auth/logout",
|
||||
"kigi/auth/logout",
|
||||
serde_json::value::to_raw_value(&serde_json::json!({}))
|
||||
.expect("serialize auth/logout params")
|
||||
.into(),
|
||||
@@ -927,7 +927,7 @@ pub(crate) async fn persist_setting(
|
||||
/// Body for `Effect::PersistPermissionMode`. Factored out for testability.
|
||||
///
|
||||
/// 1. Persist `ui.permission_mode` to disk.
|
||||
/// 2. Fire ACP `x.ai/yolo_mode_changed` (gated on disk success for
|
||||
/// 2. Fire ACP `kigi/yolo_mode_changed` (gated on disk success for
|
||||
/// `WithRollback`; always for `BestEffort`).
|
||||
/// 3. Return the matching `TaskResult`.
|
||||
pub(crate) async fn persist_permission_mode_and_notify(
|
||||
@@ -951,7 +951,7 @@ pub(crate) async fn persist_permission_mode_and_notify(
|
||||
config_str, }
|
||||
);
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/yolo_mode_changed",
|
||||
"kigi/yolo_mode_changed",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize yolo_mode_changed params")
|
||||
.into(),
|
||||
@@ -962,7 +962,7 @@ pub(crate) async fn persist_permission_mode_and_notify(
|
||||
}
|
||||
route_permission_mode_result(disk_outcome, persist, config_str)
|
||||
}
|
||||
/// Whether to fire the ACP `x.ai/yolo_mode_changed` notification.
|
||||
/// Whether to fire the ACP `kigi/yolo_mode_changed` notification.
|
||||
/// `WithRollback` suppresses on disk failure (agent must not see the
|
||||
/// optimistic value). `BestEffort` always fires.
|
||||
pub(super) fn should_send_yolo_acp_notification(
|
||||
@@ -975,7 +975,7 @@ pub(super) fn should_send_yolo_acp_notification(
|
||||
(Err(_), PermissionModePersist::WithRollback(_)) => false,
|
||||
}
|
||||
}
|
||||
/// Extract the typed kill outcome from an `x.ai/task/kill` ext response.
|
||||
/// Extract the typed kill outcome from an `kigi/task/kill` ext response.
|
||||
///
|
||||
/// The agent serializes `ExtMethodResult<KillTaskResponse>`, so the outcome
|
||||
/// lives at `result.outcome` (`{"result":{"taskId":..,"outcome":
|
||||
@@ -997,7 +997,7 @@ pub(super) fn parse_kill_outcome(
|
||||
.and_then(|envelope| envelope.result)
|
||||
.map(|payload| payload.outcome)
|
||||
}
|
||||
/// Map an `x.ai/subagent/cancel` response (payload under `result`) to a kill
|
||||
/// Map an `kigi/subagent/cancel` response (payload under `result`) to a kill
|
||||
/// outcome. Prefers the typed `outcome`; falls back to the legacy `cancelled`
|
||||
/// bool for an older shell or an unknown future `kind`. An error/unparseable
|
||||
/// body is `RpcFailed` (subagent may still be running — leave the row alone).
|
||||
@@ -1092,7 +1092,7 @@ pub(super) fn persist_hint(
|
||||
TaskResult::CancelComplete
|
||||
});
|
||||
}
|
||||
/// Parse an `x.ai/billing` ext response body (the unwrapped `result`
|
||||
/// Parse an `kigi/billing` ext response body (the unwrapped `result`
|
||||
/// payload) into Kimi usage rows. A body that fails to deserialize is an
|
||||
/// error, not an empty quota list, so a malformed response can't render
|
||||
/// as "no usage data".
|
||||
|
||||
@@ -200,7 +200,7 @@ pub(crate) fn execute(
|
||||
if chat_kind || session_flags.chat_mode {
|
||||
meta.get_or_insert_with(acp::Meta::new)
|
||||
.insert(
|
||||
"x.ai/session".into(),
|
||||
"kigi/session".into(),
|
||||
serde_json::json!({ "kind" : "chat" }),
|
||||
);
|
||||
}
|
||||
@@ -238,7 +238,7 @@ pub(crate) fn execute(
|
||||
payload["gitRef"] = serde_json::Value::String(r.clone());
|
||||
}
|
||||
let ext_req = acp::ExtRequest::new(
|
||||
"x.ai/git/worktree/resume_session",
|
||||
"kigi/git/worktree/resume_session",
|
||||
serde_json::value::to_raw_value(&payload)
|
||||
.expect("serialize resume params")
|
||||
.into(),
|
||||
@@ -342,7 +342,7 @@ pub(crate) fn execute(
|
||||
params["gitRef"] = serde_json::Value::String(r.clone());
|
||||
}
|
||||
let ext_req = acp::ExtRequest::new(
|
||||
"x.ai/git/worktree/create_from_worktree_sync",
|
||||
"kigi/git/worktree/create_from_worktree_sync",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize worktree params")
|
||||
.into(),
|
||||
@@ -470,7 +470,7 @@ pub(crate) fn execute(
|
||||
}
|
||||
if let Some(true) = session_flags.restore_code {
|
||||
meta.get_or_insert_with(acp::Meta::new)
|
||||
.insert("x.ai/restore_code".into(), serde_json::Value::Bool(true));
|
||||
.insert("kigi/restore_code".into(), serde_json::Value::Bool(true));
|
||||
}
|
||||
let cwd = session_cwd.unwrap_or_else(|| cwd.to_path_buf());
|
||||
let mcp_started = std::time::Instant::now();
|
||||
@@ -670,7 +670,7 @@ pub(crate) fn execute(
|
||||
params["query"] = serde_json::Value::String(q.clone());
|
||||
}
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/session/list",
|
||||
"kigi/session/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize session list params")
|
||||
.into(),
|
||||
@@ -725,7 +725,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/sessions/list",
|
||||
"kigi/sessions/list",
|
||||
serde_json::value::to_raw_value(&serde_json::json!({}))
|
||||
.expect("serialize roster list params")
|
||||
.into(),
|
||||
@@ -743,7 +743,7 @@ pub(crate) fn execute(
|
||||
}
|
||||
None => {
|
||||
tracing::warn!(
|
||||
"failed to parse x.ai/sessions/list response"
|
||||
"failed to parse kigi/sessions/list response"
|
||||
);
|
||||
TaskResult::RosterFailed {
|
||||
error: "parse error".to_string(),
|
||||
@@ -768,7 +768,7 @@ pub(crate) fn execute(
|
||||
{ "cwd" : cwd.to_string_lossy(), "limit" : 30, }
|
||||
);
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/session/list",
|
||||
"kigi/session/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize session list params")
|
||||
.into(),
|
||||
@@ -1211,7 +1211,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), }
|
||||
);
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/toggle_plan_mode",
|
||||
"kigi/toggle_plan_mode",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize toggle_plan_mode params")
|
||||
.into(),
|
||||
@@ -1233,7 +1233,7 @@ pub(crate) fn execute(
|
||||
"expectedVersion" : expected_version, }
|
||||
);
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/queue/remove",
|
||||
"kigi/queue/remove",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize queue/remove params")
|
||||
.into(),
|
||||
@@ -1253,7 +1253,7 @@ pub(crate) fn execute(
|
||||
ordered_ids, }
|
||||
);
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/queue/reorder",
|
||||
"kigi/queue/reorder",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize queue/reorder params")
|
||||
.into(),
|
||||
@@ -1272,7 +1272,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), }
|
||||
);
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/queue/clear",
|
||||
"kigi/queue/clear",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize queue/clear params")
|
||||
.into(),
|
||||
@@ -1292,7 +1292,7 @@ pub(crate) fn execute(
|
||||
new_text, }
|
||||
);
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/queue/edit",
|
||||
"kigi/queue/edit",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize queue/edit params")
|
||||
.into(),
|
||||
@@ -1315,7 +1315,7 @@ pub(crate) fn execute(
|
||||
params["newText"] = serde_json::Value::String(new_text);
|
||||
}
|
||||
let notification = acp::ExtNotification::new(
|
||||
"x.ai/queue/interject",
|
||||
"kigi/queue/interject",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize queue/interject params")
|
||||
.into(),
|
||||
@@ -1396,7 +1396,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/compact_conversation",
|
||||
"kigi/compact_conversation",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize compact params")
|
||||
.into(),
|
||||
@@ -1419,7 +1419,7 @@ pub(crate) fn execute(
|
||||
session_id, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/prompt_history",
|
||||
"kigi/prompt_history",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize prompt_history params")
|
||||
.into(),
|
||||
@@ -1467,7 +1467,7 @@ pub(crate) fn execute(
|
||||
task_id: task_id.clone(),
|
||||
};
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/task/kill",
|
||||
"kigi/task/kill",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize kill params")
|
||||
.into(),
|
||||
@@ -1500,7 +1500,7 @@ pub(crate) fn execute(
|
||||
subagent_id, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/subagent/cancel",
|
||||
"kigi/subagent/cancel",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize cancel params")
|
||||
.into(),
|
||||
@@ -1527,7 +1527,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), "taskId" : task_id, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/scheduler/delete",
|
||||
"kigi/scheduler/delete",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize scheduler delete params")
|
||||
.into(),
|
||||
@@ -1547,7 +1547,7 @@ pub(crate) fn execute(
|
||||
tool_call_id, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/terminal/background",
|
||||
"kigi/terminal/background",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize background params")
|
||||
.into(),
|
||||
@@ -1862,7 +1862,7 @@ pub(crate) fn execute(
|
||||
}
|
||||
let params = serde_json::json!({});
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/auth/get_url",
|
||||
"kigi/auth/get_url",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize auth_url params")
|
||||
.into(),
|
||||
@@ -1901,7 +1901,7 @@ pub(crate) fn execute(
|
||||
.spawn(async move {
|
||||
let params = serde_json::json!({ "code" : code });
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/auth/submit_code",
|
||||
"kigi/auth/submit_code",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize auth code params")
|
||||
.into(),
|
||||
@@ -1935,7 +1935,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), "cache" : cache, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/mcp/list",
|
||||
"kigi/mcp/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize mcp/list params")
|
||||
.into(),
|
||||
@@ -1976,7 +1976,7 @@ pub(crate) fn execute(
|
||||
server_name, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/mcp/auth_trigger",
|
||||
"kigi/mcp/auth_trigger",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize mcp/auth_trigger params")
|
||||
.into(),
|
||||
@@ -2024,7 +2024,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/hooks/list",
|
||||
"kigi/hooks/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize hooks/list params")
|
||||
.into(),
|
||||
@@ -2061,7 +2061,7 @@ pub(crate) fn execute(
|
||||
{ "sessionId" : session_id.0.to_string(), }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/plugins/list",
|
||||
"kigi/plugins/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize plugins/list params")
|
||||
.into(),
|
||||
@@ -2099,7 +2099,7 @@ pub(crate) fn execute(
|
||||
action,
|
||||
};
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/hooks/action",
|
||||
"kigi/hooks/action",
|
||||
serde_json::value::to_raw_value(&req_body)
|
||||
.expect("serialize hooks/action params")
|
||||
.into(),
|
||||
@@ -2139,7 +2139,7 @@ pub(crate) fn execute(
|
||||
action,
|
||||
};
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/plugins/action",
|
||||
"kigi/plugins/action",
|
||||
serde_json::value::to_raw_value(&req_body)
|
||||
.expect("serialize plugins/action params")
|
||||
.into(),
|
||||
@@ -2176,7 +2176,7 @@ pub(crate) fn execute(
|
||||
.spawn(async move {
|
||||
let params = serde_json::json!({ "cwd" : "." });
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/skills/list",
|
||||
"kigi/skills/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize skills/list params")
|
||||
.into(),
|
||||
@@ -2215,7 +2215,7 @@ pub(crate) fn execute(
|
||||
{ "name" : skill_name, "enabled" : enabled, "cwd" : ".", }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/skills/toggle",
|
||||
"kigi/skills/toggle",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize skills/toggle params")
|
||||
.into(),
|
||||
@@ -2235,7 +2235,7 @@ pub(crate) fn execute(
|
||||
.map_err(|_| "couldn't toggle skill".to_string());
|
||||
if parsed.is_ok() {
|
||||
let refresh = acp::ExtRequest::new(
|
||||
"x.ai/skills/refresh-baseline",
|
||||
"kigi/skills/refresh-baseline",
|
||||
serde_json::value::to_raw_value(&serde_json::json!({}))
|
||||
.expect("serialize empty params")
|
||||
.into(),
|
||||
@@ -2273,7 +2273,7 @@ pub(crate) fn execute(
|
||||
config: *config,
|
||||
};
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/mcp/upsert",
|
||||
"kigi/mcp/upsert",
|
||||
serde_json::value::to_raw_value(&req_body)
|
||||
.expect("serialize mcp/upsert params")
|
||||
.into(),
|
||||
@@ -2308,7 +2308,7 @@ pub(crate) fn execute(
|
||||
server_name,
|
||||
};
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/mcp/delete",
|
||||
"kigi/mcp/delete",
|
||||
serde_json::value::to_raw_value(&req_body)
|
||||
.expect("serialize mcp/delete params")
|
||||
.into(),
|
||||
@@ -2337,7 +2337,7 @@ pub(crate) fn execute(
|
||||
server_name, "enabled" : enabled, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/mcp/toggle",
|
||||
"kigi/mcp/toggle",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize mcp/toggle params")
|
||||
.into(),
|
||||
@@ -2367,7 +2367,7 @@ pub(crate) fn execute(
|
||||
server_name, "tool_name" : tool_name, "enabled" : enabled, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/mcp/toggle_tool",
|
||||
"kigi/mcp/toggle_tool",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize mcp/toggle_tool params")
|
||||
.into(),
|
||||
@@ -2446,7 +2446,7 @@ pub(crate) fn execute(
|
||||
cwd: String,
|
||||
}
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/session/rename",
|
||||
"kigi/session/rename",
|
||||
serde_json::value::to_raw_value(
|
||||
&RenameRequest {
|
||||
session_id: session_id.0.to_string(),
|
||||
@@ -2503,7 +2503,7 @@ pub(crate) fn execute(
|
||||
cwd: String,
|
||||
}
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/session/delete",
|
||||
"kigi/session/delete",
|
||||
serde_json::value::to_raw_value(
|
||||
&DeleteRequest {
|
||||
session_id: session_id.clone(),
|
||||
@@ -2605,7 +2605,7 @@ pub(crate) fn execute(
|
||||
}
|
||||
};
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/feedback",
|
||||
"kigi/feedback",
|
||||
raw_params.into(),
|
||||
);
|
||||
match acp_send(request, &tx).await {
|
||||
@@ -2636,7 +2636,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/memory/rewrite",
|
||||
"kigi/memory/rewrite",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!(
|
||||
{ "sessionId" : session_id.0.to_string(), "rawText" :
|
||||
@@ -2703,7 +2703,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/btw",
|
||||
"kigi/btw",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!(
|
||||
{ "sessionId" : session_id.0.to_string(), "question" :
|
||||
@@ -2746,7 +2746,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/recap",
|
||||
"kigi/recap",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!(
|
||||
{ "sessionId" : session_id.0.to_string(), "auto" : auto, }
|
||||
@@ -2790,7 +2790,7 @@ pub(crate) fn execute(
|
||||
blocks.as_deref(),
|
||||
);
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/interject",
|
||||
"kigi/interject",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize interject params")
|
||||
.into(),
|
||||
@@ -2820,7 +2820,7 @@ pub(crate) fn execute(
|
||||
.spawn(async move {
|
||||
let params = serde_json::json!({ "kind" : kind, "name" : name });
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/bundle/entry/get",
|
||||
"kigi/bundle/entry/get",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize bundle/entry/get params")
|
||||
.into(),
|
||||
@@ -2876,7 +2876,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/bundle/status",
|
||||
"kigi/bundle/status",
|
||||
serde_json::value::to_raw_value(&serde_json::json!({}))
|
||||
.expect("serialize bundle/status params")
|
||||
.into(),
|
||||
@@ -2935,7 +2935,7 @@ pub(crate) fn execute(
|
||||
.spawn(async move {
|
||||
let params = serde_json::json!({ "cwd" : cwd });
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/commands/list",
|
||||
"kigi/commands/list",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize commands/list params")
|
||||
.into(),
|
||||
@@ -2971,7 +2971,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/rewind/points",
|
||||
"kigi/rewind/points",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!(
|
||||
{ "sessionId" : session_id.0.to_string() }
|
||||
@@ -3030,7 +3030,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/rewind/execute",
|
||||
"kigi/rewind/execute",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!(
|
||||
{ "sessionId" : session_id.0.to_string(),
|
||||
@@ -3084,7 +3084,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/rewind/execute",
|
||||
"kigi/rewind/execute",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!(
|
||||
{ "sessionId" : session_id.0.to_string(),
|
||||
@@ -3144,7 +3144,7 @@ pub(crate) fn execute(
|
||||
{ "query" : query, "limit" : 20, "includeContent" : true, }
|
||||
);
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/session/search",
|
||||
"kigi/session/search",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize deep search params")
|
||||
.into(),
|
||||
@@ -3229,7 +3229,7 @@ pub(crate) fn execute(
|
||||
parent_is_worktree,
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/session/fork",
|
||||
"kigi/session/fork",
|
||||
serde_json::value::to_raw_value(&payload)
|
||||
.expect("serialize fork params")
|
||||
.into(),
|
||||
@@ -3308,7 +3308,7 @@ pub(crate) fn execute(
|
||||
tasks
|
||||
.spawn(async move {
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/billing",
|
||||
"kigi/billing",
|
||||
serde_json::value::to_raw_value(&serde_json::json!({}))
|
||||
.expect("serialize usage params")
|
||||
.into(),
|
||||
@@ -3362,7 +3362,7 @@ pub(crate) fn execute(
|
||||
token_only, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/suggest",
|
||||
"kigi/suggest",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize suggest params")
|
||||
.into(),
|
||||
@@ -3401,7 +3401,7 @@ pub(crate) fn execute(
|
||||
session_id, }
|
||||
);
|
||||
let req = acp::ExtRequest::new(
|
||||
"x.ai/suggestPrompt",
|
||||
"kigi/suggestPrompt",
|
||||
serde_json::value::to_raw_value(¶ms)
|
||||
.expect("serialize suggestPrompt params")
|
||||
.into(),
|
||||
@@ -3428,13 +3428,13 @@ pub(crate) fn execute(
|
||||
}
|
||||
(false, meta)
|
||||
}
|
||||
/// Fetch session info from ACP via `x.ai/session/info`.
|
||||
/// Fetch session info from ACP via `kigi/session/info`.
|
||||
async fn fetch_session_info(
|
||||
session_id: &acp::SessionId,
|
||||
tx: &AcpAgentTx,
|
||||
) -> Result<SessionInfoResponse, String> {
|
||||
let request = acp::ExtRequest::new(
|
||||
"x.ai/session/info",
|
||||
"kigi/session/info",
|
||||
serde_json::value::to_raw_value(
|
||||
&serde_json::json!({ "sessionId" : session_id.0.to_string() }),
|
||||
)
|
||||
@@ -3584,7 +3584,7 @@ fn prompt_request_meta(
|
||||
}
|
||||
serde_json::Value::Object(map)
|
||||
}
|
||||
/// Build the `x.ai/interject` params. The optional structured `content`
|
||||
/// Build the `kigi/interject` params. The optional structured `content`
|
||||
/// (text + images) is omitted ENTIRELY when `None` so the legacy wire
|
||||
/// shape stays byte-identical. Extracted from the spawn for testability.
|
||||
fn build_interject_params(
|
||||
|
||||
@@ -67,7 +67,7 @@ fn prompt_request_meta_omits_screen_mode_when_unset() {
|
||||
assert_eq!(meta, serde_json::json!({ "promptId" : "p-2" }));
|
||||
}
|
||||
/// Text-only interjections must omit the `content` key entirely — the
|
||||
/// legacy `x.ai/interject` wire shape stays byte-identical.
|
||||
/// legacy `kigi/interject` wire shape stays byte-identical.
|
||||
#[test]
|
||||
fn interject_params_omit_content_when_no_blocks() {
|
||||
let sid = acp::SessionId::new("s1");
|
||||
@@ -83,7 +83,7 @@ fn interject_params_omit_content_when_no_blocks() {
|
||||
fn picker_keeps_conversation_with_empty_cwd_and_missing_updated_at() {
|
||||
let payload = serde_json::json!(
|
||||
{ "sessions" : [{ "sessionId" : "conv_abc", "cwd" : "", "summary" :
|
||||
"Compare GPU vendors", "source" : "conversation", "_meta" : { "x.ai/session" : {
|
||||
"Compare GPU vendors", "source" : "conversation", "_meta" : { "kigi/session" : {
|
||||
"kind" : "chat" } } }] }
|
||||
);
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
@@ -97,7 +97,7 @@ fn picker_keeps_old_conversation_past_cutoff() {
|
||||
let payload = serde_json::json!(
|
||||
{ "sessions" : [{ "sessionId" : "conv_old", "cwd" : "", "summary" :
|
||||
"Ancient chat", "source" : "conversation", "updatedAt" : "2020-01-01T00:00:00Z",
|
||||
"_meta" : { "x.ai/session" : { "kind" : "chat" } } }] }
|
||||
"_meta" : { "kigi/session" : { "kind" : "chat" } } }] }
|
||||
);
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
assert_eq!(entries.len(), 1, "old conversation must still render");
|
||||
@@ -112,13 +112,13 @@ fn picker_drops_local_with_missing_updated_at() {
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
assert!(entries.is_empty(), "local rows still require a parseable updatedAt");
|
||||
}
|
||||
/// Untitled grok.com chats must stay listed, rendered as "Untitled".
|
||||
/// Untitled kimi.com chats must stay listed, rendered as "Untitled".
|
||||
#[test]
|
||||
fn picker_keeps_untitled_conversation_as_untitled() {
|
||||
let payload = serde_json::json!(
|
||||
{ "sessions" : [{ "sessionId" : "conv_untitled", "cwd" : "", "summary" : "",
|
||||
"source" : "conversation", "updatedAt" : "2026-07-01T00:00:00Z", "_meta" : {
|
||||
"x.ai/session" : { "kind" : "chat" } } }] }
|
||||
"kigi/session" : { "kind" : "chat" } } }] }
|
||||
);
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
assert_eq!(entries.len(), 1, "untitled conversation must not vanish");
|
||||
@@ -277,7 +277,7 @@ fn interject_params_carry_content_when_blocks_present() {
|
||||
assert_eq!(content.len(), 1);
|
||||
assert_eq!(content[0] ["text"], "look at [Image #1]");
|
||||
}
|
||||
/// `x.ai/billing` ext result (a serialized shell `UsageResponse`) parses
|
||||
/// `kigi/billing` ext result (a serialized shell `UsageResponse`) parses
|
||||
/// into typed rows; unknown labels/reset hints survive the round trip.
|
||||
#[test]
|
||||
fn parse_usage_response_reads_rows_from_fixture() {
|
||||
@@ -473,7 +473,7 @@ async fn persist_setting_type_mismatch_errors_simple_mode() {
|
||||
}
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
/// Spawn a fake ACP agent that counts `x.ai/yolo_mode_changed`
|
||||
/// Spawn a fake ACP agent that counts `kigi/yolo_mode_changed`
|
||||
/// notifications. Exits when the channel closes.
|
||||
fn spawn_fake_acp_agent(
|
||||
mut rx: tokio::sync::mpsc::UnboundedReceiver<kigi_acp_lib::AcpAgentMessage>,
|
||||
@@ -483,7 +483,7 @@ fn spawn_fake_acp_agent(
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = rx.recv().await {
|
||||
if let kigi_acp_lib::AcpAgentMessage::ExtNotification(args) = msg {
|
||||
if args.request.method.as_ref() == "x.ai/yolo_mode_changed" {
|
||||
if args.request.method.as_ref() == "kigi/yolo_mode_changed" {
|
||||
counter_clone.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
let _ = args.response_tx.send(Ok(()));
|
||||
@@ -590,7 +590,7 @@ async fn persist_permission_mode_acp_notification_fires_once_on_best_effort() {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
||||
assert_eq!(
|
||||
counter.load(Ordering::SeqCst), 1,
|
||||
"ACP `x.ai/yolo_mode_changed` notification must fire exactly once \
|
||||
"ACP `kigi/yolo_mode_changed` notification must fire exactly once \
|
||||
on BestEffort path (regardless of disk outcome)",
|
||||
);
|
||||
assert!(
|
||||
@@ -972,7 +972,7 @@ async fn fetch_session_list_pushes_query_and_echoes_seq() {
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = rx.recv().await {
|
||||
if let AcpAgentMessage::ExtMethod(args) = msg {
|
||||
assert_eq!(args.request.method.as_ref(), "x.ai/session/list");
|
||||
assert_eq!(args.request.method.as_ref(), "kigi/session/list");
|
||||
let params: serde_json::Value = serde_json::from_str(
|
||||
args.request.params.get(),
|
||||
)
|
||||
@@ -1094,7 +1094,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: false,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan",
|
||||
"kigi-plan",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1103,7 +1103,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: false,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan-no-subagents",
|
||||
"kigi-plan-no-subagents",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1112,7 +1112,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan",
|
||||
"kigi-plan",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1121,7 +1121,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan-no-subagents",
|
||||
"kigi-plan-no-subagents",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1130,7 +1130,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-ask-user",
|
||||
"kigi-ask-user",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1139,7 +1139,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-ask-user",
|
||||
"kigi-ask-user",
|
||||
),
|
||||
];
|
||||
for (flags, expected_name) in test_cases {
|
||||
@@ -1156,13 +1156,13 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
);
|
||||
}
|
||||
}
|
||||
/// Default flags produce no agent profile (uses grok-build default).
|
||||
/// Default flags produce no agent profile (uses kigi default).
|
||||
#[test]
|
||||
fn default_flags_produce_no_profile() {
|
||||
let flags = SessionFlags::default();
|
||||
assert_eq!(flags.agent_profile(), None);
|
||||
}
|
||||
/// --subagents alone produces no profile (grok-build already has TaskTool).
|
||||
/// --subagents alone produces no profile (kigi already has TaskTool).
|
||||
#[test]
|
||||
fn subagents_without_plan_produces_no_profile() {
|
||||
let flags = SessionFlags {
|
||||
@@ -1178,7 +1178,7 @@ fn subagents_without_plan_produces_no_profile() {
|
||||
/// escape hatch and drops `agentProfile` — the tests would then assert the
|
||||
/// wrong branch. Empty string counts as unset (`!s.trim().is_empty()`).
|
||||
/// Callers must be `#[serial_test::serial(KIGI_AGENT)]` (process-global env).
|
||||
fn without_grok_agent() -> crate::test_util::EnvVarGuard {
|
||||
fn without_kigi_agent() -> crate::test_util::EnvVarGuard {
|
||||
crate::test_util::EnvVarGuard::set("KIGI_AGENT", "")
|
||||
}
|
||||
/// At the runtime defaults (every `--no-*` flag false → every
|
||||
@@ -1187,7 +1187,7 @@ fn without_grok_agent() -> crate::test_util::EnvVarGuard {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn runtime_default_flags_produce_plan_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: true,
|
||||
@@ -1195,7 +1195,7 @@ fn runtime_default_flags_produce_plan_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1204,7 +1204,7 @@ fn runtime_default_flags_produce_plan_meta() {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn plan_only_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: false,
|
||||
@@ -1212,7 +1212,7 @@ fn plan_only_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan-no-subagents");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan-no-subagents");
|
||||
assert_eq!(meta["askUserQuestion"], false);
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1220,7 +1220,7 @@ fn plan_only_meta() {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn plan_with_subagents_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: true,
|
||||
@@ -1228,15 +1228,15 @@ fn plan_with_subagents_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan");
|
||||
assert_eq!(meta["askUserQuestion"], false);
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
/// --ask-user alone selects the grok-build-ask-user profile.
|
||||
/// --ask-user alone selects the kigi-ask-user profile.
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn ask_user_alone_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: false,
|
||||
subagents: false,
|
||||
@@ -1244,7 +1244,7 @@ fn ask_user_alone_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-ask-user");
|
||||
assert_eq!(meta["agentProfile"], "kigi-ask-user");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1252,7 +1252,7 @@ fn ask_user_alone_meta() {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn plan_with_ask_user_uses_plan_profile() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: false,
|
||||
@@ -1260,14 +1260,14 @@ fn plan_with_ask_user_uses_plan_profile() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan-no-subagents");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan-no-subagents");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
/// --no-plan --no-subagents --no-ask-user picks the default profile but
|
||||
/// must still emit `askUserQuestion: false` so the shell can strip the
|
||||
/// tool at the builder. Mirrors the runtime: `subagents` toggle alone
|
||||
/// does not need an `agentProfile` (default `grok-build` already has it).
|
||||
/// does not need an `agentProfile` (default `kigi` already has it).
|
||||
#[test]
|
||||
fn subagents_alone_emits_only_ask_user_question_disable() {
|
||||
let flags = SessionFlags {
|
||||
@@ -1280,12 +1280,12 @@ fn subagents_alone_emits_only_ask_user_question_disable() {
|
||||
assert!(meta.get("agentProfile").is_none());
|
||||
assert_eq!(meta["askUserQuestion"], false);
|
||||
}
|
||||
/// All three flags on at the runtime default produce grok-build-plan
|
||||
/// All three flags on at the runtime default produce kigi-plan
|
||||
/// and no `askUserQuestion` field.
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn all_flags_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: true,
|
||||
@@ -1293,7 +1293,7 @@ fn all_flags_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1388,7 +1388,7 @@ fn to_meta_chat_mode_stamps_kind_and_omits_agent_profile() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().expect("chat_mode must emit meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert!(
|
||||
meta.get("agentProfile").is_none(), "K12: chat mode must omit Build agentProfile"
|
||||
);
|
||||
@@ -1414,7 +1414,7 @@ fn load_meta_chat_kind_alone_stamps_kind_and_strips_profile() {
|
||||
scrub_chat_workspace_bind_meta(&mut meta);
|
||||
}
|
||||
let meta = meta.expect("chat_kind must produce meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert!(
|
||||
meta.get("agentProfile").is_none(),
|
||||
"entry chat_kind must strip Build agentProfile"
|
||||
@@ -1444,7 +1444,7 @@ fn chat_create_meta_never_includes_workspace_bind_keys_when_cloud_fields_set() {
|
||||
apply_chat_kind_meta(&mut meta);
|
||||
scrub_chat_workspace_bind_meta(&mut meta);
|
||||
let meta = meta.expect("chat create must emit meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert_chat_meta_has_no_workspace_bind_keys(
|
||||
&serde_json::Value::Object(meta.clone()),
|
||||
);
|
||||
@@ -1457,15 +1457,15 @@ fn chat_load_meta_never_includes_workspace_bind_keys() {
|
||||
{
|
||||
let obj = meta.get_or_insert_with(acp::Meta::new);
|
||||
obj.insert("envId".into(), serde_json::json!("env-poison"));
|
||||
obj.insert("x.ai/cloud_server_id".into(), serde_json::json!("srv-poison"));
|
||||
obj.insert("kigi/cloud_server_id".into(), serde_json::json!("srv-poison"));
|
||||
obj.insert(
|
||||
"x.ai/cloud_existing_workspace".into(),
|
||||
"kigi/cloud_existing_workspace".into(),
|
||||
serde_json::json!({ "server_id" : "srv-poison", "cwd" : "/ws", }),
|
||||
);
|
||||
}
|
||||
scrub_chat_workspace_bind_meta(&mut meta);
|
||||
let meta = meta.expect("chat load must emit meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert_chat_meta_has_no_workspace_bind_keys(
|
||||
&serde_json::Value::Object(meta.clone()),
|
||||
);
|
||||
@@ -1491,9 +1491,9 @@ fn agent_profile_definitions_have_correct_names() {
|
||||
use std::str::FromStr;
|
||||
use kigi_agent::config::BuiltinAgentName;
|
||||
for name in [
|
||||
"grok-build-plan",
|
||||
"grok-build-plan-no-subagents",
|
||||
"grok-build-ask-user",
|
||||
"kigi-plan",
|
||||
"kigi-plan-no-subagents",
|
||||
"kigi-ask-user",
|
||||
] {
|
||||
let builtin = BuiltinAgentName::from_str(name).unwrap();
|
||||
let def = builtin.definition();
|
||||
@@ -1542,23 +1542,23 @@ fn format_session_info_shows_conversation_id_when_present() {
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_shows_resolved_when_enabled_and_different() {
|
||||
let info = make_session_info("grok-4.5", Some("grok-4.3"), 1000, 10000);
|
||||
let info = make_session_info("kigi-4.5", Some("kigi-4.3"), 1000, 10000);
|
||||
let text = format_session_info(&info, None, true);
|
||||
assert!(text.contains("Model: grok-4.5 (grok-4.3)"));
|
||||
assert!(text.contains("Model: kigi-4.5 (kigi-4.3)"));
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_hides_resolved_when_disabled() {
|
||||
let info = make_session_info("grok-4.5", Some("grok-4.3"), 1000, 10000);
|
||||
let info = make_session_info("kigi-4.5", Some("kigi-4.3"), 1000, 10000);
|
||||
let text = format_session_info(&info, None, false);
|
||||
assert!(text.contains("Model: grok-4.5"));
|
||||
assert!(! text.contains("grok-4.3"));
|
||||
assert!(text.contains("Model: kigi-4.5"));
|
||||
assert!(! text.contains("kigi-4.3"));
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_no_parens_when_resolved_matches_requested() {
|
||||
let info = make_session_info("grok-4.5", Some("grok-4.5"), 1000, 10000);
|
||||
let info = make_session_info("kigi-4.5", Some("kigi-4.5"), 1000, 10000);
|
||||
let text = format_session_info(&info, None, true);
|
||||
assert!(text.contains("Model: grok-4.5"));
|
||||
assert!(! text.contains("(grok-4.5)"));
|
||||
assert!(text.contains("Model: kigi-4.5"));
|
||||
assert!(! text.contains("(kigi-4.5)"));
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_shows_model_hash_when_catalog_flag_set() {
|
||||
@@ -1647,7 +1647,7 @@ fn session_picker_entry_maps_to_dormant_roster_row() {
|
||||
cwd: "/repo/app".to_string(),
|
||||
hostname: Some("box".to_string()),
|
||||
source: "local".to_string(),
|
||||
model_id: Some("grok-4".to_string()),
|
||||
model_id: Some("kigi-4".to_string()),
|
||||
num_messages: 3,
|
||||
last_active_at: Some(updated),
|
||||
branch: None,
|
||||
@@ -1660,7 +1660,7 @@ fn session_picker_entry_maps_to_dormant_roster_row() {
|
||||
assert_eq!(roster.title.as_deref(), Some("Wire up dashboard"));
|
||||
assert_eq!(roster.cwd, "/repo/app");
|
||||
assert!(roster.is_worktree, "worktree_label present → is_worktree");
|
||||
assert_eq!(roster.model_id.as_deref(), Some("grok-4"));
|
||||
assert_eq!(roster.model_id.as_deref(), Some("kigi-4"));
|
||||
assert_eq!(roster.activity, RosterActivity::Dormant);
|
||||
assert!(! roster.resident);
|
||||
assert_eq!(roster.last_change_unix_ms, updated.timestamp_millis());
|
||||
|
||||
Reference in new issue
Block a user