Grok Build 源码深度技术解析:xAI 开源编码 Agent 的 Rust 架构全貌

从 Leader-Follower 守护进程、每会话 OS 线程 Actor 到 fail-closed 沙箱的实现剖析

Posted by 爱折腾的工程师 on Monday, August 24, 2026

一、项目背景:xAI 的官方开源编码 Agent

如果说 OpenAI 的 Codex CLI 是编码 Agent 领域最常被引用的 Rust 样本,那么 xAI 的 Grok Build(命令名 grok)就是另一个值得逐行精读的对照组:它由 SpaceXAI 官方出品、以 Apache-2.0 协议开源,是一个运行在终端里的全屏 TUI 编码 Agent——理解代码库、编辑文件、执行 shell 命令、搜索网页、管理长任务,支持交互式使用、headless 脚本/CI 模式,以及通过 Agent Client Protocol(ACP)嵌入编辑器。

这个仓库有几处与众不同的"出身"值得先划重点:

  • 它是 monorepo 的定期快照。根目录一个 SOURCE_REV 文件记录了源码对应的 SpaceXAI 内部 monorepo commit SHA,仓库由内部主仓周期性同步导出,因此不接受外部贡献CONTRIBUTING.md 明确说明);
  • Cargo.toml 是生成物,首行注释直接写着 “Auto-generated workspace root. Prefer editing per-crate Cargo.toml files."——单一事实来源在各 crate 自己的 manifest 里,这是大型 monorepo 导出时防漂移的典型手段;
  • 生而 Rust。没有 Codex 那段 TypeScript → Rust 的重写史,90+ 个 crate 的 workspace 从第一天就按 Rust edition 2024 组织,构建产物名为 xai-grok-pager,官方安装包发布为 grok

项目概貌

维度 数据
核心语言 Rust(workspace edition 2024,90+ crates)
进程模型 Leader-Follower 单例守护进程(Unix domain socket)
接入形态 TUI / headless CLI(grok -p)/ ACP 编辑器嵌入 / WebSocket serve
模型接口 xAI API(OpenAI 兼容层,async-openai fork,SSE 流式)
终端 UI ratatui 0.29 + crossterm + 自维护组件(textarea / inline)
持久化 SQLite journal + ~/.grok/sessions/ 会话目录
沙箱 nono(Landlock/Seatbelt)+ bubblewrap 再执行 + seccomp 子进程断网
脚本运行时 Rhai(workflow 引擎)
可观测 fastrace + OpenTelemetry(OTLP)+ Mixpanel
构建体系 Cargo workspace + DotSlash 工具链(bin/protoc

本文基于当前源码快照分析,涉及文件路径均相对 grok-build/ 仓库根目录。文中观点仅代表个人技术解读。

本文导读

  • 第二节先用一张分层架构图建立全局认知:为什么 Grok 选了 Leader-Follower 守护进程而不是每次冷启动;
  • 第三节是主菜:每会话一个 OS 线程的 Actor 模型、五命名空间工具系统、fail-closed 的沙箱纵深、pager 式 TUI 与扩展生态;
  • 第四、五节看配置/会话/遥测等基础设施与工程治理实践;
  • 适合关注 AI Coding Agent、终端工程、权限治理或 Rust 工程化的读者。

二、架构概览:Leader 单例守护进程

Grok Build 分层架构总览

整个 workspace 最有辨识度的决策藏在 xai-grok-shell 的模块注释里——crates/codegen/xai-grok-shell/src/leader/mod.rs 用一幅 ASCII 图开门见山:

//! ┌─────────────────────────────────────────────────────────────┐
//! │                        Leader Process                        │
//! │   Agent (MvpAgent) —— Shared state across all clients        │
//! │   IPC Server (Unix socket) —— Namespaces request IDs        │
//! └───────────────────────────┼──────────────────────────────────┘
//!                             │ IPC (Unix socket at ~/.grok/leader.sock)
//!         ┌───────────────────┼───────────────────┐
//!         ▼                   ▼                   ▼
//!   ┌───────────────┐   ┌───────────────┐   ┌───────────────┐
//!   │   TUI Client  │   │  IDE Extension │   │ Headless CLI  │
//!   └───────────────┘   └───────────────┘   └───────────────┘

这与 Codex CLI “每次 CLI 启动即独立进程、状态随进程生灭"的模型形成了鲜明对照:Grok 在一台机器上常驻一个 leader 进程,持有全部 Agent 与会话状态;TUI、IDE 扩展、headless 脚本都是轻客户端,通过 ~/.grok/leader.sock 以 ACP(JSON-RPC)多路复用同一组会话。带来的直接收益:

  • 会话跨终端存活:关掉 TUI 重开,会话还在;IDE 和终端可以同时附着到同一个会话;
  • 请求 ID 命名空间化:IPC Server 为每个客户端的请求 ID 加命名空间前缀,避免多客户端碰撞,并跟踪"哪个会话归哪个客户端"做定向路由;
  • 连接即拉起:组合根里的 connect_or_spawnxai-grok-pager-bin/src/main.rs:46)先尝试连接既有 socket,连不上再 spawn 一个 leader——用户完全无感。

