MoonshotAI / MoonshotAI/kimi-code

Expose steering over ACP: map _session/steering to the existing Session.steer()

Open
#2,370 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

Summary

kimi acp currently has no way for an ACP client to inject a message into a running turn, even though Kimi Code already implements steering everywhere else. As a result, ACP hosts can only queue a follow-up and wait for the turn to finish, while the TUI can steer it immediately with Ctrl-S.

This is a request to expose the existing capability through the ACP surface, matching the extension method that claude-agent-acp and codex-acp already ship.

The capability already exists — only the ACP surface is missing
Core SDK packages/node-sdk/src/session.tsasync steer(input: string | PromptInput)rpc.steer({ sessionId, input })
Official smoke test packages/node-sdk/examples/kimi-harness-steer-smoke.ts — calls await session.steer(STEER) while a prompt stream is still running
TUI docs/en/reference/keyboard.mdCtrl-S: "Steer: inject the current input directly into the running turn"
ACP adapter packages/acp-adapter/** — no reference to steering anywhere; AcpSession.prompt() maps straight to session.prompt()

The adapter already holds the same KimiHarness / Session instance that exposes steer(), so this is a thin mapping rather than new functionality.

Prior art: the wire shape is already established by two other adapters

Both adapters below implement the same extension method, so hosts can support all of them with one code path:

  • @agentclientprotocol/claude-agent-acp (verified in 0.62.0)
  • @agentclientprotocol/codex-acp (verified in 1.1.7)

Advertisement — top-level _meta in the initialize response:

{ "_meta": { "steering": { "supported": true } } }

Request_session/steering:

{ "sessionId": "…", "prompt": [ { "type": "text", "text": "…" } ] }

Response:

{ "outcome": "injected" }

injected means the prompt joined the turn that is currently running. Both adapters also define a startedNewTurn outcome for the case where the target turn had already finished.

One caveat worth avoiding from the start

In claude-agent-acp, the startedNewTurn path starts a detached turn: it emits session/update notifications, but no ACP request owns its lifecycle, so its terminal response is discarded and hosts cannot reliably consume or cancel it (see claude-agent-acp#903, and the proposed opt-in host-owned fallback in PR #919: _meta.steering.idleBehavior: "promptRequired" → a promptRequired outcome that leaves the content unconsumed).

Since Kimi would be implementing this fresh, it can skip that problem entirely: when there is no live turn to steer, leave the content unconsumed and let the host submit it as a normal session/prompt. Steering is an operation on an in-flight turn, not an alternative way to start one. Whatever signal you choose for "no live turn" (a distinct outcome value, or an error the host can branch on) is fine from our side — the important part is that the host keeps ownership of the new turn's lifecycle.

Why it matters

We are building a desktop client that drives Claude Code, Codex and Kimi Code through a single ACP transport. Our message-queue feature lets users type while a turn is running; a queued message can either wait for the turn to end or be sent immediately. Capability is detected at runtime from _meta.steering.supported, with no per-vendor branching — so the moment kimi acp advertises it, Kimi users get the same behaviour with no changes on our side. Until then, Kimi is the only one of the three where "send now" has to degrade to "send next".

Question

Would you accept a PR for this? If so, we are happy to prepare it (adapter method + _meta advertisement + tests). We wanted to align on the shape first, per CONTRIBUTING.md.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/acp-adapter/**, compare AcpSession.prompt() with the existing Session.steer() entry point in packages/node-sdk/src/session.ts, and review the steering smoke test in packages/node-sdk/examples/kimi-harness-steer-smoke.ts. Add the ACP advertisement, request mapping, outcomes, and tests; done means an in-flight turn accepts steering while content is left unconsumed when no turn is active.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.