Skip to content

feat: add plugin manager and official plugins - #119

Merged
wbxl2000 merged 4 commits into
mainfrom
qer/plugins-v1
May 27, 2026
Merged

feat: add plugin manager and official plugins#119
wbxl2000 merged 4 commits into
mainfrom
qer/plugins-v1

Conversation

@wbxl2000

Copy link
Copy Markdown
Collaborator

Summary

  • Add user/global plugin installation and an interactive /plugins manager for install, update, enable, disable, removal, marketplace browsing, and MCP server toggles.
  • Add plugin manifest loading for kimi.plugin.json and .kimi-plugin/plugin.json, plugin-provided skills/session start, and plugin-owned MCP servers that are enabled by default but can be disabled.
  • Add official kimi-datasource and curated Superpowers plugin bundles, marketplace/CDN build tooling, and bilingual documentation.

Verification

  • pnpm -C apps/kimi-code exec tsc -p tsconfig.json --noEmit --pretty false
  • pnpm -w exec vitest run apps/kimi-code/test/tui/components/dialogs/plugins-selector.test.ts apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts apps/kimi-code/test/utils/plugin-marketplace.test.ts apps/kimi-code/test/cli/options.test.ts apps/kimi-code/test/tui/printable-key-guard.test.ts
  • pnpm -w exec vitest run packages/agent-core/test/plugin/manifest.test.ts packages/agent-core/test/plugin/manager.test.ts packages/agent-core/test/plugin/archive.test.ts packages/agent-core/test/rpc/plugins-rpc.test.ts packages/agent-core/test/plugin/integration.test.ts
  • pnpm -w exec vitest run packages/agent-core/test/profile/default-agent-profiles.test.ts packages/agent-core/test/profile/agent-profile-loader.test.ts
  • pnpm -w exec vitest run packages/agent-core/test/agent/tool.test.ts packages/agent-core/test/agent/skill-tool-manager.test.ts
  • pnpm -C packages/agent-core exec tsc -p tsconfig.json --noEmit --pretty false
  • node --check apps/kimi-code/scripts/build-plugin-marketplace-cdn.mjs
  • pnpm run build:plugin-marketplace
  • git diff --check --cached

@changeset-bot

changeset-bot Bot commented May 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 460ac4e

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

This PR includes changesets to release 4 packages
Name Type
@moonshot-ai/agent-core Minor
@moonshot-ai/kimi-code-sdk Minor
@moonshot-ai/kimi-code Minor
@moonshot-ai/migration-legacy Patch

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 May 27, 2026

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

commit: 460ac4e

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@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: ba9d24bc92

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

Comment thread plugins/marketplace.json
"description": "Planning, TDD, debugging, and delivery workflows for coding agents.",
"homepage": "https://github.com/obra/superpowers",
"keywords": ["skills", "planning", "tdd", "debugging", "code-review"],
"source": "./curated/superpowers"

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 Remove missing plugin marketplace source

This local relative source is consumed by build-plugin-marketplace-cdn.mjs, which stats every local marketplace source and throws when it is absent. I checked the plugin tree and only plugins/official/kimi-datasource exists, so the root build:plugin-marketplace target will fail for the committed marketplace until this entry is either backed by a checked-in/available plugin archive or changed to a reachable remote source.

Useful? React with 👍 / 👎.

if (registry === undefined) return undefined;
const blocks: string[] = [];
for (const sessionStart of sessionStarts) {
const skill = registry.getSkill(sessionStart.skillName);

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 Resolve session-start skills by plugin identity

When a plugin's sessionStart.skill name is also defined by a project/user skill, this name-only lookup can inject the wrong skill: plugin skill roots are appended after project/user roots and the registry keeps the first skill for a normalized name. In that collision scenario, startup will render the non-plugin skill under the plugin's <plugin_session_start> block instead of the plugin-owned session-start content, so this should verify skill.plugin?.id === sessionStart.pluginId or otherwise resolve the specific plugin skill.

Useful? React with 👍 / 👎.

Comment on lines +78 to +79
.then(() => pipeline(stream, createWriteStream(destPath)))
.then(() => restoreFilePermissions(destPath, entry))

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 Bound plugin archive extraction size

Installing a plugin from a marketplace or direct zip URL currently streams every archive entry to disk without any compressed or uncompressed size limit, so a small zip bomb or simply an oversized plugin archive can exhaust the user's disk during /plugins install. Please enforce a maximum download/extracted byte budget before writing entries, or reject archives whose declared uncompressed sizes exceed the budget.

Useful? React with 👍 / 👎.

return undefined;
}

const found = await search(dir);

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 Prefer the archive root manifest first

For zip installs where the archive root itself contains kimi.plugin.json or .kimi-plugin/plugin.json, this starts by searching child directories and can return a nested example/subplugin manifest instead of the actual root plugin if one exists. Check hasManifest(dir) before descending so a valid top-level plugin archive is not accidentally installed as a nested plugin.