三个 Agent 入口对应三种进程形态:run_leader(守护进程)、run_stdio_agent(独立 stdio 子进程,供编辑器 spawn)、run_headless(一次性执行)。交互式 TUI 甚至也走 ACP 协议与 agent 通信——agent 可以是进程内线程、leader 共享进程,或独立 stdio/WebSocket 进程,前端完全解耦。

一个安全细节值得一提:沙箱激活时 leader 模式会被禁用warn_leader_disabled_by_sandbox)。一个被内核级沙箱约束的进程去提供机器级全局 socket 服务显然矛盾,Grok 的选择是 fail-closed 降级为单进程模式。

按依赖方向自上而下,整个 workspace 可归纳为六层:

  • 接入层xai-grok-pager(TUI)+ xai-acp-lib(Agent Client Protocol 封装)+ headless 参数面;
  • 运行时层xai-grok-shell(leader/stdio/headless 入口、会话编排)+ xai-grok-agent(Agent 构建)+ xai-agent-lifecycle + xai-chat-state
  • 能力层xai-grok-tools(工具实现与注册表)+ xai-tool-runtime / xai-tool-protocol / xai-tool-types(统一工具契约)+ xai-grok-mcp + xai-grok-hooks + xai-grok-plugin-marketplace
  • 宿主层xai-grok-workspace(文件系统、VCS、执行、checkpoint)+ xai-grok-sandbox + xai-fast-worktree(按 session/ab/pool/fork 类型管理的 git worktree 池);
  • 基础层xai-grok-config(七层合并配置)+ xai-grok-auth + xai-grok-models + xai-grok-telemetry + xai-sqlite-journal + 30 余个叶子工具 crate;
  • vendor 层third_party/ 内嵌了完整 Mermaid 渲染栈(dagre/graphlib/mermaid-to-svg 的 Rust 移植),支撑终端内渲染流程图。

三、核心机制解析

3.1 会话模型:每会话一个 OS 线程

会话并发模型

Codex 用 SQ/EQ 双队列在单线程事件循环里仲裁一切;Grok 则走了另一条路——三层嵌套的线程隔离

  1. 进程级MvpAgent(ACP Agent trait 实现)挂在 leader 的 LocalSet 上,持有 SessionRegistry 会话句柄表;
  2. 会话级:每个会话是一个 SessionActor——注意,是独立 OS 线程,不是 tokio task。每线程自带 current-thread runtime + LocalSet,因此 SessionActor 天然 !Send,用 RefCell/Cell 做内部可变性,零跨线程锁;
  3. Turn 级:一个 turn 是 spawn_local 出来的 AgentTask(持有 AbortHandle),turn 内部跑"采样-工具"循环。
// crates/codegen/xai-grok-shell/src/session/acp_session.rs:645
pub(crate) struct SessionActor {
    pub(crate) session_info: SessionInfo,
    pub(crate) state: TokioMutex<State>,               // 任务调度状态
    pub(crate) chat_state_handle: xai_chat_state::ChatStateHandle, // 委托 ChatStateActor
    pub(crate) current_prompt_id: Arc<Mutex<Option<String>>>,
    pub(crate) compaction: CompactionConfig,
    pub(crate) pending_interjections: InterjectionBuffer<acp::ImageContent>,
    // ...
}

State 结构(acp_session.rs:338)是调度核心:running_task(当前 AgentTask)、pending_inputs(排队输入)、pending_notificationsedit_holds。对话历史与 token 统计则被整体迁移到独立的 ChatStateActor 线程,会话线程只持 handle——读写分离到线程粒度。

