F3: Kimi inference pipeline + full grok cloud-surface excision
Sampler / inference (PRD F3):
- kimi_compat.rs: single adaptation point for the Kimi chat/completions
dialect (thinking-field mapping, model_id stripping, empty-content
tool-call message fix, stream_options.include_usage), with kimi-cli
source citations
- Rate-limit handling reworked for Kimi/Moonshot semantics; UA kigi/{version}
- /models replaces the xAI models-v2 endpoint everywhere; idle model
refresh carries X-Msh-* device headers only (X-XAI-Token-Auth and
x-grok-client-mode/CLIENT_MODE_HEADER machinery deleted)
Cloud-surface excision (PRD §5, zero-egress):
- remote/ conversations lane, cli-chat-proxy-types crate, prod/ dir,
share command, credit bar: deleted (single local session lane;
paginate() replaces merge_and_paginate)
- Subscription/tier gate stack deleted end-to-end: AppView
gate/tier/team/ZDR fields, app/subscription.rs watch loop,
dispatch/billing.rs paywall + SuperGrok upsell, free-usage-exhausted
chain, tier-restricted commands, GateInfo, RemoteSettings gate fields,
SettingsUpdateNotification gate fields
- /privacy + coding-data-sharing setting deleted (backed by a dead xAI
RPC; Kigi is zero-egress — nothing to share or retain remotely)
Auth UX correctness (user-reported):
- Device-flow fixtures now mirror the live Kimi payload shape
(https://www.kimi.com/code/authorize_device?user_code=..., verified
against auth.kimi.com); the fabricated auth.kimi.com/device?code=...
URLs are gone
- open_browser_detached is a no-op under cfg(test): unit tests drove
wiremock fixture URLs into the real browser (root cause of the
"garbage mock link" ABCD-1234 tabs)
- Welcome/pager-minimal rebrand: Grok Build -> Kigi, grok.com ->
kimi.com, "Sign in to Grok" -> "Sign in to Kimi"
This commit is contained in:
@@ -678,7 +678,6 @@ impl AgentView {
|
||||
.hit_plan_approval_status
|
||||
.update_hover(mouse.column, mouse.row);
|
||||
changed |= self.hit_context.update_hover(mouse.column, mouse.row);
|
||||
changed |= self.hit_credits.update_hover(mouse.column, mouse.row);
|
||||
}
|
||||
MouseEventKind::Down(MouseButton::Left) => {
|
||||
if self.hit_plan_button.contains(mouse.column, mouse.row) {
|
||||
@@ -943,7 +942,7 @@ impl AgentView {
|
||||
|| (key.code == KeyCode::Char('/') && key.modifiers.contains(KeyModifiers::SHIFT)))
|
||||
{
|
||||
self.active_modal = Some(crate::views::modal::ActiveModal::CommandPalette {
|
||||
entries: crate::views::modal::default_palette_entries(self.sharing_enabled),
|
||||
entries: crate::views::modal::default_palette_entries(),
|
||||
state: crate::views::picker::PickerState::input_active(),
|
||||
window: crate::views::modal_window::ModalWindowState::new(),
|
||||
});
|
||||
@@ -1016,7 +1015,7 @@ impl AgentView {
|
||||
}
|
||||
ActionId::CommandPalette => {
|
||||
self.active_modal = Some(crate::views::modal::ActiveModal::CommandPalette {
|
||||
entries: crate::views::modal::default_palette_entries(self.sharing_enabled),
|
||||
entries: crate::views::modal::default_palette_entries(),
|
||||
state: crate::views::picker::PickerState::input_active(),
|
||||
window: crate::views::modal_window::ModalWindowState::new(),
|
||||
});
|
||||
@@ -1462,7 +1461,7 @@ mod focus_gained_restore_tests {
|
||||
agent.session.state = AgentState::TurnRunning;
|
||||
with_permission(&mut agent);
|
||||
agent.active_modal = Some(ActiveModal::CommandPalette {
|
||||
entries: crate::views::modal::default_palette_entries(false),
|
||||
entries: crate::views::modal::default_palette_entries(),
|
||||
state: crate::views::picker::PickerState::input_active(),
|
||||
window: crate::views::modal_window::ModalWindowState::new(),
|
||||
});
|
||||
|
||||
@@ -1261,8 +1261,6 @@ mod cancel_turn_mouse_tests {
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
|
||||
@@ -727,10 +727,6 @@ pub struct AgentView {
|
||||
/// Stashed normal prompt state while editing a queued prompt.
|
||||
/// Restored when editing ends.
|
||||
pub stashed_prompt: Option<StashedPrompt>,
|
||||
/// Complete prompt stashed from a credit-limit-blocked turn. Used by
|
||||
/// `CreditLimitRecheckComplete` to retry the prompt after a tier
|
||||
/// upgrade instead of showing a stale upsell.
|
||||
pub credit_limit_stashed_prompt: Option<crate::app::agent::InFlightPrompt>,
|
||||
/// Complete prompt stashed from a turn that failed because the login
|
||||
/// expired (401 / re-auth). Used by the `AuthComplete` handler to
|
||||
/// auto-resubmit the prompt after a successful mid-session re-auth so
|
||||
@@ -754,10 +750,6 @@ pub struct AgentView {
|
||||
/// Unlike `chat_kind`, stays `false` for a `/chat` one-shot session in
|
||||
/// a Build process, whose picker still lists local sessions.
|
||||
pub app_chat_mode: bool,
|
||||
/// Mocked credit balance for the status bar indicator.
|
||||
pub credit_balance: Option<crate::views::credit_bar::CreditBalance>,
|
||||
/// Auto top-up rule paired with `credit_balance` for the prompt warning.
|
||||
pub auto_topup: Option<crate::views::credit_bar::AutoTopupInfo>,
|
||||
/// Current goal orchestration state. Set by `GoalUpdated` session
|
||||
/// notifications, cleared when a new session starts.
|
||||
pub goal_state: Option<super::agent::GoalDisplayState>,
|
||||
@@ -947,7 +939,6 @@ pub struct AgentView {
|
||||
pub hovered_prompt: bool,
|
||||
pub hit_badge: HitArea,
|
||||
pub hit_context: HitArea,
|
||||
pub hit_credits: HitArea,
|
||||
pub hit_todo_close: HitArea,
|
||||
pub hit_bg_close: HitArea,
|
||||
pub hit_subagent_close: HitArea,
|
||||
@@ -1235,8 +1226,6 @@ pub struct AgentView {
|
||||
/// Hit area for the [✗] close button in the subagent frame title bar.
|
||||
pub hit_subagent_frame_close: HitArea,
|
||||
/// Whether the `/share` slash command is available (mirrors
|
||||
/// `AppView::sharing_enabled`). Used to gate palette entries.
|
||||
pub sharing_enabled: bool,
|
||||
/// Input flight recorder — rolling buffer of recent key events.
|
||||
/// Dumped to file via Esc→d combo for debugging.
|
||||
pub(crate) input_log: crate::input_log::InputRingBuffer,
|
||||
@@ -1512,23 +1501,6 @@ fn translate_local_submit(
|
||||
persist_mode,
|
||||
})
|
||||
}
|
||||
LocalQuestionKind::CreditLimitUpsell => {
|
||||
let q = qv.questions.first();
|
||||
let url = q
|
||||
.and_then(|q| q.options.get(*idx))
|
||||
.and_then(|o| o.id.as_deref())
|
||||
.unwrap_or(super::dispatch::UPSELL_URL_PAYG);
|
||||
InputOutcome::Action(Action::OpenUrl(url.to_string()))
|
||||
}
|
||||
LocalQuestionKind::FreeUsageUpsell => {
|
||||
let url = qv
|
||||
.questions
|
||||
.first()
|
||||
.and_then(|q| q.options.get(*idx))
|
||||
.and_then(|o| o.id.as_deref())
|
||||
.unwrap_or(super::dispatch::UPSELL_URL_UPGRADE);
|
||||
InputOutcome::Action(Action::OpenUrl(url.to_string()))
|
||||
}
|
||||
LocalQuestionKind::AgentTypeMismatch { model_id, effort } => {
|
||||
let start_new = *idx == 0;
|
||||
InputOutcome::Action(Action::AgentTypeMismatchAnswered {
|
||||
@@ -2217,8 +2189,6 @@ pub(super) mod test_fixtures {
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
@@ -2278,8 +2248,6 @@ pub(super) mod test_fixtures {
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
@@ -3010,8 +2978,6 @@ pub(crate) fn test_agent_view(session_id: Option<&str>, cwd: std::path::PathBuf)
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
|
||||
@@ -454,8 +454,6 @@ pub(super) mod paste_key_tests {
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
|
||||
@@ -703,8 +703,6 @@ mod plan_chip_tests {
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
|
||||
@@ -329,7 +329,6 @@ impl AgentView {
|
||||
let thinking_label = self.scrollback.thinking_fold_label();
|
||||
let selected_is_user_prompt = selected_entry.is_some_and(|e| e.block.is_user_prompt());
|
||||
let selected_is_agent_message = selected_entry.is_some_and(|e| e.block.is_agent_message());
|
||||
let selected_is_credit_limit = selected_entry.is_some_and(|e| e.block.is_credit_limit());
|
||||
let mut hints = agent::build_hints(
|
||||
self.active_pane,
|
||||
&self.prompt,
|
||||
@@ -355,7 +354,6 @@ impl AgentView {
|
||||
!self.visible_queue_is_empty(),
|
||||
selected_is_user_prompt,
|
||||
selected_is_agent_message,
|
||||
selected_is_credit_limit,
|
||||
crate::terminal::terminal_context().shift_enter_unavailable(),
|
||||
self.scrollback_search.as_ref(),
|
||||
);
|
||||
@@ -1300,7 +1298,6 @@ impl AgentView {
|
||||
self.hit_bg_status.rect = areas.get("bg_tasks").copied();
|
||||
self.hit_goal_status.rect = areas.get("goal").copied();
|
||||
self.hit_context.rect = areas.get("context").copied();
|
||||
self.hit_credits.rect = areas.get("credits").copied();
|
||||
self.hit_plan_button.rect = areas.get("plan").copied();
|
||||
self.hit_queue_badge.rect = areas.get("queue").copied();
|
||||
self.hit_badge.rect = areas.get("badge").copied();
|
||||
@@ -2041,23 +2038,6 @@ impl AgentView {
|
||||
}
|
||||
let mode_flags: &[PromptFlag] = &mode_flags_vec;
|
||||
let multiline = self.multiline_mode;
|
||||
let usage_visible = self
|
||||
.prompt
|
||||
.slash_controller
|
||||
.registry()
|
||||
.get("usage")
|
||||
.is_some();
|
||||
let warning = self.credit_balance.as_ref().and_then(|bal| {
|
||||
crate::views::credit_bar::usage_warning_for_session(
|
||||
bal,
|
||||
self.auto_topup.as_ref(),
|
||||
usage_visible,
|
||||
self.chat_kind,
|
||||
)
|
||||
});
|
||||
let usage_warning_text: Option<String> = warning.as_ref().map(|(t, _)| t.clone());
|
||||
let usage_warning = usage_warning_text.as_deref();
|
||||
let usage_warning_critical = warning.is_some_and(|(_, critical)| critical);
|
||||
let model_label = match self.session.models.reasoning_effort {
|
||||
Some(eff) => format!("{model_id} ({eff})"),
|
||||
None => model_id,
|
||||
@@ -2067,8 +2047,6 @@ impl AgentView {
|
||||
model_name: &model_label,
|
||||
flags: mode_flags,
|
||||
multiline,
|
||||
usage_warning,
|
||||
usage_warning_critical,
|
||||
},
|
||||
PromptMode::EditingQueued { id, .. } => {
|
||||
let pos = self.session.queue_position(*id).map(|i| i + 1).unwrap_or(1);
|
||||
@@ -2077,8 +2055,6 @@ impl AgentView {
|
||||
model_name: &editing_label,
|
||||
flags: mode_flags,
|
||||
multiline,
|
||||
usage_warning,
|
||||
usage_warning_critical,
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2087,8 +2063,6 @@ impl AgentView {
|
||||
model_name: label,
|
||||
flags: &[],
|
||||
multiline: false,
|
||||
usage_warning,
|
||||
usage_warning_critical,
|
||||
}
|
||||
} else {
|
||||
info
|
||||
|
||||
@@ -206,8 +206,6 @@ mod sync_rewind_anchor_to_picker_tests {
|
||||
restore_degree: None,
|
||||
rate_limited: false,
|
||||
model_incompatible: false,
|
||||
credit_limit_blocked: false,
|
||||
free_usage_blocked: false,
|
||||
available_commands: Vec::new(),
|
||||
available_commands_generation: 0,
|
||||
available_tools: None,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Session lifecycle: bind/reload/replay bookkeeping, turn activity
|
||||
//! resolution, context/credit updates, and app-scoped gates.
|
||||
//! resolution, context updates, and app-scoped gates.
|
||||
#[cfg(test)]
|
||||
use super::test_agent_view;
|
||||
use super::{
|
||||
@@ -85,7 +85,6 @@ impl AgentView {
|
||||
bash_turn: false,
|
||||
cron_task_id: None,
|
||||
stashed_prompt: None,
|
||||
credit_limit_stashed_prompt: None,
|
||||
reauth_stashed_prompt: None,
|
||||
active_modal: None,
|
||||
modal_buttons: Vec::new(),
|
||||
@@ -93,8 +92,6 @@ impl AgentView {
|
||||
context_state: None,
|
||||
chat_kind: false,
|
||||
app_chat_mode: false,
|
||||
credit_balance: None,
|
||||
auto_topup: None,
|
||||
goal_state: None,
|
||||
parked_wait_marker_for: None,
|
||||
end_work_announced: false,
|
||||
@@ -152,7 +149,6 @@ impl AgentView {
|
||||
hovered_prompt: false,
|
||||
hit_badge: Default::default(),
|
||||
hit_context: Default::default(),
|
||||
hit_credits: Default::default(),
|
||||
hit_todo_close: Default::default(),
|
||||
hit_bg_close: Default::default(),
|
||||
hit_subagent_close: Default::default(),
|
||||
@@ -257,7 +253,6 @@ impl AgentView {
|
||||
active_subagent: None,
|
||||
is_subagent_view: false,
|
||||
hit_subagent_frame_close: Default::default(),
|
||||
sharing_enabled: false,
|
||||
input_log: crate::input_log::InputRingBuffer::new(),
|
||||
esc_pressed_at: None,
|
||||
pending_first_prompt: None,
|
||||
@@ -740,21 +735,6 @@ impl AgentView {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Apply Build coding-credit balance only for non-chat agents.
|
||||
/// Gateway/chat-kind sessions keep credits unset so bars/warnings stay off.
|
||||
pub fn apply_credit_balance(
|
||||
&mut self,
|
||||
balance: Option<crate::views::credit_bar::CreditBalance>,
|
||||
auto_topup: Option<crate::views::credit_bar::AutoTopupInfo>,
|
||||
) {
|
||||
if self.chat_kind {
|
||||
self.credit_balance = None;
|
||||
self.auto_topup = None;
|
||||
return;
|
||||
}
|
||||
self.credit_balance = balance;
|
||||
self.auto_topup = auto_topup;
|
||||
}
|
||||
/// Record a key event to the input flight recorder.
|
||||
///
|
||||
/// Zero heap allocations — stores raw `Copy` types in the ring buffer.
|
||||
@@ -801,18 +781,6 @@ impl AgentView {
|
||||
textarea_changed: delta.textarea_changed,
|
||||
});
|
||||
}
|
||||
/// Set the sharing-enabled flag on this view and propagate it to the
|
||||
/// slash-command registry so the `/share` entry stays hidden/visible in
|
||||
/// lockstep with `AgentView::sharing_enabled`. Use this instead of
|
||||
/// mutating `sharing_enabled` directly when a new agent is created or a
|
||||
/// session is loaded, so the field and registry can't drift.
|
||||
pub fn set_sharing_enabled(&mut self, enabled: bool) {
|
||||
self.sharing_enabled = enabled;
|
||||
self.prompt
|
||||
.slash_controller
|
||||
.registry_mut()
|
||||
.set_share_visible(enabled);
|
||||
}
|
||||
/// Show or hide the `/usage` slash command in this agent's registry.
|
||||
pub fn set_usage_visible(&mut self, visible: bool) {
|
||||
self.prompt
|
||||
@@ -839,13 +807,11 @@ impl AgentView {
|
||||
/// One place for the app-scoped gates a new/adopted session inherits so the session-creation sites cannot drift.
|
||||
pub(crate) fn apply_app_scoped_gates(
|
||||
&mut self,
|
||||
sharing_enabled: bool,
|
||||
usage_visible: bool,
|
||||
chat_mode: bool,
|
||||
screen_mode: crate::app::ScreenMode,
|
||||
restricted_commands: &[String],
|
||||
) {
|
||||
self.set_sharing_enabled(sharing_enabled);
|
||||
self.set_usage_visible(usage_visible);
|
||||
self.app_chat_mode = chat_mode;
|
||||
self.prompt.set_screen_mode(screen_mode);
|
||||
|
||||
Reference in New Issue
Block a user