* feat(agent-core-v2): let plugins contribute system prompt instructions via the manifest systemPrompt field
* feat(agent-core-v2): add systemPromptPath to load plugin system prompt from a file
* docs: explain plugin system prompt templates
* fix(agent-core-v2): refresh plugin system prompts after changes
* fix(agent-core-v2): freeze restored profile bindings and converge plugin contributions at session scope
- restore no longer re-renders or re-persists prompts: a resumed agent
keeps its replayed profile binding (prompt and tool set) as persisted
- a new Session-level convergence point reloads plugin skills into the
session skill catalog before fanning out to every live agent prompt,
and every catalog-kind plugin mutation awaits the whole pipeline;
MCP-only toggles carry a distinct change kind and skip it
- live refreshes after a restart re-resolve the bound profile by name
and rebind the full slice (prompt, disallowed tools, active tools)
atomically, warning and keeping the persisted state when the profile
is gone; renders reuse the first-render timestamp and unchanged
prompts are not re-persisted, so convergence never churns the wire
- cap plugin system-prompt contributions (32 KB per field/file, 64 KB
aggregate per prompt build) with manifest diagnostics and warnings
- bump the changeset to minor: this is a new user-facing capability
* fix(agent-core-v2): register the new session domain and dedupe the missing-profile warning
- add sessionPluginContribution to the domain-layer registry so
lint:domain stays green
- emit system-prompt-refresh-profile-missing once per profile name,
matching the service's other deduped warnings
- document the convergence timeout escape hatch and the klient
exclusion of enabledSystemPrompts
* fix(agent-core-v2): dedupe the plugin budget warning and surface section read failures
- emit plugin-sections-oversized once per skipped-plugin signature
- let enabledSystemPrompts failures propagate to the refresh catch
(keeps the current prompt and warns) instead of silently rendering
and persisting a prompt without plugin instructions
- cover the convergence timeout cut-off with a fake-timers test
- clarify that the first-render timestamp anchors per process
* fix(agent-core-v2): serialize session convergence and restore onDidReload timing
- run at most one convergence per session and bound each change's wait
by the timeout, so a fan-out emitter never interleaves deliveries
after a timed-out convergence
- fire onDidReload as soon as the reload commits again, keeping hook
reloads independent of prompt convergence
- sign the plugin budget warning with an unambiguous key
* docs(agent-core-v2): align convergence wording with the serialized semantics
- the timeout retry promise only holds once stalled work clears
- note the per-session serial delivery cost model on the plugin change
contract and the dual-queue invariant on the service
* fix(agent-core-v2): keep empty plugin sections byte-neutral in the prompt template
- place ${plugin_sections} on the same template line as
${skills_section} so prompts without either block render exactly as
before this feature
- note on the change contract that waitUntil work must not call back
into plugin mutations, and spell out the per-session convergence
order in the user docs
* fix(agent-core-v2): pin a fork's profile so refresh triggers never rebind it
- applyBindingSnapshot left the fork with no pinned profile, which
routed in-process forks into the post-restart catalog rebind and
could reset an inherited tool set; forks now inherit the source
agent's pinned profile object
- pin the first-render timestamp reuse with a ${now}-embedding test
and document the anchored ${now} semantics
- tighten the plugin docs budget and resume-refresh wording
* fix(agent-core-v2): join in-flight convergence during agent bootstrap
- an agent created while a plugin convergence is in flight now waits
for it, and a restored agent refreshes once after it, so a plugin
mutation never straddles an agent's bootstrap
- warn on a non-string systemPrompt field and strip a UTF-8 BOM from
systemPromptPath files before trimming
- correct the consumption-surface wording (every CLI surface on the
experimental flag, not just kimi -p), the per-session queueing note,
and the single-plugin combined budget clause
* fix(agent-core-v2): bound the bootstrap convergence join by the timeout
A permanently wedged convergence kept convergeTail pending forever,
and the unconditional settled() wait in bindBootstrap would have
blocked every later agent creation in that session; the join now
races the shared convergence timeout and continues (a restored agent
still refreshes once, which never touches the tail), and the timeout
constant moves to the contract for reuse
* fix(agent-core-v2): close the convergence race against in-progress restores
- a convergence fan-out could land while an agent's wire log is still
replaying, dispatching a replay-visible config record whose effect
the rest of the replay then overwrites; refreshSystemPrompt now
skips while the wire restore is in progress
- convergence completion is tracked by a generation counter; bootstrap
compares it (after a bounded join) and refreshes a restored agent
exactly once when a round completed after its creation began,
replacing the wasConverging flag that could miss both windows
* fix(agent-core-v2): bound each convergence so a wedged participant cannot stop the pipeline
- the fan-out now races the convergence timeout, so convergeTail always
settles: a permanently hung refresh delays its round (blocked entries
drain oldest-first on later changes) instead of killing the session's
convergence for good
- warn when agent bootstrap stops waiting on a stalled convergence
- diagnose a blank systemPromptPath and pin the plugin-root escape
guard with traversal, absolute-path, and symlink tests
* fix(agent-core-v2): bound the skill reload, preserve user-tool overlays, roll the prompt clock daily
- the convergence's skill-reload segment now races the same timeout as
the fan-out, so no segment of the pipeline can wedge a session for
good; it continues with the previous catalog and retries next change
- a cold rebind that resets the tool set replays session-added user
tools onto the new base instead of dropping them for the rest of the
process
- the rendered timestamp re-anchors when the UTC date rolls over, so
long-lived processes keep a fresh clock while steady-state renders
stay byte-stable within a day
- the plugin budget warning dedupes per plugin id, and the docs note
that systemPromptPath content is frozen until the next reload
* feat(agent-core-v2): converge cold plugin changes on resume through a drift-free gate
- restore replays the persisted binding untouched, then bootstrap
refreshes only when drift-free inputs changed while the session was
cold: the catalog profile's tool set/denylist, or the plugin-sections
baseline persisted alongside the prompt on the existing bind/update
payloads; directory-listing and date drift wait for live triggers,
so quiet resumes append no replay-visible records
- the rendered timestamp is day-precision (UTC date at 00:00,
re-anchored on rollover), keeping steady-state renders byte-stable
across resumes and sessions on the same day
- consolidate both timeout helpers onto a shared raceOutcome, and drop
the generation counter the gate supersedes
- align the plugin-sections precedence prose with the AGENTS.md
disclaimer (no self-granted authority, system instructions win on
conflict)
* fix(agent-core-v2): bound the restored-prompt gate and land the sections baseline
- the gate's plugin-sections read now races the convergence timeout, so
agent creation never blocks behind an unrelated plugin mutation
- refreshes serialize per agent through a tail, so overlapping triggers
cannot write prompts out of order
- when plugin sections change but a plugin-free custom prompt does not,
the new baseline lands as a sections-only update instead of making
every later resume re-render in vain
- align the system prompt's Date and Time paragraph with the
day-precision anchored timestamp
* Update plugin system-prompt instructions in changeset
Live sessions pick up plugin changes, while the default TUI and `kimi -p` paths ignore these fields.
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* refactor(agent-core-v2): keep plugin skill reload user-driven
Plugin mutations still converge live agent prompts, but the session
skill catalog goes back to refreshing only on explicit plugin reload,
as before: the prompt feature does not need skill convergence, and the
pre-existing manual-reload semantics stay uniform across all plugin
contributions. Removes the convergence-driven skill reload, the
reloadSource de-privatization, and their tests; restores the
PluginSkillSource onDidReload forwarding and its catalog tests.
* refactor(agent-core-v2): apply plugin system-prompt changes only on explicit reload
Drop the live convergence machinery (the plugin onDidChange barrier,
the sessionPluginContribution fan-out, the restored-prompt drift gate,
and the day-precision render clock) so plugin system-prompt sections
take effect at the same point as every other plugin contribution:
/plugins reload or a new session. The profile now refreshes when the
session skill catalog re-pulls its plugin source on reload, reading
both the skill list and the prompt sections fresh.
* feat(agent-core): let plugins contribute system prompt instructions via the manifest systemPrompt field
* chore(agent-core-v2): remove inline implementation comment
* docs: clarify plugin prompt refresh semantics
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* feat(cli): add plugin quota and update notices
- Show "Note: This plugin consumes your quota." after installing
quota-consuming official plugins (currently Kimi Datasource).
- Show a one-time update notice after invoking an outdated plugin (a
plugin MCP tool call or a /<plugin>:<command> turn); the last
notified version is persisted so each new marketplace version
reminds once.
- Skip the third-party trust prompt for loopback sources that mirror
the official plugin CDN path, so the dev plugin marketplace no
longer prompts when installing official plugins.
* feat(cli): report plugin update notices at turn end
Buffer plugin MCP tool usage during the turn and report it together
with plugin command usage when the turn's output has fully ended,
instead of firing the check mid-turn at tool result time. Cancelled
turns no longer trigger the notice.
* fix(cli): refresh plugin MCP map on miss and serialize notice writes
Address review findings on the plugin update notifier:
- The memoized MCP server-to-plugin map is reused across /reload,
/new, and session switches, so plugins installed or enabled later in
the same app run never resolved. Refresh the map once on a lookup
miss, and never pin an empty map when there is no session.
- Concurrent notices (a turn that used two outdated plugins) raced on
the read-modify-write cycle of the notice state file and could drop
each other's entries. Serialize checks through a promise queue so
each notified version is persisted exactly once.
* fix(cli): gate plugin notices on official provenance and survive tool-name truncation
Address review findings:
- The quota note and the update notice keyed on the plugin id alone,
so a local/GitHub fork reusing a billed plugin's manifest id was
treated as the official build. Both now require official provenance
(a zip install from the official CDN plugin path or its loopback dev
mirror) via a shared isOfficialPluginInstall check.
- Resolving plugin MCP tools by splitting on the '__' separator broke
for qualified names core truncates to 64 chars, which can cut the
separator. Match known server names by longest prefix with a name
boundary instead, which survives truncation as long as the server
part itself is intact.
* revert(cli): drop the dev marketplace trust relaxation
The loopback carve-out let any local service bypass the third-party
trust prompt by serving a zip under the official path shape, which
does not prove official provenance (review P1). Revert to the single
rule — only https://code.kimi.com/kimi-code/plugins/official/* is a
trusted official source — and restore the stock dev marketplace
server. Installing official plugins from the dev marketplace shows
the trust prompt again.
* fix(cli): restrict update notices to the official catalog and settle tests
- Skip the update check when the loaded marketplace is not the default
official catalog, so a custom KIMI_CODE_PLUGIN_MARKETPLACE_URL can
no longer produce a notice that claims to come from the Official
Marketplace.
- Return a never-rejecting promise from the notifier entry points so
tests await the serialized queue directly instead of relying on
zero-delay timers for ordering.
* feat(plugins): source Superpowers from GitHub and show update badges
Source the Superpowers plugin from its GitHub release (v6.0.3) instead of a vendored copy, and drop the explicit version field.
Derive marketplace entry versions from GitHub source URLs when the version field is omitted, keeping the source URL the single source of truth.
Show update badges for installed plugins on the /plugins Installed tab.
* docs(plugins): document Installed tab update badges
* fix(plugins): stamp GitHub source version in CDN catalog
Older CLIs only read the explicit marketplace version and cannot derive it from a GitHub source URL. When publishing the CDN catalog, stamp the version derived from a pinned GitHub source so those clients still surface update badges.
The source plugins/marketplace.json keeps no explicit version; the version is derived at build time instead.
* feat(plugins): resolve latest version for bare GitHub sources at runtime
Point the Superpowers marketplace entry at the bare GitHub repo URL so it tracks the latest release instead of a pinned tag.
When a marketplace entry omits version and its source is a bare GitHub repo URL, resolve the latest release tag at load time (via the /releases/latest redirect) to fill the version for update detection.
Revert the build-time version stamping; it is no longer needed. Older CLIs that only read the explicit catalog version will no longer see update badges for Superpowers, since the catalog no longer carries one.
* feat(plugins): make Enter update and add I for details on Installed tab
On the Installed tab, Enter now installs the available update when one is present, and falls back to opening plugin details otherwise.
Add the I key to always open plugin details, so details remain reachable when Enter is occupied by an update. Update the installed hint, docs and changeset accordingly.
* feat(plugins): show installing state inside the plugins panel
Move the "Installing … from marketplace" notice from a transient status message into the plugins panel itself, so the user sees progress in the interactive card while an install or update is in flight.
* feat(plugins): highlight reload hint and add dev:cli:marketplace
Highlight "Run /new or /reload to apply plugin changes." in warning color after plugin install and remove, and make the two notices symmetric.
Add a root dev:cli:marketplace script that points the dev CLI at the production marketplace instead of the local dev server.
* fix(plugins): dedupe install success notice
Drop the redundant showNotice on marketplace installs so the success message is shown only once, symmetric with remove.
* fix(plugins): reset installing state on install failure
When a marketplace or Custom-tab install rejects, clear the installing state and return to the list so the user can retry, instead of leaving the panel stuck on the one-way "Installing…" view.
* feat(tui): redesign /plugins as a tabbed panel
Split the /plugins manager into Installed / Official / Third-party /
Custom tabs. The Official and Third-party marketplace catalogs load
lazily, so /plugins opens instantly and keeps working offline, with
fetch failures shown inline instead of closing the panel. The tab strip
is shared with the /model provider tabs via the new renderTabStrip
helper.
* fix(tui): show untiered marketplace entries and update badges
Address Codex review feedback on the /plugins tab redesign:
- Untiered marketplace entries (no `tier` field) now appear on the
Third-party tab instead of being invisible in both marketplace tabs.
- Installed plugins whose marketplace version is newer than the local
version render an `update <local> → <latest>` badge again, and
up-to-date plugins show `installed · v<version>` — restoring the
update visibility the pre-redesign marketplace UI had.
* fix(tui): decode Space for installed-plugin toggle
In terminals that send printable keys via Kitty/CSI-u sequences (e.g. VS
Code's integrated terminal), the Space key arrives as a printable char
rather than a Key.space match, so the Installed-tab Space toggle silently
stopped working. Check both matchesKey(Key.space) and the decoded
printable char to match the MCP selector and other dialogs.
* fix(tui): open custom marketplaces on the Third-party tab
When `/plugins marketplace <source>` points at a custom catalog whose
entries omit `tier`, those entries are classified into the Third-party
tab. Opening on Official left the visible tab empty and Enter could not
install anything, unlike the old marketplace picker which showed all
entries from the supplied source. Open on Third-party when a custom
source is supplied; the default catalog still lands on Official.
* docs(plugins): drop open-url wording and hyphenate Shift-Tab
Address Codex review feedback:
- The marketplace Enter action is install/update only (open-url rows were
removed), so say "install or update" instead of "open or install" and
drop the leftover changeset sentence about setup URLs.
- Use `Shift-Tab` (hyphen) instead of `Shift+Tab` to match the docs
typography convention.
* fix(tui): keep marketplace selection valid while loading
When the Official/Third-party catalog is still loading, `entries` is empty
and pressing ↓ computed `Math.min(-1, selectedIndex + 1)` = -1. The later
Enter then read `entries[-1]` and the first install silently did nothing.
Clamp the index to 0 while there are no entries.
* fix(tui): count tab separators in tab-strip fit check
renderTabStrip declared a strip to fit whenever the sum of tab cell widths
fit, but the returned string also inserts single spaces between tabs via
`segments.join(' ')`. At widths around 43-45 columns for a four-tab strip
this declared a fit while the joined line was wider, so the trailing tab
got truncated instead of showing the `<`/`>` scroll markers. Count the
inter-tab separators in both the full-fit check and the scrolling window
fit check.
* docs(plugins): fix Kimi Datasource redirect anchor
The datasource.md redirect pointed at ./plugins.html#kimi-datasource, but
plugins.md no longer has a `## Kimi Datasource` heading — it is now
`## Official Plugins`. Update the en/zh redirect targets and fallback
links to #official-plugins / #官方插件 so the link lands on an existing
anchor.
* docs(plugins): restore concise Kimi Datasource section
The `## Official Plugins` section had replaced the original
`## Kimi Datasource` section, leaving the datasource.md redirect pointing
at a missing anchor and the Datasource capabilities/usage unreachable.
Restore a concise `## Kimi Datasource` section (intro + OAuth login +
install steps + usage) in both en and zh so the #kimi-datasource anchor
is valid again and the content is reachable.
* docs(plugins): restore Installing-from-GitHub subheading
The tab-redesign rewrite had dropped the `### Installing from GitHub` /
`### 从 GitHub 安装` subheading and its lead sentence, leaving only the
four URL forms. Restore the heading and lead sentence in both en and zh.
* docs(plugins): expand Kimi Datasource and tidy marketplace docs
- Condense the Official / Third-party / Custom tab overview and trust-badge note
- Trim the custom marketplace JSON section to the minimal id + source shape
- Move and expand the Kimi Datasource section with install, usage, and coverage
* docs(plugins): fix heading style and drop Next steps section
- Use sentence case for the Datasource headings (How to use, What you can do)
- Rename the Datasource caveat heading to Billing and limitations / 计费与限制 to avoid a duplicate Notes / 注意事项 anchor
- Remove the Next steps section, which linked back to the on-page Datasource anchor
* fix(tui): repaint plugins panel from current theme palette
The /plugins panel and MCP selector captured a palette snapshot at construction. In auto theme mode, applyResolvedAutoTheme swaps currentTheme.palette and re-renders without remounting the open panel, so it kept stale colors until closed.
Read currentTheme.palette during render instead, drop the colors opt from both components and their call sites, and add a regression test that switches palettes on a mounted panel.
* fix(tui): repaint model tab strip from current theme palette
TabbedModelSelectorComponent cached a palette snapshot in opts and used it only for the tab strip. In auto theme mode the inner model list repaints from currentTheme but the strip kept the old colors until the dialog was closed.
Read currentTheme.palette on the render path instead, drop the colors opt and its three call sites, and add a regression test that switches palettes on a mounted selector and asserts the strip repaints. This removes the last palette snapshot among editor-replacement dialogs.
- Register the yuandian_law (元典法律数据库) data source for Chinese
laws/regulations and judicial case search.
- Append a request-id / tool-call-id trace line to every tool result so
failures can be correlated with backend logs.
- Fix the documented MCP tool names in SKILL.md (-data -> _data).
- Also includes the dev marketplace-server env isolation fix in dev.mjs.
Co-authored-by: qer <Anna_Knapprfr@mail.com>
* fix: align datasource plugin environment
* refactor: inject managed Kimi env into all stdio plugins
Pin the datasource credential-name test to the canonical
resolveKimiCodeOAuthKey so a digest drift in the standalone plugin
fails CI, and drop the hardcoded plugin-name special case so every
stdio plugin receives the active managed Kimi base URL / OAuth host
consistently (process.env and KIMI_CODE_HOME are already shared with
all plugins).
Installed plugins whose marketplace version is newer than the local
version now render an `update <local> → <latest>` badge and update in
place on Enter; up-to-date plugins show `installed · v<version>`.
Dev-server and CDN-build marketplace generation now stamp each entry's
version from the plugin manifest so the advertised "latest" stays accurate.
Adds a pure computeUpdateStatus() (semver, no spurious downgrades) with tests.
Co-authored-by: qer <Anna_Knapprfr@mail.com>
* docs: merge Kimi Datasource into plugins page and add terminal tip to getting started
- Merge datasource.md content into plugins.md as a dedicated section,
placed between installation management and plugin manifest sections
- Replace verbose feature tables with scenario-driven use cases and a
condensed coverage table
- Add /skill:kimi-datasource as an explicit invocation method alongside
natural language; update /new references to /reload
- Promote GitHub URL formats and notes to named H3 subsections within
installation management
- Add terminal recommendation tip (Kitty / Ghostty) in the Installation
section of getting-started
- Remove standalone datasource.md sidebar entries from zh and en nav
* docs: remove stale datasource pages and add redirects to plugins
Delete zh/en datasource.md (content now merged into plugins.md) and
add VitePress redirects so existing bookmarks and search results for
/customization/datasource land on /customization/plugins instead.
* docs: restore datasource pages as forwarding stubs
Replace deleted files with minimal pages that link to the merged
section in plugins.md. VitePress redirects only fire in SSG builds;
dev-server visitors hitting the old URL would 404 without these stubs.
* docs: add dev-server redirect middleware for removed datasource pages
VitePress `redirects` config only fires during SSG build; the dev
server ignores it, causing 404s on the old /customization/datasource
URLs. Add a Vite `configureServer` middleware that handles the redirect
in dev mode, while the top-level `redirects` config continues to
generate meta-refresh HTML pages for the production build.
---------
Co-authored-by: qer <wbxl2000@outlook.com>
* feat(plugin): install plugins from a GitHub repository URL
Allow `/plugins install <github-url>` (and marketplace `source` entries) to
take a GitHub repo URL directly. A new `github` source kind joins the
existing `local-path` and `zip-url` kinds.
Recognized URL forms (parsing in source.ts):
- `https://github.com/<o>/<r>` — bare; resolves to latest
release tag, falling back
to default branch HEAD.
- `https://github.com/<o>/<r>/tree/<ref>` — branch / tag / SHA;
value passed to codeload
in its short form so the
backend resolves either.
- `https://github.com/<o>/<r>/releases/tag/<tag>` — explicit tag, uses
refs/tags/<tag> to avoid
same-named-branch ambiguity.
- `https://github.com/<o>/<r>/commit/<sha>` — explicit commit SHA.
The resolver deliberately avoids `api.github.com`: its 60/hour anonymous
quota is shared with every other tool on the egress IP (browser, gh CLI,
IDE integrations) and a first-time install failing because some other tool
ate the budget is unacceptable UX. Instead we:
- GET `github.com/<o>/<r>/releases/latest` with manual redirect and parse
the `Location` header (302 → tag URL; 404 → no own release).
- Fall back to `codeload.github.com/<o>/<r>/zip/HEAD` for repos with no
releases (or for forks that inherit upstream tags but have no own release
page, which redirect to bare `/releases`).
- Only treat the explicit 404 from `/releases/latest` as "no release" — 5xx,
403, 429, and any other non-2xx status surface a hard error rather than
silently installing the default branch, so the user knows when transient
GitHub issues changed the install path.
UI changes in the TUI:
- `/plugins install` now shows a live Braille spinner while resolving and
downloading, then flips to a final status that distinguishes Installed
(fresh) vs Updated (same repo identity, new version) vs Migrated (source
changed, e.g. CDN zip-url → GitHub).
- `/plugins list`, the `/plugins` overview, and `/plugins info` show the
install provenance inline. `zip-url` installs now display the URL host
(e.g. `via code.kimi.com`, `via 127.0.0.1:port`) instead of the opaque
`zip-url` literal. GitHub installs show `github <owner>/<repo>@<ref>`.
- Three-tier trust badge driven by the marketplace context recorded at
install time: `official` (green) for `tier: official`, `curated` (blue) for
`tier: curated`, `third-party` (muted) for anything not installed through
the marketplace selector. CLI `/plugins install <url>` always records as
third-party; the marketplace selector passes the tier through. A
re-install replaces the marketplace context: switching to a third-party
source clears the badge, which matches the underlying trust change.
`installed.json` gains optional `github` and `marketplace` fields
(back-compatible). PluginSummary surfaces `source`, `originalSource`,
`github`, and `marketplace` so the TUI can label installs without an extra
round trip to PluginInfo. The SDK's `session.installPlugin(source)` gains
an optional `{ marketplace }` second argument so the marketplace selector
can forward `{ id, tier }` through RPC; the CLI install path omits it.
Tests: 112 plugin-suite tests (URL parser, resolver, store round-trip,
manager integration). The manager integration tests assert codeload URLs
shape (short form for `/tree/<ref>`, explicit `refs/tags/` for
`/releases/tag/`) and verify marketplace context is persisted across
reloads and cleared on a third-party re-install.
* chore(changeset): plugin install from GitHub
* docs(plugins): document GitHub install URLs and trust badges
* fix(plugin): preserve URL-encoded characters in GitHub ref names
Git permits ref characters that have special meaning in URLs — most
notably `#`, which is a valid tag character (e.g. `release#1`) but the URL
fragment delimiter. The resolver decoded the tag from GitHub's
`/releases/latest` 302 redirect Location header and then interpolated the
raw value into the codeload URL. The literal `#1` became a fragment and
the HTTP request reached the server as `…/refs/tags/release` — a wrong or
truncated ref, leading to install failure for a release whose URL was
otherwise valid.
Two symmetric changes:
- The codeload URL builder now splits the ref on `/` (so multi-segment
refs like `feat/foo` keep their path separators) and percent-encodes
each segment.
- The GitHub URL parser now percent-decodes each segment from the URL's
pathname when extracting `/tree/<ref>`, `/releases/tag/<tag>`, and
`/commit/<sha>`. Storage and display see the human-readable Git ref
name; the resolver re-encodes on the way out.
Malformed `%xx` sequences in user-typed URLs are tolerated: we keep the
raw segment so the caller surfaces a normal "ref not found" error
downstream instead of crashing during parse.
* fix: restrict plugin trust badges
* chore: remove fetch when show plugin list
---------
Co-authored-by: qer <Anna_Knapprfr@mail.com>
* docs: simplify plugins documentation
* docs: restore plugin caveats lost during simplification
Re-add three behaviors that were dropped from the simplified plugins
docs: the stdio MCP `cwd` must start with `./`, local-path installs run
from the managed copy (so editing the source after install requires a
reinstall), and `/plugins remove` only deletes the install record while
leaving files on disk. Mirror the changes in both en and zh.