Files
leafyy 827d22502e feat(plugin-host): import extensions from folders (#2506)
AIRI desktop could load Extensions that were already present on disk,
but users could not safely add an Extension folder. This PR completes
Extension Manifest v2 and adds a review-first folder import flow. An
imported Extension remains disabled and unloaded until the user
explicitly enables and loads it.

The design was informed by the incomplete `claude-code-plugin`
experiment and the Agent Activity Extension work tracked in #2507.

## User flow

1. Select an Extension folder in Plugin Host Devtools.
2. Review its identity, version, runtime, entrypoints, permissions, Kit
declarations, file count, and total size.
3. Confirm the import.
4. Enable and load the Extension when it is ready to run.
5. Disable and unload it to stop its runtime session.

## What changed

### Extension Manifest v2

- Add a strict schema for identity, version, AIRI compatibility,
runtimes, entrypoints, permissions, and Kit declarations.
- Reject unknown fields, duplicate runtime or Kit declarations, unsafe
Extension ids, missing entrypoints, and invalid semantic versions.
- Check `engines.airi` and the current runtime before importing an
Extension entrypoint.
- Keep Plugin Host transfer types in the runtime-neutral
`@proj-airi/stage-shared/plugin-host` boundary.

### Folder import

- Add separate prepare and commit steps so package code cannot run
during review.
- Bind the reviewed manifest to a package fingerprint and revalidate the
source before and after copying it.
- Reject symbolic links, absolute entrypoints, entrypoints outside the
package, duplicate Extension ids, and source changes after review.
- Limit packages to 10,000 entries and 512 MiB and manifests to 1 MiB.
Hash and copy file data with streams.
- Copy into `.imports` staging and publish the package with an atomic
rename.
- Record the validated committed entry directly in the registry after a
successful import.
- Retain the macOS security-scoped bookmark from folder selection
through commit.
- Wait for an active import during Host shutdown so no managed-directory
write outlives the Host.

### Desktop controls

- Add Devtools actions for importing an Extension folder.
- Add combined **Enable and load** and **Disable and unload** actions
that model real user behavior.
- Add English and Simplified Chinese strings for the new controls and
import review.

## Scope

This PR defines Kit declarations as manifest data. Extension-hosted Kit
routing, Provider and Consumer lifecycle, revocable clients, and
dependency activation order are isolated in draft PR #2549.

## Verification

- GitHub CI passed: unit tests, type checks, lint, provenance checks,
and all configured builds.
- Focused Plugin SDK core, directory importer, and Electron Plugin Host
tests: 86 passed.
- Stage UI Plugin Host store tests: 8 passed.
- `pnpm typecheck`: 52 workspace tasks passed.
- `pnpm lint`: passed with 646 existing repository warnings and no
errors.
- `sem diff --staged --no-cosmetics -v --file-exts .ts .tsx`: the final
shutdown batch analyzed 113 entities; its JSON report contained no
diagnostics.
- The importer shutdown regression failed before the fix and passed
after it.

## Visual change

| Before | After |
|---|---|
| Extension folder import was unavailable. | ![Plugin Host Extension
folder import
review](https://github.com/user-attachments/assets/813b820e-4663-473c-965c-b29bbcfb2601)
|
2026-09-16 11:31:04 +08:00
..
2026-08-26 20:13:10 +08:00