为什么用 OS 线程而不是 tokio task? 这是对 tokio 生态默认假设的一次反向操作:既然会话状态本来就不需要跨线程共享,!Send + 线程私有堆反而消灭了锁竞争和状态同步 bug;单个会话若陷入 CPU 密集解析,OS 抢占式调度保证不会饿死其他会话——这是异步任务队列给不了的隔离性。代价是每会话一个线程的内存开销,但对桌面 Agent 而言完全可接受。

Turn 循环本身与 Codex 同构:组装上下文(skills、hooks、AGENTS.md、git/环境信息)→ 模型 SSE 流式请求 → 解析 delta 与工具调用 → ToolDispatch 在沙箱内执行 → 结果回填 → 循环,直到无工具调用发出 TurnCompleted(携带 diff 汇总与 token 用量)并落盘。两个独特设计:

  • 插话(interjection):turn 运行中的新输入不是排队等下一轮,而是进入 InterjectionBufferxai-interjection-core),配合打断构成完整的中断/转向语义;
  • 服务端托管工具Agent 结构持有 hosted_tools: Vec<HostedTool>xai-grok-agent/src/agent.rs:46),像 WebSearch 这类工具以原生 API 类型发给服务端执行——本地工具与服务端工具在同一个注册表里统一声明。

Agent 的构建也颇为讲究:AgentBuilderAgentDefinition + 会话上下文产出构建后不可变Agent,工具状态(MCP 注册、完成度跟踪、重试配置)的动态变更全部走 Arc<ToolBridge> 的内部锁——“定义不可变、状态集中管”。

3.2 工具系统:统一契约与移植生态

工具契约收敛在 xai-tool-runtime 一个小 crate 里,核心 trait 用关联类型保住编译期类型安全:

// crates/common/xai-tool-runtime/src/tool.rs:36
pub trait Tool: Send + Sync {
    type Args: for<'de> Deserialize<'de> + JsonSchema + Send + 'static;
    type Output: Serialize + ToolOutput + Send + 'static;
    fn id(&self) -> ToolId;
    fn description(&self, _ctx: &ListToolsContext) -> ToolDescription;
    fn execute(&self, ctx: ToolCallContext, args: Self::Args)
        -> impl Future<Output = ToolStream<Self::Output>> + Send;
    // ...
}

执行结果是流式的:ToolStreamItem 只有 Progress(0..n 个,驱动 TUI 实时进度)与 Terminal(恰好 1 个且必须是最后一个)两种变体,长任务的原生进度条由此而来。由于带关联类型的 trait 不是对象安全的,边界处由 blanket impl 擦除为 ToolDyn,再以对象安全的 ToolDispatch 分发——类型安全与动态分发各得其所。

真正有趣的是命名空间体系。每个工具除实现运行时 Tool 外,还实现本 crate 的 ToolMetadata:声明 ToolKind(35 个变体:Read/Edit/Search/Execute/Plan/WebSearch/…)、所属命名空间、以及一份 MiniJinja 描述模板(支持 ${{ tools.by_kind.X }} 占位符——工具描述可以引用"当前还启用了哪些同类工具"来动态措辞)。命名空间枚举如下:

命名空间 来源
GrokBuild / GrokBuildConcise / GrokBuildHashline Grok 自研工具的三种表述形态
Codex 移植自 openai/codex 的工具实现
OpenCode 移植自 sst/opencode 的工具实现
MCP 外部 MCP server 动态注册

也就是说,Grok 没有闭门造车重写工具集,而是把 Codex 与 opencode 两家开源实现按 Apache-2.0 §4(b) 规范移植进自己的运行时契约xai-grok-tools/THIRD_PARTY_NOTICES.md 记录了完整许可与变更声明),同一套注册表里五族工具并存,按模型能力与配置组装。register::<T>() 在编译期完成 schema 生成与参数校验的捕获;对外还有一条 protobuf 生成面(xai-grok-tools-apixai.grok.tools.v1:ExecuteTool/ListTools/SpawnSubagent 等),让宿主服务不必依赖工具实现 crate。

模型路由则收敛在 xai-grok-modelsdefault_models.json 编译期内嵌,运行时按 CLI flag > ENV > config.toml > remote settings > defaults 解析,且分用途建模——主对话、web search 摘要、图片描述、会话标题各有独立模型槽位。

