# Profile 管理
[English](boot.md) | 中文
[boot 包组](../../packages/boot/README.zh.md)负责 launcher 提供的 profile 访问与插件管理器。[插件管理器](../../packages/boot/plugin-manager/README.zh.md)文档说明持久化、重载与包操作行为。
## 管理记录
`PluginEntryId` 标识一个 Loader 条目;调用方从 `listPlugins` 获取,不自行拼接 patch id。
`PluginInfo` 包含模块标识、实际启停状态和 fiber 阶段,以及唯一的 `patchId` 或 `readOnlyReason`。
`BundleInfo` 包含包名、可选的安装版本、组合层选择状态、删除可用性及可选的解析错误。
`InstallBundleOptions.enabled` 默认为 true,false 表示安装但不选择组合包层。`approvedBuilds` 在安装前向指定的待审批包名授予持久脚本权限。
`ChangeResult.changed` 报告磁盘修改,独立于 `application`:`applied`、`restart-required`、`overridden` 或 `failed`。可选的 `error` 包含可本地化的错误码和外部诊断。`packageResult` 记录 pnpm 退出码、有界输出、截断标志及完整诊断日志路径。`pendingBuilds` 列出整个 profile 尚未决定的包;`approvedBuilds` 记录本次操作授予权限的包名。
## 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.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
### `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
```
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 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 the profile's installed bundles, the bundles this dsh installation supplies, and the selected names that are not bundles.
* A dependency without a bundle patch is listed, as a `not-bundle` problem, only while it is selected.
* @returns Package versions, one-liners, rows, activation selections, whether the installation offers the
* bundle, and removal availability.
*/
@Remote listBundles(): 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 signal Ends a registry lookup early.
* @returns The package the spec names, or why it is refused.
*/
@Remote async inspect(spec: string, signal?: AbortSignal): 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. 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, and
* the pending build scripts to allow for this profile before pnpm runs.
* @returns Package-manager diagnostics and observed activation outcome.
*/
@Remote installBundle(spec: string, options?: InstallBundleOptions): 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 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.
* @param name Installed dependency 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.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)
### `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 a pnpm run's output, streamed as the run produces it.
```ts cordis-catalog
/**
* One chunk of a pnpm 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.
```ts cordis-catalog
/**
* An installation moved between its Host phases.
* @mode emit
* @param progress - the installation's request id and phase.
*/
'plugin-manager/install-state'(progress: PluginInstallProgress): void
```
Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin-manager/src/types.ts)