§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:
@@ -24,7 +24,7 @@ pub(super) fn dispatch_logout(_app: &mut AppView) -> Vec<Effect> {
|
||||
/// On the eager-auth path (cached token), login_method_id is never set
|
||||
/// because the user skipped the login screen.
|
||||
///
|
||||
/// Does **not** invent `grok.com` when no interactive method is advertised
|
||||
/// Does **not** invent `kimi-code` when no interactive method is advertised
|
||||
/// (e.g. `preferred_method=api_key` with no key — empty `auth_methods`).
|
||||
/// Callers already surface "No login method available" when this leaves
|
||||
/// `login_method_id` unset.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Mid-turn interjection dispatch: optimistic local echo, the
|
||||
//! `x.ai/interject` effect, and prompt-history recording. Split out of
|
||||
//! `kigi/interject` effect, and prompt-history recording. Split out of
|
||||
//! `dispatch.rs` verbatim (pure code motion).
|
||||
|
||||
use crate::app::actions::Effect;
|
||||
@@ -9,10 +9,10 @@ use crate::scrollback::block::RenderBlock;
|
||||
|
||||
/// Send a mid-turn interjection. Pushes a standard user prompt block locally
|
||||
/// for instant feedback, records the text in prompt history, clears the
|
||||
/// prompt, and fires the `x.ai/interject` ext method carrying a client-minted
|
||||
/// prompt, and fires the `kigi/interject` ext method carrying a client-minted
|
||||
/// id.
|
||||
///
|
||||
/// The shell broadcasts `x.ai/session/interjection` to every attached pane so
|
||||
/// The shell broadcasts `kigi/session/interjection` to every attached pane so
|
||||
/// other clients viewing the same session render it too (multi-client /
|
||||
/// dashboard mode). Our own broadcast echoes back carrying the same id; the id
|
||||
/// is recorded in `self_interjection_ids` so `handle_interjection` drops the
|
||||
@@ -43,7 +43,7 @@ pub(super) fn dispatch_interject(
|
||||
record_interject_prompt_history(agent, &text);
|
||||
|
||||
// Push a standard user prompt block locally for instant feedback, and
|
||||
// record its id so the broadcast echo (`x.ai/session/interjection`) is
|
||||
// record its id so the broadcast echo (`kigi/session/interjection`) is
|
||||
// deduped instead of rendering a second copy on this pane.
|
||||
let interjection_id = uuid::Uuid::new_v4().to_string();
|
||||
agent.self_interjection_ids.insert(interjection_id.clone());
|
||||
|
||||
@@ -69,7 +69,7 @@ pub(super) fn dispatch_send_feedback(app: &mut AppView, text: String) -> Vec<Eff
|
||||
};
|
||||
|
||||
agent.scrollback.push_block(RenderBlock::system(
|
||||
"Thanks for the feedback! The Grok Build team is on it.".to_string(),
|
||||
"Thanks for the feedback! The Kigi team is on it.".to_string(),
|
||||
));
|
||||
|
||||
vec![Effect::SendFeedback {
|
||||
@@ -79,7 +79,7 @@ pub(super) fn dispatch_send_feedback(app: &mut AppView, text: String) -> Vec<Eff
|
||||
}]
|
||||
}
|
||||
|
||||
/// Send a raw remember note for LLM-powered rewriting via `x.ai/memory/rewrite`.
|
||||
/// Send a raw remember note for LLM-powered rewriting via `kigi/memory/rewrite`.
|
||||
/// Clears remember mode and prompts the LLM to reformat the note with session
|
||||
/// context. Falls back to direct `SaveMemoryNote` when no session is available.
|
||||
pub(super) fn dispatch_send_remember_note(app: &mut AppView, text: String) -> Vec<Effect> {
|
||||
@@ -327,7 +327,7 @@ pub(crate) fn scrollback_has_user_messages(
|
||||
}
|
||||
|
||||
/// Request a session recap. Bypasses the prompt queue — works even while the
|
||||
/// agent is mid-turn. Fires the `x.ai/recap` ext method; the recap arrives
|
||||
/// agent is mid-turn. Fires the `kigi/recap` ext method; the recap arrives
|
||||
/// asynchronously as a `SessionRecap` notification (rendered in scrollback).
|
||||
///
|
||||
/// `auto` is `false` for an explicit `/recap` and `true` for the automatic
|
||||
@@ -343,7 +343,7 @@ pub(super) fn dispatch_send_recap(app: &mut AppView, auto: bool) -> Vec<Effect>
|
||||
};
|
||||
|
||||
// Shell is authoritative (remote settings / config / env). Skip client requests
|
||||
// entirely when the feature is off so we never hit `x.ai/recap`.
|
||||
// entirely when the feature is off so we never hit `kigi/recap`.
|
||||
if !app.session_recap_available {
|
||||
if !auto {
|
||||
agent.show_toast("Session recap is not enabled");
|
||||
@@ -420,7 +420,7 @@ pub(super) fn handle_memory_note_saved(
|
||||
.scrollback
|
||||
.push_block(crate::scrollback::block::RenderBlock::system(format!(
|
||||
"Memory saved to {}",
|
||||
crate::util::display_user_grok_path("memory/MEMORY.md")
|
||||
crate::util::display_user_kigi_path("memory/MEMORY.md")
|
||||
)));
|
||||
}
|
||||
Err(error) => {
|
||||
|
||||
@@ -23,7 +23,7 @@ use agent_client_protocol as acp;
|
||||
/// existing `set_yolo_mode(true)` flow to flip the local YOLO state, drain
|
||||
/// any remaining queued permissions, persist `[ui] permission_mode =
|
||||
/// "always-approve"` to `~/.kigi/config.toml`, and fire the
|
||||
/// `x.ai/yolo_mode_changed` ACP notification. See the option-id constant
|
||||
/// `kigi/yolo_mode_changed` ACP notification. See the option-id constant
|
||||
/// doc-comment for the full client/shell split. Under a managed-policy
|
||||
/// pin step (b) is refused with a toast — the request is still allowed once.
|
||||
pub(super) fn dispatch_permission_select(
|
||||
|
||||
@@ -32,7 +32,7 @@ pub(super) fn consume_chat_kind(app: &mut AppView) -> bool {
|
||||
/// The prompt is always pushed to the queue first. If the agent is idle
|
||||
/// (and has a session), `maybe_drain_queue` pops the front prompt and
|
||||
/// sends it in the same dispatch call — no deferred ticks.
|
||||
/// Start (if needed) and submit the initial prompt from `grok "<prompt>"`.
|
||||
/// Start (if needed) and submit the initial prompt from `kigi "<prompt>"`.
|
||||
///
|
||||
/// Shared by the TUI startup path (already authenticated) and the post-login
|
||||
/// `AuthComplete` path (deferred via `deferred_startup.prompt`). It does nothing
|
||||
@@ -511,7 +511,7 @@ pub(super) fn dispatch_send_prompt_inner(
|
||||
// immediately instead of being held in the local drip-feed queue. The
|
||||
// agent appends it to its authoritative `pending_inputs` (no concurrent
|
||||
// turn starts — validated keystone) and drives the drain via
|
||||
// `x.ai/queue/changed`. We render an optimistic echo into the shared
|
||||
// `kigi/queue/changed`. We render an optimistic echo into the shared
|
||||
// queue keyed by `prompt_id`; the broadcast reconciles it by id.
|
||||
//
|
||||
// The IDLE case is unchanged (falls through to the local path below,
|
||||
@@ -930,7 +930,7 @@ pub(super) fn handle_prompt_response(
|
||||
// Server-authoritative queue lifecycle: this prompt's RPC
|
||||
// resolved without becoming the running turn (removed,
|
||||
// cancelled, rewound). Retire its optimistic echo so a
|
||||
// later `x.ai/queue/changed` broadcast can't re-pin a
|
||||
// later `kigi/queue/changed` broadcast can't re-pin a
|
||||
// stale placeholder and reorder the queue.
|
||||
if let Some(sid) = agent.session.session_id.as_ref().map(|s| s.0.to_string()) {
|
||||
retire_optimistic_echo(
|
||||
@@ -1171,7 +1171,7 @@ pub(super) fn handle_prompt_response(
|
||||
// title into the body automatically.
|
||||
let notif_title = session_name
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| "Grok".into());
|
||||
.unwrap_or_else(|| "Kigi".into());
|
||||
|
||||
app.deferred_notification = Some((
|
||||
NotificationEvent {
|
||||
|
||||
@@ -62,7 +62,7 @@ pub(super) fn immediate_server_send_eligible(agent: &AgentView) -> bool {
|
||||
|
||||
/// Push the optimistic shared-queue echo for an immediate server-authoritative
|
||||
/// send and mirror it into the owning agent so the queue pane renders it
|
||||
/// immediately, before the confirming `x.ai/queue/changed` broadcast.
|
||||
/// immediately, before the confirming `kigi/queue/changed` broadcast.
|
||||
pub(super) fn push_server_queue_echo(
|
||||
app: &mut AppView,
|
||||
agent_id: AgentId,
|
||||
@@ -91,7 +91,7 @@ pub(super) fn push_server_queue_echo(
|
||||
///
|
||||
/// The agent's `pending_inputs` is the single source of truth for queue
|
||||
/// contents and order; the only client-side queue state is the optimistic echo
|
||||
/// that bridges the round-trip before the confirming `x.ai/queue/changed`
|
||||
/// that bridges the round-trip before the confirming `kigi/queue/changed`
|
||||
/// broadcast. Once a prompt's RPC resolves (or we pull it back into the input
|
||||
/// on cancel) it will never reappear in a future broadcast, so its echo must be
|
||||
/// dropped — otherwise the reconcile in [`AppView::apply_queue_changed`] keeps
|
||||
@@ -633,7 +633,7 @@ pub(crate) fn apply_turn_start_shim(
|
||||
agent.session.current_prompt_id = Some(prompt_id.clone());
|
||||
agent.attached_as_viewer = adopted_from_other_client;
|
||||
// A new (adopted) turn is starting: drop the prior turn's chips but KEEP the
|
||||
// seen ring, so a buffer-replayed `x.ai/follow_ups` for an older response
|
||||
// seen ring, so a buffer-replayed `kigi/follow_ups` for an older response
|
||||
// stays rejected (no stale revival). This is correct for BOTH passive-viewer
|
||||
// and self-driven adoption: the adopted turn's OWN follow_ups still
|
||||
// re-render via the stamped `promptId` match in `apply_follow_ups` (the
|
||||
@@ -1150,7 +1150,7 @@ mod tests {
|
||||
}
|
||||
|
||||
/// FIX 4 (b) via the shim: after starting a NEW turn, a buffer-replayed
|
||||
/// `x.ai/follow_ups` for a PRIOR turn's response stays rejected (its
|
||||
/// `kigi/follow_ups` for a PRIOR turn's response stays rejected (its
|
||||
/// `promptId` is not the active turn and it is already seen) — no stale
|
||||
/// revival. Covers the self-driven turn start (`p-self`).
|
||||
#[test]
|
||||
|
||||
@@ -95,8 +95,8 @@ pub(in crate::app::dispatch) fn apply_persist_worktree_mode(
|
||||
/// Build the two persistence options shared by the fork and new-session
|
||||
/// worktree question modals ("Always worktree" / "Never worktree").
|
||||
pub(super) fn worktree_persist_options()
|
||||
-> [kigi_tools::implementations::grok_build::ask_user_question::QuestionOption; 2] {
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::QuestionOption;
|
||||
-> [kigi_tools::implementations::kigi::ask_user_question::QuestionOption; 2] {
|
||||
use kigi_tools::implementations::kigi::ask_user_question::QuestionOption;
|
||||
[
|
||||
QuestionOption {
|
||||
label: "Always worktree".into(),
|
||||
@@ -117,7 +117,7 @@ pub(super) fn worktree_persist_options()
|
||||
/// instead -- the modal-collision protocol.
|
||||
fn open_fork_question(app: &mut AppView, directive: Option<String>) -> Vec<Effect> {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let ActiveView::Agent(id) = app.active_view else {
|
||||
return vec![];
|
||||
};
|
||||
@@ -168,7 +168,7 @@ fn open_fork_question(app: &mut AppView, directive: Option<String>) -> Vec<Effec
|
||||
/// `worktree == true` reuses the existing
|
||||
/// [`Effect::CreateWorktreeSession`] pipeline (with `load_session_id`
|
||||
/// set to the parent session id). `worktree == false` emits the new
|
||||
/// [`Effect::ForkSession`] which calls `x.ai/session/fork` directly.
|
||||
/// [`Effect::ForkSession`] which calls `kigi/session/fork` directly.
|
||||
pub(in crate::app::dispatch) fn dispatch_fork_resolved(
|
||||
app: &mut AppView,
|
||||
worktree: bool,
|
||||
|
||||
@@ -154,7 +154,7 @@ pub(in crate::app::dispatch) fn dispatch_new_session(app: &mut AppView) -> Vec<E
|
||||
/// [`dispatch_new_worktree_session`].
|
||||
pub(in crate::app::dispatch) fn open_new_session_question(app: &mut AppView) -> Vec<Effect> {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let ActiveView::Agent(id) = app.active_view else {
|
||||
return vec![];
|
||||
};
|
||||
@@ -211,7 +211,7 @@ pub(in crate::app::dispatch) fn open_agent_type_mismatch_question(
|
||||
model_name: &str,
|
||||
) -> Vec<Effect> {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let ActiveView::Agent(id) = app.active_view else {
|
||||
return vec![];
|
||||
};
|
||||
@@ -408,7 +408,7 @@ pub(in crate::app::dispatch) fn clear_startup_actions(app: &mut AppView) {
|
||||
let _ = app.deferred_startup.take();
|
||||
}
|
||||
/// Replay the session-startup actions deferred until auth + trust both resolved
|
||||
/// (`--resume` / `--worktree` / initial-prompt / `grok dashboard`). Extracted
|
||||
/// (`--resume` / `--worktree` / initial-prompt / `kigi dashboard`). Extracted
|
||||
/// from the `AuthComplete` handler so the folder-trust answer can run the SAME
|
||||
/// machinery; whichever gate resolves last drains it (each call site guards on
|
||||
/// the other gate being `Done`, so it runs exactly once).
|
||||
|
||||
@@ -606,7 +606,7 @@ pub(in crate::app::dispatch) fn dispatch_trigger_deep_search(
|
||||
}
|
||||
}
|
||||
/// Chat-mode replacement for local deep search: refetch the session list
|
||||
/// with the picker query pushed down as `x.ai/session/list` `query`.
|
||||
/// with the picker query pushed down as `kigi/session/list` `query`.
|
||||
/// Keystrokes are coalesced through [`Effect::DebounceSessionSearch`]; a
|
||||
/// forced search (Ctrl+/) or a cleared query fetches immediately. Every
|
||||
/// trigger bumps `session_picker_list_seq`, so stale in-flight debounces
|
||||
|
||||
@@ -68,7 +68,7 @@ pub(in crate::app::dispatch) fn dispatch_sessions_confirm_close(
|
||||
remove_agent_and_cleanup(app, closed_id);
|
||||
effects
|
||||
}
|
||||
/// Rename the current session via x.ai/session/rename.
|
||||
/// Rename the current session via kigi/session/rename.
|
||||
///
|
||||
/// Produces Effect::RenameSession which spawns an async ACP ext request.
|
||||
/// On completion, TaskResult::RenameSessionComplete shows the result.
|
||||
|
||||
@@ -248,7 +248,7 @@ pub(in crate::app::dispatch) fn set_ask_user_question_timeout_enabled(
|
||||
app: &mut AppView,
|
||||
new: bool,
|
||||
) -> Vec<Effect> {
|
||||
use kigi_tools::implementations::grok_build::ask_user_question;
|
||||
use kigi_tools::implementations::kigi::ask_user_question;
|
||||
let prev_state = app.ask_user_question_timeout_enabled;
|
||||
let prev_effective =
|
||||
prev_state.unwrap_or(ask_user_question::DEFAULT_ASK_USER_QUESTION_TIMEOUT_ENABLED);
|
||||
@@ -1206,8 +1206,8 @@ pub(in crate::app::dispatch) fn set_auto_dark_theme(app: &mut AppView, new: Stri
|
||||
.as_deref()
|
||||
.and_then(crate::theme::canonical_name)
|
||||
.filter(|s| *s != "auto")
|
||||
// No prior config: fall back to GrokNight (the default).
|
||||
.unwrap_or_else(|| crate::theme::ThemeKind::GrokNight.display_name());
|
||||
// No prior config: fall back to KigiNight (the default).
|
||||
.unwrap_or_else(|| crate::theme::ThemeKind::KigiNight.display_name());
|
||||
let new_canonical = match crate::theme::canonical_name(&new) {
|
||||
Some(c) if c != crate::theme::ThemeKind::Auto.display_name() => c,
|
||||
_ => {
|
||||
@@ -1320,7 +1320,7 @@ pub(in crate::app::dispatch) fn set_auto_light_theme(
|
||||
.as_deref()
|
||||
.and_then(crate::theme::canonical_name)
|
||||
.filter(|s| *s != "auto")
|
||||
.unwrap_or_else(|| crate::theme::ThemeKind::GrokDay.display_name());
|
||||
.unwrap_or_else(|| crate::theme::ThemeKind::KigiDay.display_name());
|
||||
let new_canonical = match crate::theme::canonical_name(&new) {
|
||||
Some(c) if c != crate::theme::ThemeKind::Auto.display_name() => c,
|
||||
_ => {
|
||||
@@ -1430,7 +1430,7 @@ pub(in crate::app::dispatch) fn set_default_model_inner(
|
||||
// or `/clear` creates a fresh session by cloning `app.models`
|
||||
// (`dispatch_new_session_inner_with_id`), so without this the new session —
|
||||
// and the welcome card it commits — would show the previous default until
|
||||
// the next `x.ai/models/update` roundtrip.
|
||||
// the next `kigi/models/update` roundtrip.
|
||||
if app.models.available.contains_key(id) {
|
||||
app.models.set_current(id.clone(), None);
|
||||
}
|
||||
@@ -1510,7 +1510,7 @@ pub(in crate::app::dispatch) fn set_default_model(
|
||||
|
||||
// Persist the **model ID** (catalog key), not the display name.
|
||||
// The shell's `resolve_default_model` matches by slug / map key,
|
||||
// so persisting the human-readable name (e.g. "Grok Build")
|
||||
// so persisting the human-readable name (e.g. "Kigi")
|
||||
// would silently fail to resolve on the next startup.
|
||||
//
|
||||
// Chat (`--chat` / KIGI_CHAT_MODE) catalogs use opaque `/rest/modes`
|
||||
@@ -1798,7 +1798,7 @@ pub(in crate::app::dispatch) fn set_max_thoughts_width(app: &mut AppView, new: i
|
||||
/// (`show_tips`, `auto_update`, ask_user_question timeout).
|
||||
/// Matches the consumer's `.unwrap_or(...)` fallback.
|
||||
pub(super) fn pr13_effective_default(key: &str) -> Option<bool> {
|
||||
use kigi_tools::implementations::grok_build::ask_user_question;
|
||||
use kigi_tools::implementations::kigi::ask_user_question;
|
||||
match key {
|
||||
"show_tips" => Some(true),
|
||||
"auto_update" => Some(true),
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::app::app_view::{ActiveView, AppView};
|
||||
use crate::notifications::{NotificationEvent, NotificationEventKind};
|
||||
use crate::scrollback::block::RenderBlock;
|
||||
|
||||
/// Show session info: fetch via x.ai/session/info and display in scrollback.
|
||||
/// Show session info: fetch via kigi/session/info and display in scrollback.
|
||||
///
|
||||
/// Produces Effect::ShowSessionInfo which spawns an async ACP ext request.
|
||||
/// On completion, TaskResult::SessionInfoComplete shows the formatted info.
|
||||
@@ -49,7 +49,7 @@ pub(super) fn scrub_error_for_toast(error: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Show context info: fetch via x.ai/session/info and display rich breakdown.
|
||||
/// Show context info: fetch via kigi/session/info and display rich breakdown.
|
||||
///
|
||||
/// Produces Effect::ShowContextInfo which spawns an async ACP ext request.
|
||||
/// On completion, TaskResult::ContextInfoComplete shows the formatted info.
|
||||
@@ -72,7 +72,7 @@ pub(super) fn dispatch_show_context_info(app: &mut AppView) -> Vec<Effect> {
|
||||
|
||||
/// `/usage` — fetch Kimi usage/quota rows and display them inline.
|
||||
///
|
||||
/// Produces [`Effect::FetchUsage`], which asks the shell's `x.ai/billing`
|
||||
/// Produces [`Effect::FetchUsage`], which asks the shell's `kigi/billing`
|
||||
/// extension (`GET {base}/usages`); [`handle_usage_fetched`] renders the
|
||||
/// rows as a system block in scrollback.
|
||||
pub(super) fn dispatch_show_usage(app: &mut AppView) -> Vec<Effect> {
|
||||
@@ -225,7 +225,7 @@ pub(super) fn notify_session_ready(
|
||||
) {
|
||||
notification_service.notify(NotificationEvent {
|
||||
kind: NotificationEventKind::SessionReady,
|
||||
title: "Grok".into(),
|
||||
title: "Kigi".into(),
|
||||
body: NotificationEventKind::SessionReady.as_str().into(),
|
||||
session_id: agent.session.session_id.as_ref().map(|s| s.0.to_string()),
|
||||
});
|
||||
|
||||
@@ -218,7 +218,7 @@ fn cancel_login_strips_reauth_prompt_from_scrollback() {
|
||||
}
|
||||
|
||||
/// Empty `auth_methods` (preferred_method pin unavailable) must not invent
|
||||
/// `grok.com` or start an OIDC flow the agent did not advertise.
|
||||
/// `kimi-code` or start an OIDC flow the agent did not advertise.
|
||||
#[test]
|
||||
fn login_with_empty_auth_methods_fails_closed() {
|
||||
let mut app = test_app_with_agent();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
/// `grok dashboard` before login: the startup hook consumes the
|
||||
/// `kigi dashboard` before login: the startup hook consumes the
|
||||
/// `KIGI_OPEN_DASHBOARD_AT_STARTUP` env var and stashes
|
||||
/// `deferred_startup.open_dashboard`; `AuthComplete` must then open the
|
||||
/// dashboard view. Regression test for the silent drop where the
|
||||
@@ -30,7 +30,7 @@ fn auth_complete_opens_deferred_dashboard() {
|
||||
assert!(matches!(app.auth_state, AuthState::Done));
|
||||
assert!(
|
||||
matches!(app.active_view, ActiveView::AgentDashboard),
|
||||
"deferred `grok dashboard` must open the dashboard after login",
|
||||
"deferred `kigi dashboard` must open the dashboard after login",
|
||||
);
|
||||
assert!(
|
||||
!app.deferred_startup.open_dashboard,
|
||||
@@ -575,15 +575,15 @@ fn dashboard_confirm_worktree_without_git_repo_creates_nothing() {
|
||||
#[test]
|
||||
fn dashboard_confirm_worktree_applies_pending_model_and_plan() {
|
||||
let mut app = test_app();
|
||||
seed_model(&mut app, "grok-4.5", "Grok 4.5");
|
||||
seed_model(&mut app, "kigi-4.5", "Kigi 4.5");
|
||||
open_dashboard(&mut app);
|
||||
app.cwd_has_git_ancestor = true;
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
if let Some(d) = app.dashboard.as_mut() {
|
||||
d.pending_model = Some(crate::views::dashboard::PendingDispatchModel {
|
||||
id: model_id.clone(),
|
||||
effort: Some(kigi_shell::sampling::types::ReasoningEffort::High),
|
||||
display: "Grok 4.5".to_string(),
|
||||
display: "Kigi 4.5".to_string(),
|
||||
});
|
||||
d.pending_mode = crate::views::dashboard::DashboardDispatchMode::Plan;
|
||||
d.dispatch.set_text("do the thing");
|
||||
@@ -1120,7 +1120,7 @@ fn dashboard_peek_cycle_does_not_retire_the_nudge() {
|
||||
/// leader mode. The dashboard renders local sessions regardless; leader
|
||||
/// mode only adds the roster poll. Every entry point funnels through
|
||||
/// `Action::OpenDashboard`, so this covers `/dashboard`, `Ctrl+\`,
|
||||
/// `grok dashboard`, and the startup hook.
|
||||
/// `kigi dashboard`, and the startup hook.
|
||||
#[serial_test::serial(KIGI_AGENT_DASHBOARD)]
|
||||
#[test]
|
||||
fn dashboard_open_works_without_leader() {
|
||||
@@ -1237,9 +1237,9 @@ fn seed_model(app: &mut AppView, id: &str, name: &str) {
|
||||
#[test]
|
||||
fn dashboard_slash_model_stages_pending_model() {
|
||||
let mut app = test_app();
|
||||
seed_model(&mut app, "grok-4.5", "Grok 4.5");
|
||||
seed_model(&mut app, "kigi-4.5", "Kigi 4.5");
|
||||
open_dashboard(&mut app);
|
||||
let effects = dispatch_dashboard_dispatch_slash(&mut app, "/model grok-4.5".into());
|
||||
let effects = dispatch_dashboard_dispatch_slash(&mut app, "/model kigi-4.5".into());
|
||||
assert!(
|
||||
effects.is_empty(),
|
||||
"staging a model must not spawn a session"
|
||||
@@ -1252,8 +1252,8 @@ fn dashboard_slash_model_stages_pending_model() {
|
||||
.pending_model
|
||||
.as_ref()
|
||||
.expect("pending_model must be set");
|
||||
assert_eq!(pending.id.0.as_ref(), "grok-4.5");
|
||||
assert_eq!(pending.display, "Grok 4.5");
|
||||
assert_eq!(pending.id.0.as_ref(), "kigi-4.5");
|
||||
assert_eq!(pending.display, "Kigi 4.5");
|
||||
assert!(pending.effort.is_none());
|
||||
// The catalog snapshot's `current` tracks the staged model so the
|
||||
// next `/model` dropdown marks it `(current)` (not the seeded default).
|
||||
@@ -1265,7 +1265,7 @@ fn dashboard_slash_model_stages_pending_model() {
|
||||
.current
|
||||
.as_ref()
|
||||
.map(|id| id.0.as_ref()),
|
||||
Some("grok-4.5"),
|
||||
Some("kigi-4.5"),
|
||||
"staging must update the snapshot's current selection",
|
||||
);
|
||||
}
|
||||
@@ -1279,7 +1279,7 @@ fn dashboard_slash_model_stages_pending_model() {
|
||||
#[test]
|
||||
fn dashboard_slash_command_error_gets_error_glyph_prefix() {
|
||||
let mut app = test_app();
|
||||
seed_model(&mut app, "grok-4.5", "Grok 4.5");
|
||||
seed_model(&mut app, "kigi-4.5", "Kigi 4.5");
|
||||
open_dashboard(&mut app);
|
||||
let effects = dispatch_dashboard_dispatch_slash(&mut app, "/model nonexistent".into());
|
||||
assert!(effects.is_empty(), "a failed command must not dispatch");
|
||||
@@ -1512,14 +1512,14 @@ fn dashboard_cycle_mode_skips_always_approve_under_policy_pin() {
|
||||
fn dashboard_open_reseeds_pending_model_and_mode() {
|
||||
use crate::views::dashboard::DashboardDispatchMode;
|
||||
let mut app = test_app();
|
||||
seed_model(&mut app, "grok-4.5", "Grok 4.5");
|
||||
seed_model(&mut app, "kigi-4.5", "Kigi 4.5");
|
||||
open_dashboard(&mut app);
|
||||
// Stage a model + non-default mode as if from a previous session.
|
||||
if let Some(d) = app.dashboard.as_mut() {
|
||||
d.pending_model = Some(crate::views::dashboard::PendingDispatchModel {
|
||||
id: acp::ModelId::new(std::sync::Arc::from("grok-4.5")),
|
||||
id: acp::ModelId::new(std::sync::Arc::from("kigi-4.5")),
|
||||
effort: None,
|
||||
display: "Grok 4.5".to_string(),
|
||||
display: "Kigi 4.5".to_string(),
|
||||
});
|
||||
d.pending_mode = DashboardDispatchMode::Plan;
|
||||
}
|
||||
@@ -1727,14 +1727,14 @@ fn dashboard_dispatch_new_agent_is_working_with_prompt_title() {
|
||||
#[test]
|
||||
fn dashboard_dispatch_applies_pending_model_and_plan() {
|
||||
let mut app = test_app();
|
||||
seed_model(&mut app, "grok-4.5", "Grok 4.5");
|
||||
seed_model(&mut app, "kigi-4.5", "Kigi 4.5");
|
||||
open_dashboard(&mut app);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
if let Some(d) = app.dashboard.as_mut() {
|
||||
d.pending_model = Some(crate::views::dashboard::PendingDispatchModel {
|
||||
id: model_id.clone(),
|
||||
effort: Some(kigi_shell::sampling::types::ReasoningEffort::High),
|
||||
display: "Grok 4.5".to_string(),
|
||||
display: "Kigi 4.5".to_string(),
|
||||
});
|
||||
d.pending_mode = crate::views::dashboard::DashboardDispatchMode::Plan;
|
||||
}
|
||||
@@ -1770,14 +1770,14 @@ fn dashboard_dispatch_applies_pending_model_and_plan() {
|
||||
#[test]
|
||||
fn dashboard_new_agent_button_applies_pending_model_and_plan() {
|
||||
let mut app = test_app();
|
||||
seed_model(&mut app, "grok-4.5", "Grok 4.5");
|
||||
seed_model(&mut app, "kigi-4.5", "Kigi 4.5");
|
||||
open_dashboard(&mut app);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
if let Some(d) = app.dashboard.as_mut() {
|
||||
d.pending_model = Some(crate::views::dashboard::PendingDispatchModel {
|
||||
id: model_id.clone(),
|
||||
effort: Some(kigi_shell::sampling::types::ReasoningEffort::High),
|
||||
display: "Grok 4.5".to_string(),
|
||||
display: "Kigi 4.5".to_string(),
|
||||
});
|
||||
d.pending_mode = crate::views::dashboard::DashboardDispatchMode::Plan;
|
||||
}
|
||||
@@ -4624,7 +4624,7 @@ fn dashboard_permission_followup_rejects_with_message() {
|
||||
fn dashboard_question_answer_sends_and_clears() {
|
||||
use crate::views::prompt_widget::StashedPrompt;
|
||||
use crate::views::question_view::QuestionViewState;
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{
|
||||
AskUserQuestionMode, Question, QuestionOption,
|
||||
};
|
||||
|
||||
@@ -4673,7 +4673,7 @@ fn dashboard_question_answer_walks_multiple_questions() {
|
||||
use crate::views::dashboard::peek::{PeekPanelState, compute_peek_fields};
|
||||
use crate::views::prompt_widget::StashedPrompt;
|
||||
use crate::views::question_view::QuestionViewState;
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{
|
||||
AskUserQuestionMode, Question, QuestionOption,
|
||||
};
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@ fn test_app() -> AppView {
|
||||
agent_override: None,
|
||||
bootstrap_acp_commands: Vec::new(),
|
||||
auth_methods: vec![acp::AuthMethod::Agent(acp::AuthMethodAgent::new(
|
||||
acp::AuthMethodId::new("grok.com"),
|
||||
"Grok".to_string(),
|
||||
acp::AuthMethodId::new("kimi-code"),
|
||||
"Kigi".to_string(),
|
||||
))],
|
||||
auth_state: AuthState::Done,
|
||||
trust_state: TrustState::Done,
|
||||
@@ -462,7 +462,7 @@ fn fork_test_app() -> AppView {
|
||||
app
|
||||
}
|
||||
/// Build a minimal `AcpArgs<acp::ExtRequest>` for an
|
||||
/// `x.ai/ask_user_question` ext-method request. Returns the args
|
||||
/// `kigi/ask_user_question` ext-method request. Returns the args
|
||||
/// plus the receiver half of the response oneshot so the test can
|
||||
/// assert the handler completes the ACP roundtrip.
|
||||
fn make_ask_user_question_args(
|
||||
@@ -471,14 +471,13 @@ fn make_ask_user_question_args(
|
||||
kigi_acp_lib::AcpArgs<acp::ExtRequest>,
|
||||
tokio::sync::oneshot::Receiver<kigi_acp_lib::AcpResult<acp::ExtResponse>>,
|
||||
) {
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{
|
||||
AskUserQuestionExtRequest, Question, QuestionOption,
|
||||
};
|
||||
let req = AskUserQuestionExtRequest {
|
||||
session_id: "test-session".into(),
|
||||
tool_call_id: tool_call_id.into(),
|
||||
mode:
|
||||
kigi_tools::implementations::grok_build::ask_user_question::AskUserQuestionMode::Default,
|
||||
mode: kigi_tools::implementations::kigi::ask_user_question::AskUserQuestionMode::Default,
|
||||
questions: vec![Question {
|
||||
question: "ACP-driven question".into(),
|
||||
options: vec![QuestionOption {
|
||||
@@ -493,7 +492,7 @@ fn make_ask_user_question_args(
|
||||
};
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
let ext = acp::ExtRequest::new(
|
||||
"x.ai/ask_user_question",
|
||||
"kigi/ask_user_question",
|
||||
serde_json::value::to_raw_value(&req)
|
||||
.expect("serialize AskUserQuestionExtRequest")
|
||||
.into(),
|
||||
@@ -742,7 +741,7 @@ fn with_theme_test_env(f: impl FnOnce()) {
|
||||
.unwrap_or_else(|e| e.into_inner());
|
||||
crate::theme::cache::reset_for_test();
|
||||
crate::theme::cache::seed_auto_theme_defaults_for_test();
|
||||
crate::theme::cache::set(crate::theme::ThemeKind::GrokNight);
|
||||
crate::theme::cache::set(crate::theme::ThemeKind::KigiNight);
|
||||
crate::theme::system_appearance::clear_mock();
|
||||
f();
|
||||
crate::theme::system_appearance::clear_mock();
|
||||
|
||||
@@ -598,7 +598,7 @@ fn yolo_on_drain_clears_double_click_tracker() {
|
||||
/// 2. The dispatcher returns a `PersistPermissionMode` effect with
|
||||
/// canonical `"always-approve"` — this is what flips
|
||||
/// `[ui] permission_mode` on disk AND fires the
|
||||
/// `x.ai/yolo_mode_changed` ACP notification back to the shell.
|
||||
/// `kigi/yolo_mode_changed` ACP notification back to the shell.
|
||||
/// 3. The agent's per-session `yolo_mode` flag is flipped to true,
|
||||
/// so subsequent permission requests are auto-approved by
|
||||
/// `handle_permission_request`.
|
||||
@@ -651,7 +651,7 @@ fn enable_always_approve_sends_response_and_flips_yolo_and_persists() {
|
||||
|
||||
// (2) The dispatcher returns a PersistPermissionMode effect with
|
||||
// canonical "always-approve". This is the bridge that writes
|
||||
// ~/.kigi/config.toml AND fires x.ai/yolo_mode_changed.
|
||||
// ~/.kigi/config.toml AND fires kigi/yolo_mode_changed.
|
||||
let persist = effects
|
||||
.iter()
|
||||
.find_map(|e| match e {
|
||||
@@ -725,7 +725,7 @@ fn enable_always_approve_is_idempotent_when_yolo_already_on() {
|
||||
.any(|e| matches!(e, Effect::PersistPermissionMode { .. })),
|
||||
"redundant PersistPermissionMode when YOLO already on — the dispatcher \
|
||||
must short-circuit to avoid double-writing config.toml and double-firing \
|
||||
x.ai/yolo_mode_changed",
|
||||
kigi/yolo_mode_changed",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ fn manual_recap_with_no_messages_toasts_empty_state_and_skips_request() {
|
||||
|
||||
assert!(
|
||||
effects.is_empty(),
|
||||
"empty session must not fire x.ai/recap: {effects:?}"
|
||||
"empty session must not fire kigi/recap: {effects:?}"
|
||||
);
|
||||
let agent = app.agents.get(&id).unwrap();
|
||||
assert!(agent.pending_recap_entry.is_none(), "no loading spinner");
|
||||
@@ -86,7 +86,7 @@ fn manual_recap_during_batch_load_with_prompts_still_requests() {
|
||||
|
||||
assert!(
|
||||
matches!(effects.as_slice(), [Effect::SendRecap { auto: false, .. }]),
|
||||
"batched resume with user prompts must still fire x.ai/recap: {effects:?}"
|
||||
"batched resume with user prompts must still fire kigi/recap: {effects:?}"
|
||||
);
|
||||
let agent = app.agents.get(&id).unwrap();
|
||||
assert!(agent.pending_recap_entry.is_some());
|
||||
|
||||
@@ -846,7 +846,7 @@ fn prompt_response_resets_turn_state() {
|
||||
assert_eq!(app.agents[&id].scrollback.len(), 1);
|
||||
}
|
||||
|
||||
/// Turn end with prompt suggestions enabled fires the `x.ai/suggestPrompt`
|
||||
/// Turn end with prompt suggestions enabled fires the `kigi/suggestPrompt`
|
||||
/// fetch (before the billing refresh), and the loaded suggestion routes back
|
||||
/// into the agent's controller by id + generation.
|
||||
#[test]
|
||||
@@ -879,8 +879,8 @@ fn turn_end_fetches_prompt_suggestion_when_enabled() {
|
||||
};
|
||||
assert_eq!(*agent_id, id);
|
||||
assert!(session_id.is_some());
|
||||
// No `grok-build-0.1` in the test catalog and no env override →
|
||||
// `None` on the wire; the shell then uses its own `grok-build-0.1`
|
||||
// No `kigi-0.1` in the test catalog and no env override →
|
||||
// `None` on the wire; the shell then uses its own `kigi-0.1`
|
||||
// default (suggestion calls never use the session model).
|
||||
assert_eq!(*model, None);
|
||||
|
||||
@@ -1255,7 +1255,7 @@ fn turn_complete_notification_suppressed_when_queue_non_empty() {
|
||||
/// Regression: cancelling while prompts are queued must hand the queue to
|
||||
/// the agent untouched. The FRONT queued prompt runs next (promoted
|
||||
/// server-side), the rest stay queued in order, and the authoritative
|
||||
/// `x.ai/queue/changed` rebroadcast — not client-side prediction — updates
|
||||
/// `kigi/queue/changed` rebroadcast — not client-side prediction — updates
|
||||
/// the mirror. Nothing resurrects or reorders.
|
||||
#[test]
|
||||
fn cancel_hands_queue_to_agent_without_reordering() {
|
||||
@@ -1771,7 +1771,7 @@ fn send_prompt_works_after_reconnect_clears() {
|
||||
fn switch_model_holds_prompt_until_complete() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
|
||||
dispatch(
|
||||
Action::SwitchModel {
|
||||
@@ -1905,7 +1905,7 @@ fn submit_question_answers_cancel_clears_local_modal_and_restores_prompt() {
|
||||
// exercising the prompt.restore + cleanup_question_state contract
|
||||
// that lives in `submit_question_answers` itself.
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
|
||||
let mut app = fork_test_app();
|
||||
let id = AgentId(0);
|
||||
|
||||
@@ -255,7 +255,7 @@ fn mark_turn_finished_clears_start_and_stamps_active() {
|
||||
fn switch_model_dispatch_produces_effect_and_sets_pending() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
assert!(!app.agents[&id].session.model_switch_pending);
|
||||
let effects = dispatch(
|
||||
Action::SwitchModel {
|
||||
@@ -989,7 +989,7 @@ fn dispatch_fork_no_flag_always_reopens_modal_after_previous_answer() {
|
||||
#[test]
|
||||
fn translate_local_submit_skipped_returns_changed_with_no_action() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: vec![QuestionOption {
|
||||
@@ -1018,7 +1018,7 @@ fn translate_local_submit_skipped_returns_changed_with_no_action() {
|
||||
#[test]
|
||||
fn translate_local_submit_no_selection_returns_changed_no_action() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..2)
|
||||
@@ -1047,7 +1047,7 @@ fn translate_local_submit_no_selection_returns_changed_no_action() {
|
||||
#[test]
|
||||
fn translate_local_submit_out_of_range_index_returns_changed_no_action() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..2)
|
||||
@@ -1077,7 +1077,7 @@ fn translate_local_submit_out_of_range_index_returns_changed_no_action() {
|
||||
#[test]
|
||||
fn handle_ask_user_question_does_not_push_system_block_when_displaced_acp_modal() {
|
||||
use crate::views::question_view::QuestionViewState;
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let mut app = fork_test_app();
|
||||
let id = AgentId(0);
|
||||
let stashed = app.agents.get_mut(&id).unwrap().prompt.stash();
|
||||
|
||||
@@ -30,8 +30,8 @@ fn worktree_forked_sets_session_id_eagerly_and_emits_load() {
|
||||
assert!(app.agents[&id].session.session_id.is_none());
|
||||
assert!(!app.agents[&id].session.loading_replay);
|
||||
|
||||
let worktree_path = PathBuf::from("/tmp/grok-worktrees/pager-fork");
|
||||
let session_cwd = PathBuf::from("/tmp/grok-worktrees/pager-fork/sub");
|
||||
let worktree_path = PathBuf::from("/tmp/kigi-worktrees/pager-fork");
|
||||
let session_cwd = PathBuf::from("/tmp/kigi-worktrees/pager-fork/sub");
|
||||
let effects = dispatch(
|
||||
Action::TaskComplete(TaskResult::WorktreeForked {
|
||||
agent_id: id,
|
||||
@@ -76,8 +76,8 @@ fn worktree_forked_with_restore_shows_summary_in_scrollback() {
|
||||
);
|
||||
let id = AgentId(0);
|
||||
|
||||
let worktree_path = PathBuf::from("/tmp/grok-worktrees/pager-fork");
|
||||
let session_cwd = PathBuf::from("/tmp/grok-worktrees/pager-fork/sub");
|
||||
let worktree_path = PathBuf::from("/tmp/kigi-worktrees/pager-fork");
|
||||
let session_cwd = PathBuf::from("/tmp/kigi-worktrees/pager-fork/sub");
|
||||
let effects = dispatch(
|
||||
Action::TaskComplete(TaskResult::WorktreeForked {
|
||||
agent_id: id,
|
||||
@@ -130,8 +130,8 @@ fn worktree_forked_with_restore_failure_shows_warning_banner() {
|
||||
);
|
||||
let id = AgentId(0);
|
||||
|
||||
let worktree_path = PathBuf::from("/tmp/grok-worktrees/pager-fail");
|
||||
let session_cwd = PathBuf::from("/tmp/grok-worktrees/pager-fail/sub");
|
||||
let worktree_path = PathBuf::from("/tmp/kigi-worktrees/pager-fail");
|
||||
let session_cwd = PathBuf::from("/tmp/kigi-worktrees/pager-fail/sub");
|
||||
dispatch(
|
||||
Action::TaskComplete(TaskResult::WorktreeForked {
|
||||
agent_id: id,
|
||||
@@ -472,7 +472,7 @@ fn open_fork_question_refuses_when_existing_question_is_open() {
|
||||
let mut app = fork_test_app();
|
||||
// Plant an existing question (e.g. an ACP-driven one).
|
||||
use crate::views::question_view::QuestionViewState;
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "existing ACP question?".into(),
|
||||
options: vec![QuestionOption {
|
||||
@@ -1047,7 +1047,7 @@ fn fork_session_failed_pushes_turn_failed_block() {
|
||||
#[test]
|
||||
fn translate_local_submit_yes_returns_worktree_true_action() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..2)
|
||||
@@ -1090,7 +1090,7 @@ fn translate_local_submit_yes_returns_worktree_true_action() {
|
||||
#[test]
|
||||
fn translate_local_submit_no_returns_worktree_false_action() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..2)
|
||||
@@ -1131,7 +1131,7 @@ fn translate_local_submit_no_returns_worktree_false_action() {
|
||||
#[test]
|
||||
fn translate_local_submit_always_returns_persist_always_for_fork() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..4)
|
||||
@@ -1173,7 +1173,7 @@ fn translate_local_submit_always_returns_persist_always_for_fork() {
|
||||
#[test]
|
||||
fn translate_local_submit_never_returns_persist_never_for_fork() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..4)
|
||||
@@ -1216,7 +1216,7 @@ fn translate_local_submit_never_returns_persist_never_for_fork() {
|
||||
fn handle_ask_user_question_pushes_system_block_when_displaced_local_fork_modal() {
|
||||
use crate::scrollback::block::RenderBlock;
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
|
||||
let mut app = fork_test_app();
|
||||
let id = AgentId(0);
|
||||
|
||||
@@ -172,7 +172,7 @@ fn worktree_session_created_sets_session_and_cwd() {
|
||||
&mut app,
|
||||
);
|
||||
let id = AgentId(0);
|
||||
let worktree_path = PathBuf::from("/tmp/grok-worktrees/pager-123");
|
||||
let worktree_path = PathBuf::from("/tmp/kigi-worktrees/pager-123");
|
||||
let session_cwd = worktree_path.clone();
|
||||
let effects = dispatch(
|
||||
Action::TaskComplete(TaskResult::WorktreeSessionCreated {
|
||||
@@ -353,13 +353,13 @@ fn worktree_session_created_drains_queued_prompts() {
|
||||
let effects = dispatch(Action::SendPrompt("hello".into()), &mut app);
|
||||
assert!(effects.is_empty(), "no session_id yet, can't drain");
|
||||
assert_eq!(app.agents[&id].session.queue_len(), 1);
|
||||
let worktree_path = PathBuf::from("/tmp/grok-worktrees/pager-abc");
|
||||
let worktree_path = PathBuf::from("/tmp/kigi-worktrees/pager-abc");
|
||||
let effects = dispatch(
|
||||
Action::TaskComplete(TaskResult::WorktreeSessionCreated {
|
||||
agent_id: id,
|
||||
session_id: acp::SessionId::new("wt-drain-1"),
|
||||
worktree_path,
|
||||
session_cwd: PathBuf::from("/tmp/grok-worktrees/pager-abc"),
|
||||
session_cwd: PathBuf::from("/tmp/kigi-worktrees/pager-abc"),
|
||||
models: None,
|
||||
}),
|
||||
&mut app,
|
||||
@@ -485,7 +485,7 @@ fn switch_model_without_session_does_nothing() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
app.agents.get_mut(&id).unwrap().session.session_id = None;
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
let effects = dispatch(
|
||||
Action::SwitchModel {
|
||||
model_id,
|
||||
@@ -659,7 +659,7 @@ fn new_session_starts_with_prompt_focused() {
|
||||
fn switch_model_deferred_when_no_session_id() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
app.agents.get_mut(&id).unwrap().session.session_id = None;
|
||||
let effects = dispatch(
|
||||
Action::SwitchModel {
|
||||
@@ -679,7 +679,7 @@ fn switch_model_deferred_when_no_session_id() {
|
||||
fn deferred_model_switch_applied_on_session_created() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
let session_id: acp::SessionId = "new-session".into();
|
||||
app.agents.get_mut(&id).unwrap().session.session_id = None;
|
||||
app.agents
|
||||
@@ -708,7 +708,7 @@ fn deferred_model_switch_applied_on_session_created() {
|
||||
#[test]
|
||||
fn deferred_model_switch_applied_on_worktree_session_created() {
|
||||
let mut app = test_app_git();
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
dispatch(
|
||||
Action::NewWorktreeSession {
|
||||
load_session_id: None,
|
||||
@@ -1314,7 +1314,7 @@ fn dispatch_new_session_has_empty_scrollback() {
|
||||
#[test]
|
||||
fn translate_local_submit_always_returns_persist_always_for_new_session() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..4)
|
||||
@@ -1354,7 +1354,7 @@ fn translate_local_submit_always_returns_persist_always_for_new_session() {
|
||||
#[test]
|
||||
fn translate_local_submit_never_returns_persist_never_for_new_session() {
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "?".into(),
|
||||
options: (0..4)
|
||||
|
||||
@@ -1214,7 +1214,7 @@ fn project_picker_skip_falls_back_to_original_cwd() {
|
||||
fn project_picker_freeform_path_used_when_no_option_selected() {
|
||||
use crate::views::prompt_widget::StashedPrompt;
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let q = Question {
|
||||
question: "Pick".into(),
|
||||
id: None,
|
||||
@@ -1253,7 +1253,7 @@ fn project_picker_freeform_path_used_when_no_option_selected() {
|
||||
fn project_picker_freeform_overrides_dont_ask() {
|
||||
use crate::views::prompt_widget::StashedPrompt;
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionSelection, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let opt = |label: &str| QuestionOption {
|
||||
label: label.into(),
|
||||
description: String::new(),
|
||||
@@ -1310,7 +1310,7 @@ fn needs_project_picker_false_when_disabled() {
|
||||
fn project_picker_dont_ask_again_sets_disable_flag() {
|
||||
use crate::views::prompt_widget::StashedPrompt;
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionSelection, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let opt = |label: &str| QuestionOption {
|
||||
label: label.into(),
|
||||
description: String::new(),
|
||||
@@ -1348,7 +1348,7 @@ fn project_picker_dont_ask_again_sets_disable_flag() {
|
||||
fn project_picker_recent_project_selection_uses_that_path() {
|
||||
use crate::views::prompt_widget::StashedPrompt;
|
||||
use crate::views::question_view::{LocalQuestionKind, QuestionSelection, QuestionViewState};
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{Question, QuestionOption};
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{Question, QuestionOption};
|
||||
let opt = |label: &str| QuestionOption {
|
||||
label: label.into(),
|
||||
description: String::new(),
|
||||
|
||||
@@ -24,7 +24,7 @@ fn model_with_support(id: &str, supports: bool) -> (acp::ModelId, acp::ModelInfo
|
||||
}
|
||||
|
||||
fn models_with_current(supports: bool) -> ModelState {
|
||||
let (id, info) = model_with_support("grok-build", supports);
|
||||
let (id, info) = model_with_support("kigi", supports);
|
||||
let mut models = ModelState::default();
|
||||
models.available.insert(id.clone(), info);
|
||||
models.current = Some(id);
|
||||
|
||||
@@ -227,7 +227,7 @@ fn set_default_model_allowed_when_agent_chat_kind() {
|
||||
fn slash_model_valid_dispatches_set_default_model_with_switch_and_persist() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
app.agents
|
||||
.get_mut(&id)
|
||||
.unwrap()
|
||||
@@ -236,9 +236,9 @@ fn slash_model_valid_dispatches_set_default_model_with_switch_and_persist() {
|
||||
.available
|
||||
.insert(
|
||||
model_id.clone(),
|
||||
acp::ModelInfo::new(model_id.clone(), "Grok 4.5".to_string()),
|
||||
acp::ModelInfo::new(model_id.clone(), "Kigi 4.5".to_string()),
|
||||
);
|
||||
let effects = dispatch(Action::SendPrompt("/model Grok 4.5".into()), &mut app);
|
||||
let effects = dispatch(Action::SendPrompt("/model Kigi 4.5".into()), &mut app);
|
||||
assert_eq!(
|
||||
effects.len(),
|
||||
2,
|
||||
@@ -904,8 +904,8 @@ fn clear_default_model_persists_but_keeps_live_current() {
|
||||
use agent_client_protocol as acp;
|
||||
use std::sync::Arc;
|
||||
let mut app = test_app_with_agent();
|
||||
let id = acp::ModelId::new(Arc::from("grok-test"));
|
||||
let info = acp::ModelInfo::new(id.clone(), "Grok Test".to_string());
|
||||
let id = acp::ModelId::new(Arc::from("kigi-test"));
|
||||
let info = acp::ModelInfo::new(id.clone(), "Kigi Test".to_string());
|
||||
let agent_id = AgentId(0);
|
||||
app.agents
|
||||
.get_mut(&agent_id)
|
||||
@@ -949,8 +949,8 @@ fn set_default_model_resolves_known_name() {
|
||||
use agent_client_protocol as acp;
|
||||
use std::sync::Arc;
|
||||
let mut app = test_app_with_agent();
|
||||
let id = acp::ModelId::new(Arc::from("grok-4.5"));
|
||||
let info = acp::ModelInfo::new(id.clone(), "Grok 4.5".to_string());
|
||||
let id = acp::ModelId::new(Arc::from("kigi-4.5"));
|
||||
let info = acp::ModelInfo::new(id.clone(), "Kigi 4.5".to_string());
|
||||
let agent_id = AgentId(0);
|
||||
app.agents
|
||||
.get_mut(&agent_id)
|
||||
@@ -963,7 +963,7 @@ fn set_default_model_resolves_known_name() {
|
||||
assert_eq!(effects.len(), 2);
|
||||
assert!(
|
||||
matches!(& effects[0], Effect::PersistSetting { key : "default_model", value :
|
||||
crate ::settings::SettingValue::String(s), .. } if s == "grok-4.5")
|
||||
crate ::settings::SettingValue::String(s), .. } if s == "kigi-4.5")
|
||||
);
|
||||
assert!(matches!(& effects[1], Effect::SwitchModel { model_id : mid, .. } if mid == & id));
|
||||
assert_eq!(app.agents[&agent_id].session.models.current, Some(id));
|
||||
@@ -976,8 +976,8 @@ fn set_default_model_idempotent_when_already_current() {
|
||||
use agent_client_protocol as acp;
|
||||
use std::sync::Arc;
|
||||
let mut app = test_app_with_agent();
|
||||
let id = acp::ModelId::new(Arc::from("grok-already"));
|
||||
let info = acp::ModelInfo::new(id.clone(), "Grok Already".to_string());
|
||||
let id = acp::ModelId::new(Arc::from("kigi-already"));
|
||||
let info = acp::ModelInfo::new(id.clone(), "Kigi Already".to_string());
|
||||
let agent_id = AgentId(0);
|
||||
app.agents
|
||||
.get_mut(&agent_id)
|
||||
@@ -2666,16 +2666,16 @@ fn dispatch_cycle_mode_refreshes_open_modal_snapshot() {
|
||||
"current_value_for must read the refreshed snapshot",
|
||||
);
|
||||
}
|
||||
/// `dispatch(Action::SetTheme("grokday"), &mut app)` emits
|
||||
/// `dispatch(Action::SetTheme("kigiday"), &mut app)` emits
|
||||
/// exactly one `Effect::PersistSetting`, mutates
|
||||
/// `app.current_ui.theme`, fires a toast, and toggles AUTO_MODE
|
||||
/// off (kind is concrete).
|
||||
///
|
||||
/// Note: we persist `grokday` (a non-truecolor theme) here
|
||||
/// Note: we persist `kigiday` (a non-truecolor theme) here
|
||||
/// because `Effect::PersistSetting`'s payload is `&'static str`
|
||||
/// from the registry's canonical table — the persisted CANONICAL
|
||||
/// is what we're asserting, NOT the live theme cache (which
|
||||
/// `clamp_to_terminal` might fold to GrokNight in non-truecolor
|
||||
/// `clamp_to_terminal` might fold to KigiNight in non-truecolor
|
||||
/// test environments). Persist + canonical contract is the test
|
||||
/// invariant; the cache contract is exercised separately by the
|
||||
/// `*_applies_when_*` tests.
|
||||
@@ -2685,8 +2685,8 @@ fn set_theme_emits_persist_setting_with_correct_payload() {
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
assert_eq!(app.current_ui.theme, None);
|
||||
crate::theme::cache::set(crate::theme::ThemeKind::GrokNight);
|
||||
let effects = dispatch(Action::SetTheme("grokday".into()), &mut app);
|
||||
crate::theme::cache::set(crate::theme::ThemeKind::KigiNight);
|
||||
let effects = dispatch(Action::SetTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(effects.len(), 1);
|
||||
match &effects[0] {
|
||||
Effect::PersistSetting {
|
||||
@@ -2695,12 +2695,12 @@ fn set_theme_emits_persist_setting_with_correct_payload() {
|
||||
rollback_value,
|
||||
} => {
|
||||
assert_eq!(*key, "theme");
|
||||
assert_eq!(*value, SettingValue::Enum("grokday"));
|
||||
assert_eq!(*rollback_value, SettingValue::Enum("groknight"));
|
||||
assert_eq!(*value, SettingValue::Enum("kigiday"));
|
||||
assert_eq!(*rollback_value, SettingValue::Enum("kiginight"));
|
||||
}
|
||||
other => panic!("expected PersistSetting, got {other:?}"),
|
||||
}
|
||||
assert_eq!(app.current_ui.theme.as_deref(), Some("grokday"));
|
||||
assert_eq!(app.current_ui.theme.as_deref(), Some("kigiday"));
|
||||
assert!(
|
||||
!crate::theme::cache::is_auto_mode(),
|
||||
"concrete theme commit must disable AUTO_MODE",
|
||||
@@ -2708,7 +2708,7 @@ fn set_theme_emits_persist_setting_with_correct_payload() {
|
||||
});
|
||||
}
|
||||
/// Same payload contract as `set_theme_emits_persist_setting_with_correct_payload`
|
||||
/// for the auto-dark sibling. Uses `grokday` to avoid the
|
||||
/// for the auto-dark sibling. Uses `kigiday` to avoid the
|
||||
/// `clamp_to_terminal` ambiguity in non-truecolor test envs;
|
||||
/// `apply_kind` doesn't fire here anyway (parent theme is not
|
||||
/// auto by default) but using a non-truecolor canonical keeps
|
||||
@@ -2718,7 +2718,7 @@ fn set_auto_dark_theme_emits_persist_setting_with_correct_payload() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let effects = dispatch(Action::SetAutoDarkTheme("grokday".into()), &mut app);
|
||||
let effects = dispatch(Action::SetAutoDarkTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(effects.len(), 1);
|
||||
match &effects[0] {
|
||||
Effect::PersistSetting {
|
||||
@@ -2727,12 +2727,12 @@ fn set_auto_dark_theme_emits_persist_setting_with_correct_payload() {
|
||||
rollback_value,
|
||||
} => {
|
||||
assert_eq!(*key, "auto_dark_theme");
|
||||
assert_eq!(*value, SettingValue::Enum("grokday"));
|
||||
assert_eq!(*rollback_value, SettingValue::Enum("groknight"));
|
||||
assert_eq!(*value, SettingValue::Enum("kigiday"));
|
||||
assert_eq!(*rollback_value, SettingValue::Enum("kiginight"));
|
||||
}
|
||||
other => panic!("expected PersistSetting, got {other:?}"),
|
||||
}
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("grokday"));
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("kigiday"));
|
||||
});
|
||||
}
|
||||
#[test]
|
||||
@@ -2740,7 +2740,7 @@ fn set_auto_light_theme_emits_persist_setting_with_correct_payload() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let effects = dispatch(Action::SetAutoLightTheme("groknight".into()), &mut app);
|
||||
let effects = dispatch(Action::SetAutoLightTheme("kiginight".into()), &mut app);
|
||||
assert_eq!(effects.len(), 1);
|
||||
match &effects[0] {
|
||||
Effect::PersistSetting {
|
||||
@@ -2749,14 +2749,14 @@ fn set_auto_light_theme_emits_persist_setting_with_correct_payload() {
|
||||
rollback_value,
|
||||
} => {
|
||||
assert_eq!(*key, "auto_light_theme");
|
||||
assert_eq!(*value, SettingValue::Enum("groknight"));
|
||||
assert_eq!(*rollback_value, SettingValue::Enum("grokday"));
|
||||
assert_eq!(*value, SettingValue::Enum("kiginight"));
|
||||
assert_eq!(*rollback_value, SettingValue::Enum("kigiday"));
|
||||
}
|
||||
other => panic!("expected PersistSetting, got {other:?}"),
|
||||
}
|
||||
assert_eq!(
|
||||
app.current_ui.auto_light_theme.as_deref(),
|
||||
Some("groknight"),
|
||||
Some("kiginight"),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -2809,11 +2809,11 @@ fn preview_auto_light_theme_emits_no_persist_and_no_current_ui_mutation() {
|
||||
/// Auto-theme commit applies the live theme **only** when
|
||||
/// `theme="auto"` AND the system is in the matching mode.
|
||||
///
|
||||
/// Scenario: `theme="groknight"` (concrete) + system=Dark. User
|
||||
/// commits `auto_dark_theme="grokday"`. The setting is dormant
|
||||
/// Scenario: `theme="kiginight"` (concrete) + system=Dark. User
|
||||
/// commits `auto_dark_theme="kigiday"`. The setting is dormant
|
||||
/// (parent theme is concrete, not auto), so the live display
|
||||
/// must stay on GrokNight even though we're committing a
|
||||
/// different theme. Uses `grokday` to avoid `clamp_to_terminal`
|
||||
/// must stay on KigiNight even though we're committing a
|
||||
/// different theme. Uses `kigiday` to avoid `clamp_to_terminal`
|
||||
/// ambiguity in non-truecolor envs.
|
||||
#[test]
|
||||
fn set_auto_dark_theme_does_not_apply_when_theme_is_not_auto() {
|
||||
@@ -2822,28 +2822,28 @@ fn set_auto_dark_theme_does_not_apply_when_theme_is_not_auto() {
|
||||
crate::theme::system_appearance::SystemAppearance::Dark,
|
||||
));
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetTheme("groknight".into()), &mut app);
|
||||
let _ = dispatch(Action::SetTheme("kiginight".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokNight,
|
||||
crate::theme::ThemeKind::KigiNight,
|
||||
);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("grokday".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokNight,
|
||||
crate::theme::ThemeKind::KigiNight,
|
||||
"auto_dark_theme commit must NOT change live display when theme is not auto",
|
||||
);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("grokday"));
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("kigiday"));
|
||||
});
|
||||
}
|
||||
/// Auto-theme commit DOES apply the live theme when both
|
||||
/// (a) parent theme = auto AND (b) system matches.
|
||||
///
|
||||
/// Uses `GrokDay` (non-truecolor-requiring) for the dark-mode
|
||||
/// Uses `KigiDay` (non-truecolor-requiring) for the dark-mode
|
||||
/// fixture: the test environment's color detection may not report
|
||||
/// truecolor support, and `Theme::apply_kind` clamps
|
||||
/// truecolor-only themes (TokyoNight, RosePineMoon) down to
|
||||
/// GrokNight. Using a non-truecolor theme avoids the clamp
|
||||
/// KigiNight. Using a non-truecolor theme avoids the clamp
|
||||
/// uncertainty. The "live apply" contract is what we're testing
|
||||
/// — the specific theme picked is incidental.
|
||||
#[test]
|
||||
@@ -2857,21 +2857,21 @@ fn set_auto_dark_theme_applies_when_theme_is_auto_and_system_is_dark() {
|
||||
assert!(crate::theme::cache::is_auto_mode());
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokNight,
|
||||
crate::theme::ThemeKind::KigiNight,
|
||||
);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("grokday".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokDay,
|
||||
crate::theme::ThemeKind::KigiDay,
|
||||
"auto_dark_theme commit must update live display when theme=auto + system=Dark",
|
||||
);
|
||||
});
|
||||
}
|
||||
/// Auto-theme commit does NOT apply when system is in the
|
||||
/// non-matching mode (auto_dark_theme + system=Light).
|
||||
/// Uses `groknight` for the auto_dark_theme
|
||||
/// Uses `kiginight` for the auto_dark_theme
|
||||
/// value to avoid `clamp_to_terminal` ambiguity (we want a
|
||||
/// concrete kind that's clearly different from GrokDay, the
|
||||
/// concrete kind that's clearly different from KigiDay, the
|
||||
/// active resolved theme).
|
||||
#[test]
|
||||
fn set_auto_dark_theme_does_not_apply_when_system_is_light() {
|
||||
@@ -2883,20 +2883,20 @@ fn set_auto_dark_theme_does_not_apply_when_system_is_light() {
|
||||
let _ = dispatch(Action::SetTheme("auto".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokDay,
|
||||
crate::theme::ThemeKind::KigiDay,
|
||||
);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("groknight".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("kiginight".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokDay,
|
||||
crate::theme::ThemeKind::KigiDay,
|
||||
"auto_dark_theme commit must NOT change live display when system=Light",
|
||||
);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("groknight"),);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("kiginight"),);
|
||||
});
|
||||
}
|
||||
/// Symmetric to the dark test: `set_auto_light_theme` applies only
|
||||
/// when theme=auto + system=Light. Uses a non-truecolor theme
|
||||
/// (`groknight`) for the same clamp reason as the dark variant.
|
||||
/// (`kiginight`) for the same clamp reason as the dark variant.
|
||||
#[test]
|
||||
fn set_auto_light_theme_applies_when_theme_is_auto_and_system_is_light() {
|
||||
with_theme_test_env(|| {
|
||||
@@ -2907,12 +2907,12 @@ fn set_auto_light_theme_applies_when_theme_is_auto_and_system_is_light() {
|
||||
let _ = dispatch(Action::SetTheme("auto".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokDay,
|
||||
crate::theme::ThemeKind::KigiDay,
|
||||
);
|
||||
let _ = dispatch(Action::SetAutoLightTheme("groknight".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoLightTheme("kiginight".into()), &mut app);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokNight,
|
||||
crate::theme::ThemeKind::KigiNight,
|
||||
"auto_light_theme must update display when theme=auto + system=Light",
|
||||
);
|
||||
});
|
||||
@@ -2986,7 +2986,7 @@ fn set_auto_light_theme_rejects_auto_value() {
|
||||
fn set_theme_toast_format_uses_display_name() {
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetTheme("grokday".into()), &mut app);
|
||||
let _ = dispatch(Action::SetTheme("kigiday".into()), &mut app);
|
||||
let toast = read_toast(&app);
|
||||
assert!(
|
||||
toast.contains("Theme"),
|
||||
@@ -2994,7 +2994,7 @@ fn set_theme_toast_format_uses_display_name() {
|
||||
);
|
||||
assert!(
|
||||
toast.contains("Kigi Day"),
|
||||
"toast must use display name `Kigi Day`, not canonical `grokday`, got: {toast:?}",
|
||||
"toast must use display name `Kigi Day`, not canonical `kigiday`, got: {toast:?}",
|
||||
);
|
||||
assert!(toast.contains('\u{2713}'), "toast must contain the ✓ glyph");
|
||||
});
|
||||
@@ -3003,7 +3003,7 @@ fn set_theme_toast_format_uses_display_name() {
|
||||
fn set_auto_dark_theme_toast_format_uses_display_name() {
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("grokday".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("kigiday".into()), &mut app);
|
||||
let toast = read_toast(&app);
|
||||
assert!(toast.contains("Auto dark theme"));
|
||||
assert!(toast.contains("Kigi Day"));
|
||||
@@ -3014,7 +3014,7 @@ fn set_auto_dark_theme_toast_format_uses_display_name() {
|
||||
fn set_auto_light_theme_toast_format_uses_display_name() {
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetAutoLightTheme("groknight".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoLightTheme("kiginight".into()), &mut app);
|
||||
let toast = read_toast(&app);
|
||||
assert!(toast.contains("Auto light theme"));
|
||||
assert!(toast.contains("Kigi Night"));
|
||||
@@ -3024,7 +3024,7 @@ fn set_auto_light_theme_toast_format_uses_display_name() {
|
||||
/// reverts `app.current_ui.theme` AND the live cache (mirror of
|
||||
/// `rollback_known_key_reverts_cache_and_no_effect`).
|
||||
///
|
||||
/// Uses non-truecolor themes (`grokday` ↔ `groknight`) to avoid
|
||||
/// Uses non-truecolor themes (`kigiday` ↔ `kiginight`) to avoid
|
||||
/// the `clamp_to_terminal` interaction in test environments that
|
||||
/// don't report truecolor support.
|
||||
#[test]
|
||||
@@ -3032,28 +3032,28 @@ fn rollback_theme_reverts_current_ui_and_cache() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetTheme("grokday".into()), &mut app);
|
||||
assert_eq!(app.current_ui.theme.as_deref(), Some("grokday"));
|
||||
let _ = dispatch(Action::SetTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(app.current_ui.theme.as_deref(), Some("kigiday"));
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokDay,
|
||||
crate::theme::ThemeKind::KigiDay,
|
||||
);
|
||||
let _ = dispatch(
|
||||
Action::TaskComplete(TaskResult::SettingPersistFailed {
|
||||
key: "theme",
|
||||
rollback_value: SettingValue::Enum("groknight"),
|
||||
rollback_value: SettingValue::Enum("kiginight"),
|
||||
error: "disk full".into(),
|
||||
}),
|
||||
&mut app,
|
||||
);
|
||||
assert_eq!(
|
||||
app.current_ui.theme.as_deref(),
|
||||
Some("groknight"),
|
||||
Some("kiginight"),
|
||||
"rollback must update app.current_ui.theme",
|
||||
);
|
||||
assert_eq!(
|
||||
crate::theme::cache::current_kind(),
|
||||
crate::theme::ThemeKind::GrokNight,
|
||||
crate::theme::ThemeKind::KigiNight,
|
||||
"rollback must update the live theme cache too",
|
||||
);
|
||||
});
|
||||
@@ -3063,17 +3063,17 @@ fn rollback_auto_dark_theme_reverts_current_ui() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("grokday".into()), &mut app);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("grokday"));
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("kigiday"));
|
||||
let _ = dispatch(
|
||||
Action::TaskComplete(TaskResult::SettingPersistFailed {
|
||||
key: "auto_dark_theme",
|
||||
rollback_value: SettingValue::Enum("groknight"),
|
||||
rollback_value: SettingValue::Enum("kiginight"),
|
||||
error: "disk full".into(),
|
||||
}),
|
||||
&mut app,
|
||||
);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("groknight"),);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("kiginight"),);
|
||||
});
|
||||
}
|
||||
#[test]
|
||||
@@ -3081,20 +3081,20 @@ fn rollback_auto_light_theme_reverts_current_ui() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetAutoLightTheme("groknight".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoLightTheme("kiginight".into()), &mut app);
|
||||
assert_eq!(
|
||||
app.current_ui.auto_light_theme.as_deref(),
|
||||
Some("groknight"),
|
||||
Some("kiginight"),
|
||||
);
|
||||
let _ = dispatch(
|
||||
Action::TaskComplete(TaskResult::SettingPersistFailed {
|
||||
key: "auto_light_theme",
|
||||
rollback_value: SettingValue::Enum("grokday"),
|
||||
rollback_value: SettingValue::Enum("kigiday"),
|
||||
error: "disk full".into(),
|
||||
}),
|
||||
&mut app,
|
||||
);
|
||||
assert_eq!(app.current_ui.auto_light_theme.as_deref(), Some("grokday"));
|
||||
assert_eq!(app.current_ui.auto_light_theme.as_deref(), Some("kigiday"));
|
||||
});
|
||||
}
|
||||
/// Edge case — if the rollback value is
|
||||
@@ -3109,8 +3109,8 @@ fn rollback_auto_dark_theme_with_auto_value_clears_to_none() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("grokday".into()), &mut app);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("grokday"));
|
||||
let _ = dispatch(Action::SetAutoDarkTheme("kigiday".into()), &mut app);
|
||||
assert_eq!(app.current_ui.auto_dark_theme.as_deref(), Some("kigiday"));
|
||||
let _ = dispatch(
|
||||
Action::TaskComplete(TaskResult::SettingPersistFailed {
|
||||
key: "auto_dark_theme",
|
||||
@@ -3131,10 +3131,10 @@ fn rollback_auto_light_theme_with_auto_value_clears_to_none() {
|
||||
use crate::settings::SettingValue;
|
||||
with_theme_test_env(|| {
|
||||
let mut app = test_app_with_agent();
|
||||
let _ = dispatch(Action::SetAutoLightTheme("groknight".into()), &mut app);
|
||||
let _ = dispatch(Action::SetAutoLightTheme("kiginight".into()), &mut app);
|
||||
assert_eq!(
|
||||
app.current_ui.auto_light_theme.as_deref(),
|
||||
Some("groknight"),
|
||||
Some("kiginight"),
|
||||
);
|
||||
let _ = dispatch(
|
||||
Action::TaskComplete(TaskResult::SettingPersistFailed {
|
||||
|
||||
@@ -198,16 +198,16 @@ fn dispatch_confirm_reset_setting_reset_dispatches_typed_setter_for_shared_enum(
|
||||
&mut app,
|
||||
);
|
||||
|
||||
// Reset → SetTheme("groknight") (the registered default).
|
||||
// Reset → SetTheme("kiginight") (the registered default).
|
||||
assert_eq!(effects.len(), 1);
|
||||
match &effects[0] {
|
||||
Effect::PersistSetting { key, value, .. } => {
|
||||
assert_eq!(*key, "theme");
|
||||
assert_eq!(value, &SettingValue::Enum("groknight"));
|
||||
assert_eq!(value, &SettingValue::Enum("kiginight"));
|
||||
}
|
||||
other => panic!("expected PersistSetting, got {other:?}"),
|
||||
}
|
||||
assert_eq!(app.current_ui.theme.as_deref(), Some("groknight"));
|
||||
assert_eq!(app.current_ui.theme.as_deref(), Some("kiginight"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -421,7 +421,7 @@ fn uninstall_result_notice_is_footer_only_not_row_anchored() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Regression (Bugbot): a failed `x.ai/subagent/cancel` RPC must NOT
|
||||
/// Regression (Bugbot): a failed `kigi/subagent/cancel` RPC must NOT
|
||||
/// finalize the row — the subagent may still be running. Only a shell
|
||||
/// response of "nothing live" finalizes it.
|
||||
#[test]
|
||||
@@ -509,7 +509,7 @@ fn cancel_complete_does_nothing() {
|
||||
fn switch_model_complete_success_updates_model_and_pushes_message() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
|
||||
// Set up available models so the display name can be resolved.
|
||||
app.agents
|
||||
@@ -520,7 +520,7 @@ fn switch_model_complete_success_updates_model_and_pushes_message() {
|
||||
.available
|
||||
.insert(
|
||||
model_id.clone(),
|
||||
acp::ModelInfo::new(model_id.clone(), "Grok 4.5".to_string()),
|
||||
acp::ModelInfo::new(model_id.clone(), "Kigi 4.5".to_string()),
|
||||
);
|
||||
app.agents
|
||||
.get_mut(&id)
|
||||
@@ -562,12 +562,12 @@ fn switch_model_complete_success_updates_model_and_pushes_message() {
|
||||
fn switch_model_complete_skips_message_and_persist_when_unchanged() {
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
|
||||
let agent = app.agents.get_mut(&id).unwrap();
|
||||
agent.session.models.available.insert(
|
||||
model_id.clone(),
|
||||
acp::ModelInfo::new(model_id.clone(), "Grok 4.5".to_string()),
|
||||
acp::ModelInfo::new(model_id.clone(), "Kigi 4.5".to_string()),
|
||||
);
|
||||
agent.session.models.current = Some(model_id.clone());
|
||||
agent.session.models.reasoning_effort = None;
|
||||
@@ -667,7 +667,7 @@ fn switch_to_non_reasoning_model_clears_persisted_effort() {
|
||||
use kigi_shell::sampling::types::ReasoningEffort;
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
|
||||
// Simulate prior reasoning effort from a previous model.
|
||||
app.agents
|
||||
@@ -686,7 +686,7 @@ fn switch_to_non_reasoning_model_clears_persisted_effort() {
|
||||
.available
|
||||
.insert(
|
||||
model_id.clone(),
|
||||
acp::ModelInfo::new(model_id.clone(), "Grok Build".to_string()),
|
||||
acp::ModelInfo::new(model_id.clone(), "Kigi".to_string()),
|
||||
);
|
||||
app.agents
|
||||
.get_mut(&id)
|
||||
@@ -773,7 +773,7 @@ fn switch_model_incompatible_agent_shows_question_modal() {
|
||||
|
||||
let err = kigi_shell::agent::config::ModelSwitchIncompatibleAgentError {
|
||||
code: "MODEL_SWITCH_INCOMPATIBLE_AGENT".into(),
|
||||
active_agent_type: "grok-build".into(),
|
||||
active_agent_type: "kigi".into(),
|
||||
required_agent_type: "cursor".into(),
|
||||
model_id: "cursor-model".into(),
|
||||
suggestion: "start_new_session".into(),
|
||||
@@ -836,7 +836,7 @@ fn incompatible_agent_rollback_restores_previous_model() {
|
||||
|
||||
let err = kigi_shell::agent::config::ModelSwitchIncompatibleAgentError {
|
||||
code: "MODEL_SWITCH_INCOMPATIBLE_AGENT".into(),
|
||||
active_agent_type: "grok-build".into(),
|
||||
active_agent_type: "kigi".into(),
|
||||
required_agent_type: "cursor".into(),
|
||||
model_id: "cursor-model".into(),
|
||||
suggestion: "start_new_session".into(),
|
||||
@@ -882,7 +882,7 @@ fn incompatible_agent_closes_active_modal() {
|
||||
|
||||
let err = kigi_shell::agent::config::ModelSwitchIncompatibleAgentError {
|
||||
code: "MODEL_SWITCH_INCOMPATIBLE_AGENT".into(),
|
||||
active_agent_type: "grok-build".into(),
|
||||
active_agent_type: "kigi".into(),
|
||||
required_agent_type: "cursor".into(),
|
||||
model_id: "cursor-model".into(),
|
||||
suggestion: "start_new_session".into(),
|
||||
@@ -919,19 +919,19 @@ fn same_agent_type_switch_no_modal() {
|
||||
// should succeed normally — no modal, no IncompatibleAgent error.
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_a = acp::ModelId::new(std::sync::Arc::from("grok-build-a"));
|
||||
let model_b = acp::ModelId::new(std::sync::Arc::from("grok-build-b"));
|
||||
let model_a = acp::ModelId::new(std::sync::Arc::from("kigi-a"));
|
||||
let model_b = acp::ModelId::new(std::sync::Arc::from("kigi-b"));
|
||||
|
||||
// Add both models to the catalog (no agentType → both use grok-build).
|
||||
// Add both models to the catalog (no agentType → both use kigi).
|
||||
let agent = app.agents.get_mut(&id).unwrap();
|
||||
agent.session.models.available.insert(
|
||||
model_a.clone(),
|
||||
acp::ModelInfo::new(model_a.clone(), "Grok Build A".to_string()),
|
||||
acp::ModelInfo::new(model_a.clone(), "Kigi A".to_string()),
|
||||
);
|
||||
agent.session.models.set_current(model_a, None);
|
||||
agent.session.models.available.insert(
|
||||
model_b.clone(),
|
||||
acp::ModelInfo::new(model_b.clone(), "Grok Build B".to_string()),
|
||||
acp::ModelInfo::new(model_b.clone(), "Kigi B".to_string()),
|
||||
);
|
||||
agent.session.model_switch_pending = true;
|
||||
|
||||
@@ -963,7 +963,7 @@ fn switch_model_pending_lifecycle() {
|
||||
// Full lifecycle: false -> dispatch SwitchModel -> true -> SwitchModelComplete -> false
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("grok-4.5"));
|
||||
let model_id = acp::ModelId::new(std::sync::Arc::from("kigi-4.5"));
|
||||
|
||||
// Initially false.
|
||||
assert!(!app.agents[&id].session.model_switch_pending);
|
||||
|
||||
@@ -246,7 +246,7 @@ fn plugins_list_response() -> kigi_hooks_plugins_types::PluginsListResponse {
|
||||
plugins: vec![
|
||||
test_plugin_info(
|
||||
"user-tool",
|
||||
Some(kigi_hooks_plugins_types::PluginOrigin::UserGrok),
|
||||
Some(kigi_hooks_plugins_types::PluginOrigin::UserKigi),
|
||||
),
|
||||
test_plugin_info(
|
||||
"claude-tool",
|
||||
|
||||
@@ -160,7 +160,7 @@ fn cancel_turn_leaves_shared_queue_for_agent_to_drain() {
|
||||
// shared queue (broadcast to all attached clients). The agent owns the
|
||||
// drain: on cancel the FRONT queued prompt runs next (promoted
|
||||
// server-side), so the pager must NOT pull it back into the input or
|
||||
// mutate the queue locally — the `x.ai/queue/changed` rebroadcast is the
|
||||
// mutate the queue locally — the `kigi/queue/changed` rebroadcast is the
|
||||
// source of truth.
|
||||
let mut app = test_app_with_agent();
|
||||
let id = AgentId(0);
|
||||
|
||||
@@ -202,7 +202,7 @@ pub(crate) fn dispatch_open_transcript_pager(app: &mut AppView) {
|
||||
return;
|
||||
};
|
||||
|
||||
let path = std::env::temp_dir().join(format!("grok-transcript-{}.md", uuid::Uuid::new_v4()));
|
||||
let path = std::env::temp_dir().join(format!("kigi-transcript-{}.md", uuid::Uuid::new_v4()));
|
||||
match std::fs::write(&path, content) {
|
||||
Ok(()) => {
|
||||
app.pending_pager_path = Some(path);
|
||||
@@ -636,7 +636,7 @@ pub(super) fn handle_skills_toggle_done(
|
||||
}
|
||||
}
|
||||
}
|
||||
// The toggle effect already called x.ai/skills/refresh-baseline
|
||||
// The toggle effect already called kigi/skills/refresh-baseline
|
||||
// which triggers the session to reload skills and push an
|
||||
// AvailableCommandsUpdate notification with the updated list.
|
||||
vec![]
|
||||
|
||||
@@ -258,7 +258,7 @@ pub(super) fn do_cancel_turn(app: &mut AppView, cancel_subagents: bool) -> Vec<E
|
||||
|
||||
// Server-authoritative queue: the agent owns the drain. On an interactive
|
||||
// cancel we only tear down the running turn and let the agent promote the
|
||||
// FRONT queued prompt as the next turn — its `x.ai/queue/changed`
|
||||
// FRONT queued prompt as the next turn — its `kigi/queue/changed`
|
||||
// rebroadcast (carrying `running_prompt_id`) is the source of truth, and the
|
||||
// pager adopts it via `handle_queue_changed` / `apply_turn_start_shim`. We
|
||||
// do NOT pull any queued prompt back into the input or predict the new queue
|
||||
@@ -277,7 +277,7 @@ pub(super) fn do_cancel_turn(app: &mut AppView, cancel_subagents: bool) -> Vec<E
|
||||
}]
|
||||
}
|
||||
|
||||
/// Grace window between a driver-side `x.ai/session/prompt_complete`
|
||||
/// Grace window between a driver-side `kigi/session/prompt_complete`
|
||||
/// broadcast and that turn's `session/prompt` RPC response, after which
|
||||
/// [`reconcile_overdue_turn_ends`] finishes the turn from the broadcast. The
|
||||
/// healthy-path gap is milliseconds (the shell emits the broadcast just
|
||||
@@ -285,7 +285,7 @@ pub(super) fn do_cancel_turn(app: &mut AppView, cancel_subagents: bool) -> Vec<E
|
||||
/// genuinely lost, not merely slow.
|
||||
pub(crate) const TURN_END_RECONCILE_GRACE: std::time::Duration = std::time::Duration::from_secs(2);
|
||||
|
||||
/// Finish turns whose end was announced by `x.ai/session/prompt_complete`
|
||||
/// Finish turns whose end was announced by `kigi/session/prompt_complete`
|
||||
/// but whose `session/prompt` RPC response never arrived.
|
||||
///
|
||||
/// The RPC response is the driver's only turn-state exit, and it can be lost
|
||||
|
||||
Reference in New Issue
Block a user