3.3 沙箱:fail-closed 的纵深防御

沙箱纵深防御

沙箱 crate 的文档注释第一句就亮明立场:

//! crates/codegen/xai-grok-sandbox/src/lib.rs:8
//! OS-level sandboxing for Grok Build via nono.
//! Applied once at process startup. ... Network is left open at the
//! process level (agent needs LLM API); child network is blocked
//! per-subprocess via seccomp.

第一层是进程级内核沙箱:基于 nono crate 走 Landlock(Linux)/ Seatbelt(macOS),SandboxManager::apply() 在启动时应用一次且不可逆,覆盖进程内 tokio::fs 与全部子进程。注意一个坦诚的权衡:进程级网络保持开放——Agent 自己要访问 LLM API,索性把断网下沉到子进程粒度。

第二层是 Linux bwrap 再执行:当 profile 带 deny 列表时,进程用 bubblewrap 重新 exec 自己——--cap-drop ALL、deny_write 路径 --ro-bind 只读挂载、deny_read 路径用 chmod 000 的占位符 bind-over(读取即 EPERM),并给 hooks 目录准备专门的写保护挂载计划。__GROK_INSIDE_BWRAP 环境变量防止重复再执行。

第三层是子进程网络:已知 Linux 启动路径按子进程安装 seccomp 网络过滤(should_restrict_child_network),Agent 主进程流量不受影响。

第四层是策略与体验.grok/sandbox.toml 定义 profiles(workspace / strict / devbox / custom,支持 extends 继承);沙箱激活时 bash 自动放行(should_auto_allow_bash)——边界既然硬了,就不必每次打扰用户。

但这个 crate 最值得学习的不是分层本身,而是fail-closed 被贯彻到了判定语义的每个角落

// crates/codegen/xai-grok-sandbox/src/lib.rs:110
/// This is the configured request, not a report that enforcement succeeded —
/// `is_active()` can be false while the process is still confined (e.g. some
/// Linux bwrap paths), and a requested-but-unapplied profile already warns the
/// user. Keying on the request is the fail-closed choice.
pub fn requested_confinement_profile() -> Option<&'static str> { ... }

判定"是否受限"以请求的 profile 而非"成功应用"为准——因为部分 Linux bwrap 路径下 is_active() 会是 false 而进程实际仍被约束;同理 requires_read_deny 直接看配置里有没有 deny(解析失败返回空集时若据其判定就会静默 fail-open)。每处"看似可以简化"的分支,注释都解释了为什么不简化。

3.4 TUI:pager 隐喻与 Elm 架构

TUI crate 叫 “pager” 不是偶然——整个界面的本质是一个终端分页器:可滚动的对话回滚区(scrollback)+ 底部固定实时区(prompt/状态行),而非传统全屏仪表盘。三种屏幕模式:

// crates/codegen/xai-grok-pager/src/app/mod.rs:312
pub(crate) enum ScreenMode {
    Fullscreen,   // alternate screen 全屏
    Inline,       // 不进 alternate screen(tmux control mode / Zellij)
    /// Scrollback-native (experimental, `--minimal`): finalized blocks are
    /// printed into the terminal's native scrollback via `insert_before` ...
    Minimal,
}

Minimal 模式最能体现 pager 语义:已完结的对话块通过 insert_before 直接写进终端原生 scrollback,TUI 只保留一个小 pinned 区——历史归终端管,应用只管增量。/minimal/fullscreen 可运行中原地切换。

渲染架构是教科书级 Elm 单向数据流:actions(Action/Effect/TaskResult 枚举)→ AppView(根组件)→ dispatch(Action → 状态变更 + Vec<Effect>纯同步、可单测)→ effects(异步任务 spawn)→ event_loop(一条 biased tokio::select! 只做 IO 管道)。输入系统的单一事实来源是动作注册表:同一个注册表同时服务快捷键栏、命令面板 fuzzy 搜索与按键分发,按键按 Pane → Agent → Global 三层冒泡。

两处细节可见打磨深度:resize 防抖 16ms(拖拽窗口每秒几十个 resize 事件,稳定后只做一次全量重排);启动期 type-ahead 过滤(终端能力查询应答 DA2/OSC 会泄漏成 Esc+可打印字节,从第一个 Esc 截断丢弃,防止幽灵文本混进输入框)。

