Skip to content

feat(agent-core-v2): add built-in capabilities (kimi-cu, kimi-webbridge) with REST routes - #2407

Open
wbxl2000 wants to merge 15 commits into
mainfrom
feat/built-in-capabilities
Open

feat(agent-core-v2): add built-in capabilities (kimi-cu, kimi-webbridge) with REST routes#2407
wbxl2000 wants to merge 15 commits into
mainfrom
feat/built-in-capabilities

Conversation

@wbxl2000

@wbxl2000 wbxl2000 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a capability domain to agent-core-v2: a closed registry of built-in product capabilities that own layered readiness detection and idempotent install orchestration, exposed by kap-server as REST routes — and wired into the plugin marketplace so shelf installs are complete installs.

Capability domain (agent-core-v2/src/app/capability/)

Two hardcoded entries (install sources are fixed official CDN URLs, never client-supplied):

  • kimi-cu (macOS): official plugin (stdio MCP wrapper + skill) → KimiCU.app download + ditto into /Applications (osascript elevation fallback) → launchd service registration → TCC permission state machine (machine-readable via bare request-permissions).
  • kimi-webbridge (macOS/Linux/Windows): platform-matrix daemon download → start-if-down (never stop/restart/uninstall — Kimi Work desktop coexistence contract) → plugin wiring via IPluginService → removes stale user-source skill copies (user priority 20 shadows plugin priority 5).

Installs are idempotent and re-entrant; progress lives in memory and is client-polled (no WS events in v1). installPlugin's upsert semantics make reinstall = upgrade.

kap-server routes

  • GET /api/v1/capabilities · GET /api/v1/capabilities/{id} · POST /api/v1/capabilities/{id}:install
  • New wire codes: 40418, 40922, 40923

Marketplace

  • kimi-webbridge plugin (official) — the real browser-control usage skill, version-aligned with the bundled upstream skill (v1.11.3). It takes over the kimi-webbridge id, replacing the WebBridge guide plugin (v3.0.4, install/remove guide skills) — the intended end state. Packaged by the existing CDN build. The plugins/cdn artifacts need a republish for it to appear in production.
  • kimi-cu marketplace entry — sourced directly from the CU team's CDN zip (no repackaging), making the shelf row installable.

Shelf-install hook

CapabilityService subscribes to IPluginService.onDidReload: when a capability's wiring step flips to ok through any install path (marketplace shelf, TUI, CLI), it auto-completes the missing binary layers (KimiCU.app + launchd service, or the WebBridge daemon). Triggers only on the false→true edge, so completed installs with still-missing manual steps (TCC permissions) never retrigger heavy downloads on later reloads.

Tests

  • 24 domain unit tests (entries with faked host effects; orchestration; hook edge cases) + 5 route e2e tests
  • Full suites green: agent-core-v2, kap-server, lint:domain, oxlint, typecheck; API surface snapshot updated (3 new routes)

Notes

  • Real-machine e2e verified on the desktop host: detects → install → ready for both entries.
  • The TUI's hardcoded WebBridge promo row dedupes by id and will shadow the real marketplace entry until removed/adjusted (follow-up).
  • Machines with only the guide plugin (v3.0.4) report the skill layer as satisfied until they reinstall/upgrade onto this plugin — accepted transition state of the intended replacement.

…ge) with REST routes

Add a capability domain holding a closed registry of built-in product
capabilities. Each entry owns layered readiness detection and idempotent
install orchestration: binary runtimes from fixed official CDN URLs
(KimiCU.app + launchd service + TCC permission state; the WebBridge
daemon with start-if-down semantics for Kimi Work coexistence) plus
agent wiring through the plugin service. The WebBridge wiring un-shadows
stale user-source skill copies (user priority beats plugin priority).

kap-server exposes the domain as GET /api/v1/capabilities,
GET /api/v1/capabilities/{id}, and POST /api/v1/capabilities/{id}:install
with client-polled progress and new wire codes 40418 / 40922 / 40923.

The plugin marketplace gains an official kimi-webbridge entry
(browser-control skills) packaged by the existing CDN build.
@changeset-bot

