F6: kimi-cli command parity — kigi acp, mcp auth, --mcp-config-file

- `kigi acp`: top-level alias for the stdio ACP server (kimi-cli `acp`).
  AgentArgs.mode is now optional — bare `kigi agent` and `kigi acp` both
  default to stdio at dispatch; `kigi acp <mode>` is rejected.
- `kigi mcp auth <name>`: authorize an OAuth-enabled remote MCP server
  (kimi-cli `mcp auth`). Reuses the doctor's interactive connection path:
  starts the named server with OauthInteractivity::Interactive (browser
  flow when required), completes the handshake, and reports the tool
  count. Stdio servers and unknown names fail with actionable errors.
- `--mcp-config-file <PATH>` (repeatable, global): extra MCP config files
  in the .mcp.json shape ({"mcpServers": {...}}), kimi-cli semantics.
  Files are validated at parse time (fail fast on unreadable/invalid
  JSON), carried across the TUI -> shell boundary via
  KIGI_MCP_CONFIG_FILES, and merged at HIGHEST priority — an explicitly
  passed file overrides every config scope. Covered by loader unit tests
  and verified live: an injected server surfaces in the session's
  x.ai/mcp/servers_updated notification via both the flag and the env.

The stale bare-agent-requires-mode CLI test is re-contracted to the new
default-to-stdio behavior.
This commit is contained in:
2026-07-17 20:15:56 -04:00
parent 74b210535e
commit a3f062b522
6 changed files with 246 additions and 12 deletions
+8 -5
View File
@@ -1359,12 +1359,15 @@ mod tests {
assert!(args.no_leader);
assert!(matches!(args.command, Some(Command::Agent(_))));
}
/// The `agent` subcommand requires an explicit mode (stdio|serve|leader);
/// the old bare `agent` headless form was removed.
/// Bare `agent` parses with no mode and defaults to stdio at dispatch
/// (kimi-cli parity, F6 — the `acp` alias relies on the same default).
#[test]
fn cli_bare_agent_subcommand_requires_mode() {
assert!(try_parse_pager(&["grok-pager", "--leader", "agent"]).is_err());
assert!(try_parse_pager(&["grok-pager", "agent"]).is_err());
fn cli_bare_agent_subcommand_defaults_to_stdio() {
let args = try_parse_pager(&["grok-pager", "agent"]).unwrap();
let Some(Command::Agent(agent)) = args.command else {
panic!("expected agent subcommand");
};
assert!(agent.mode.is_none(), "bare agent carries no explicit mode");
}
#[test]
fn leader_defaults_off_without_config() {