Useful? React with 👍 / 👎.

}

function pluginMcpRuntimeName(pluginId: string, serverName: string): string {
return `plugin-${pluginId}-${serverName}`;

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 Disambiguate plugin MCP runtime names

Because plugin ids may contain hyphens and MCP server names are only checked for non-empty strings, different plugin/server pairs can produce the same runtime key here, e.g. plugin a-b server c and plugin a server b-c both become plugin-a-b-c. When both are enabled, enabledMcpServers() writes them into the same object key and one server silently overwrites the other; use an escaping scheme or structured separator that cannot collide.

Useful? React with 👍 / 👎.

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@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: 34bca195fc

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

Comment thread plugins/marketplace.json
"description": "Planning, TDD, debugging, and delivery workflows for coding agents.",
"homepage": "https://github.com/obra/superpowers",
"keywords": ["skills", "planning", "tdd", "debugging", "code-review"],
"source": "./curated/superpowers"

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 Remove absent Superpowers source from marketplace

In a clean checkout this marketplace entry points at plugins/curated/superpowers, but that directory is not tracked in this commit (git ls-tree for plugins/curated/superpowers is empty). The new build:plugin-marketplace script materializes every local relative source and throws Marketplace source does not exist when the path is missing, so the CDN marketplace build cannot succeed unless a developer has an uncommitted local clone.

Useful? React with 👍 / 👎.

Comment on lines 225 to +226
for (const entry of subdirs) {
await walkSkillDir(path.join(dirPath, entry), source, false, depth + 1);
await walkSkillDir(path.join(dirPath, entry), root, false, depth + 1);

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 Stop descending after root plugin SKILL.md

When a plugin uses the root SKILL.md fallback, it is registered as a single skill bundle above, but this unconditional subdirectory walk still scans its child directories. For plugins that keep bundled references/examples under the root, any nested */SKILL.md will be exposed as an extra public plugin skill, unlike the existing directory-bundle rule that deliberately does not descend into a directory containing SKILL.md.

Useful? React with 👍 / 👎.

});
if (resolvedCommand === undefined) return undefined;
command = resolvedCommand;
} else if (command.includes('/') || path.isAbsolute(command)) {

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 Reject Windows backslash plugin commands

On Windows, a plugin MCP command such as ..\..\outside.exe or .\bin\server.exe contains no /, so it falls through this check as if it were a PATH command instead of being resolved and confined by resolvePluginPathField. Since plugin MCP servers are later launched with the plugin root as cwd, backslash relative paths can escape the managed plugin directory or bypass the intended inside-plugin validation.

Useful? React with 👍 / 👎.

Comment on lines +107 to +110
if (
matchesKey(data, Key.enter) ||
matchesKey(data, Key.space) ||
printableChar(data) === ' '

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Preserve spaces while searching choice pickers

For searchable ChoicePickerComponent instances, such as the provider selector in the /connect flow, pressing space now selects the highlighted item before SearchableList can append the space to the query. Users trying to search multi-word provider names can accidentally accept the current selection instead of continuing their search; space-to-select should be limited to non-searchable pickers or empty search state.

Useful? React with 👍 / 👎.

Comment on lines +157 to +164
if (
trimmed.startsWith('http://') ||
trimmed.startsWith('https://') ||
trimmed.startsWith('~/') ||
trimmed === '~' ||
isAbsolute(trimmed)
) {
return trimmed;

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 Resolve root-relative remote marketplace sources

For a remote marketplace, an entry like "source": "/plugins/demo.zip" is a normal origin-relative URL, but this branch returns it as a local absolute filesystem path before the new URL(..., location.resolved) fallback runs. Installing that marketplace entry then calls the plugin installer with /plugins/demo.zip and fails with a local-path error instead of downloading from the marketplace host.

Useful? React with 👍 / 👎.

return {
...config,
command: process.execPath,
args: [KIMI_NODE_FALLBACK_SUBCOMMAND, ...(config.args ?? [])],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Preserve Node flags in native plugin fallback

In native builds, any plugin MCP server declared as command: "node" is rewritten to the hidden __plugin_run_node command, but the first original Node argument becomes the required entry path. A valid server command such as node --enable-source-maps ./server.mjs therefore tries to realpath("--enable-source-maps") and fails only in native distributions, even though it works when node is available on PATH.

Useful? React with 👍 / 👎.

Comment thread apps/kimi-code/src/constant/app.ts Outdated
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
Signed-off-by: qer <wbxl2000@outlook.com>
@wbxl2000
wbxl2000 merged commit ebf6e81 into main May 27, 2026
6 checks passed
@wbxl2000
wbxl2000 deleted the qer/plugins-v1 branch May 27, 2026 14:47
@github-actions github-actions Bot mentioned this pull request May 27, 2026
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