Skip to content

feat(kilo-plugin): serve a Kilo v2 handshake as plugin RPC - #15285

Merged
marius-kilocode merged 9 commits into
v2from
plugin-rpc-routes
Oct 21, 2026
Merged

marius-kilocode merged 9 commits into
v2from
plugin-rpc-routes

Conversation

@marius-kilocode

@marius-kilocode marius-kilocode commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

What Problem This Solves

A VS Code or JetBrains client that connects to a v2 server cannot tell a Kilo v2 server from an upstream OpenCode server. GET /api/info reports a version but no product name, and the OpenAPI title is "opencode". Also, the v2 line had no stated rule for how a Kilo route group (the v1 /kilocode/* HttpApi groups) reaches the server.

Why This Change Was Made

Part 1 of U-E1-08 (Kilo server extension surface).

  • Route groups: a Kilo route group is the RPC of a plugin in KiloPlugins. The contract is in packages/schema/src/kilocode/<feature>.ts, the plugin registers the handlers with ctx.rpc.register, and upstream rpc.call serves it at POST /api/rpc/:rpcID/:method. The host already registers KiloPlugins, so this needs no new mount point and no seam. The comment on KiloPlugins now states the rule.
  • Handshake: new kilocode.handshake RPC (packages/schema/src/kilocode/handshake.ts, plugin packages/kilo-plugin/src/handshake/index.ts). Method get returns { product: "kilo", version, channel }, from the app identity that the host gives the server (ctx.app).
    • Kilo v2 server: {"output":{"product":"kilo",...}}.
    • Upstream OpenCode server: RPC error rpc.unavailable.
    • Kilo v1 server: HTTP 404 (no /api/rpc route).
  • Not in this PR: parent watchdog, /reload, watcher policy, capabilities in the handshake. GET /api/plugin already lists the active kilocode.* plugins, so a capability list would repeat it.

User Impact

No visible change in the TUI. Clients can call client.rpc(KiloHandshakeRpc.Definition).get({}) (contract from @opencode/schema/kilocode/handshake) to confirm a Kilo v2 server before they use v2 routes. Kotlin clients can call POST /api/rpc/kilocode.handshake/get with {"input":{}}.

Placement

Change Rung Why not lower Proof
kilocode.handshake contract and plugin 1 n/a schema/src/kilocode/handshake.ts, kilo-plugin/src/handshake/index.ts
Kilo route groups as plugin RPC 1 n/a KiloPlugins in kilo-plugin/src/index.ts, kilo_port(server:5e0f8563b425)

Shared upstream files changed: none. Core-internal imports added: none. Mirrored files: none. Shared patches: none changed by this PR. The baseline is 27 files, 204 marked, 39 unmarked in script/upstream/shared-patches.json after the config discovery seam (#15282).

Progress map

server: 0/96 to 1/96. patch 0/10 to 1/10; landed 1 plugin.

Done, and why:

  • kilo_port (1): patch:server:5e0f8563b425, v1 server/routes/instance/httpapi/api.ts:29 imported the Kilo HttpApi groups into the upstream Api. v2 serves each Kilo group as the RPC of a plugin in KiloPlugins. Each group module keeps its own open cell.

Still open:

  • patch:server:6125d390ed46 (v1 httpapi/server.ts:125): it also provides the v1 listener layer (CORS, presence), which is not ported.
  • Parent watchdog, reload and the other server cells: later parts of U-E1-08 and the feature units of each group.

Corrections: the contract was first named server.ts. The progress map matches module cells by feature and file name, so that name closed two unrelated v1 cells (kilocode/server/server.ts, the OpenAPI title, and kilocode/server/httpapi/server.ts, the listener layer). The file is named handshake.ts so only the verified cell closes.

Evidence

  • New test packages/kilo-cli/test/handshake.test.ts: starts the host entry as serve --stdio with isolated HOME and XDG and KILO_SERVER_PASSWORD, then calls the handshake and kilocode.gateway authStatus through the generated client against a local stand-in for the Kilo API. Pass.
  • bun typecheck: packages/schema, packages/kilo-plugin, packages/kilo-cli pass.
  • bun test with isolated HOME and XDG: schema 68/68, kilo-plugin 25/25, kilo-cli 11/11.
  • Startup ratchet (bun run startup in packages/kilo-cli): pass. New budget kilocode.handshake: 50 in startup-budget.json, the same value as the other Kilo plugins (measured median 0 ms on CI and locally); the ratchet requires a budget for each Kilo plugin.
  • bun run check:generated (packages/client): no drift. Plugin RPC methods are not in the OpenAPI surface.
  • bun script/check-shared-patches.ts --worktree, bun script/check-opencode-annotations.ts --worktree, bun script/upstream/placement.ts --imports: ok.
  • bun script/upstream/progress.ts twice (identical), then --check: up to date.
  • Self-test (pass): env KILO_V2_PROFILE=/tmp/kilo-v2-handshake KILO_SERVER_PASSWORD=selftest bun dev serve --port 47123, then curl:
    • POST /api/rpc/kilocode.handshake/get, with and without a location: {"output":{"product":"kilo","version":"local","channel":"local"}}
    • POST /api/rpc/kilocode.gateway/authStatus: answered
    • unknown method: rpc.method_not_found; no auth: 401; no errors in the log
  • Self-test of the release build after merging v2 (pass): built the host with bun run script/build.ts --single --skip-web-ui (Bun 1.4.2), then a client script started bin/kilo serve --stdio with isolated HOME and XDG, KILO_SERVER_PASSWORD and KILO_CLIENT=vscode, as an IDE would:
    • handshake: {"product":"kilo","version":"0.0.0-plugin-rpc-routes-202610210645","channel":"plugin-rpc-routes"}, the build version and channel (/api/info reports the same version). product stays kilo with KILO_CLIENT=vscode.
    • first call 650 ms (it boots the location and waits for plugin activation), next call 1 ms
    • kilocode.gateway authStatus answered; /api/plugin lists kilocode.handshake, kilocode.gateway, kilo.agent, kilo.agent.ceiling as active; no password: 401; the server exits with code 0 when stdin closes
  • Negative cases (pass):
    • upstream server without the host (in process, createRoutes without overrides): {"type":"rpc.unavailable","message":"RPC is unavailable: kilocode.handshake"}
    • Kilo v1 (kilo 7.8.12 with isolated HOME and XDG): 404 with v1 credentials (user kilo), 401 with user opencode. A client that sends opencode credentials to a v1 server gets 401, not 404.
  • Local bun run check: lint passes. Typecheck fails locally in upstream packages (ai, cli, server, ...) because a worktree nested in another checkout resolves @types/node from the parent checkout. These packages do not import the changed files.

Limits: the version is local until a Kilo build defines OPENCODE_VERSION and OPENCODE_CHANNEL.

Add the kilocode.handshake RPC contract and its plugin. The handshake returns the product, version and channel of the server, so a client can confirm that it talks to a Kilo v2 server. Kilo route groups are plugin RPCs that the host registers through KiloPlugins and the server serves at POST /api/rpc/:rpcID/:method. A host test starts the host entry and calls the handshake and a Gateway route through the generated client. Part 1 of U-E1-08.
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

➖ v2 migration progress: 0.9% → 0.9% (+1 done, 0 total, 0 dropped; 90/9829 cells)

Placement: 0 new marked lines in shared files, 1 new kilo_port annotation, 0 new core-internal imports.

Ratchets: 9 core-internal imports (base 9); shared patches by rung 20 seam, 7 patch (base 20 seam, 7 patch).

Feature Before After Change
server 0/96 1/96 +1 patch done
1 cells closed
  • patch:server:5e0f8563b425

v2 migration progress map at this commit

Full map · how cells close

@kilo-code-bot

kilo-code-bot Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Incremental review of 476e4f47..61899af2. The only new change is chore(progress): regenerate the history as on the merge with v2, which rewrites the History table in migration-tracking/progress/README.md and the matching points in history.svg for 2026-10-20 (88 → 87) and 2026-10-21 (88 → 89). Both files are generated by script/upstream/progress.ts, and the migration progress map is CI-owned (kilo-v2.yml runs progress.ts --check), so no finding is raised for it here.

The previous SUGGESTION about stale shared-patch counts is resolved: the U-E1-08 row now states 27 files / 204 marked / 39 unmarked, matching the limits in script/upstream/shared-patches.json, and the existing inline comment on that row is outdated (line: null). The PR's diff against the current base still contains only Kilo-owned paths. The handshake contract, plugin, KiloPlugins rule comment, startup budget and stdio integration test are unchanged since the last review, so the earlier analysis and the no-resource-leak conclusion still hold.

Observation (not counted as a finding; the progress CI job owns this check): regenerating from this branch's first-parent history gives 2026-10-20 = 88 and 2026-10-21 = 88 (6b405b8d and 701d1ed8, with merge 6097cece skipped because its progress.json equals the current output), while the v2 chain gives 2026-10-20 = 87 (0311551d) and no 2026-10-21 point. The committed 87/89 pair does not reproduce from either topology, so the progress job is likely to report it.

Files Reviewed (2 files in this step; 11 files overall)
  • migration-tracking/progress/README.md - generated history rows changed, no finding
  • migration-tracking/progress/history.svg - generated chart points changed, no finding
  • migration-tracking/plans/kilo-v2-migration-plan.md - previous suggestion fixed, no new issues
  • migration-tracking/progress/progress.json, progress.svg, badge.svg - unchanged, no issues
  • packages/schema/src/kilocode/handshake.ts - unchanged, no issues
  • packages/kilo-plugin/src/handshake/index.ts - unchanged, no issues
  • packages/kilo-plugin/src/index.ts - unchanged, no issues
  • packages/kilo-plugin/test/index.test.ts - unchanged, no issues
  • packages/kilo-cli/test/handshake.test.ts - unchanged, no leak
  • packages/kilo-cli/startup-budget.json - unchanged, no issues
Previous Review Summaries (4 snapshots, latest commit 476e4f4)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 476e4f4)

Status: No Issues Found | Recommendation: Merge

Incremental review of 7e17e577..476e4f47. The branch merged the new base c596529a (v2 with the config-discovery seam, #15282) and then updated the U-E1-08 row of migration-tracking/plans/kilo-v2-migration-plan.md. That row now states a baseline of 27 files, 204 marked, 39 unmarked "after the config discovery seam (#15282)", which matches the current limits in script/upstream/shared-patches.json (27 / 204 / 39) and the regenerated migration-tracking/progress/README.md (27 shared patches, 20 seam / 7 patch). The prior SUGGESTION (stale 32/288/39 counts from v2.1.0) is resolved; the existing inline comment on that row is now outdated (line: null).

The PR's own diff against the new base (c596529a..HEAD) still contains only Kilo-owned paths, so "Shared patches: none changed by this PR" remains accurate. The handshake contract, plugin, KiloPlugins rule comment, startup-budget entry and stdio integration test were untouched by the merge: packages/plugin and packages/core/src/plugin did not change between the previous review and HEAD, so the Rpc.define, Schema.toStandardSchemaV1, ctx.app and ctx.rpc.register usage still matches the current base. The stdio test fixture is using-scoped, releases the reader lock in finally, ends stdin and awaits child.exited, and removes the temp root, so no resource or memory leak was introduced.

No new inline comments.

Files Reviewed (1 file in this step; 11 files overall)
  • migration-tracking/plans/kilo-v2-migration-plan.md - previous suggestion fixed, no new issues
  • migration-tracking/progress/README.md - regenerated counts consistent with the plan row
  • packages/schema/src/kilocode/handshake.ts - unchanged since last review, no issues
  • packages/kilo-plugin/src/handshake/index.ts - unchanged, no issues
  • packages/kilo-plugin/src/index.ts - unchanged, no issues
  • packages/kilo-plugin/test/index.test.ts - unchanged, no issues
  • packages/kilo-cli/test/handshake.test.ts - unchanged, no leak
  • packages/kilo-cli/startup-budget.json - unchanged, no issues
  • migration-tracking/progress/progress.json - regenerated, no issues
  • migration-tracking/progress/progress.svg - regenerated, no issues
  • migration-tracking/progress/history.svg - regenerated, no issues

Previous review (commit 7e17e57)

Status: No Issues Found | Recommendation: Merge

Incremental review of 7cb656d0..7e17e577. The only change since the previous review is the U-E1-08 row in migration-tracking/plans/kilo-v2-migration-plan.md: the shared-patch counts now read 32 files, 288 marked, 39 unmarked, matching script/upstream/shared-patches.json (limits: 32 / 288 / 39) and the regenerated migration-tracking/progress/README.md (32 shared patches). The added v1 result ("404 ... (401 with the opencode user)") matches the PR body and the negative-case evidence. The previous SUGGESTION is resolved.

The handshake contract, plugin, KiloPlugins rule comment, startup-budget entry and stdio integration test are unchanged in this step and stay consistent with the current base (0311551d, v2 after 2.1.0). The stdio fixture remains using-scoped with reader lock and child process released in finally, so no resource or memory leak.

No new inline comments.

Files Reviewed (1 file in this step; 11 files overall)
  • migration-tracking/plans/kilo-v2-migration-plan.md - previous suggestion fixed, no new issues

Previous review (commit 7cb656d)

Status: 1 Issue Found | Recommendation: Address before merge

Incremental review, base moved to 0311551d (v2 after 2.1.0). Since commit 12b1c32e only the generated progress history/README and the progress.json ratchet were regenerated; the handshake contract, plugin, startup-budget entry and integration test are unchanged and still match the current base (Rpc.define, Schema.toStandardSchemaV1, ctx.app, ctx.rpc.register, KiloApp version/channel). No memory or resource leak in the stdio test: the fixture is using-scoped, the reader lock and child process are released in finally. One documentation count became stale through the merge.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
migration-tracking/plans/kilo-v2-migration-plan.md 463 The U-E1-08 row still says shared patches are "31 files, 317 marked, 50 unmarked". At this HEAD the baseline in script/upstream/shared-patches.json is 32 files, 288 marked, 39 unmarked, and the regenerated migration-tracking/progress/README.md in this PR reports 32 shared patches. The PR body repeats the old numbers, so update both.
Files Reviewed (11 files)
  • packages/schema/src/kilocode/handshake.ts - no issues
  • packages/kilo-plugin/src/handshake/index.ts - no issues
  • packages/kilo-plugin/src/index.ts - no issues
  • packages/kilo-plugin/test/index.test.ts - no issues
  • packages/kilo-cli/test/handshake.test.ts - no issues
  • packages/kilo-cli/startup-budget.json - no issues
  • migration-tracking/plans/kilo-v2-migration-plan.md - 1 suggestion
  • migration-tracking/progress/README.md - no issues
  • migration-tracking/progress/progress.json - no issues
  • migration-tracking/progress/progress.svg - no issues
  • migration-tracking/progress/history.svg - no issues

Fix these issues in Kilo Cloud

Previous review (commit 12b1c32)

Status: No Issues Found | Recommendation: Merge

Kilo-owned placement only: the handshake contract lives in packages/schema/src/kilocode/, the plugin in packages/kilo-plugin/, and the integration test in packages/kilo-cli/test/. ctx.app is the App identity the host replaces with KiloApp (packages/kilo-cli/src/host.ts:58), the startup-budget key matches the plugin id, and the test verifies the RPC through the generated client against a real stdio server. Generated migration progress files were not reviewed line by line; CI owns their freshness.

Files Reviewed (11 files)
  • packages/schema/src/kilocode/handshake.ts
  • packages/kilo-plugin/src/handshake/index.ts
  • packages/kilo-plugin/src/index.ts
  • packages/kilo-plugin/test/index.test.ts
  • packages/kilo-cli/test/handshake.test.ts
  • packages/kilo-cli/startup-budget.json
  • migration-tracking/plans/kilo-v2-migration-plan.md
  • migration-tracking/progress/README.md
  • migration-tracking/progress/progress.json
  • migration-tracking/progress/progress.svg
  • migration-tracking/progress/history.svg

Reviewed by deepseek-flash-latest · Input: 36K · Output: 19.5K · Cached: 783K

Review guidance: REVIEW.md from base branch v2

Comment thread migration-tracking/plans/kilo-v2-migration-plan.md Outdated
…pc-routes

# Conflicts:
#	migration-tracking/plans/kilo-v2-migration-plan.md
#	migration-tracking/progress/README.md
#	migration-tracking/progress/history.svg
#	migration-tracking/progress/progress.json
#	migration-tracking/progress/progress.svg
@marius-kilocode
marius-kilocode merged commit 981607b into v2 Oct 21, 2026
33 of 34 checks passed
@marius-kilocode
marius-kilocode deleted the plugin-rpc-routes branch October 21, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants