feat(kimi-inspect): add kap-server web inspector with dev-only /api/v1/debug RPC surface - #1806
Conversation
- new apps/kimi-inspect app: connect screen (server URL + optional bearer token, persisted in localStorage, deep-linkable via ?url=/?token=), workspace/session browser sidebar, per-session chat view, and live Service panels with data and trigger buttons for Session/Agent scopes - built on @moonshot-ai/klient (HTTP for calls, /api/v2/ws for events); Vite dev server proxies /api to a running kap-server - register the workspace in AGENTS.md project map and flake.nix workspacePaths/workspaceNames
🦋 Changeset detectedLatest commit: 86ee696 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6e9dd59c15
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const entries = useMemo( | ||
| () => [...mapHistory((history.data ?? []) as readonly HistoryMessage[]), ...stream], | ||
| [history.data, stream], |
There was a problem hiding this comment.
Reset transient chat state when selection changes
Because ChatView remains mounted while App only changes sessionId/agentId, stream and running are not scoped to the selected conversation. If a user switches sessions or agents while an optimistic prompt/streamed turn is present, these entries are still appended to the new history and the old running state can disable Send/Cancel for the wrong agent; reset or key this state on sessionId/agentId.
Useful? React with 👍 / 👎.
| if (fn === undefined) { | ||
| return Promise.reject(new Error(`no such method on proxy: ${method}`)); | ||
| } | ||
| return fn(arg); |
There was a problem hiding this comment.
Preserve service method arity in panel calls
call always invokes the proxy with exactly one argument. Through HttpChannel this serializes no-arg calls as [null], and a JSON array entered for a multi-parameter dynamic method becomes nested; the v2 dispatcher only spreads the top-level array (packages/kap-server/src/transport/dispatcher.ts:129), so generic buttons for methods such as sessionApprovalService.decide(id, response) pass the wrong arguments, and optional no-arg methods like sessionInteractionService.listPending() get null instead of no filter.
Useful? React with 👍 / 👎.
- kimi-inspect: replace @moonshot-ai/klient with an in-app old-klient-style channel layer (service-bound IChannel, HTTP ProxyChannel, shared /api/v2/ws socket with ref-counted event listens), typed by agent-core-v2 interfaces; /channels descriptors + serviceByName keep every wire protocol loaded 1:1 - kimi-inspect: local server auto-discovery (Vite middleware over the kap-server instance registry + home token), zero-config startup connect, and a header switcher for runtime server switching - kap-server: wire the dormant --debug-endpoints flag to a new whitelist-free /api/v1/debug dispatcher (every scoped service callable), gated to loopback binds; repo dev scripts pass the flag - kimi-inspect: probe the debug surface at connect, falling back to /api/v2 on servers without it - tests: channel + discovery unit tests in kimi-inspect; debug RPC and loopback-gating coverage in the kap-server rpc/debugNonloopback suites
The private dev app never ships, so it should never appear in a changeset. Add it to the changeset config ignore list (next to vis*) and note the rule in the gen-changesets skill.
…1/debug RPC surface (MoonshotAI#1806) * feat(kimi-inspect): add web inspector for kap-server /api/v2 surface - new apps/kimi-inspect app: connect screen (server URL + optional bearer token, persisted in localStorage, deep-linkable via ?url=/?token=), workspace/session browser sidebar, per-session chat view, and live Service panels with data and trigger buttons for Session/Agent scopes - built on @moonshot-ai/klient (HTTP for calls, /api/v2/ws for events); Vite dev server proxies /api to a running kap-server - register the workspace in AGENTS.md project map and flake.nix workspacePaths/workspaceNames * fix(kimi-inspect): align dependency versions with the workspace (sherif) * feat: dev /api/v1/debug RPC surface and kimi-inspect channel rework - kimi-inspect: replace @moonshot-ai/klient with an in-app old-klient-style channel layer (service-bound IChannel, HTTP ProxyChannel, shared /api/v2/ws socket with ref-counted event listens), typed by agent-core-v2 interfaces; /channels descriptors + serviceByName keep every wire protocol loaded 1:1 - kimi-inspect: local server auto-discovery (Vite middleware over the kap-server instance registry + home token), zero-config startup connect, and a header switcher for runtime server switching - kap-server: wire the dormant --debug-endpoints flag to a new whitelist-free /api/v1/debug dispatcher (every scoped service callable), gated to loopback binds; repo dev scripts pass the flag - kimi-inspect: probe the debug surface at connect, falling back to /api/v2 on servers without it - tests: channel + discovery unit tests in kimi-inspect; debug RPC and loopback-gating coverage in the kap-server rpc/debugNonloopback suites * chore(changesets): ignore @moonshot-ai/kimi-inspect The private dev app never ships, so it should never appear in a changeset. Add it to the changeset config ignore list (next to vis*) and note the rule in the gen-changesets skill.
…1/debug RPC surface (MoonshotAI#1806) * feat(kimi-inspect): add web inspector for kap-server /api/v2 surface - new apps/kimi-inspect app: connect screen (server URL + optional bearer token, persisted in localStorage, deep-linkable via ?url=/?token=), workspace/session browser sidebar, per-session chat view, and live Service panels with data and trigger buttons for Session/Agent scopes - built on @moonshot-ai/klient (HTTP for calls, /api/v2/ws for events); Vite dev server proxies /api to a running kap-server - register the workspace in AGENTS.md project map and flake.nix workspacePaths/workspaceNames * fix(kimi-inspect): align dependency versions with the workspace (sherif) * feat: dev /api/v1/debug RPC surface and kimi-inspect channel rework - kimi-inspect: replace @moonshot-ai/klient with an in-app old-klient-style channel layer (service-bound IChannel, HTTP ProxyChannel, shared /api/v2/ws socket with ref-counted event listens), typed by agent-core-v2 interfaces; /channels descriptors + serviceByName keep every wire protocol loaded 1:1 - kimi-inspect: local server auto-discovery (Vite middleware over the kap-server instance registry + home token), zero-config startup connect, and a header switcher for runtime server switching - kap-server: wire the dormant --debug-endpoints flag to a new whitelist-free /api/v1/debug dispatcher (every scoped service callable), gated to loopback binds; repo dev scripts pass the flag - kimi-inspect: probe the debug surface at connect, falling back to /api/v2 on servers without it - tests: channel + discovery unit tests in kimi-inspect; debug RPC and loopback-gating coverage in the kap-server rpc/debugNonloopback suites * chore(changesets): ignore @moonshot-ai/kimi-inspect The private dev app never ships, so it should never appear in a changeset. Add it to the changeset config ignore list (next to vis*) and note the rule in the gen-changesets skill.
…1/debug RPC surface (MoonshotAI#1806) * feat(kimi-inspect): add web inspector for kap-server /api/v2 surface - new apps/kimi-inspect app: connect screen (server URL + optional bearer token, persisted in localStorage, deep-linkable via ?url=/?token=), workspace/session browser sidebar, per-session chat view, and live Service panels with data and trigger buttons for Session/Agent scopes - built on @moonshot-ai/klient (HTTP for calls, /api/v2/ws for events); Vite dev server proxies /api to a running kap-server - register the workspace in AGENTS.md project map and flake.nix workspacePaths/workspaceNames * fix(kimi-inspect): align dependency versions with the workspace (sherif) * feat: dev /api/v1/debug RPC surface and kimi-inspect channel rework - kimi-inspect: replace @moonshot-ai/klient with an in-app old-klient-style channel layer (service-bound IChannel, HTTP ProxyChannel, shared /api/v2/ws socket with ref-counted event listens), typed by agent-core-v2 interfaces; /channels descriptors + serviceByName keep every wire protocol loaded 1:1 - kimi-inspect: local server auto-discovery (Vite middleware over the kap-server instance registry + home token), zero-config startup connect, and a header switcher for runtime server switching - kap-server: wire the dormant --debug-endpoints flag to a new whitelist-free /api/v1/debug dispatcher (every scoped service callable), gated to loopback binds; repo dev scripts pass the flag - kimi-inspect: probe the debug surface at connect, falling back to /api/v2 on servers without it - tests: channel + discovery unit tests in kimi-inspect; debug RPC and loopback-gating coverage in the kap-server rpc/debugNonloopback suites * chore(changesets): ignore @moonshot-ai/kimi-inspect The private dev app never ships, so it should never appear in a changeset. Add it to the changeset config ignore list (next to vis*) and note the rule in the gen-changesets skill.
Related Issue
No linked issue (internal dev-tooling PR) — the problem is described below.
Problem
Debugging the v2 (kap-server) engine today means either driving klient's typed facade or hand-crafting
/api/v2calls: there is no interactive way to browse workspaces/sessions, watch a live agent, or inspect and invoke Services. Two gaps make this worse:--debug-endpointsflag has been fully plumbed (startServeroption, CLI flag, loopback gating instart.ts) but mounts zero routes — a dead end for exactly this use case.~/.kimi-code/server.tokenby hand, with no discovery of the instances already running on the machine.What changed
1. New app:
apps/kimi-inspect— web inspector for the/api/v2surfacePrivate dev app (not published), React 19 + Vite + react-query. Workspace/session browser, per-session chat with live deltas, dynamic Service panels (data + trigger buttons) driven by the server's
/channelsintrospection, pending-interaction handling, and a merged core/session/agent WS event log. Registered inpnpm-workspace.yaml,flake.nixworkspace lists, and the rootAGENTS.mdproject map.2. In-app channel layer (old-klient / VS Code
ProxyChannelmodel)The app composes its own transport (
apps/kimi-inspect/src/channel/) instead of deep-importing klient internals: service-boundIChannel(call/listen), an HTTPProxyChannelrouting to the RPC surface,makeProxytyped byagent-core-v2interfaces/decorator ids, and a shared/api/v2/wssocket with ref-counted service-emitterlistens (soonDidXxxmembers work 1:1)./{rpcBase}/channelsdescriptors +serviceByNamematerialize every exposed Service into a typed proxy — all protocols load 1:1. This drops the app's@moonshot-ai/klientdependency.3. Zero-config local development
A dev middleware (
GET /__inspect/servers) scans the local kap-server instance registry (~/.kimi-code/server/instances+ legacylock) and the home token, so the inspector auto-connects on startup (no URL/token typing) and can switch between running servers from a header dropdown at runtime. Manual URL/token and?url=deep links keep working unchanged; statically hosted builds fall back to the manual form.4. kap-server: dev-only
/api/v1/debugRPC surfaceWires the dormant
--debug-endpointsflag to a real surface (src/transport/registerDebugRoutes.ts): the same reflection dispatcher and envelope semantics as/api/v2, but the channel lookup spans the whole scoped DI registry — every scoped Service (App/Session/Agent) is callable and listed via/api/v1/debug/channels. Gated to loopback binds by the pre-existingstart.tscheck and still behind the global bearer-auth hook. The/api/v2whitelist is untouched (klient's production contract is unchanged). The dispatcher's channel lookup was parameterized and route registration factored into a shared helper used by both surfaces. Repo dev scripts (dev:server,dev:kap-server,dev:kap-server:multi) now pass--debug-endpoints; the inspector probes/api/v1/debugat connect and falls back to/api/v2on servers without it.Tests
test/rpc.test.ts(full listing, non-whitelisted call, unknown-service 40001, bearer gating), andtest/debugNonloopback.e2e.test.tspins the three mount states (public-bind 404 / loopback default-off 404 / loopback mounted). Full suite: 669 tests green.src/channel/channel.test.ts) and server-discovery unit tests (vite/serverDiscovery.test.ts).Checklist
gen-changesets:.changeset/debug-rpc-surface.mdpatches@moonshot-ai/kimi-code(kap-server enters the CLI bundle);kimi-inspectis a private dev app and follows the no-changeset precedent of its initial commit.gen-docs, or this PR needs no doc update: internal dev tooling; no user-facing CLI behavior change (the flag is off by default in production).