§9 acceptance: grep-zero sweep — every internal x.ai/grok identifier renamed
The PRD's first acceptance gate now holds: grep -RinE '\bx\.ai\b|grok' crates/ --include='*.rs' → 0 matches (exempt: NOTICE and third-party license archives, README provenance, and the required 'Based on Grok Build Open Source' attribution, now sourced from version_attribution.txt). Wire-visible renames (both sides in this repo, changed in lockstep): - Auth method id 'grok.com' → 'kimi-code' (AuthMethodKind::KimiCode). - Every x.ai/* and _x.ai/* ACP ext method and meta key → kigi/* / _kigi/* (~200 names; grokShell → kigiShell). Session-file replay keeps a read-side alias for the legacy '_x.ai/session/update' method so existing updates.jsonl histories load; writes emit only the new name (both directions test-pinned). - Agent types grok-build* → kigi* with a documented legacy-prefix alias at resolution time so persisted sessions keep resolving. - ToolNamespace/BuiltinAgentName GrokBuild* → Kigi* (wire snake_case kigi/kigi_concise/kigi_hashline; schema regenerated); grok_build implementation dirs renamed to kigi*. - x-grok-* headers → x-kigi-*, __GROK_* sentinels → __KIGI_*, themes grokday/groknight → kigiday/kiginight (old persisted values fall back to the default theme), web_fetch allowlist xAI hosts → kimi.com + moonshot platforms, changelog CDN → this repo, grok-build changelog archives deleted. - BYOK default endpoint removed: [endpoints] api_base_url is now truly optional with NO default — consumers fail fast with the flag name when unset (no silent x.ai egress). Mock harnesses inject it explicitly. - System-prompt identity fixed: 'released by xAI' → 'an unofficial community CLI for Kimi' (template + regenerated encrypted form). Also repaired pre-existing grok-era test debt found by the sweep: the stale trace_classify default-model pin, the grok-pager UA label test, pty-harness stale-binary reuse and non-hermetic moonshot routing (a PTY test could previously reach the real api.moonshot.cn), and the outdated oauth fixture scope key. Gates: §9 grep 0; fmt clean; workspace check/clippy 0/0 (-D warnings); FULL cargo test --workspace: 234 suites, 21,961 passed, 0 failed; deny advisories ok.
This commit is contained in:
1 parent
86e3724310
commit
6f31415ed6
1056 files changed
+8410
-18307
No files matched your search
@@ -22,7 +22,7 @@ impl RoleCapability {
|
||||
/// `can_execute` for terminal/bash).
|
||||
fn is_satisfied(
|
||||
self,
|
||||
summary: &kigi_tools::implementations::grok_build::task::types::SubagentTypeSummary,
|
||||
summary: &kigi_tools::implementations::kigi::task::types::SubagentTypeSummary,
|
||||
) -> bool {
|
||||
match self {
|
||||
Self::Skeptic => summary.can_read && summary.can_search,
|
||||
@@ -42,7 +42,7 @@ pub(crate) struct PanelResolveCache {
|
||||
/// result for the role's `general-purpose` toolset on that harness).
|
||||
describe: std::collections::HashMap<
|
||||
String,
|
||||
kigi_tools::implementations::grok_build::task::types::SubagentDescribeOutcome,
|
||||
kigi_tools::implementations::kigi::task::types::SubagentDescribeOutcome,
|
||||
>,
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ fn role_tool_names_from(
|
||||
cache: &PanelResolveCache,
|
||||
inherit: &crate::session::goal_role_tools::RoleToolNames,
|
||||
) -> crate::session::goal_role_tools::RoleToolNames {
|
||||
use kigi_tools::implementations::grok_build::task::types::SubagentDescribeOutcome;
|
||||
use kigi_tools::implementations::kigi::task::types::SubagentDescribeOutcome;
|
||||
// `override_.agent_type` is the committed harness; the cache is keyed on it.
|
||||
match override_.agent_type.as_deref() {
|
||||
Some(harness) => match cache.describe.get(harness) {
|
||||
@@ -115,9 +115,9 @@ impl SessionActor {
|
||||
&self,
|
||||
current_tokens: i64,
|
||||
purpose: DrainPurpose,
|
||||
extra: Vec<kigi_tools::implementations::grok_build::update_goal::UpdateGoalEnvelope>,
|
||||
extra: Vec<kigi_tools::implementations::kigi::update_goal::UpdateGoalEnvelope>,
|
||||
) {
|
||||
use kigi_tools::implementations::grok_build::update_goal::{RejectReason, UpdateGoalAck};
|
||||
use kigi_tools::implementations::kigi::update_goal::{RejectReason, UpdateGoalAck};
|
||||
// The `update_goal` tool and its `GoalUpdateHandle` are always
|
||||
// registered (see `spawn_session_actor`), so a model can call
|
||||
// `update_goal` in a session that never entered goal mode — e.g. any
|
||||
@@ -650,10 +650,10 @@ impl SessionActor {
|
||||
attempt: u32,
|
||||
outcome: crate::session::goal_classifier::GoalClassifierOutcome,
|
||||
notify: &crate::session::goal_orchestrator::GoalNotifySender,
|
||||
) -> kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck {
|
||||
) -> kigi_tools::implementations::kigi::update_goal::UpdateGoalAck {
|
||||
use crate::session::goal_classifier::GoalClassifierOutcome;
|
||||
use crate::session::goal_tracker::GoalClassifierVerdict;
|
||||
use kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck;
|
||||
use kigi_tools::implementations::kigi::update_goal::UpdateGoalAck;
|
||||
|
||||
let current_tokens = self.chat_state_handle.get_total_tokens().await as i64;
|
||||
let (tokens_used, finished_marginal) = self.goal_tokens(current_tokens);
|
||||
@@ -1299,7 +1299,7 @@ impl SessionActor {
|
||||
choice: &crate::agent::config::GoalRoleModelChoice,
|
||||
capability: RoleCapability,
|
||||
event_tx: &tokio::sync::mpsc::UnboundedSender<
|
||||
kigi_tools::implementations::grok_build::task::types::SubagentEvent,
|
||||
kigi_tools::implementations::kigi::task::types::SubagentEvent,
|
||||
>,
|
||||
) -> (
|
||||
crate::session::goal_planner::RoleSpawnOverride,
|
||||
@@ -1372,17 +1372,15 @@ impl SessionActor {
|
||||
pair: &crate::util::config::GoalRoleModel,
|
||||
capability: RoleCapability,
|
||||
event_tx: &tokio::sync::mpsc::UnboundedSender<
|
||||
kigi_tools::implementations::grok_build::task::types::SubagentEvent,
|
||||
kigi_tools::implementations::kigi::task::types::SubagentEvent,
|
||||
>,
|
||||
available_models: &indexmap::IndexMap<String, crate::agent::config::ModelEntry>,
|
||||
cache: &mut PanelResolveCache,
|
||||
) -> crate::session::goal_planner::RoleSpawnOverride {
|
||||
use crate::session::events::{Event, GoalRoleModelFailOpenReason as Reason};
|
||||
use crate::session::goal_planner::RoleSpawnOverride;
|
||||
use kigi_tools::implementations::grok_build::task::backend::{
|
||||
ChannelBackend, SubagentBackend,
|
||||
};
|
||||
use kigi_tools::implementations::grok_build::task::types::SubagentDescribeOutcome;
|
||||
use kigi_tools::implementations::kigi::task::backend::{ChannelBackend, SubagentBackend};
|
||||
use kigi_tools::implementations::kigi::task::types::SubagentDescribeOutcome;
|
||||
|
||||
let fail_open = |reason: Reason| {
|
||||
self.emit_event(Event::GoalRoleModelFailOpen {
|
||||
@@ -1408,7 +1406,7 @@ impl SessionActor {
|
||||
}
|
||||
// 2b. Reject a STRICT harness whose flavor isn't representable (e.g.
|
||||
// `codex`): it resolves, but `resolve_subagent_toolset` would
|
||||
// silently run grok-build flavor. Non-strict names (grok-build
|
||||
// silently run kigi flavor. Non-strict names (kigi
|
||||
// family) run the default flavor and pass; unresolvable names fall
|
||||
// through to the describe `Unknown` arm below.
|
||||
if kigi_agent::config::is_strict_harness_agent_type(&pair.agent_type)
|
||||
@@ -1511,9 +1509,9 @@ impl SessionActor {
|
||||
/// toolset; [`RoleToolNames::from_parent`] applies the literal fallback for
|
||||
/// any kind the bridge lacks, and resolves `{WRITE_TOOL}` from the parent
|
||||
/// `Edit` tool when the bridge has no `Write` (so the inherit / retry render
|
||||
/// agrees with `from_summary` — `search_replace` on the default grok-build
|
||||
/// agrees with `from_summary` — `search_replace` on the default kigi
|
||||
/// host, not the literal `write`). The `{TOOLSET_TOOLS}` block is empty on
|
||||
/// this path (no per-role toolset enumeration); on the default grok-build
|
||||
/// this path (no per-role toolset enumeration); on the default kigi
|
||||
/// host the bridge resolves the parent's real tool ids (`read_file`, …).
|
||||
pub(crate) async fn resolve_inherit_role_tool_names(
|
||||
&self,
|
||||
@@ -2340,7 +2338,7 @@ impl SessionActor {
|
||||
#[cfg(test)]
|
||||
mod role_capability_tests {
|
||||
use super::RoleCapability;
|
||||
use kigi_tools::implementations::grok_build::task::types::SubagentTypeSummary;
|
||||
use kigi_tools::implementations::kigi::task::types::SubagentTypeSummary;
|
||||
|
||||
fn summary(can_read: bool, can_search: bool, can_execute: bool) -> SubagentTypeSummary {
|
||||
SubagentTypeSummary {
|
||||
@@ -2371,7 +2369,7 @@ mod role_tool_names_tests {
|
||||
use super::{PanelResolveCache, role_tool_names_from};
|
||||
use crate::session::goal_planner::RoleSpawnOverride;
|
||||
use crate::session::goal_role_tools::RoleToolNames;
|
||||
use kigi_tools::implementations::grok_build::task::types::{
|
||||
use kigi_tools::implementations::kigi::task::types::{
|
||||
SubagentDescribeOutcome, SubagentTypeSummary,
|
||||
};
|
||||
use kigi_tools::types::tool::ToolKind;
|
||||
|
||||
@@ -15,10 +15,10 @@ impl DrainSource {
|
||||
pub(super) fn into_parts(
|
||||
self,
|
||||
) -> (
|
||||
kigi_tools::implementations::grok_build::update_goal::UpdateGoalInput,
|
||||
kigi_tools::implementations::kigi::update_goal::UpdateGoalInput,
|
||||
Option<
|
||||
tokio::sync::oneshot::Sender<
|
||||
kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck,
|
||||
kigi_tools::implementations::kigi::update_goal::UpdateGoalAck,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
@@ -33,11 +33,9 @@ impl DrainSource {
|
||||
/// source). No-op for `Pending` source — its ack was already resolved.
|
||||
pub(super) fn try_send_ack(
|
||||
ack_tx: Option<
|
||||
tokio::sync::oneshot::Sender<
|
||||
kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck,
|
||||
>,
|
||||
tokio::sync::oneshot::Sender<kigi_tools::implementations::kigi::update_goal::UpdateGoalAck>,
|
||||
>,
|
||||
ack: kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck,
|
||||
ack: kigi_tools::implementations::kigi::update_goal::UpdateGoalAck,
|
||||
) {
|
||||
if let Some(tx) = ack_tx {
|
||||
send_ack(tx, ack);
|
||||
@@ -154,9 +152,9 @@ impl<F: FnOnce(&mut crate::session::goal_tracker::GoalTracker)> Drop for Tracker
|
||||
/// the receiver was dropped (benign — tool future aborted).
|
||||
pub(super) fn send_ack(
|
||||
ack_tx: tokio::sync::oneshot::Sender<
|
||||
kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck,
|
||||
kigi_tools::implementations::kigi::update_goal::UpdateGoalAck,
|
||||
>,
|
||||
ack: kigi_tools::implementations::grok_build::update_goal::UpdateGoalAck,
|
||||
ack: kigi_tools::implementations::kigi::update_goal::UpdateGoalAck,
|
||||
) {
|
||||
if ack_tx.send(ack).is_err() {
|
||||
tracing::debug!("update_goal ack receiver dropped before harness could respond");
|
||||
@@ -702,14 +700,14 @@ mod fold_tokens_by_model_tests {
|
||||
#[test]
|
||||
fn mixed_models_sum_marginals_sorted_desc() {
|
||||
let records = vec![
|
||||
rec(Some("g1"), 0, 100, Some("grok-3")),
|
||||
rec(Some("g1"), 100, 500, Some("grok-4")), // marginal 400
|
||||
rec(Some("g1"), 0, 50, Some("grok-3")), // grok-3 total 150
|
||||
rec(Some("g1"), 0, 100, Some("kigi-3")),
|
||||
rec(Some("g1"), 100, 500, Some("kigi-4")), // marginal 400
|
||||
rec(Some("g1"), 0, 50, Some("kigi-3")), // kigi-3 total 150
|
||||
];
|
||||
let out = fold_tokens_by_model(&records, "g1", "cur");
|
||||
assert_eq!(
|
||||
out,
|
||||
vec![("grok-4".to_owned(), 400), ("grok-3".to_owned(), 150)]
|
||||
vec![("kigi-4".to_owned(), 400), ("kigi-3".to_owned(), 150)]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -736,38 +734,38 @@ mod fold_tokens_by_model_tests {
|
||||
#[test]
|
||||
fn single_distinct_model_collapses_to_one_entry() {
|
||||
let records = vec![
|
||||
rec(Some("g1"), 0, 100, Some("grok-4")),
|
||||
rec(Some("g1"), 0, 200, None), // folds under current = grok-4
|
||||
rec(Some("g1"), 0, 100, Some("kigi-4")),
|
||||
rec(Some("g1"), 0, 200, None), // folds under current = kigi-4
|
||||
];
|
||||
let out = fold_tokens_by_model(&records, "g1", "grok-4");
|
||||
assert_eq!(out, vec![("grok-4".to_owned(), 300)]);
|
||||
let out = fold_tokens_by_model(&records, "g1", "kigi-4");
|
||||
assert_eq!(out, vec![("kigi-4".to_owned(), 300)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn other_goal_records_excluded() {
|
||||
let records = vec![
|
||||
rec(Some("g1"), 0, 100, Some("grok-4")),
|
||||
rec(Some("g2"), 0, 999, Some("grok-4")),
|
||||
rec(None, 0, 999, Some("grok-4")),
|
||||
rec(Some("g1"), 0, 100, Some("kigi-4")),
|
||||
rec(Some("g2"), 0, 999, Some("kigi-4")),
|
||||
rec(None, 0, 999, Some("kigi-4")),
|
||||
];
|
||||
let out = fold_tokens_by_model(&records, "g1", "cur");
|
||||
assert_eq!(out, vec![("grok-4".to_owned(), 100)]);
|
||||
assert_eq!(out, vec![("kigi-4".to_owned(), 100)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn last_below_anchor_does_not_underflow() {
|
||||
let records = vec![rec(Some("g1"), 500, 100, Some("grok-4"))];
|
||||
let records = vec![rec(Some("g1"), 500, 100, Some("kigi-4"))];
|
||||
// marginal saturates to 0 -> skipped as a zero-token entry.
|
||||
assert!(fold_tokens_by_model(&records, "g1", "cur").is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn captured_model_survives_mid_goal_current_model_switch() {
|
||||
// A record captured `grok-4` at spawn keeps it even though the
|
||||
// current model at aggregation time is `grok-3`.
|
||||
let records = vec![rec(Some("g1"), 0, 100, Some("grok-4"))];
|
||||
let out = fold_tokens_by_model(&records, "g1", "grok-3");
|
||||
assert_eq!(out, vec![("grok-4".to_owned(), 100)]);
|
||||
// A record captured `kigi-4` at spawn keeps it even though the
|
||||
// current model at aggregation time is `kigi-3`.
|
||||
let records = vec![rec(Some("g1"), 0, 100, Some("kigi-4"))];
|
||||
let out = fold_tokens_by_model(&records, "g1", "kigi-3");
|
||||
assert_eq!(out, vec![("kigi-4".to_owned(), 100)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -788,11 +786,11 @@ mod fold_tokens_by_model_tests {
|
||||
// An empty id folds into the SAME bucket as records that
|
||||
// explicitly captured the current model id.
|
||||
let records = vec![
|
||||
rec(Some("g1"), 0, 100, Some("grok-4")),
|
||||
rec(Some("g1"), 0, 100, Some("kigi-4")),
|
||||
rec(Some("g1"), 0, 200, Some("")),
|
||||
];
|
||||
let out = fold_tokens_by_model(&records, "g1", "grok-4");
|
||||
assert_eq!(out, vec![("grok-4".to_owned(), 300)]);
|
||||
let out = fold_tokens_by_model(&records, "g1", "kigi-4");
|
||||
assert_eq!(out, vec![("kigi-4".to_owned(), 300)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,7 +820,7 @@ pub(crate) fn planner_failure_pause_message() -> String {
|
||||
}
|
||||
|
||||
pub(crate) fn goal_slash_and_harness_available(goal_enabled: bool, tool_names: &[String]) -> bool {
|
||||
use kigi_tools::implementations::grok_build::UPDATE_GOAL_TOOL_NAME;
|
||||
use kigi_tools::implementations::kigi::UPDATE_GOAL_TOOL_NAME;
|
||||
goal_enabled && tool_names.iter().any(|n| n == UPDATE_GOAL_TOOL_NAME)
|
||||
}
|
||||
|
||||
@@ -1468,9 +1466,7 @@ impl SessionActor {
|
||||
self.agent
|
||||
.borrow()
|
||||
.tool_bridge()
|
||||
.update_resource(
|
||||
kigi_tools::implementations::grok_build::task::types::GoalLoopActive(active),
|
||||
)
|
||||
.update_resource(kigi_tools::implementations::kigi::task::types::GoalLoopActive(active))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ pub(crate) type PendingInterjection =
|
||||
/// converted into standalone prompt turns (arrived while idle, or after the
|
||||
/// running turn's final drain). The prefix keeps the turn's user echo
|
||||
/// persist-only: every pane already rendered the text from the
|
||||
/// `x.ai/session/interjection` broadcast, so a live echo would duplicate it.
|
||||
/// `kigi/session/interjection` broadcast, so a live echo would duplicate it.
|
||||
pub(crate) const INTERJECT_FALLBACK_PROMPT_PREFIX: &str = "interject-fallback-";
|
||||
|
||||
impl SessionActor {
|
||||
@@ -164,7 +164,7 @@ impl SessionActor {
|
||||
self.notifications
|
||||
.gateway
|
||||
.forward_fire_and_forget(acp::ExtNotification::new(
|
||||
"x.ai/session/interjection",
|
||||
"kigi/session/interjection",
|
||||
params.into(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ impl SessionActor {
|
||||
/// the sampler call goes through `prepare_chat_completion().conversation_collect()`
|
||||
/// — a side-channel direct-HTTP call that does NOT publish events
|
||||
/// on the per-session shared sampler channel. The client never
|
||||
/// sees "Grok is thinking", streaming token chunks, or any other
|
||||
/// sees "Kigi is thinking", streaming token chunks, or any other
|
||||
/// session update from a classifier fire. Stalled verdicts only
|
||||
/// queue a `<system-reminder>` into chat state via
|
||||
/// `push_system_reminder`; no `InputItem` is pushed into
|
||||
@@ -549,18 +549,18 @@ impl SessionActor {
|
||||
model: Some(model_id.clone()),
|
||||
temperature: Some(0.0),
|
||||
max_output_tokens: Some(LAZINESS_MAX_OUTPUT_TOKENS),
|
||||
// Don't pass `reasoning_effort` — `grok-4.5` (and
|
||||
// other tool-flavoured Grok variants) reject the field at
|
||||
// Don't pass `reasoning_effort` — `kigi-4.5` (and
|
||||
// other tool-flavoured Kigi variants) reject the field at
|
||||
// the proxy with `400 Bad Request: Model does not support
|
||||
// parameter reasoningEffort`. Omitting it lets each model
|
||||
// apply its own default. The classifier task is one short
|
||||
// JSON object — even on reasoning-capable models the
|
||||
// default suffices; no need to force it off.
|
||||
reasoning_effort: None,
|
||||
x_grok_conv_id: Some(session_id_str.clone()),
|
||||
x_grok_req_id: Some(format!("{LAZINESS_REQ_ID_PREFIX}{}", uuid::Uuid::new_v4())),
|
||||
x_grok_session_id: Some(session_id_str),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(session_id_str.clone()),
|
||||
x_kigi_req_id: Some(format!("{LAZINESS_REQ_ID_PREFIX}{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_session_id: Some(session_id_str),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..ConversationRequest::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ impl LazinessAbortReason {
|
||||
/// Prompt-structure mitigations against motivated reasoning:
|
||||
/// "Do not roleplay", JSON-only, no chain-of-thought,
|
||||
/// no role context, transcript framed as third-party data.
|
||||
/// Prefix on `x_grok_req_id` for laziness-classifier sampler calls.
|
||||
/// Prefix on `x_kigi_req_id` for laziness-classifier sampler calls.
|
||||
/// Centralised here so the production producer
|
||||
/// (`maybe_fire_laziness_check`) AND the offline replay harness
|
||||
/// (`crate::trace_classifier::build_classifier_request`) share a
|
||||
|
||||
@@ -150,7 +150,7 @@ impl SessionActor {
|
||||
);
|
||||
}
|
||||
}
|
||||
/// Emit per-server `x.ai/mcp/tools_changed` notifications.
|
||||
/// Emit per-server `kigi/mcp/tools_changed` notifications.
|
||||
///
|
||||
/// Each emission carries the owning
|
||||
/// `sessionId` so the pager can route via `find_session_match`
|
||||
@@ -182,7 +182,7 @@ impl SessionActor {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Handle explicit auth trigger from the client (x.ai/mcp/auth_trigger).
|
||||
/// Handle explicit auth trigger from the client (kigi/mcp/auth_trigger).
|
||||
///
|
||||
/// Runs force_reauth (browser flow), then re-initializes the server
|
||||
/// and registers its tools.
|
||||
@@ -580,7 +580,7 @@ impl SessionActor {
|
||||
/// On success: the new `Arc<McpClient>` is in
|
||||
/// `mcp_state.owned_clients[server]` with `ClientState::Ready`,
|
||||
/// the dispatcher's `notify_tx` is wired to its
|
||||
/// `GrokClientHandler`, and the liveness watcher is armed —
|
||||
/// `KigiClientHandler`, and the liveness watcher is armed —
|
||||
/// matching the post-handshake state produced by
|
||||
/// [`Self::ensure_mcp_tools_initialized`] for a fresh server.
|
||||
///
|
||||
@@ -603,7 +603,7 @@ impl SessionActor {
|
||||
/// `Reason::Initialized` from the dispatcher's mapping, one
|
||||
/// `Reason::RestartSucceeded` from the restart task).
|
||||
///
|
||||
/// The `GrokClientHandler` constructed inside `try_handshake`
|
||||
/// The `KigiClientHandler` constructed inside `try_handshake`
|
||||
/// holds the SHARED `Arc<Mutex<Option<Sender>>>` slot
|
||||
/// (`SharedEventTx`), so wiring the sender AFTER the handshake
|
||||
/// still routes subsequent `tools/list_changed` /
|
||||
@@ -814,7 +814,7 @@ impl SessionActor {
|
||||
self.notifications
|
||||
.gateway
|
||||
.forward_fire_and_forget(acp::ExtNotification::new(
|
||||
"x.ai/mcp_initialized",
|
||||
"kigi/mcp_initialized",
|
||||
params.into(),
|
||||
));
|
||||
}
|
||||
@@ -884,7 +884,7 @@ impl SessionActor {
|
||||
self.notifications
|
||||
.gateway
|
||||
.forward_fire_and_forget(acp::ExtNotification::new(
|
||||
"x.ai/mcp_initialized",
|
||||
"kigi/mcp_initialized",
|
||||
params.into(),
|
||||
));
|
||||
}
|
||||
@@ -1432,7 +1432,7 @@ impl SessionActor {
|
||||
"elapsedMs" : elapsed.as_millis() as u64, }
|
||||
)) {
|
||||
gateway.forward_fire_and_forget(acp::ExtNotification::new(
|
||||
"x.ai/mcp_initialized",
|
||||
"kigi/mcp_initialized",
|
||||
params.into(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -314,10 +314,10 @@ impl SessionActor {
|
||||
ConversationItem::user(user_message),
|
||||
],
|
||||
model: Some(model),
|
||||
x_grok_conv_id: Some(session_id.clone()),
|
||||
x_grok_req_id: Some(format!("xai-dream-{}", uuid::Uuid::new_v4())),
|
||||
x_grok_session_id: Some(session_id),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(session_id.clone()),
|
||||
x_kigi_req_id: Some(format!("xai-dream-{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_session_id: Some(session_id),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..Default::default()
|
||||
};
|
||||
let response = sampling_client
|
||||
@@ -413,10 +413,10 @@ impl SessionActor {
|
||||
let request = ConversationRequest {
|
||||
items,
|
||||
model: Some(model),
|
||||
x_grok_conv_id: Some(session_id.clone()),
|
||||
x_grok_req_id: Some(format!("xai-flush-{}", uuid::Uuid::new_v4())),
|
||||
x_grok_session_id: Some(session_id.clone()),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(session_id.clone()),
|
||||
x_kigi_req_id: Some(format!("xai-flush-{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_session_id: Some(session_id.clone()),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -608,7 +608,7 @@ impl SessionActor {
|
||||
}
|
||||
|
||||
/// Rewrite a raw memory note into well-structured markdown via a one-shot
|
||||
/// LLM call using the `grok-build` model.
|
||||
/// LLM call using the `kigi` model.
|
||||
///
|
||||
/// Follows the same streaming pattern as [`handle_ai_suggest`]: prepares
|
||||
/// a sampling client, builds a system+user prompt, streams the response,
|
||||
|
||||
@@ -207,7 +207,7 @@ impl SessionActor {
|
||||
}
|
||||
bridge
|
||||
.update_resource(
|
||||
kigi_tools::implementations::grok_build::update_goal::GoalUpdateHandle(
|
||||
kigi_tools::implementations::kigi::update_goal::GoalUpdateHandle(
|
||||
self.goal_update_tx.clone(),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -94,7 +94,7 @@ impl SessionActor {
|
||||
.borrow()
|
||||
.tool_bridge()
|
||||
.update_resource(
|
||||
kigi_tools::implementations::grok_build::task::types::CurrentPromptIdResource(
|
||||
kigi_tools::implementations::kigi::task::types::CurrentPromptIdResource(
|
||||
prompt_id.clone(),
|
||||
),
|
||||
)
|
||||
@@ -249,7 +249,7 @@ impl SessionActor {
|
||||
let Some(buffer) = &self.tool_context.monitor_event_buffer else {
|
||||
return;
|
||||
};
|
||||
for event in kigi_tools::implementations::grok_build::task::types::drain_owned(
|
||||
for event in kigi_tools::implementations::kigi::task::types::drain_owned(
|
||||
buffer,
|
||||
Some(self.session_info.id.0.as_ref()),
|
||||
) {
|
||||
@@ -308,7 +308,7 @@ impl SessionActor {
|
||||
notifications: Vec<PendingNotification>,
|
||||
task_output_tool_name: &str,
|
||||
) -> bool {
|
||||
use kigi_tools::implementations::grok_build::task::types::MonitorEventNotification;
|
||||
use kigi_tools::implementations::kigi::task::types::MonitorEventNotification;
|
||||
|
||||
// Collapse monitor entries: collect their text into events, remember
|
||||
// where the first one sat so the batch lands in arrival position.
|
||||
|
||||
@@ -277,7 +277,7 @@ pub(super) fn build_truncated_prompt_message(
|
||||
}
|
||||
/// Replace the file-referencing offload `notice` embedded in `message` with the
|
||||
/// no-file [`OFFLOAD_FAILED_NOTICE`]. Position-independent (the notice sits at the
|
||||
/// end for grok ordering), so a failed offload never
|
||||
/// end for kigi ordering), so a failed offload never
|
||||
/// leaves the model chasing a "read this file" pointer to a file that does not
|
||||
/// exist. Returns `message` unchanged if the notice is absent (defensive).
|
||||
pub(super) fn strip_offload_notice(message: &str, notice: &str) -> String {
|
||||
|
||||
@@ -319,7 +319,7 @@ impl SessionActor {
|
||||
entry_count = payload.entries.len(),
|
||||
entries = ?payload.entries.iter().map(|e| e.id.as_str()).collect::<Vec<_>>(),
|
||||
session = self.session_info.id.0.as_ref(),
|
||||
"broadcasting x.ai/queue/changed to subscribers",
|
||||
"broadcasting kigi/queue/changed to subscribers",
|
||||
);
|
||||
if let Ok(params) = serde_json::value::to_raw_value(&payload) {
|
||||
self.notifications
|
||||
@@ -426,7 +426,7 @@ impl SessionActor {
|
||||
/// stale `expected_version`, or is owned by another client, or
|
||||
/// - the row is not a plain prompt (it would reach the model as prompt text).
|
||||
///
|
||||
/// Always re-broadcasts `x.ai/queue/changed` so every client reconciles
|
||||
/// Always re-broadcasts `kigi/queue/changed` so every client reconciles
|
||||
/// (the row vanishes on success, is unchanged on a no-op).
|
||||
/// `new_text` (when `Some`) replaces the stored queue text in the
|
||||
/// interjection — the client edited the row before interjecting. It rides
|
||||
@@ -609,7 +609,7 @@ impl SessionActor {
|
||||
/// user has explicitly typed replacement text).
|
||||
/// 2. Update `queue_meta.text`, bump `queue_meta.version`, and record
|
||||
/// `last_editor` (the original `owner` attribution is preserved).
|
||||
/// 3. Re-broadcast `x.ai/queue/changed` so every subscriber renders the
|
||||
/// 3. Re-broadcast `kigi/queue/changed` so every subscriber renders the
|
||||
/// new text and version.
|
||||
///
|
||||
/// **No-op cases** (each is a benign discard with no rebroadcast — nothing
|
||||
|
||||
@@ -110,10 +110,10 @@ impl SessionActor {
|
||||
tools: tool_specs,
|
||||
model: Some(model.clone()),
|
||||
temperature: None,
|
||||
x_grok_conv_id: Some(btw_session_id.clone()),
|
||||
x_grok_req_id: Some(format!("xai-btw-{}", uuid::Uuid::new_v4())),
|
||||
x_grok_session_id: Some(parent_session_id.clone()),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(btw_session_id.clone()),
|
||||
x_kigi_req_id: Some(format!("xai-btw-{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_session_id: Some(parent_session_id.clone()),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -238,8 +238,8 @@ impl SessionActor {
|
||||
// ~25–40 words, and `clean_recap_text` caps it at a generous
|
||||
// RECAP_MAX_CHARS safety net, so an explicit token cap isn't needed.
|
||||
let started_at = chrono::Utc::now().to_rfc3339();
|
||||
let x_grok_conv_id = format!("recap-{}", uuid::Uuid::new_v4());
|
||||
let x_grok_req_id = format!("xai-recap-{}", uuid::Uuid::new_v4());
|
||||
let x_kigi_conv_id = format!("recap-{}", uuid::Uuid::new_v4());
|
||||
let x_kigi_req_id = format!("xai-recap-{}", uuid::Uuid::new_v4());
|
||||
// Clone the exact request items for the on-disk artifact (recap never
|
||||
// mutates conversation state, so this file is the only durable record).
|
||||
let chat_history_for_artifact = items.clone();
|
||||
@@ -248,10 +248,10 @@ impl SessionActor {
|
||||
tools: vec![],
|
||||
model: Some(model.clone()),
|
||||
temperature: None,
|
||||
x_grok_conv_id: Some(x_grok_conv_id.clone()),
|
||||
x_grok_req_id: Some(x_grok_req_id.clone()),
|
||||
x_grok_session_id: Some(self.session_info.id.to_string()),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(x_kigi_conv_id.clone()),
|
||||
x_kigi_req_id: Some(x_kigi_req_id.clone()),
|
||||
x_kigi_session_id: Some(self.session_info.id.to_string()),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -265,8 +265,8 @@ impl SessionActor {
|
||||
auto,
|
||||
strip_reasoning,
|
||||
tag,
|
||||
&x_grok_req_id,
|
||||
&x_grok_conv_id,
|
||||
&x_kigi_req_id,
|
||||
&x_kigi_conv_id,
|
||||
started_at,
|
||||
None,
|
||||
None,
|
||||
@@ -291,8 +291,8 @@ impl SessionActor {
|
||||
auto,
|
||||
strip_reasoning,
|
||||
tag,
|
||||
&x_grok_req_id,
|
||||
&x_grok_conv_id,
|
||||
&x_kigi_req_id,
|
||||
&x_kigi_conv_id,
|
||||
started_at,
|
||||
None,
|
||||
Some(raw_response.as_str()).filter(|s| !s.is_empty()),
|
||||
@@ -307,7 +307,7 @@ impl SessionActor {
|
||||
}
|
||||
|
||||
// New prompt while generating: keep artifact, skip display, leave watermark.
|
||||
// Applies to manual `/recap` too: spinner-less clients (e.g. Grok
|
||||
// Applies to manual `/recap` too: spinner-less clients (e.g. Kigi
|
||||
// Desktop) would otherwise append the late recap mid-turn.
|
||||
if self.recap_was_cancelled(recap_epoch) {
|
||||
tracing::info!(
|
||||
@@ -322,8 +322,8 @@ impl SessionActor {
|
||||
auto,
|
||||
strip_reasoning,
|
||||
tag,
|
||||
&x_grok_req_id,
|
||||
&x_grok_conv_id,
|
||||
&x_kigi_req_id,
|
||||
&x_kigi_conv_id,
|
||||
started_at,
|
||||
Some(summary.as_str()),
|
||||
Some(raw_response.as_str()),
|
||||
@@ -346,8 +346,8 @@ impl SessionActor {
|
||||
auto,
|
||||
strip_reasoning,
|
||||
tag,
|
||||
&x_grok_req_id,
|
||||
&x_grok_conv_id,
|
||||
&x_kigi_req_id,
|
||||
&x_kigi_conv_id,
|
||||
started_at,
|
||||
Some(summary.as_str()),
|
||||
Some(raw_response.as_str()),
|
||||
@@ -365,8 +365,8 @@ impl SessionActor {
|
||||
auto,
|
||||
strip_reasoning,
|
||||
tag,
|
||||
&x_grok_req_id,
|
||||
&x_grok_conv_id,
|
||||
&x_kigi_req_id,
|
||||
&x_kigi_conv_id,
|
||||
started_at,
|
||||
Some(summary.as_str()),
|
||||
Some(raw_response.as_str()),
|
||||
@@ -433,8 +433,8 @@ impl SessionActor {
|
||||
auto: bool,
|
||||
strip_reasoning: bool,
|
||||
reminder_tag: &str,
|
||||
x_grok_req_id: &str,
|
||||
x_grok_conv_id: &str,
|
||||
x_kigi_req_id: &str,
|
||||
x_kigi_conv_id: &str,
|
||||
started_at: String,
|
||||
summary: Option<&str>,
|
||||
raw_response: Option<&str>,
|
||||
@@ -449,8 +449,8 @@ impl SessionActor {
|
||||
created_at: started_at,
|
||||
trigger: if auto { "auto" } else { "manual" }.to_owned(),
|
||||
model: model.to_owned(),
|
||||
x_grok_req_id: x_grok_req_id.to_owned(),
|
||||
x_grok_conv_id: x_grok_conv_id.to_owned(),
|
||||
x_kigi_req_id: x_kigi_req_id.to_owned(),
|
||||
x_kigi_conv_id: x_kigi_conv_id.to_owned(),
|
||||
strip_reasoning,
|
||||
reminder_tag: reminder_tag.to_owned(),
|
||||
chat_history,
|
||||
@@ -578,7 +578,7 @@ impl SessionActor {
|
||||
/// Temperature, max_output_tokens, and
|
||||
/// reasoning_effort are left unset — mirrors [`Self::handle_recap`]: the
|
||||
/// proxy may inject provider defaults, a small token cap silently empties
|
||||
/// a reasoning model's response, and some models (e.g. `grok-build`)
|
||||
/// a reasoning model's response, and some models (e.g. `kigi`)
|
||||
/// reject an explicit `reasoningEffort` with a 400. Output is filtered
|
||||
/// through [`prompt_suggest::sanitize_suggestion`]; any failure returns
|
||||
/// through [`prompt_suggest::sanitize_suggestion`]; any failure returns
|
||||
@@ -643,10 +643,10 @@ impl SessionActor {
|
||||
tools: vec![],
|
||||
model: Some(model),
|
||||
temperature: None,
|
||||
x_grok_conv_id: Some(format!("promptsuggest-{}", uuid::Uuid::new_v4())),
|
||||
x_grok_req_id: Some(format!("xai-promptsuggest-{}", uuid::Uuid::new_v4())),
|
||||
x_grok_session_id: Some(self.session_info.id.to_string()),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(format!("promptsuggest-{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_req_id: Some(format!("xai-promptsuggest-{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_session_id: Some(self.session_info.id.to_string()),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ pub(crate) fn date_rollover_reminder(
|
||||
}
|
||||
/// Body of the one-shot interrupt `<system-reminder>` injected on the next real
|
||||
/// user turn after a mid-stream abort that left the model with no other signal.
|
||||
/// Wrapped in grok's `<system-reminder>` shape by [`SessionActor::push_system_reminder`].
|
||||
/// Wrapped in kigi's `<system-reminder>` shape by [`SessionActor::push_system_reminder`].
|
||||
/// See [`SessionActor::maybe_inject_interrupt_reminder`].
|
||||
pub(crate) const INTERRUPT_REMINDER: &str = "[Request interrupted by user]";
|
||||
/// TodoGate when enabled and the prompt carries `<task_completion_discipline>`
|
||||
@@ -317,7 +317,7 @@ impl SessionActor {
|
||||
let Some(tx) = &self.tool_context.subagent_event_tx else {
|
||||
return;
|
||||
};
|
||||
use kigi_tools::implementations::grok_build::task::types::{
|
||||
use kigi_tools::implementations::kigi::task::types::{
|
||||
SubagentCompletionsRequest, SubagentEvent,
|
||||
};
|
||||
let suppress_ids = self
|
||||
|
||||
@@ -525,7 +525,7 @@ impl SessionActor {
|
||||
.send(PersistenceMsg::MergeRewindPointsFrom { target_index });
|
||||
}
|
||||
|
||||
/// Out-of-band history repair (`x.ai/session/repair`) for a resident
|
||||
/// Out-of-band history repair (`kigi/session/repair`) for a resident
|
||||
/// session: run `kigi_chat_state::compaction_utils::repair_history` inside
|
||||
/// the chat-state actor, then flush persistence so `chat_history.jsonl`
|
||||
/// is rewritten on disk before the caller sees success.
|
||||
|
||||
@@ -386,7 +386,7 @@ pub(super) async fn run_session(
|
||||
acp::ContentBlock::Text(t) = b { Some(t.text.clone()) } else { None } })
|
||||
.collect::< Vec < _ >> ().join("\n"); let task_id = source.task_id()
|
||||
.to_owned(); const MAX_BUFFER_EVENTS : usize = 50; buffer
|
||||
.push_capped(kigi_tools::implementations::grok_build::task::types::MonitorEventNotification
|
||||
.push_capped(kigi_tools::implementations::kigi::task::types::MonitorEventNotification
|
||||
{ task_id : task_id.clone(), event_text, owner_session_id : Some(session
|
||||
.session_info.id.0.to_string(),), }, MAX_BUFFER_EVENTS,);
|
||||
tracing::debug!(task_id = % task_id,
|
||||
|
||||
@@ -33,7 +33,7 @@ struct SessionTokenAuthGate {
|
||||
is_session_based: bool,
|
||||
model_byok: crate::agent::auth_method::ModelByok,
|
||||
/// Whether the request targets a first-party host. Lets an `Unknown`
|
||||
/// BYOK status still refresh against cli-chat-proxy / `*.x.ai` without
|
||||
/// BYOK status still refresh against the first-party cli-chat-proxy hosts without
|
||||
/// risking a session-token leak to a third-party BYOK endpoint.
|
||||
endpoint_is_first_party: bool,
|
||||
}
|
||||
@@ -419,10 +419,10 @@ impl SessionActor {
|
||||
kigi_workspace::permission::classifier_output_json_schema(),
|
||||
),
|
||||
reasoning_effort: classifier_reasoning_effort,
|
||||
x_grok_conv_id: Some(session_id.clone()),
|
||||
x_grok_req_id: Some(format!("xai-perm-auto-{}", uuid::Uuid::new_v4())),
|
||||
x_grok_session_id: Some(session_id),
|
||||
x_grok_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
x_kigi_conv_id: Some(session_id.clone()),
|
||||
x_kigi_req_id: Some(format!("xai-perm-auto-{}", uuid::Uuid::new_v4())),
|
||||
x_kigi_session_id: Some(session_id),
|
||||
x_kigi_agent_id: Some(crate::util::agent_id::agent_id()),
|
||||
..ConversationRequest::default()
|
||||
};
|
||||
let fut = sampling_client.conversation_collect(request);
|
||||
|
||||
@@ -289,7 +289,7 @@ impl SessionActor {
|
||||
);
|
||||
}
|
||||
/// The activation reminder template for the active template (no
|
||||
/// first-entry/reentry distinction), or grok's reentry/full variant.
|
||||
/// first-entry/reentry distinction), or kigi's reentry/full variant.
|
||||
/// Shared by turn-start injection (`inject_plan_mode_reminders` case 1)
|
||||
/// and the mid-turn toggle (`activate_plan_mode_mid_turn`).
|
||||
fn plan_activation_template(&self, is_reentry: bool) -> &'static str {
|
||||
|
||||
@@ -146,8 +146,8 @@ pub(crate) async fn spawn_session_actor(
|
||||
inference_idle_timeout_secs: u64,
|
||||
max_retries: Option<u32>,
|
||||
web_search_config: kigi_tools::implementations::WebSearchConfig,
|
||||
web_fetch_config: kigi_tools::implementations::grok_build::web_fetch::WebFetchConfig,
|
||||
app_builder_deployer_config: kigi_tools::implementations::grok_build::deploy_app::AppBuilderDeployerConfig,
|
||||
web_fetch_config: kigi_tools::implementations::kigi::web_fetch::WebFetchConfig,
|
||||
app_builder_deployer_config: kigi_tools::implementations::kigi::deploy_app::AppBuilderDeployerConfig,
|
||||
write_file_enabled: bool,
|
||||
goal_enabled: bool,
|
||||
subagents_enabled: bool,
|
||||
@@ -180,7 +180,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
std::sync::Arc<dyn kigi_tools::computer::types::TerminalBackend>,
|
||||
>,
|
||||
parent_scheduler_handle: Option<
|
||||
kigi_tools::implementations::grok_build::scheduler::types::SchedulerHandle,
|
||||
kigi_tools::implementations::kigi::scheduler::types::SchedulerHandle,
|
||||
>,
|
||||
max_turns: Option<usize>,
|
||||
forked_tool_override: Option<Vec<ToolSpec>>,
|
||||
@@ -224,7 +224,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
"CLI --allow catch-all ignored: always-approve disabled by managed policy"
|
||||
);
|
||||
if startup_hints.non_interactive {
|
||||
eprintln!("grok: --allow catch-all ignored: {reason}");
|
||||
eprintln!("kigi: --allow catch-all ignored: {reason}");
|
||||
}
|
||||
}
|
||||
if !cli_permission_rules.is_empty() {
|
||||
@@ -531,7 +531,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
};
|
||||
let reminder_policy = resolve_reminder_policy(remote_settings.as_ref(), todo_gate);
|
||||
let (user_question_tx, user_question_rx) = tokio::sync::mpsc::unbounded_channel::<
|
||||
kigi_tools::implementations::grok_build::ask_user_question::types::UserQuestionRequest,
|
||||
kigi_tools::implementations::kigi::ask_user_question::types::UserQuestionRequest,
|
||||
>();
|
||||
let attribution_callback_for_spec = auth_manager.as_ref().map(|am| {
|
||||
crate::auth::attribution::ShellAttribution::new_tool_callback(
|
||||
@@ -672,7 +672,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
state.set_acp_servers(acp_mcp_servers, invoker);
|
||||
tracing::info!(
|
||||
session_id = % session_info.id.0, acp_mcp_servers = acp_server_count,
|
||||
"Registered in-process SDK MCP servers (x.ai/mcp/sdk_call)"
|
||||
"Registered in-process SDK MCP servers (kigi/mcp/sdk_call)"
|
||||
);
|
||||
}
|
||||
Arc::new(TokioMutex::new(state))
|
||||
@@ -763,7 +763,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
let scheduler_handle_for_handle = {
|
||||
let toolset = agent.tool_bridge().toolset();
|
||||
let res = toolset.resources.lock().await;
|
||||
res.get::<kigi_tools::implementations::grok_build::scheduler::types::SchedulerHandle>()
|
||||
res.get::<kigi_tools::implementations::kigi::scheduler::types::SchedulerHandle>()
|
||||
.cloned()
|
||||
};
|
||||
if let Err(e) = workspace_ops.bind_local_session(
|
||||
@@ -831,13 +831,13 @@ pub(crate) async fn spawn_session_actor(
|
||||
"Creating feedback manager"
|
||||
);
|
||||
let feedback_client_type = match client_type {
|
||||
ClientType::GrokTUI => crate::session::feedback_types::ClientType::Tui,
|
||||
ClientType::GrokWeb => crate::session::feedback_types::ClientType::Web,
|
||||
ClientType::KigiTUI => crate::session::feedback_types::ClientType::Tui,
|
||||
ClientType::KigiWeb => crate::session::feedback_types::ClientType::Web,
|
||||
ClientType::Nebula => crate::session::feedback_types::ClientType::Nebula,
|
||||
ClientType::Extension => crate::session::feedback_types::ClientType::Extension,
|
||||
ClientType::Generic => crate::session::feedback_types::ClientType::Agent,
|
||||
ClientType::Desktop => crate::session::feedback_types::ClientType::Desktop,
|
||||
ClientType::GrokPager => crate::session::feedback_types::ClientType::Tui,
|
||||
ClientType::KigiPager => crate::session::feedback_types::ClientType::Tui,
|
||||
};
|
||||
let feedback_config = FeedbackManagerConfig {
|
||||
feedback_enabled: feedback_flags.enabled,
|
||||
@@ -930,7 +930,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
.map(|e| e.to_string())
|
||||
.collect();
|
||||
let (goal_update_tx, goal_update_rx) = tokio::sync::mpsc::unbounded_channel::<
|
||||
kigi_tools::implementations::grok_build::update_goal::UpdateGoalEnvelope,
|
||||
kigi_tools::implementations::kigi::update_goal::UpdateGoalEnvelope,
|
||||
>();
|
||||
let mut effective_config = crate::config::load_effective_config()
|
||||
.ok()
|
||||
@@ -1224,7 +1224,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
.borrow()
|
||||
.tool_bridge()
|
||||
.update_resource(
|
||||
kigi_tools::implementations::grok_build::update_goal::GoalUpdateHandle(
|
||||
kigi_tools::implementations::kigi::update_goal::GoalUpdateHandle(
|
||||
session.goal_update_tx.clone(),
|
||||
),
|
||||
)
|
||||
@@ -1288,7 +1288,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
}
|
||||
{
|
||||
use agent_client_protocol::Client as _;
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::{
|
||||
use kigi_tools::implementations::kigi::ask_user_question::{
|
||||
AskUserQuestionExtRequest, AskUserQuestionExtResponse, UserQuestionError,
|
||||
UserQuestionResponse,
|
||||
};
|
||||
@@ -1300,7 +1300,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
let mut user_question_rx = user_question_rx;
|
||||
tokio::task::spawn_local(async move {
|
||||
while let Some(mut request) = user_question_rx.recv().await {
|
||||
use kigi_tools::implementations::grok_build::ask_user_question::AskUserQuestionMode;
|
||||
use kigi_tools::implementations::kigi::ask_user_question::AskUserQuestionMode;
|
||||
let mode = match *current_prompt_mode.lock() {
|
||||
PromptMode::Plan => AskUserQuestionMode::Plan,
|
||||
_ => AskUserQuestionMode::Default,
|
||||
@@ -1316,7 +1316,7 @@ pub(crate) async fn spawn_session_actor(
|
||||
"ask_user_question reverse-request must carry a non-empty sessionId (design §5.4)"
|
||||
);
|
||||
let ext_request = agent_client_protocol::ExtRequest::new(
|
||||
"x.ai/ask_user_question",
|
||||
"kigi/ask_user_question",
|
||||
serde_json::value::to_raw_value(&ext_req)
|
||||
.expect("AskUserQuestionExtRequest serialization should not fail")
|
||||
.into(),
|
||||
@@ -1521,8 +1521,8 @@ pub(crate) async fn spawn_session_on_thread(
|
||||
inference_idle_timeout_secs: u64,
|
||||
max_retries: Option<u32>,
|
||||
web_search_config: kigi_tools::implementations::WebSearchConfig,
|
||||
web_fetch_config: kigi_tools::implementations::grok_build::web_fetch::WebFetchConfig,
|
||||
app_builder_deployer_config: kigi_tools::implementations::grok_build::deploy_app::AppBuilderDeployerConfig,
|
||||
web_fetch_config: kigi_tools::implementations::kigi::web_fetch::WebFetchConfig,
|
||||
app_builder_deployer_config: kigi_tools::implementations::kigi::deploy_app::AppBuilderDeployerConfig,
|
||||
write_file_enabled: bool,
|
||||
goal_enabled: bool,
|
||||
subagents_enabled: bool,
|
||||
@@ -1556,7 +1556,7 @@ pub(crate) async fn spawn_session_on_thread(
|
||||
std::sync::Arc<dyn kigi_tools::computer::types::TerminalBackend>,
|
||||
>,
|
||||
parent_scheduler_handle: Option<
|
||||
kigi_tools::implementations::grok_build::scheduler::types::SchedulerHandle,
|
||||
kigi_tools::implementations::kigi::scheduler::types::SchedulerHandle,
|
||||
>,
|
||||
max_turns: Option<usize>,
|
||||
forked_tool_override: Option<Vec<ToolSpec>>,
|
||||
|
||||
@@ -179,7 +179,7 @@ impl SessionActor {
|
||||
|
||||
fn cancel_subagents_for_prompt_id(&self, parent_prompt_id: &str) {
|
||||
if let Some(event_tx) = self.tool_context.subagent_event_tx.clone() {
|
||||
use kigi_tools::implementations::grok_build::task::types::{
|
||||
use kigi_tools::implementations::kigi::task::types::{
|
||||
SubagentCancelRequest, SubagentCancelTarget, SubagentEvent,
|
||||
};
|
||||
let _ = event_tx.send(SubagentEvent::Cancel(SubagentCancelRequest {
|
||||
@@ -346,7 +346,7 @@ impl SessionActor {
|
||||
// * normal interactive cancel: remove ONLY the running turn,
|
||||
// PRESERVING every queued prompt so the `Cancel` handler's
|
||||
// follow-up `maybe_start_running_task` promotes the new front (the
|
||||
// user's next queued prompt) and rebroadcasts `x.ai/queue/changed`.
|
||||
// user's next queued prompt) and rebroadcasts `kigi/queue/changed`.
|
||||
// The cancelling client does not pull any prompt back into its
|
||||
// input — the server queue is the single source of truth for what
|
||||
// runs next. Previously every cancel did `std::mem::take`,
|
||||
@@ -418,7 +418,7 @@ impl SessionActor {
|
||||
.borrow()
|
||||
.tool_bridge()
|
||||
.update_resource(
|
||||
kigi_tools::implementations::grok_build::task::types::CurrentPromptIdResource(
|
||||
kigi_tools::implementations::kigi::task::types::CurrentPromptIdResource(
|
||||
String::new(),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -135,7 +135,7 @@ pub(super) fn should_intercept_exit_plan_approval(
|
||||
pub(super) enum PlanEditGate {
|
||||
/// Execute normally (plan mode inactive, not an edit, or allowed target).
|
||||
Allow,
|
||||
/// Grok-toolset edit outside the plan file (plan-file-only rule).
|
||||
/// Kigi-toolset edit outside the plan file (plan-file-only rule).
|
||||
RejectNonPlanFile,
|
||||
}
|
||||
/// Gate edit-class tool calls while plan mode is active.
|
||||
@@ -149,7 +149,7 @@ pub(super) enum PlanEditGate {
|
||||
/// file is editable in plan mode (plan docs are written with these
|
||||
/// same tools); everything else is rejected. Pre-existing behavior.
|
||||
/// - **Compat-toolset `Delete`** is **not** on the markdown carve-out: it maps to
|
||||
/// `AccessKind::Edit` and is plan-file-only (same as grok edits). Deleting
|
||||
/// `AccessKind::Edit` and is plan-file-only (same as kigi edits). Deleting
|
||||
/// an arbitrary `.md` in plan mode must not pass.
|
||||
/// - **Every other edit tool** (`AccessKind::Edit`) is restricted to the plan
|
||||
/// file itself, via the same predicate that auto-approves plan-file edits
|
||||
@@ -192,7 +192,7 @@ pub(super) enum PlanApprovalOutcome {
|
||||
}
|
||||
impl PlanApprovalOutcome {
|
||||
fn from_response(
|
||||
resp: &kigi_tools::implementations::grok_build::exit_plan_mode::ExitPlanModeExtResponse,
|
||||
resp: &kigi_tools::implementations::kigi::exit_plan_mode::ExitPlanModeExtResponse,
|
||||
) -> Self {
|
||||
match resp.outcome.as_str() {
|
||||
"approved" => Self::Approved,
|
||||
@@ -255,7 +255,7 @@ fn resume_action_for(outcome: PlanApprovalOutcome, feedback: Option<String>) ->
|
||||
}
|
||||
}
|
||||
impl SessionActor {
|
||||
/// Merge the canonical `x.ai/tool` identity envelope into a tool-call
|
||||
/// Merge the canonical `kigi/tool` identity envelope into a tool-call
|
||||
/// event's `_meta`, resolving the tool from the live toolset by wire name.
|
||||
pub(super) fn stamp_tool_meta(
|
||||
&self,
|
||||
@@ -1203,7 +1203,7 @@ impl SessionActor {
|
||||
};
|
||||
Ok(Ok(prepared))
|
||||
}
|
||||
/// Issue the `x.ai/exit_plan_mode` reverse-request and await the user's
|
||||
/// Issue the `kigi/exit_plan_mode` reverse-request and await the user's
|
||||
/// decision. Shared by the mid-turn intercept and the resume
|
||||
/// re-park. Marks `awaiting_plan_approval` while the request is
|
||||
/// outstanding and clears it on every exit path via [`AwaitingApprovalGuard`].
|
||||
@@ -1212,11 +1212,11 @@ impl SessionActor {
|
||||
tool_call_id: &acp::ToolCallId,
|
||||
plan_content: Option<String>,
|
||||
) -> Result<
|
||||
kigi_tools::implementations::grok_build::exit_plan_mode::ExitPlanModeExtResponse,
|
||||
kigi_tools::implementations::kigi::exit_plan_mode::ExitPlanModeExtResponse,
|
||||
acp::Error,
|
||||
> {
|
||||
use agent_client_protocol::Client as _;
|
||||
use kigi_tools::implementations::grok_build::exit_plan_mode::{
|
||||
use kigi_tools::implementations::kigi::exit_plan_mode::{
|
||||
ExitPlanModeExtRequest, ExitPlanModeExtResponse,
|
||||
};
|
||||
let ext_req = ExitPlanModeExtRequest {
|
||||
@@ -1229,7 +1229,7 @@ impl SessionActor {
|
||||
"exit_plan_mode reverse-request must carry a non-empty sessionId (design §5.4)"
|
||||
);
|
||||
let ext_request = acp::ExtRequest::new(
|
||||
"x.ai/exit_plan_mode",
|
||||
"kigi/exit_plan_mode",
|
||||
serde_json::value::to_raw_value(&ext_req)
|
||||
.expect("ExitPlanModeExtRequest serialization should not fail")
|
||||
.into(),
|
||||
@@ -2540,7 +2540,7 @@ mod plan_mode_edit_gate_tests {
|
||||
plan_mode_edit_gate(tracker, input, &AccessKind::from(input))
|
||||
}
|
||||
fn search_replace(path: &str) -> ToolInput {
|
||||
use kigi_tools::implementations::grok_build::search_replace::SearchReplaceInput;
|
||||
use kigi_tools::implementations::kigi::search_replace::SearchReplaceInput;
|
||||
ToolInput::SearchReplace(SearchReplaceInput {
|
||||
file_path: path.into(),
|
||||
old_string: "a".into(),
|
||||
@@ -2555,10 +2555,10 @@ mod plan_mode_edit_gate_tests {
|
||||
content: "x".into(),
|
||||
})
|
||||
}
|
||||
/// Grok edit tools are plan-file-only while plan mode is active — the
|
||||
/// Kigi edit tools are plan-file-only while plan mode is active — the
|
||||
/// enforcement that makes plan mode read-only even under always-approve.
|
||||
#[test]
|
||||
fn grok_edits_outside_plan_file_rejected() {
|
||||
fn kigi_edits_outside_plan_file_rejected() {
|
||||
let t = active_tracker();
|
||||
assert_eq!(
|
||||
gate(&t, &search_replace("/tmp/src/main.rs")),
|
||||
@@ -2567,7 +2567,7 @@ mod plan_mode_edit_gate_tests {
|
||||
assert_eq!(
|
||||
gate(&t, &write("/tmp/README.md")),
|
||||
PlanEditGate::RejectNonPlanFile,
|
||||
"grok tools get no markdown exception — plan file only"
|
||||
"kigi tools get no markdown exception — plan file only"
|
||||
);
|
||||
}
|
||||
/// The carve-out and the permission bypass share `should_auto_approve_edit`,
|
||||
@@ -2644,7 +2644,7 @@ mod plan_approval_helper_tests {
|
||||
PlanApprovalOutcome, ResumeAction, ext_method_no_client, resume_action_for,
|
||||
revise_plan_message,
|
||||
};
|
||||
use kigi_tools::implementations::grok_build::exit_plan_mode::ExitPlanModeExtResponse;
|
||||
use kigi_tools::implementations::kigi::exit_plan_mode::ExitPlanModeExtResponse;
|
||||
fn resp(outcome: &str) -> ExitPlanModeExtResponse {
|
||||
ExitPlanModeExtResponse {
|
||||
outcome: outcome.into(),
|
||||
|
||||
@@ -41,11 +41,11 @@ fn str_arg<'a>(args: &'a serde_json::Value, keys: &[&str]) -> Option<&'a str> {
|
||||
/// serializing concurrent same-file edits inside `execute_tool_calls`.
|
||||
///
|
||||
/// Different toolsets advertise the path under different JSON keys:
|
||||
/// - `file_path` — grok_build (`search_replace`), opencode (`EditTool`,
|
||||
/// `WriteTool`, `ReadTool`), codex (`read_file`), grok_build_hashline
|
||||
/// - `file_path` — kigi (`search_replace`), opencode (`EditTool`,
|
||||
/// `WriteTool`, `ReadTool`), codex (`read_file`), kigi_hashline
|
||||
/// (`hashline_edit`)
|
||||
/// - `path` — alternate edit/read tools
|
||||
/// - `target_file` — grok_build (`read_file`, via `#[serde(rename)]`)
|
||||
/// - `target_file` — kigi (`read_file`, via `#[serde(rename)]`)
|
||||
///
|
||||
/// Returning the same string for two calls in a batch causes them to share a
|
||||
/// `tokio::sync::Mutex` and therefore run sequentially in model-emitted order.
|
||||
@@ -202,7 +202,7 @@ impl SessionActor {
|
||||
is_background: false,
|
||||
});
|
||||
// Bash mode has no model-issued wire name; resolve the toolset's
|
||||
// execute tool by kind so the x.ai/tool identity still stamps.
|
||||
// execute tool by kind so the kigi/tool identity still stamps.
|
||||
let bash_marker = serde_json::json!({"bash_mode": true}).as_object().cloned();
|
||||
let exec_wire = {
|
||||
let agent = self.agent.borrow();
|
||||
@@ -366,7 +366,7 @@ pub(crate) const MAX_ARGS_IN_ERROR: usize = 2_000;
|
||||
///
|
||||
/// 1. The normal error description (so the model knows *what* failed).
|
||||
/// 2. The **original arguments string** the model produced (capped at
|
||||
/// [`MAX_ARGS_IN_ERROR`] bytes). Without this, grok-shell would sanitize
|
||||
/// [`MAX_ARGS_IN_ERROR`] bytes). Without this, kigi-shell would sanitize
|
||||
/// the arguments to `"{}"` before forwarding them to the provider (to
|
||||
/// avoid 400 errors), so the model would only see an empty object and have
|
||||
/// to regenerate all its work from scratch.
|
||||
|
||||
@@ -60,9 +60,7 @@ impl UsageDrainOutcome {
|
||||
/// Same policy as freeze's terminal outcome: FG live → fail-closed;
|
||||
/// sticky and background → report only.
|
||||
pub(super) fn from_outstanding_reply(
|
||||
reply: Option<
|
||||
&kigi_tools::implementations::grok_build::task::types::SubagentOutstandingReply,
|
||||
>,
|
||||
reply: Option<&kigi_tools::implementations::kigi::task::types::SubagentOutstandingReply>,
|
||||
) -> Self {
|
||||
match reply {
|
||||
None => Self {
|
||||
@@ -1050,7 +1048,7 @@ impl SessionActor {
|
||||
let Some(tx) = &self.tool_context.subagent_event_tx else {
|
||||
return false;
|
||||
};
|
||||
use kigi_tools::implementations::grok_build::task::types::{
|
||||
use kigi_tools::implementations::kigi::task::types::{
|
||||
SubagentEvent, SubagentMarkUsageNotAppliedRequest,
|
||||
};
|
||||
let (respond_to, ack) = tokio::sync::oneshot::channel();
|
||||
@@ -1074,12 +1072,12 @@ impl SessionActor {
|
||||
/// `push_user_message`, NOT `inject_synthetic_user_message`: the latter
|
||||
/// persists a `UserMessageChunk` to `updates.jsonl`, which resume
|
||||
/// replays — the raw XML would render as a user prompt. Clients see
|
||||
/// monitor events only via the structured `x.ai/monitor_event` channel.
|
||||
/// monitor events only via the structured `kigi/monitor_event` channel.
|
||||
pub(crate) async fn inject_pending_monitor_events(&self) {
|
||||
let Some(buffer) = &self.tool_context.monitor_event_buffer else {
|
||||
return;
|
||||
};
|
||||
let mine = kigi_tools::implementations::grok_build::task::types::drain_owned(
|
||||
let mine = kigi_tools::implementations::kigi::task::types::drain_owned(
|
||||
buffer,
|
||||
Some(self.session_info.id.0.as_ref()),
|
||||
);
|
||||
@@ -1632,12 +1630,12 @@ impl SessionActor {
|
||||
)),
|
||||
);
|
||||
let mut request = request;
|
||||
request.x_grok_session_id = Some(self.session_info.id.to_string());
|
||||
request.x_grok_turn_idx =
|
||||
request.x_kigi_session_id = Some(self.session_info.id.to_string());
|
||||
request.x_kigi_turn_idx =
|
||||
Some(self.chat_state_handle.get_prompt_index().await.to_string());
|
||||
request.x_grok_agent_id = Some(crate::util::agent_id::agent_id());
|
||||
if request.x_grok_deployment_id.is_none() {
|
||||
request.x_grok_deployment_id = crate::managed_config::resolve_deployment_id(
|
||||
request.x_kigi_agent_id = Some(crate::util::agent_id::agent_id());
|
||||
if request.x_kigi_deployment_id.is_none() {
|
||||
request.x_kigi_deployment_id = crate::managed_config::resolve_deployment_id(
|
||||
crate::managed_config::resolve_deployment_key().as_deref(),
|
||||
);
|
||||
}
|
||||
@@ -2115,7 +2113,7 @@ mod user_echo_broadcast_tests {
|
||||
);
|
||||
}
|
||||
/// Interject-fallback turns are persist-only: every pane already rendered
|
||||
/// the text from the `x.ai/session/interjection` broadcast, so a live
|
||||
/// the text from the `kigi/session/interjection` broadcast, so a live
|
||||
/// echo would duplicate the block.
|
||||
#[test]
|
||||
fn interject_fallback_turn_is_persist_only() {
|
||||
|
||||
@@ -78,7 +78,7 @@ impl SessionActor {
|
||||
self.emit_transient_notification(notification);
|
||||
}
|
||||
|
||||
/// Emit `x.ai/git_head_changed` after an edit/shell command that may have
|
||||
/// Emit `kigi/git_head_changed` after an edit/shell command that may have
|
||||
/// moved HEAD (e.g. `git checkout`), so clients update their status bar
|
||||
/// immediately rather than waiting for the debounced fs-watch refresh.
|
||||
pub(super) async fn maybe_notify_git_branch(&self) {
|
||||
@@ -112,7 +112,7 @@ impl SessionActor {
|
||||
main_repo,
|
||||
};
|
||||
if let Ok(raw) = serde_json::value::to_raw_value(¶ms) {
|
||||
let notification = acp::ExtNotification::new("x.ai/git_head_changed", raw.into());
|
||||
let notification = acp::ExtNotification::new("kigi/git_head_changed", raw.into());
|
||||
self.notifications
|
||||
.gateway
|
||||
.forward_fire_and_forget(notification);
|
||||
@@ -123,12 +123,11 @@ impl SessionActor {
|
||||
pub(super) async fn outstanding_reply_for_prompt(
|
||||
&self,
|
||||
prompt_id: &str,
|
||||
) -> Option<kigi_tools::implementations::grok_build::task::types::SubagentOutstandingReply>
|
||||
{
|
||||
) -> Option<kigi_tools::implementations::kigi::task::types::SubagentOutstandingReply> {
|
||||
let Some(tx) = &self.tool_context.subagent_event_tx else {
|
||||
return Some(Default::default());
|
||||
};
|
||||
use kigi_tools::implementations::grok_build::task::types::{
|
||||
use kigi_tools::implementations::kigi::task::types::{
|
||||
SubagentEvent, SubagentOutstandingRequest,
|
||||
};
|
||||
let (respond_to, rx) = tokio::sync::oneshot::channel();
|
||||
@@ -147,9 +146,7 @@ impl SessionActor {
|
||||
/// Report-level incomplete (error-path attach, tests). Same OR as
|
||||
/// [`super::turn::UsageDrainOutcome::report_incomplete`].
|
||||
pub(super) fn usage_incomplete_from_reply(
|
||||
reply: Option<
|
||||
&kigi_tools::implementations::grok_build::task::types::SubagentOutstandingReply,
|
||||
>,
|
||||
reply: Option<&kigi_tools::implementations::kigi::task::types::SubagentOutstandingReply>,
|
||||
) -> bool {
|
||||
super::turn::UsageDrainOutcome::from_outstanding_reply(reply).report_incomplete()
|
||||
}
|
||||
@@ -158,7 +155,7 @@ impl SessionActor {
|
||||
let Some(tx) = &self.tool_context.subagent_event_tx else {
|
||||
return;
|
||||
};
|
||||
use kigi_tools::implementations::grok_build::task::types::{
|
||||
use kigi_tools::implementations::kigi::task::types::{
|
||||
SubagentClearUsageNotAppliedRequest, SubagentEvent,
|
||||
};
|
||||
let _ = tx.send(SubagentEvent::ClearUsageNotApplied(
|
||||
@@ -186,7 +183,7 @@ impl SessionActor {
|
||||
.borrow()
|
||||
.tool_bridge()
|
||||
.update_resource(
|
||||
kigi_tools::implementations::grok_build::task::types::CurrentPromptIdResource(
|
||||
kigi_tools::implementations::kigi::task::types::CurrentPromptIdResource(
|
||||
String::new(),
|
||||
),
|
||||
)
|
||||
@@ -257,7 +254,7 @@ impl SessionActor {
|
||||
|
||||
// Durable twin of the fire-and-forget `prompt_complete` (emitted from
|
||||
// `MvpAgent::prompt`): publish the turn's terminal on the persisted +
|
||||
// replayed `_x.ai/session/update` rail so a viewer that re-attaches
|
||||
// replayed `_kigi/session/update` rail so a viewer that re-attaches
|
||||
// mid-turn finalizes from replay instead of stranding on "Waiting…".
|
||||
// The caller flushed the replay buffer first, so this lands strictly
|
||||
// after the turn's last `session/update` delta. Emit ONLY for a
|
||||
|
||||
@@ -199,8 +199,8 @@ pub(crate) enum DrainPurpose {
|
||||
/// Origin of a drain entry. `Pending` entries had their acks resolved
|
||||
/// at defer time; `Channel` entries still carry a live oneshot.
|
||||
pub(crate) enum DrainSource {
|
||||
Pending(kigi_tools::implementations::grok_build::update_goal::UpdateGoalInput),
|
||||
Channel(kigi_tools::implementations::grok_build::update_goal::UpdateGoalEnvelope),
|
||||
Pending(kigi_tools::implementations::kigi::update_goal::UpdateGoalInput),
|
||||
Channel(kigi_tools::implementations::kigi::update_goal::UpdateGoalEnvelope),
|
||||
}
|
||||
|
||||
/// Reason a NotAchieved verdict was synthesized without invoking the
|
||||
|
||||
@@ -230,7 +230,7 @@ impl SessionActor {
|
||||
self.notifications
|
||||
.gateway
|
||||
.forward_fire_and_forget(acp::ExtNotification::new(
|
||||
"x.ai/session_notification",
|
||||
"kigi/session_notification",
|
||||
params.into(),
|
||||
));
|
||||
}
|
||||
@@ -734,7 +734,7 @@ impl SessionActor {
|
||||
.ok();
|
||||
if let Some(params) = params {
|
||||
let ext_notification =
|
||||
acp::ExtNotification::new("x.ai/session_notification", params.into());
|
||||
acp::ExtNotification::new("kigi/session_notification", params.into());
|
||||
self.notifications
|
||||
.gateway
|
||||
.forward_fire_and_forget(ext_notification);
|
||||
|
||||
Reference in new issue
Block a user