# Profile management
English | [中文](boot.zh.md)
The [boot package group](../../packages/boot/README.md) owns launcher-provided profile access and the plugin manager. [Plugin Manager](../../packages/boot/plugin-manager/README.md) documents persistence, reload and package-operation behavior.
## Management records
`PluginEntryId` identifies one Loader entry; callers obtain it from `listPlugins` rather than constructing a patch id.
`PluginInfo` carries module identity, effective enablement, fiber phase and optional display `meta`, plus a unique `patchId` or a `readOnlyReason`.
`BundleInfo.official` identifies project-maintained shipped optional bundles and on-demand catalog entries independently of installation. `availability` identifies a readable installation-provided or profile package, or `missing`; on-demand catalog entries exclude undeclared transitive copies. `installed` records the profile dependency declaration. An on-demand `installTarget` carries the host-derived exact spec and version. `BundleInfo` also carries the package name, optional installed version, selected enablement, removal availability, update eligibility (`updatable`), optional resolution or unsupported-platform error, and, for a bundle the profile's own dependency supplies and the installation does not, `source`: that dependency as a spec `pnpm add` accepts. Its optional `meta` and each `BundleRowInfo.meta` contain display text or a metadata diagnostic; Clients select a language at render time.
`InstallBundleOptions.saveExact` passes `--save-exact` to the shared package installer. `InstallBundleOptions.enabled` defaults to true. False installs without selecting the bundle layer. `approvedBuilds` grants persistent script permission to the supplied pending package names before installation. `registry` names the registry asked first; absent, the configured one.
`BundleDetail` is a profile bundle's long description: `{ status: 'found' }` with its `origin` (`locale` or `readme`), its `path` inside the package, and its `markdown`, or `{ status: 'none' }`; [`readBundleDetail`](../../packages/boot/plugin-manager/README.md#bundle-detail-documents) documents the order and the image route. `NpmFileSource` names a public npm file CDN, `jsdelivr`, `unpkg`, or `npmmirror`; a read's `npmFileSources` lists the ones to ask first.
`PluginRegistries` carries the configured first registry, `null` for the one pnpm's own configuration names, the fallbacks asked after it, and `resolved`, the URL pnpm's own configuration names or `null` while unread. `InspectOptions.registry` names the registry a lookup asks first.
`ChangeResult.changed` reports a disk edit independently of `application`: `applied`, `restart-required`, `overridden` or `failed`. Optional `error` carries a localizable code and external diagnostic. `packageResult` records the run's exit status, bounded output, truncation flag and complete diagnostic log path, plus `timedOut` when the manager terminated a run that stopped printing or the GitHub connection check hit its deadline; a terminated run records the coerced status 1 because its process returned none. A terminated run is classified `timeout` whatever exit status the signal left behind, so installation and removal report failure instead of success and no further registry is asked. `pendingBuilds` lists undecided packages across the profile; `approvedBuilds` records the names granted permission by this operation; `registries` lists the registries an installation asked, in order; `bundle` and `version` name the package a finished installation added and its manifest version; `failedAt` says whether the last failed run could not reach the registry it asked or the host a git or tarball spec is fetched from.
## Market records
[Plugin Market](../../packages/boot/plugin-market/README.md) reads index format 1, validated by [`dsh-plugin-market-index`](../../packages/util/plugin-market-index/README.md).
`MarketIndexSummary` carries one configured index URL with the `title` and `description` of its last successful read and, when the last read failed, its `error`.
`MarketQuery` selects one page of an index: fuzzy `text`, a `category`, `labels` that must all be present, a `MarketSort`, `offset`, `limit` up to 100, `refresh` to fetch again instead of using a cached document, and `fetchedAt` to continue the pages of one document. `MarketSearchResult` carries the index URL, `title`, optional `description`, market `metadata`, the document's `fetchedAt`, the page's `entries`, the `total` number of matches, and the `nextOffset`. Each `MarketListingEntry` adds `defaultVersion`, the version installed by default, and `installation`, the profile's status for the package name; each of its `versions` adds `install`, the exact spec and optional first registry for `installBundle`, and `compatibility`, the evaluation of its `engines.dsh` including a version exemption.
`PluginDetail` is a market entry's long description: `{ status: 'found' }` with its `origin` (`locale`, `readme`, or `repository`), its `markdown`, and a `document` id whose images `GET /api/plugin-market/detail-file` serves, or `{ status: 'none' }`. The [plugin market documents the order](../../packages/boot/plugin-market/README.md#plugin-detail-documents) its sources are read in.
## Profile reconciliation
```ts type-equiv
/** Outcome of {@link Hmr.reconcileProfile}. */
interface ProfileReconciliation {
/** Diagnostics for Loader entries left inactive. */
warnings: string[]
/** Loaded modules whose files changed on disk and whose previous code keeps running until a restart. */
pending: PendingModule[]
/**
* Why every change waits for a restart: `module-comparison` when module caches cannot be inspected or their files
* compared, even when no URLs are known; `package-moved` when the runtime resolution cannot publish a moved package.
*/
restartReason?: 'module-comparison' | 'package-moved'
}
```
```ts type-equiv
/** A changed module that loads only after a restart. */
interface PendingModule {
url: string
/**
* `host-module`: the process entry point's static graph imports it. `unmanaged-plugin`: it is imported by a plugin
* that runs outside a traversable Loader entry. `module-comparison`: loaded modules could not be compared with disk.
*/
reason: 'host-module' | 'unmanaged-plugin' | 'module-comparison'
}
```
## Cordis API
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
### `ctx.actionCards` — `ActionCards`
Card tool, kind registry, Session projection, user actions and status notices.
```ts cordis-catalog
/**
* Register one action kind for the caller's lifetime.
* @param kind - the kind's skill, details schema, verbs and handler.
* @returns disposer removing the kind; actions on its cards are then unavailable.
* @throws when another kind already registered the same action.
*/
register(kind: ActionCardKind): () => void
/**
* Record a card decision in the Session log; the next model request reports it.
* @param agent - agent whose Session owns the card.
* @param decision - the card's new state.
* @throws when no kind ever registered the decision's action with this service, or its phase is one the projection derives.
*/
record(agent: Agent, decision: ActionCardDecision): void
/**
* Read the cards of one Session.
* @param session - a Session whose projections are prepared.
* @returns proposals and decisions by call id.
*/
view(session: Session): ActionCardView
/**
* Apply a user action to a logged card. Shared checks run first, then the kind reconciles the card; `dismiss` is
* recorded here and every other verb goes to the card's kind. `dismiss` also works on an unstarted card whose kind
* is no longer registered. Concurrent actions on one card share one operation.
* @param agent - live root resolved from the displayed Session.
* @param callId - the card's `propose_action` call id.
* @param verb - `dismiss` or one of the kind's verbs.
* @param payload - kind-defined fields such as a chosen location.
* @returns acceptance of background work, the decision in effect, or a refusal.
*/
@Remote act(agent: Agent, callId: ToolCallId, verb: string, payload?: Record): Promise
```
Types: [Agent](core.md) · [Session](session.md) · [ToolCallId](core.md)
Source: [`packages/experimental/action-cards/src/index.ts`](../../packages/experimental/action-cards/src/index.ts)
### `ctx.configEditor` — `ConfigEditor`
Persist complete raw configs and apply them through the normal Loader path.
```ts cordis-catalog
/** Addressable profile rows; nested Includes have independent configuration ownership.
* @returns Active entries with unique profile patch ids.
*/
entries(): Entry[]
/** Read inherited and explicit profile values for the active entries.
* @returns Detached layer values alongside their Loader entries.
*/
configuration(): Array<{ entry: Entry; inherited: Record; override: Record }>
/** Validate, persist, and reconcile a plugin's next config; ordinary fields keep normal lifecycle rules.
* @param entry Current Loader entry, also used to detect replacement during the write.
* @param change Derive a raw config from the current entry and its inherited layer.
* @returns Fulfillment after Loader reconciliation completes.
*/
async edit( entry: Entry, change: (current: Record, inherited: Record) => Record, ): Promise
```
Source: [`packages/boot/config-editor/src/index.ts`](../../packages/boot/config-editor/src/index.ts)
### `ctx.headlessStartup` — `HeadlessStartupValues`
What the runner row reads from HEADLESS_STARTUP_SERVICE.
Source: [`packages/bundle/headless/src/startup.ts`](../../packages/bundle/headless/src/startup.ts)
### `ctx.hmr` — `Hmr`
Hot reload service with Cordis-compatible module configuration and events.
```ts cordis-catalog
/** Serialize a caller-owned mutation with all automatic reload paths.
* @param operation Work that must not overlap module or configuration replacement.
* @returns The operation result after its asynchronous work completes.
*/
runExclusive(operation: () => Promise): Promise
/** Watch a configuration path through the same queue as module replacement.
* @param filename Absolute path, which may not exist yet.
* @param refresh Rebuilds configuration from its current files and awaits Loader completion.
* @returns Disposer closing this registration and waiting for its pending refresh.
*/
async watchConfig(filename: string, refresh: () => Promise): Promise<() => Promise>
/** Read direct module dependency URLs from the active Node loader.
* @param url Module URL.
* @returns Linked module URLs, or an empty list for an uncached module.
*/
async getLinked(url: string): Promise
/**
* Recompose the profile from its manifest and patch files, replacing running plugins whose loaded files below the
* profile directory or its linked package targets changed on disk, and publishing its runtime resolution. Changed
* modules are evicted and the Loader entries running them stop; app-boot's {@link recomposeProfile} then publishes the
* resolution, applies the generation, starts the stopped entries with the current files and configuration,
* imports entries whose import failed again, and judges activation. Afterwards the modules below the mappings the
* recomposition dropped are evicted, so a removed or deselected package is imported afresh when it returns. Callers run
* inside {@link runExclusive}.
* @param requiredIds Entry ids whose inactive state is reported as a failure even when it predates this call.
* @returns Inactive-entry diagnostics, the changed modules that load after a restart, and a profile-wide restart reason.
* @throws The patch read, publication, preparation, apply, or activation failure of the recomposition, including a
* replacement plugin that fails to load or start, whose previous code no longer runs.
*/
async reconcileProfile(requiredIds: readonly string[] = []): Promise
```
Source: [`packages/boot/hmr/src/index.ts`](../../packages/boot/hmr/src/index.ts)
### `ctx.pluginManager` — `PluginManager`
Manage profile files and apply their declared reload lifecycle.
```ts cordis-catalog
/**
* Read a bundle's long description: the Markdown file its locale `meta.detail` names in `language`, otherwise its
* README. An installed bundle is read from its directory without network access; an official bundle the installation
* offers before it is installed is read from the npm file CDNs at its offered version. Nothing is cached.
* @param name - the bundle's package name, as `listBundles()` lists it.
* @param language - the display language, such as `zh-CN`; documents fall back through its prefixes to English.
* @param options - `npmFileSources` names npm file CDNs to ask first for an offered bundle, in order, such as the one
* a Client measured as fastest; configured CDNs it omits follow, and CDNs that are not configured are not asked.
* @returns the document with its origin and path, or `none`.
* @throws {RemoteError} `plugin-manager/unknown-bundle`, `plugin-manager/invalid-language`, or
* `plugin-manager/detail-unavailable`.
*/
@Remote async readBundleDetail(name: string, language: string, options?: { npmFileSources?: NpmFileSource[] }): Promise
/** Read exact plugin-version exemptions saved in this profile.
* @returns Accepted package-name@version keys with the runtime versions they may run on, and any
* record or file problem the reader rejected, which the caller reports instead of failing.
*/
@Remote listVersionExemptions(): { exemptions: Record; warnings: string[] }
/** Grant or revoke one exact plugin/runtime exemption and reevaluate live plugins.
* @param packageVersion Exact manifest package name followed by @ and its version; never an installation spec or alias.
* @param runtimeVersion Exact current DSH version for grants; revocation may name a previous runtime.
* @param enabled Whether to grant rather than revoke the exemption.
* @param acceptRisk Required true for grants after the user accepts possible crashes and data loss.
* @returns Saved and runtime outcomes. Startup-only profiles require restart.
*/
@Remote setVersionExemption(packageVersion: string, runtimeVersion: string, enabled: boolean, acceptRisk?: boolean): Promise
/** Read current plugins, including why a row cannot be changed through the profile patch.
* @returns Current runtime entries with persistent patch targets.
*/
@Remote async listPlugins(): Promise
/** Read installed, installation-provided, and offline Official catalog bundles, plus selected non-bundle names.
* A dependency without a bundle patch is listed, as a `not-bundle` problem, only while it is selected.
* @returns Package versions, manifest descriptions, the installable spec of profile dependencies, rows, optional
* display metadata, activation selections, whether the installation offers the bundle, and removal availability.
*/
@Remote listBundles(): Promise
/** Read the registries this manager asks: the configured first one, its fallbacks in order, and what pnpm's own configuration names.
* @returns The registries in pnpm's comparison form; null is the one pnpm's own configuration names, `resolved` as pnpm reads it now.
*/
@Remote async registries(): Promise
/** Read what a spec names before installing it.
* @param spec One package spec: a registry name, an absolute path, a git address, or a tarball.
* @param options The registry asked first.
* @param signal Ends a registry lookup early.
* @returns The package the spec names, or why it is refused.
*/
@Remote async inspect(spec: string, options?: InspectOptions, signal?: AbortSignal): Promise
/** Read the published versions newer than an installed registry package's version, from the first registry that answers.
* Official bundles follow the DSH version and are not listed.
* @param name Installed profile dependency name.
* @param options The registry asked first; absent, the one the package was installed from in this process, else the configured one.
* @param signal Ends the lookups early.
* @returns At most `versionListLimit` newer versions, newest first, with their tags, deprecation, bundle declaration,
* and DSH compatibility, and the registry that answered; or why no list could be read, with every registry asked.
*/
@Remote async listVersions(name: string, options?: ListVersionsOptions, signal?: AbortSignal): Promise
/**
* Replace an installed registry bundle with a newer published version. The target is checked on the registry first:
* it must exist, declare a bundle, and accept the running DSH version, or nothing changes. With HMR the installed
* version is removed, so its plugins stop, and the target is installed with the same selection; when that
* installation fails or is cancelled, the removed version is installed again from the registry it came from.
* Without HMR the target is installed over the running version and the result reports the restart.
* @param name Installed profile dependency name.
* @param version Exact published version newer than the installed one.
* @param options The registry asked first, as for `listVersions`, and the request id naming the progress and the
* target installation's logs and cancellation.
* @returns The versions, the last step that ran with its result, and the reinstallation when one ran.
*/
@Remote async updateBundle(name: string, version: string, options?: UpdateBundleOptions): Promise
/** Persist a plugin entry's desired enablement and apply it on live profiles.
* @param id Loader entry identity returned by listPlugins.
* @param enabled Whether the plugin should run.
* @returns Saved and runtime outcomes, including higher-priority overrides.
*/
@Remote setPluginEnabled(id: PluginEntryId, enabled: boolean): Promise
/** Select or remove a bundle layer while retaining installed dependencies.
* @param name Bundle package name.
* @param enabled Whether the bundle contributes its patch layer.
* @returns Persisted and runtime outcomes.
*/
@Remote setBundleEnabled(name: string, enabled: boolean): Promise
/**
* Install a package using the same pnpm implementation as dsh plugin. GitHub
* repositories get a connection check bounded by githubConnectionTimeoutMs before pnpm starts;
* only network failures or timeouts stop installation, and a stop streams the check's diagnostic
* as the installation's install-log run under its request id, while pnpm owns authentication and transport fallback. An
* HTTP(S) Git URL on another host is installed over SSH instead when access probes bounded by gitTransportTimeoutMs
* find that only SSH can read it. A run
* that fails, is cancelled, or adds a package without a bundle patch restores
* `package.json` and `pnpm-lock.yaml` as they were; downloaded files can stay.
* @param spec One package spec, including local paths relative to the invocation directory.
* @param options Whether to activate the installed bundle (defaults to true), the request id a cancellation names,
* the pending build scripts to allow, whether to save an exact dependency, and the registry asked first.
* @returns Package-manager diagnostics, the registries asked, and the observed activation outcome.
*/
@Remote installBundle(spec: string, options?: InstallBundleOptions): Promise
/** Recover the result of an active installation without cancelling it.
* @param requestId The id supplied when installation started.
* @returns The installation's outcome after it settles, or null if no active request has that id.
* Completed results are not retained; null establishes neither success nor cancellation.
*/
@Remote async waitForInstall(requestId: PluginInstallRequestId): Promise
/** Stop an installation this manager owns and wait until its files are back.
* @param requestId The id the installation was started with.
* @returns `cancelled` once the Git check or pnpm exited and the files are restored, `too-late` once the bundle is being
* applied, `not-running` for any other id.
*/
@Remote async cancelInstall(requestId: PluginInstallRequestId): Promise
/** Unload and remove a profile-owned bundle dependency through dsh plugin's pnpm path; a selected name no
* dependency holds is only deselected.
* @param name Installed dependency or selected bundle name.
* @returns Removal diagnostics and the remaining profile state.
*/
@Remote removeBundle(name: string): Promise
```
Source: [`packages/boot/plugin-manager/src/index.ts`](../../packages/boot/plugin-manager/src/index.ts)
### `ctx.pluginMarket` — `PluginMarket`
Fetches, validates, and caches configured market indexes; annotates entries with the profile's installation facts.
```ts cordis-catalog
/**
* List the configured index sources without fetching them.
* @returns every source in order, with the title of its last successful read and, when the last read failed, its error.
*/
@Remote listIndexes(): MarketIndexSummary[]
/**
* Replace the configured index sources through Settings, without remounting this service.
* `plugin-market/changed` announces the committed list. A URL already configured is kept as written, so a client can
* add or remove sources beside one that `listIndexes` reports as unusable.
* @param urls - index URLs in display order.
* @throws {RemoteError} `plugin-market/invalid-index-url` for an invalid new URL or a repeated URL;
* `plugin-market/settings-unavailable` without Settings or a profile entry.
*/
@Remote async setIndexes(urls: string[]): Promise
/**
* Return one page of the plugins of a configured index that match a query. Concurrent reads of a URL share one
* fetch; a successful document is reused for `cacheTtlMs` unless `refresh` is set. Matching and ordering read only
* the document; installation status and compatibility are computed for the returned page on every call.
* @param url - a configured index URL.
* @param query - text, filters, order, page, and whether to bypass the cached document.
* @returns the index header, the page's plugins with each plugin's default version and installation status and each
* version's compatibility and install arguments, the number of matches, and the next page's offset.
* @throws {RemoteError} `plugin-market/invalid-query`, `plugin-market/unknown-index`, `plugin-market/invalid-index-url`,
* `plugin-market/fetch-failed`, or `plugin-market/invalid-index`.
*/
@Remote async search(url: string, query: MarketQuery): Promise
/**
* Read one plugin of a configured index, using the cached document as `search` does.
* @param url - a configured index URL.
* @param name - the plugin's package name.
* @returns the plugin with its default version, installation status, and annotated versions; undefined when the
* index does not list it.
* @throws {RemoteError} `plugin-market/unknown-index`, `plugin-market/invalid-index-url`, `plugin-market/fetch-failed`,
* or `plugin-market/invalid-index`.
*/
async entry(url: string, name: string): Promise
/**
* Read the long description of one listed version of a plugin market entry, from the version's source: the npm file
* CDNs for a public npm version, or its pinned Git commit. The Markdown file the package's locale `meta.detail` names
* in `language` comes first, then the package's README, then the README of the entry's `repository`, or for an npm
* version without one, of its `package.json` `repository`, at the default branch. An npm version from another
* registry has no readable package files, so only the entry's `repository` is read.
* @param url - a configured index URL.
* @param name - the plugin's package name.
* @param version - one listed version.
* @param language - the display language, such as `zh-CN`; documents fall back through its prefixes to English.
* @param options - `refresh` reads again instead of reusing a result cached for `cacheTtlMs`; `npmFileSources` names
* npm file CDNs to ask first for an npm version, in order; configured CDNs it omits follow, and CDNs that are not
* configured are not asked.
* @returns the document with its origin and image document id, or `none`.
* @throws {RemoteError} the failures of `search`, `plugin-market/unknown-plugin` for an unlisted plugin or version,
* `plugin-market/invalid-query`, or `plugin-market/detail-unavailable`.
*/
@Remote async readEntryDetail( url: string, name: string, version: string, language: string, options?: { refresh?: boolean; npmFileSources?: NpmFileSource[] }, ): Promise
```
Source: [`packages/boot/plugin-market/src/index.ts`](../../packages/boot/plugin-market/src/index.ts)
### `ctx.pluginRecommendations` — `PluginRecommendations`
Catalog lookups for card text and the enabling behind the `enable_official_plugin` card.
```ts cordis-catalog
/**
* Read the current catalog text for a logged card.
* @param agent - Exact live root resolved by the Gateway from the Session id.
* @param callId - The card's `propose_action` call id, never a package supplied by the browser.
* @returns the plugin's title, description and selection, or a refusal when the card names no available official plugin.
*/
@Remote async describe(agent: Agent, callId: ToolCallId): Promise
```
Types: [Agent](core.md) · [ToolCallId](core.md)
Source: [`packages/experimental/plugin-recommendations/src/index.ts`](../../packages/experimental/plugin-recommendations/src/index.ts)
### `ctx.pluginRegistryProbe` — `PluginRegistryProbe`
Compares public registry responses on the Host; the Client owns the initial selection.
```ts cordis-catalog
/**
* Race npm and npmmirror HTTPS ping responses through the Host's fetch proxy.
* Concurrent readers share a probe; a winner cancels and awaits the other request.
* @returns the first registry with a successful response, or null when disabled or neither responds successfully; results are cached.
* @throws rejects when the service has been unloaded.
*/
@Remote async fastest(): Promise
```
Source: [`packages/client/ui-plugin-manager/src/index.ts`](../../packages/client/ui-plugin-manager/src/index.ts)
### `ctx.profileContext` — `ProfileContext`
Current profile facts; scheduling and mutation belong to their callers.
Source: [`packages/boot/app-boot/src/profile-context.ts`](../../packages/boot/app-boot/src/profile-context.ts)
### `app-boot/*` events
#### `app-boot/config-reload` — emit
Profile patches were reconciled into the running Loader tree: every entry update settled and no new inactive entry was introduced. Carries no diff; listeners re-read Loader entries.
```ts cordis-catalog
/**
* Profile patches were reconciled into the running Loader tree: every entry update settled and no new
* inactive entry was introduced. Carries no diff; listeners re-read Loader entries.
* @mode emit
*/
'app-boot/config-reload'(): void
```
Source: [`packages/boot/app-boot/src/index.ts`](../../packages/boot/app-boot/src/index.ts)
### `hmr/*` events
#### `hmr/change` — emit
A watched file has no module or configuration handler.
```ts cordis-catalog
/** A watched file has no module or configuration handler.
* @mode emit
* @param url Canonical file URL.
*/
'hmr/change'(url: string): void
```
Source: [`packages/boot/hmr/src/index.ts`](../../packages/boot/hmr/src/index.ts)
#### `hmr/reload` — emit
Module replacements have finished loading.
```ts cordis-catalog
/** Module replacements have finished loading.
* @mode emit
* @param reloads Replaced plugins and their module locations.
*/
'hmr/reload'(reloads: Map): void
```
Source: [`packages/boot/hmr/src/index.ts`](../../packages/boot/hmr/src/index.ts)
### `plugin-manager/*` events
#### `plugin-manager/changed` — emit
The profile's plugins, bundles, or composition changed: a manager operation completed. A patch generation applied outside the manager, by HMR's watcher after a CLI or hand edit, announces nothing here.
```ts cordis-catalog
/**
* The profile's plugins, bundles, or composition changed: a manager
* operation completed. A patch generation applied outside the manager,
* by HMR's watcher after a CLI or hand edit, announces nothing here.
* @mode emit
* @param change - what changed.
*/
'plugin-manager/changed'(change: PluginChange): void
```
Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin-manager/src/types.ts)
#### `plugin-manager/install-log` — emit
One chunk of an installation run's output, streamed as the run produces it.
```ts cordis-catalog
/**
* One chunk of an installation run's output, streamed as the run produces it.
* @mode emit
* @param chunk - the chunk and the run it belongs to.
*/
'plugin-manager/install-log'(chunk: PluginInstallLogChunk): void
```
Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin-manager/src/types.ts)
#### `plugin-manager/install-state` — emit
An installation moved between its Host phases. `installing` is announced once per registry the installation asks, with the attempt's registry and position; `cancelling` and `applying` once.
```ts cordis-catalog
/**
* An installation moved between its Host phases. `installing` is announced once per registry the
* installation asks, with the attempt's registry and position; `cancelling` and `applying` once.
* @mode emit
* @param progress - the installation's request id and phase, with the attempt while installing.
*/
'plugin-manager/install-state'(progress: PluginInstallProgress): void
```
Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin-manager/src/types.ts)
#### `plugin-manager/operation` — parallel
One manager invocation started or ended; subscribers run independently without delaying management.
```ts cordis-catalog
/**
* One manager invocation started or ended; subscribers run independently without delaying management.
* @mode parallel
* @param operation - Correlated operation facts; a start without an end has an unknown outcome.
*/
'plugin-manager/operation'(operation: PluginOperation): void | Promise
```
Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin-manager/src/types.ts)
#### `plugin-manager/update-state` — emit
An update moved to its next step: checking the target, removing the installed version, installing the target, or reinstalling the removed version after the target failed. Announced once per step.
```ts cordis-catalog
/**
* An update moved to its next step: checking the target, removing the installed version, installing the target,
* or reinstalling the removed version after the target failed. Announced once per step.
* @mode emit
* @param progress - the update's request id and step.
*/
'plugin-manager/update-state'(progress: PluginUpdateProgress): void
```
Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin-manager/src/types.ts)
### `plugin-market/*` events
#### `plugin-market/changed` — emit
The configured index sources changed.
```ts cordis-catalog
/**
* The configured index sources changed.
* @mode emit
*/
'plugin-market/changed'(): void
```
Source: [`packages/boot/plugin-market/src/types.ts`](../../packages/boot/plugin-market/src/types.ts)