测试基建同样硬核:xai-grok-pager-pty-harness 用真实 PTY + 虚拟终端 + mock 推理服务器做端到端渲染断言。另一个彩蛋是 xai-grok-mermaid:vendored 了完整 Mermaid 渲染栈(dagre 布局 + graphlib + resvg 光栅化),模型输出的 mermaid 代码块可以直接在终端里渲染成图——这也解释了为什么 third_party/ 里有三个 Rust 移植的 JS 图形库。

3.5 扩展生态:Skills、Hooks、Plugins、MCP、ACP

Skills 走兼容优先路线。技能即带 SKILL.md(YAML frontmatter 写 name/description)的目录,发现路径覆盖项目/仓库/用户三级 .grok/skills/,并且默认同时扫描 .claude/.cursor/.agents/ 目录——Claude Code 与 Cursor 的技能和斜杠命令开箱即用(可通过 [compat] 配置关闭)。commands/ 目录下的扁平 .md 文件自动变成斜杠命令,与 Claude Code 的 legacy 布局对齐。发现逻辑刻意不走 .gitignore:团队常把 .claude/** 忽略为本地配置,但项目级命令仍需生效——隐藏技能请用 [skills] ignore 显式声明。

其余扩展点各占一个 cratexai-grok-hooks 覆盖生命周期钩子;xai-grok-plugin-marketplace 管理插件发现与安装;xai-grok-mcp 管理 MCP 客户端连接;xai-acp-lib 封装 Zed 系 agent-client-protocol,让任何实现 ACP 的编辑器(Zed、Neovim 插件等)都能嵌入 Grok。特色功能还有:xai-grok-voice 语音模式、xai-grok-status-line 可定制状态行、xai-workflow(内嵌 Rhai 脚本引擎的可视化工作流)、xai-grok-memory 跨会话记忆、claude_import 一键导入 Claude Code 配置、foreign-sessions 直接读取外部工具的历史会话——对一个后来者,生态兼容本身就是竞争力。

四、基础设施:配置、会话与可观测

配置系统可能是全仓库防御性设计密度最高的地方。TOML 配置按七层优先级合并:

// crates/codegen/xai-grok-config/src/lib.rs:3
//! Merge order (lowest → highest priority):
//! 1. `/etc/grok/managed_config.toml`
//! 2. `$GROK_HOME/managed_config.toml`
//! 3. `$GROK_HOME/config.toml`
//! 4. `$GROK_HOME/requirements.toml` (cloud cache; Ed25519-signed at rest ...)
//! 5. `/etc/grok/requirements.toml`
//! 6. macOS MDM managed preferences (`ai.x.grok`, admin-forced) — macOS only

这条链为企业管控而生:IT 用 managed_config 下发基线,云端用 Ed25519 签名的 requirements.toml 下发硬策略,macOS 上再叠加 MDM 强制偏好。安全边界同样成文:GROK_CONFIG 环境变量 overlay 被限制在软配置白名单(models、features 等),任何能执行代码/改认证/改出口的表(mcp_serversauthendpointsplugins)一律 fail-closed 丢弃;无 HOME 时不降级读 cwd 的 .grok/(防不可信项目目录提权);TOML 报错永不回显源行(可能含密钥)。

功能开关是"注册表驱动"的:16 个 [features] 键每个一行 FeatureSpec(key、TOML path、env 名、默认值、远程设置读取函数),解析优先级唯一化为 requirements pin → env → config → remote → default,且 off_reason() 能输出"为什么关"的人话解释(“off (a requirements.toml pin)")——可解释的配置治理。

会话层:~/.grok/sessions/{按 cwd 编码的目录}/ 全部 0700 权限并自愈;长路径用 {slug}-{blake3 前 16 hex} 编码;SQLite journal 记录事件流支撑 resume、全文会话搜索(xai-grok-session-search)与跨工具会话读取。遥测栈为 fastrace + OTLP + Mixpanel,并配了死循环检测(DoomLoopRecoverySettingsx-grok-doom-loop-check 请求头 + window_tokens + max_retries)——模型陷入重复采样时自动熔断重采样。

五、工程实践亮点

抛开功能,这个仓库有几条值得抄的工程实践:

  1. 组合根隔离:jemalloc 全局分配器、malloc_conf profiling、cryptify 字符串混淆、rustls 全部只出现在 xai-grok-pager-bin 二进制 crate,库 crate 保持纯净可复用——依赖的"脏"与二进制的"加固"分层;
  2. 硬化发布 profilerelease-dist 用 thin LTO + codegen-units=1 + 保留符号与行表(CI 先抽 .dSYM/.debug 侧车再 strip),并留有 x-prod 等按场景分档的 profile 家族;
  3. clippy 治理带故事uninlined_format_args = "allow" 旁边写着 9 行注释解释"没有 merge queue 之前为什么不能收紧”——lint 决策可追溯;
  4. 工具链即代码rust-toolchain.toml 锁版本,protoc 走 DotSlash 按需下载,构建可复现;
  5. 仓库即快照:根 Cargo.toml 生成化 + SOURCE_REV 溯源,monorepo 与开源镜像之间不存在双向同步的心智负担。

六、技术栈说明

类别 选型 用途
异步运行时 tokio(full)+ LocalSet leader、会话线程、工具并发
终端 UI ratatui 0.29 + crossterm + 自维护组件 TUI 渲染与输入
模型接口 async-openai(fork)+ eventsource-stream OpenAI 兼容 SSE 流式
序列化 serde / schemars / prost / ts-rs 协议、schema、gRPC 工具面
数据库 SQLite(journal)+ fs2 会话事件流持久化
沙箱 nono(Landlock/Seatbelt)+ bubblewrap + seccomp 内核级纵深防御
MCP rmcp 系 + agent-client-protocol 0.10 扩展与编辑器嵌入
脚本引擎 Rhai 1.25 workflow 工作流
图形渲染 vendored mermaid 栈 + resvg + tiny-skia 终端内渲染流程图
搜索 nucleo(helix 同源)+ gix 模糊文件搜索与 git 状态
内存 tikv-jemalloc(profiling) 分配器与堆分析
可观测 fastrace + OpenTelemetry(OTLP)+ Mixpanel 链路追踪与产品遥测
测试 insta / wiremock / serial_test + PTY harness 快照、mock SSE、端到端终端

七、总结与展望

把 Grok Build 的源码通读下来,最能带走的是三条与 Codex 恰成对照的架构判断:

  • 进程拓扑是产品决策。Codex 的"每次冷启动独立进程"换来了简单与隔离,Grok 的"Leader 单例守护 + 多客户端复用"换来会话永续与多端同窗——后者更像一个常驻的本地开发服务,而非一次性命令。两种模型没有对错,但 Grok 证明了 ACP + Unix socket 的组合足以把"终端 Agent"演进为"本机会话基础设施”;
  • 并发模型可以反 tokio 直觉。每会话一个 OS 线程、!Send + RefCell,用线程边界替代队列仲裁,是"问题本质是隔离而非调度"时的教科书解法;
  • fail-closed 是一种代码审美。从沙箱"以请求而非应用判定约束”,到配置"env overlay 白名单"、“报错不回显源行”,Grok 把防御写成了一致的语言——每个放宽的分支都必须先证明自己不会 fail-open。

与 Codex、Claude Code 相比,Grok Build 的差异化打法非常清晰:不重造工具而是移植成熟实现(Codex/opencode 工具按 Apache §4(b) 收编)、不另立技能格式而是兼容 Claude/Cursor 生态、不绑定单一前端而是All-in 开放协议(ACP + MCP + WebSocket serve)。对一个后发的编码 Agent,“把兼容性当功能"可能是最聪明的入场姿势。

展望后续,源码里已埋好几条演进线:xai-grok-workspace-daemon 预示宿主操作将进一步服务化、xai-grok-remoterelay 指向远程/云端会话、xai-computer-hub 系列 crate(core/sdk/mcp-adapter)暗示浏览器与计算机控制能力、语音模式与 workflow 引擎则把场景从"写代码"向"通用操作"延展。对想深入 AI Agent 工程化的开发者,xai-grok-shell/src/leader/(进程拓扑)、session/acp_session.rs(会话 Actor)与 xai-grok-sandbox/src/lib.rs(fail-closed 范本)是三块最值得精读的矿区。

参考:x.ai/cli · docs.x.ai/build/overview · 本文图表 SVG 源文件位于本站 /img/grok-build-source-analysis/

「真诚赞赏,手留余香」

爱折腾的工程师

真诚赞赏,手留余香

使用微信扫描二维码完成支付