feat(cli): add built-in Computer Use and WebBridge capabilities - #2407
Conversation
…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 detectedLatest commit: c567d9b 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: 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".
| platform: process.platform, | ||
| arch: process.arch, | ||
| kimiHomeDir: bootstrap.homeDir, | ||
| userHomeDir: homedir(), |
There was a problem hiding this comment.
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) => { |
There was a problem hiding this comment.
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 👍 / 👎.
…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.
…ugin copies The kimi-cu / kimi-webbridge wiring plugins ship inside the client release instead of the marketplace catalog, binding their visibility to the client version. Capability installs now resolve the bundled copy (env override, then npm-layout and source-checkout probes from the module) and install it as a local path, replacing the two CDN zip URLs. A missing bundle fails the wiring step with a clear reinstall-or-upgrade message.
Vendor the official kimi-cu plugin (v0.5.4, from the CU team's plugin zip) next to kimi-webbridge under plugins/official, copy both into apps/kimi-code/bundled-plugins at build time, and ship them in the npm package (files) and the native SEA blob (a new bundled-plugins asset set extracted into the native cache at startup, published to the engine via KIMI_CODE_BUNDLED_PLUGINS_DIR). Desktop points the same variable at its extraResources copy. The .gitignore build-output entries are anchored so sources under src/native and test/native stop being silently ignored.
…tries Both capabilities now distribute with the client (bundled wiring), so the catalog drops back to kimi-datasource / superpowers / vercel-plugin. Older clients never see the entries; current clients install from the Built-in section. This also reverts the marketplace blurb commit 0635e99.
The Official tab now opens with a Built-in section fed by the engine's capability registry (kimi-cu / kimi-webbridge): per-row install state (install / finish setup / ready), Enter runs the full capability install with live progress, and unsupported rows hide (kimi-cu off macOS). The WebBridge promo fallback only remains for v1 engines — on v2 the real built-in entry wins. Rows double as the reinstall path: a client upgrade ships newer wiring, and installing again upserts from the new bundle.
…ities # Conflicts: # packages/agent-core-v2/scripts/check-domain-layers.mjs # packages/agent-core-v2/src/index.ts
|
❌ Nix build failed |
The native SEA blob now embeds the bundled-plugins asset set, so the nix derivation needs the plugins tree in its src fileset and the staging step alongside copy-web-assets before build:native:sea.
Built-in visibility is simpler to get by injecting the two capability entries into the marketplace catalog at load time; the wiring plugins themselves keep installing from their fixed official CDN zips. Removes the vendored kimi-cu plugin, the bundled-plugins npm/SEA packaging and flake staging, the engine bundle resolver, and the plugins panel's Built-in section. Keeps the /agents/ and /native/ gitignore anchors so sources under src/native and test/native are not silently ignored.
…e catalog The kimi-cu / kimi-webbridge entries are appended by the client at catalog load time instead of being served by the remote marketplace.json, binding their visibility to the client version (older clients never see them). No version is pinned — reinstalling upserts the wiring — and ids the catalog already carries always win. In a source checkout the webbridge entry installs the repo's own plugin copy; packaged builds use the official CDN zip. This reverts the docs paragraph about the Built-in section, which the simpler approach makes unnecessary.
…tests The client-injected capability entries suppress the WebBridge promo and append after the catalog rows, so Kimi Datasource now leads the Official tab — the extra down-key landed on kimi-cu instead.
…tplace entries The kimi-cu / kimi-webbridge entries are injected into the marketplace catalog by the client (v2 engine, default catalog only) instead of being served remotely, binding their visibility to the client version; injected rows mask same-id catalog rows, so what these ids mean stays decided by the client release — a future official listing only reaches older clients, whose fix is to upgrade. The /plugins panel shows capability readiness on the rows (setup incomplete / installing…), platform-gates kimi-cu to macOS, and Enter finishes the runtime setup with live progress; v1 keeps the plain plugin install path and the WebBridge promo fallback. Capability and plugin calls move from the ad-hoc REST routes onto the typed klient contract (capabilityService next to pluginService), so the public REST surface returns to its pre-feature shape. Detection is presence-only — version pins removed: the current version is always read live (Info.plist, daemon status, install records), installs are detect-first and idempotent so an interrupted setup can be retried, and reinstalling pulls the latest managed artifacts (the passive upgrade path).
The domain's comment convention allows only the top-of-file block: responsibility and scope context for the recent hardening (detect-first idempotent install, executability gates, probe-failure degradation, best-effort cleanup, download watchdog, per-entry detection isolation) now lives in the module headers, and inline narration beside statements and members is removed.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 863c050c5b
ℹ️ 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".
| panel.setInstalling(truncateForStatus(label)); | ||
| host.state.ui.requestRender(); | ||
| try { | ||
| await host.requireSession().installCapability(entry.id); |
There was a problem hiding this comment.
Follow existing capability installs instead of restarting them
When /plugins is opened while a capability setup is already running, the row renders as installing…, but pressing Enter still calls installCapability() again. The service rejects duplicate starts with capability.install_in_progress, so the UI clears the panel and shows a failure even though the original install is healthy; in this state it should skip the start call and just poll getCapability() for the existing progress.
Useful? React with 👍 / 👎.
…ing it Opening /plugins while a capability setup is already running showed the installing… row, but Enter called installCapability again and the service's duplicate-start rejection (40922) surfaced as a fake failure. The panel now checks the live status first and, when an install is already running, skips the start call and just polls for the existing progress.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: efee8afde2
ℹ️ 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".
|
|
||
| async function renameAcrossDevicesFallback(from: string, to: string): Promise<void> { | ||
| const { copyFile } = await import('node:fs/promises'); | ||
| await copyFile(from, to); |
There was a problem hiding this comment.
Stage cross-device WebBridge replacements off the live binary
On POSIX hosts where os.tmpdir() and ~/.kimi-webbridge are on different filesystems, reinstalling a ready WebBridge while the daemon is still running takes this EXDEV fallback. copyFile(from, binPath) opens the running executable for write instead of atomically replacing it, which fails with ETXTBSY on Linux (or otherwise targets the live inode) and aborts an otherwise idempotent upgrade; copy to a sibling temp file under binDir and then rename over binPath on the same filesystem.
Useful? React with 👍 / 👎.
| return (this.opts.capabilities ?? []) | ||
| .filter((capability) => capability.supported) | ||
| .map(capabilityMarketplaceEntry); |
There was a problem hiding this comment.
Gate built-in rows for overridden marketplaces
Fresh evidence beyond the earlier loader-side issue is that this component still synthesizes capability rows from opts.capabilities whenever the catalog is loading or in an error state. When /plugins marketplace <url> is used or KIMI_CODE_PLUGIN_MARKETPLACE_URL is set, the loader now avoids injecting built-ins after the catalog loads, but before/after that load these fallback rows still show KimiCU/WebBridge and Enter routes to capability setup, so an explicit replacement marketplace cannot fully replace the Official tab; gate these rows on the same default-catalog condition or pass an empty capability list for overridden catalogs.
Useful? React with 👍 / 👎.
The EXDEV daemon-binary fallback now stages on the target filesystem and atomically renames over the destination instead of opening a possibly-running binary for write (ETXTBSY on Linux). And the panel's fallback capability rows (catalog loading/error) now follow the same default-catalog condition as the loader injection, so an explicitly overridden marketplace fully replaces the Official tab.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd8633a09e
ℹ️ 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".
|
|
||
| /** Client-injected v2 entries install their runtime and plugin together. */ | ||
| function isCapabilityEntry(host: SlashCommandHost, entry: PluginMarketplaceEntry): boolean { | ||
| return host.engineV2 && entry.source === `capability:${entry.id}`; |
There was a problem hiding this comment.
Reserve capability markers for injected rows
When an explicit remote marketplace contains a same-id row with source: "capability:kimi-webbridge" (or kimi-cu), the marketplace parser preserves that non-HTTP scheme and this check treats the row as the client-injected built-in even though built-ins were intentionally disabled for custom catalogs. Pressing Enter then bypasses the normal third-party trust/install path and runs installCapability() for the official runtime instead of installing the selected marketplace plugin; track injected rows with an internal flag or gate this marker on the default-catalog injection path.
Useful? React with 👍 / 👎.
The capability:<id> source string was the trust signal for routing rows into capability installs, but any catalog can write that string — a custom marketplace could smuggle a row past the third-party trust path into an official runtime install. Injected rows now carry an internal builtIn flag that the field-by-field catalog parser never produces; rendering and install routing key on the flag, and the source string is purely diagnostic.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 289289b803
ℹ️ 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 installed = await ctx.plugins.listPlugins(); | ||
| const plugin = installed.find((p) => p.id === PLUGIN_ID); | ||
| const pluginOk = plugin !== undefined && plugin.enabled && plugin.state === 'ok'; |
There was a problem hiding this comment.
Re-enable KimiCU MCP servers during setup
When a user has previously disabled the KimiCU plugin's MCP server via /plugins mcp disable, this still marks the plugin layer as OK because it only checks the plugin record's enabled/state flags. PluginManager.install() preserves per-server capability state on reinstall, and this setup path only calls setPluginEnabled, so the capability can report ready while the stdio MCP wrapper remains disabled and new sessions won't expose the Computer Use tool; include the managed MCP server enablement in readiness and repair it during install.
Useful? React with 👍 / 👎.
…ness A user who disabled the kimi-cu stdio MCP server (/plugins mcp disable) got a ready capability with no Computer Use tools in new sessions: the plugin step only checked the plugin toggle, and installPlugin's upsert preserves per-server state. Readiness now requires every declared MCP server enabled (reporting e.g. mcp 0/1 enabled), and setup re-enables disabled servers alongside the plugin toggle.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc5f9411b0
ℹ️ 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".
| timeout: commandTimeoutMs, | ||
| }); | ||
| if (direct.code === 0) return; | ||
| const script = `/usr/bin/ditto ${appleScriptQuote(unzippedApp)} ${appleScriptQuote(appPath)}`; |
There was a problem hiding this comment.
Shell-quote paths in the elevated KimiCU copy
When the direct /Applications copy falls back to the elevated AppleScript path, unzippedApp is under os.tmpdir() and can therefore include spaces or shell metacharacters from TMPDIR. appleScriptQuote() only escapes the AppleScript string delimiters, not the /bin/sh command arguments passed to do shell script, so a path like /tmp/kimi cu/... breaks the install and a crafted temp path can inject commands into the administrator-privileged script. Build the elevated command with real shell quoting, e.g. AppleScript's quoted form of, before requesting privileges.
Useful? React with 👍 / 👎.
The elevated fallback escaped paths only for the AppleScript string delimiters, not for the /bin/sh command line inside do shell script: a TMPDIR with spaces broke the install, and shell metacharacters in the temp path could inject commands into an administrator-privileged script. Paths are now POSIX single-quoted first, then the assembled command is AppleScript-escaped.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3bcdcbb90a
ℹ️ 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 stopOldProcesses(); | ||
| const unzipDir = path.join(workDir, 'unzipped'); | ||
| const unzipped = await runCommand(ctx.hostProcess, 'ditto', ['-x', '-k', zipPath, unzipDir], { |
There was a problem hiding this comment.
Validate KimiCU archive before stopping the service
When a reinstall starts from a working KimiCU and the downloaded zip is corrupt or a captive-portal/edge response, this stops/uninstalls the old service before ditto -x -k has proved the archive can be staged. If unzip then fails, the existing app bundle is still on disk but its background service has been torn down, so a failed update breaks a previously ready setup until the user retries; unzip into the temp dir before calling stopOldProcesses().
Useful? React with 👍 / 👎.
| const version = await readAppBundleVersion(infoPlist); | ||
| const appExists = await exists(appBin); | ||
| const appUsable = appExists && (await executable(appBin)); | ||
| steps.push({ | ||
| id: 'app', | ||
| state: appUsable ? 'ok' : 'missing', | ||
| detail: appExists && !appUsable ? 'not executable' : version, |
There was a problem hiding this comment.
Treat partial KimiCU bundles as missing
Fresh evidence is that the new validity check still treats any executable Contents/MacOS/kimi-cu as a good app layer even when a failed copy left the rest of KimiCU.app incomplete, such as a missing Info.plist or resources. In that state installApp stays false on retries and setup only reruns kimi-cu install, which can keep failing against the corrupt bundle; require bundle metadata/integrity before marking the app step ok.
Useful? React with 👍 / 👎.
The reinstall stopped and uninstalled the old service before the downloaded archive was unpacked: a corrupt or captive-portal zip then tore down a previously ready setup. The archive is now staged and unpacked first, and the app step additionally requires the bundle's Info.plist, so a partially copied bundle reads as missing and gets re-copied instead of failing registration against a corrupt bundle.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ebed5c4db3
ℹ️ 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 idleTimeoutMs = options.idleTimeoutMs ?? DOWNLOAD_IDLE_TIMEOUT_MS; | ||
| let resp; | ||
| try { | ||
| resp = await fetchImpl(url, { signal: AbortSignal.timeout(idleTimeoutMs) }); |
There was a problem hiding this comment.
Separate header timeout from body idle timeout
When a CDN response starts promptly but the KimiCU app zip or WebBridge binary takes more than 30s to stream over a slow connection, this AbortSignal.timeout(idleTimeoutMs) remains attached to the response body and aborts the pipeline after 30s total even if chunks continue to arrive. That defeats the later idle watchdog, which is reset per chunk, so slow-but-healthy downloads fail; use a header-phase AbortController that is cleared once headers arrive, or a separate longer total deadline.
Useful? React with 👍 / 👎.
The 30s AbortSignal stayed attached for the whole request, so a slow-but-healthy download of a large archive was aborted at 30s total even while chunks kept arriving — exactly what the per-chunk idle watchdog was meant to allow. The header phase now uses an AbortController cleared once headers arrive; the body remains governed by the inactivity watchdog alone.
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
…ities # Conflicts: # apps/kimi-code/src/tui/commands/dispatch.ts # apps/kimi-code/src/tui/commands/plugins.ts # apps/kimi-code/src/tui/kimi-tui.ts
…d fakes The lazy-session refactor routes session-less plugin calls through host.harness; the fake host now mirrors that shape.
Related Issue
No tracking issue — the problem is explained below.
Problem
Kimi Computer Use and Kimi WebBridge are built-in product capabilities, but setting either one up required several independent steps: installing a plugin, installing or starting a local runtime, and completing manual permissions or browser-extension setup. The v2 CLI had no single readiness view or retryable install action.
Their visibility must also be bound to the client release rather than a remotely changing catalog: v1 and older clients should not gain these capability entries without upgrading.
What changed
Built-in capability domain
Added a closed v2 registry for
kimi-cuandkimi-webbridgewith layered readiness detection, idempotent installation, and client-polled progress.kimi-cuis supported on macOS and manages its official plugin,KimiCU.app, background service, and Accessibility / Screen Recording permission state.kimi-webbridgesupports the available macOS, Linux, and Windows x64 assets and manages its daemon binary, start-if-down behavior, official plugin, optional browser extension state, and warnings for user skills that shadow the managed plugin.Client-injected Official entries
The v2 CLI injects the two entries into the default Official marketplace view. They are marked with an internal
capability:<id>source so only the injected rows use capability installation; a custom marketplace row with the same id still follows the normal plugin trust and install path.The injected rows replace same-id remote rows, remain visible when the remote catalog is unavailable, carry no pinned version, and are not injected for v1 or explicit custom marketplaces.
kimi-cuis hidden on unsupported platforms.The WebBridge plugin stays out of the remote catalog but is packaged from
plugins/official/kimi-webbridgeinto the CDN artifact set. Capability installation downloads both official plugins from their fixed CDN URLs; source-checkout paths are not used.TUI and typed service surface
/pluginsshows readiness, missing manual steps, install progress, retry results, and the existing runtime-retention note on plugin removal.Tests
@moonshot-ai/kimi-codeand@moonshot-ai/agent-core-v2typechecks passed.official/kimi-webbridge.zip; its manifest is the newkimi-webbridgev1.11.3 plugin rather than the legacy v3.0.4 guide.Checklist
gen-changesets, and added the required changeset.gen-docs, or this PR needs no separate docs update.