changeset-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0635e99

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Minor

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@4bdb2f6
npx https://pkg.pr.new/@moonshot-ai/kimi-code@4bdb2f6

commit: 4bdb2f6

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db8b9da550

ℹ️ 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".

await ctx.plugins.installPlugin({ source: PLUGIN_ZIP_URL });
// Un-shadow the plugin copy: the user-source skill (priority 20) wins
// over the plugin source (priority 5) on name collisions.
await rm(userSourceSkillDir, { recursive: true, force: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve existing user WebBridge skills

When the user has a hand-authored or modified ~/.kimi-code/skills/kimi-webbridge skill, this unconditional recursive removal deletes that user-owned directory during capability install. The priority conflict is real, but the installer needs to verify this is the known legacy official copy or back it up before removing it; otherwise installing WebBridge can erase user data.

Useful? React with 👍 / 👎.

Comment on lines +53 to +56
platform: process.platform,
arch: process.arch,
kimiHomeDir: bootstrap.homeDir,
userHomeDir: homedir(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the bootstrap host snapshot

When a test or embedding host seeds IBootstrapService with an overridden platform, arch, or osHomeDir, this constructor ignores that snapshot and reads process globals instead. In those contexts capability support checks and WebBridge install/detect run against the real process home/platform rather than the configured host, so sandboxed servers can write under the user's actual ~/.kimi-webbridge or report the wrong platform state; use bootstrap.platform, bootstrap.arch, and bootstrap.osHomeDir here.

Useful? React with 👍 / 👎.

ctx.fetchImpl,
);
await mkdir(binDir, { recursive: true });
await rename(staging, binPath).catch(async (error: NodeJS.ErrnoException) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overwriting a running Windows daemon

On Windows, when WebBridge was installed once and the daemon is still running from ~\.kimi-webbridge\bin\kimi-webbridge.exe, this rename tries to replace the running executable before checking /status. Windows keeps running executables locked, so an idempotent reinstall/upgrade fails with EPERM and never reaches the start-if-down/plugin refresh path; check daemon status before replacing the binary or stage a versioned replacement for a user-driven restart.

Useful? React with 👍 / 👎.

wbxl2000 added 14 commits July 30, 2026 17:15
…dge-skill

An official kimi-webbridge guide plugin (install/remove setup skills,
v3.0.4) already exists at the marketplace path the capability installer
pointed at — a different artifact owned by another release line. Give
the browser-control usage-skill plugin its own id/path instead of
colliding with (or overwriting) the guide plugin. The capability entry's
detect/install now tracks kimi-webbridge-skill; a machine with only the
guide plugin correctly reports the skill layer as missing.
…ayers

Two changes to make the plugin marketplace a first-class install path:

- Marketplace gains kimi-cu (sourced from the CU team's CDN zip — no
  repackaging) and the kimi-webbridge usage-skill plugin now claims the
  kimi-webbridge id at v4.0.0, deliberately superseding the WebBridge
  guide plugin (v3.0.4, install/remove guide skills): guide users get a
  version upgrade onto the real usage skill.
- The capability service subscribes to IPluginService.onDidReload: when
  a capability's wiring step flips to ok through ANY install path
  (shelf, TUI, CLI), it auto-completes the missing binary layers
  (KimiCU.app + service, or the WebBridge daemon). Triggers only on the
  false→true edge so completed installs with still-missing manual steps
  (TCC permissions) never retrigger heavy downloads on later reloads.
…tream skill

The plugin version tracks the bundled official usage skill (1.11.3) so
version drift against the WebBridge release line stays visible, instead
of minting an independent 4.0.0.
…on as the product version

The on-disk ~/.kimi-webbridge/bin/kimi-webbridge.version file tracks the
installer's own lineage (3.1.x, bumps on every install/upgrade run),
not the product version (v1.11.3 — daemon, extension, and skills all
share it). A downed daemon would have shown the misleading installer
number; report no version instead (live /status remains the source of
truth).
Marketplace versions are optional by schema: rows display the version
detected from the installed plugin's manifest, and update prompts only
fire on a valid semver latest > local comparison. A hand-maintained
number would drift just like the guide plugin's did. The locally built
kimi-webbridge entry keeps its manifest-stamped version (1.11.3).
…plicit reload

installPlugin / setPluginEnabled / removePlugin changed the catalog
silently — consumers listening to onDidReload (session skill-catalog
convergence, the capability shelf-install hook) only converged on an
explicit reloadPlugins(). Fire the same summary-shaped event on every
mutation (added:[id] / [] / removed:[id]) so every install path
converges. This also unbreaks the shelf-install hook on real hosts:
its unit tests passed against a fake emitter that fired on installs,
which the real service never did.
Expose the App-scope plugin service over the wire so non-CLI hosts
(desktop, web) can manage plugins end to end:

- GET  /api/v1/plugins/marketplace — catalog (pluginMarketplaceUrl
  server option / KIMI_CODE_PLUGIN_MARKETPLACE_URL env / production
  default) merged on demand with live install state; updateAvailable
  only on strict semver catalog > installed (no semver dependency)
- GET  /api/v1/plugins, POST /api/v1/plugins {source}
- POST /api/v1/plugins/{id}:{enable,disable,remove}
- New wire code 40419 plugin.not_found

Mutations flow through IPluginService, so they serialize with other
install paths and fire onDidReload (session skill catalogs and the
capability shelf-install hook converge).
CapabilityEntry.install now resolves an optional note exposed through
CapabilityInstallProgress.note (wire-visible). The webbridge entry
returns 'user-skill-migrated' when it replaces a pre-existing
user-source skill (from the official installer) with the plugin-managed
copy — clients can localize the migration instead of the skill silently
disappearing from the user's directory.
…ed promo

The hardcoded Web Bridge row was built when WebBridge had no plugin
package — it pinned above the Official tab and shadowed any catalog
entry with the same id (open-in-browser only). Now that the marketplace
carries the real kimi-webbridge plugin, flip the precedence: the catalog
entry renders and installs normally, and the pinned promo becomes a
loading/error/legacy-catalog fallback only. Footer counts keep their old
semantics (catalog-only; the promo row is never counted).
…action

Both badges shared a near-identical green-ish treatment in the same
column, making a quiet fact look like a clickable action. States now
recede (installed → textDim) while actions stay loud (install →
primary, update → warning).
… home

Multiple hosts share one KIMI_CODE_HOME (CLI, desktop, other agents), but
each PluginService kept a private in-memory snapshot: a plugin installed
or removed in one process stayed invisible to every other live process
until its next restart — new sessions there kept offering stale plugin
skills/MCP, and the capability shelf hook never saw peer installs.

Watch <home>/plugins for installed.json changes and reloadPlugins
(debounced, echo-suppressed around our own mutations) so all consumers
converge in well under a second: session skill catalogs, plugin MCP
mounts, and the capability shelf-install hook alike.
kimi-code resolves user-scope skills from two roots (~/.kimi-code/skills
and ~/.agents/skills), both at priority 20 — a stale copy in either
shadows the plugin-managed wiring (priority 5), and also keeps the
capability working after the plugin is removed, which reads as
'uninstall did nothing'. Migrate copies in both dirs during install;
other runtimes' dirs (~/.claude, ~/.codex) remain untouched.
Installing a capability plugin (kimi-cu, kimi-webbridge) from the
/plugins shelf kicked off a silent background binary install — the row
flipped to installed while megabytes of runtime downloaded invisibly.
Route capability entries through the capability surface instead: the
panel's inline installing line now mirrors live progress (step +
percent) until the install settles, and the transcript reports
ready / failure-with-retry / still-running accordingly. Capability
removal prints an explicit note that runtime binaries are deliberately
left untouched (the capability keeps working), since that read as
'uninstall did nothing'.

Plumbs the capability service through klient's global facade
('capabilityService' decorator resolves in-process) and the node-sdk
v2 client; Session exposes it with a structural feature-detect so v1
engines fail clearly.
…client

Only the capability-aware clients auto-install the KimiCU.app runtime;
older builds still get wiring-only (the wrapper's error message then
points at the official setup script). Don't overpromise in the catalog
text every version reads.
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.

1 participant