# @aliou/pi-utils-settings 中文文档

规范地址：https://npmcn.com/package/%40aliou/pi-utils-settings/

版本：0\.24\.1
npm 元数据更新时间：2026-11-03T22:00:16.025Z
中文译文更新时间：2026-11-06T00:34:06.957Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40aliou/pi-utils-settings
原文对照：https://npmcn.com/package/%40aliou/pi-utils-settings/?lang=original
项目主页：https://github.com/aliou/pi-utils-settings#readme
源码仓库：https://github.com/aliou/pi-utils-settings

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：289 kB，30 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- 运行依赖：1 个
- peer 依赖：ts-json-schema-generator \>=2\.4\.0 \<3，@earendil-works/pi-coding-agent \>=1\.4\.0 \<2
- 首次发布：2026-02-04T11:40:36.772Z
- 最新版本发布：2026-11-03T22:00:15.757Z
- 近 30 天下载量：8165（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：39（近 12 个月 39 个）

## 中文简介

Pi 扩展的共享设置 UI 和配置加载器

## 安装

```sh
npm install @aliou/pi-utils-settings
```

也可以使用：`pnpm add @aliou/pi-utils-settings`、`yarn add @aliou/pi-utils-settings`、`bun add @aliou/pi-utils-settings`

## README

![banner](https://assets.aliou.me/github/aliou/pi-utils-settings/banner.png)

# @aliou/pi-utils-设置

共享设置基础设施 [毕](https://github.com/mariozechner/pi-coding-agent) 扩展。 提供配置加载,设置 UI 命令,加上范围标签加可选的额外标签,以及可再使用的 TUI 组件.

这是一个通用库,不是 Pi 扩展 。 它意在通过需要设置 UI 或 JSON 配置管理的扩展用作依赖.

## 安装

```bash
pnpm add @aliou/pi-utils-settings
```

## API 密码

### 配置标签

通用 JSON 配置加载器带有 Global + 本地( 项目) 瞄准镜, 深度合并, 以及版本迁移 .

```typescript
import { bindProjectConfig, ConfigLoader, type Migration } from "@aliou/pi-utils-settings";

interface MyConfig {
  features?: { darkMode?: boolean };
}

interface ResolvedConfig {
  features: { darkMode: boolean };
}

const migrations: Migration<MyConfig>[] = [
  {
    name: "v1-upgrade",
    shouldRun: (config) => !config.features,
    run: (config, _filePath) => ({ ...config, features: {} }),
  },
];

const configLoader = new ConfigLoader<MyConfig, ResolvedConfig>(
  "my-extension", // reads ~/.pi/agent/extensions/my-extension.json + .pi/extensions/my-extension.json
  { features: { darkMode: false } }, // defaults
  { migrations },
);

await configLoader.load();
bindProjectConfig(pi, configLoader);

pi.on("session_start", () => {
  const config = configLoader.getConfig();
});
```

`load()` 装入默认和全局配置及重排项目状态 `"pending"`调用 `bindProjectConfig(pi, configLoader)` 紧接其后,在登记其他 `session_start` 管理者。 它召唤 `loadProject(ctx)` 使用 `ctx.cwd` 财务报告和审定财务报表 `ctx.isProjectTrusted()`。信任的工程配置被合并并迁移;未信任的配置被忽略而不读取或写入。 内存覆盖幸存 `loadProject()`。 。 。 .

`getProjectState()` 返回时 `"pending"`, (中文(简体) ), `"trusted"`,或 `"untrusted"`。需要本地节省 `"trusted"`。本地标签保持可见,但在信任之前无法编辑。 使用 `/trust` 并重新启动 Pi 以应用工程设置。 忽略的文件生成一个 `drainMessages()` 备注.

#### 版本迁移

移民可以宣布为单调 `version`:非负整数或 semver 字符串(例如扩展包版本, `"1.2.0"`;没有预放标签). 设定时, `shouldRun` 默认为“配置版本 < 迁移版本” ,加载器将配置文件印出最高应用版本。 在一个加载器中的所有版本的迁移必须使用相同的方案——混合整数和向构造所投掷的分解字符串. 已印出整数的扩展应保留整数( 已印出) `3` 读作 `3.0.0` 在铸币局下. `shouldRun`, (中文(简体) ), `run`,信息厂收到一个 `MigrationContext` 与文件路径、前/后版本,以及在加载时已经应用的迁移名称相连接.

```typescript
const migrations: Migration<MyConfig>[] = [
  {
    name: "v1-features",
    version: 1,
    // No shouldRun needed: runs when config.version < 1.
    run: (config) => ({ ...config, features: {} }),
  },
  {
    name: "v2-rename-theme",
    version: 2,
    run: (config, _filePath, ctx) => {
      // ctx.appliedMigrations: ["v1-features"], ctx.fromVersion: 1, ctx.toVersion: 2
      const { theme, ...rest } = config as MyConfig & { theme?: string };
      return { ...rest, appearance: { theme } };
    },
  },
];

await configLoader.load();
configLoader.getVersion(); // highest stamped version across scopes
```

提供两者 `version` 财务报告和审定财务报表 `shouldRun` 改为在内容上同时盖章(例如, `shouldRun: (c) => c.legacy !== undefined`) (中文(简体) ). 移民与建筑无关.

#### JSON 舍马支持

`ConfigLoader` 可以注入一个 `$schema` 字段进入设置文件,使编辑器自动完成和验证。 说对了 `buildSchemaUrl` 和自动生成的策略 `ts-json-schema-generator`。 。 。 .

```typescript
import { ConfigLoader, buildSchemaUrl } from "@aliou/pi-utils-settings";
import pkg from "./package.json";

const schemaUrl = buildSchemaUrl(pkg.name, pkg.version);

// For schemas hosted outside npm/unpkg, use a custom template:
const githubSchemaUrl = buildSchemaUrl("aliou/my-extension", "v1.0.0", {
  template: "https://raw.githubusercontent.com/{packageName}/{version}/{schemaPath}",
});

const loader = new ConfigLoader<MyConfig, ResolvedConfig>(
  "my-extension",
  defaults,
  { schemaUrl },
);
```

何时 `schemaUrl` 已经设定, `save()` 写入 `$schema` 作为 JSON 文件的第一个密钥和 `load()` 在返回配置到呼叫者之前将其剥离.

从你身上生成计划 `TConfig` 类型,安装 `ts-json-schema-generator` 用作依赖性并使用捆绑的 `pi-settings-schema` CLI(英语:CLI). 它包起发电机,注入预留 `$schema` 财务报告和审定财务报表 `version` 属性,所以您的配置类型不需要它们 :

```json
{
  "gen:schema": "pi-settings-schema -p src/config.ts -t MyConfig -o schema.json --version 2",
  "check:schema": "pi-settings-schema -p src/config.ts -t MyConfig -o schema.json --version 2 --check"
}
```

运行 `pnpm gen:schema` 生产 `schema.json`,并添加 `"schema.json"` 改为 `files` 内 `package.json` 所以它用你的Npm包装船 添加 `check:schema` 以捕捉漂流(在已犯规时,除去1). `--version` 将当前迁移版本记录在图中。 如果扩展未发布到 npm, 请执行 `schema.json` 公之于众,传一风俗 `template` 或者说 `baseUrl` 改为 `buildSchemaUrl`。 。 。 .

程序上与 `generateSettingsSchema(options)` 财务报告和审定财务报表 `finalizeSchema(schema, options)`。 。 。 .

可选 `afterMerge` 钩子在深度合并后运行,用于无法表达为简单合并的逻辑(例如,一个字段取代另一个字段):

```typescript
new ConfigLoader("my-ext", defaults, {
  afterMerge: (resolved, global, local, memory) => {
    if (local?.customField) {
      resolved.derivedField = local.customField;
    }
    return resolved;
  },
});
```

### 命令

创建一个 `/name:settings` 命令,带有范围标签(Global/local/Memory),基于草稿的编辑,以及要保存的 Ctrl+S.

所有更改(boolean toggles, enum cycling, submenu editers)作为草稿保存在内存中. 在用户按下 Ctrl+S. Esc 退出而不默认保存之前,任何内容都无法写入磁盘. 脏标签显示 `*` 标记。 使用 `onBeforeClose` 以拦截 Esc ,例如确认丢弃未保存的草稿.

Ctrl+S 从任何深度中省出,包括开放子菜单内(`ArrayEditor`, (中文(简体) ), `SettingsDetailEditor`, (中文(简体) ), `FuzzySelector`(中文(简体) ). Submenus承诺编辑每个变异的草稿,所以一个被巢存总是坚持最新的状态. 独立的组件用户可以通过 `requestSave` 在组件选项中获取外部相同行为 `registerSettingsCommand`。 。 。 .

```typescript
import { registerSettingsCommand, type SettingsSection } from "@aliou/pi-utils-settings";

registerSettingsCommand<MyConfig, ResolvedConfig>(pi, {
  commandName: "my-ext:settings",
  title: "My Extension Settings",
  configStore: configLoader, // implements ConfigStore interface
  buildSections: (tabConfig, resolved, { setDraft, theme }) => [
    {
      label: "General",
      items: [
        {
          id: "features.darkMode",
          label: "Dark mode",
          description: theme.fg("dim", "Enable dark mode"),
          currentValue: (tabConfig?.features?.darkMode ?? resolved.features.darkMode) ? "on" : "off",
          values: ["on", "off"],
        },
      ],
    },
  ],
  // --- Optional: Custom change handler ---
  // The default handler stores all values as raw strings ("on"/"off", "pnpm", etc).
  // Use onSettingChange to convert display values to the correct storage types:
  // - Booleans: newValue === "on" -> true
  // - Numbers: Number.parseInt(newValue, 10)
  // Return null to fall through to the default string storage.
  onSettingChange: (id, newValue, config) => {
    const updated = structuredClone(config);
    if (id === "features.darkMode") {
      updated.features = { ...updated.features, darkMode: newValue === "on" };
      return updated;
    }
    return null; // Fall through for other fields
  },
  // Optional: return false to keep the settings UI open on Esc.
  onBeforeClose: (isDirty) => !isDirty,
});
```

您也可以用 `extraTabs`数字 :

```typescript
import { registerSettingsCommand, type ExtraSettingsTab } from "@aliou/pi-utils-settings";

const extraTabs: ExtraSettingsTab<MyConfig, ResolvedConfig>[] = [
  {
    id: "examples",
    label: "Examples",
    buildSections: ({ resolved, getRawForScope, enabledScopes }) => {
      const globalConfig = getRawForScope("global");
      return [
        {
          label: "Examples",
          items: [
            {
              id: "example.enabledScopes",
              label: "Enabled scopes",
              currentValue: enabledScopes.join(", "),
            },
            {
              id: "example.darkModeDefault",
              label: "Dark mode default",
              currentValue: resolved.features.darkMode ? "on" : "off",
            },
            {
              id: "example.globalPresent",
              label: "Global config",
              currentValue: globalConfig ? "present" : "missing",
              description: "Read-only info tab not tied to a scope.",
            },
          ],
        },
      ];
    },
  },
];
```

`Ctrl+S` 行为不变:只保存了肮脏的瞄准镜草稿. 额外标签可以通过调用更新草稿 `setDraftForScope(...)` 从子菜单召回.

价值循环项目`values`在额外标签中,添加 `onSettingChange` 并明确选择目标范围. `applySettingChangeToScope(...)` 重用命令级别 `onSettingChange` 处理器, 当处理器返回时返回默认的点- 路径字符串存储 `null`。 。 。 .

```typescript
const extraTabs: ExtraSettingsTab<MyConfig, ResolvedConfig>[] = [
  {
    id: "presets",
    label: "Presets",
    buildSections: ({ getDraftForScope, getRawForScope }) => {
      const config = getDraftForScope("global") ?? getRawForScope("global");
      return [
        {
          label: "Presets",
          items: [
            {
              id: "features.darkMode",
              label: "Dark mode",
              currentValue: config?.features?.darkMode ? "on" : "off",
              values: ["on", "off"],
            },
          ],
        },
      ];
    },
    onSettingChange: (id, newValue, ctx) => {
      ctx.applySettingChangeToScope("global", id, newValue);
    },
  },
];
```

`buildSections` ctx 现在包含 `theme`,两者都是 `SettingsListTheme` 和满分 `Theme`。这意味着您可以使用列表助手(`label`, (中文(简体) ), `value`, (中文(简体) ), `hint`,并将同一对象传递给需要完整部件 `Theme`。 。 。 .

```typescript
import { Wizard } from "@aliou/pi-utils-settings";

buildSections: (_tabConfig, _resolved, ctx) => [
  {
    label: "Setup",
    items: [
      {
        id: "setup.wizard",
        label: "Run setup",
        currentValue: ctx.theme.fg("accent", "open"),
        submenu: (_value, done) =>
          new Wizard({
            title: "Setup",
            theme: ctx.theme,
            steps: [{ label: "Step", build: () => ({ render: () => [ctx.theme.hint("Ready")], handleInput: () => {} }) }],
            onComplete: () => done("done"),
            onCancel: () => done(undefined),
          }),
      },
    ],
  },
];
```

#### 命令别名

Pi没有命令假名机制 所以 `aliases` 将每个条目注册为第二个完整命令,该命令将打开相同的设置 UI ,并预选一个标签。 异形忽略了他们的论点.

```typescript
import {
  registerSettingsCommand,
  type ExtraSettingsTab,
  type SettingsCommandAlias,
} from "@aliou/pi-utils-settings";

const aliases: SettingsCommandAlias[] = [
  // Opens the settings UI on the "proxy" extra tab below: /my-ext:proxy
  { commandName: "my-ext:proxy", tabId: "proxy" },
  // Scope tabs work too. The palette description defaults to
  // `Open ${title} (${tabLabel})`, e.g. "Open My Extension Settings (Memory)":
  { commandName: "my-ext:memory", tabId: "memory" },
  // Optional explicit description:
  { commandName: "my-ext:setup", tabId: "global", description: "Open the setup tab" },
];

const extraTabs: ExtraSettingsTab<MyConfig, ResolvedConfig>[] = [
  { id: "proxy", label: "Proxy", buildSections: () => [/* ... */] },
];

registerSettingsCommand<MyConfig, ResolvedConfig>(pi, {
  commandName: "my-ext:settings",
  title: "My Extension Settings",
  configStore: configLoader,
  extraTabs,
  aliases,
  buildSections: (tabConfig, resolved, { setDraft, theme }) => [/* ... */],
});
```

`tabId` 必须是范围 id (`global`编号 :`local`编号 :`memory`或一个 `extraTabs` 编号. 登记在前面验证:重复的别名命令名称,与主命令名称等同的别名,或未知 `tabId` 抛出(带有 `[settings]`\- 任何命令注册前的前缀消息). 一个有效但失效的瞄准镜会默默地降解到默认分页而不是出错.

主命令也接受标签参数 : `/my-ext:settings proxy` 预选标签。 第一个被限制的白空令牌是先对制表符进行不敏感大小写匹配,再对制表符标签进行;一个未知的令牌显示警告并打开默认制表符,空格保留已存在的默认行为. 主命令登记册 `getArgumentCompletions`,返回一个 `AutocompleteItem` 每个当前已注册的标签(启用范围外加额外标签)被打出前缀过滤—— `value` 是标签编号, `label` 标签标签。 异名没有完成.

### 子菜单支持

项目可通过提供 a 打开子菜单 `submenu` 工厂。 工厂收到现值, a `done` 调用,和 a `{ requestRender, hideHint }` 上下文,使 sync 子菜单可以触发重画. `done(value)` 执行值并关闭子菜单, `done(undefined)` 取消,和 `done(value, { navigateTo: itemId })` 关闭后跳转到另一个项目(见下文)。 使用 `setDraft` 子菜单内 `onSave` 以保留草稿中的更改(与简单的值相同保存模型):

```typescript
import { ArrayEditor, setNestedValue } from "@aliou/pi-utils-settings";

{
  id: "tags",
  label: "Tags",
  currentValue: `${tags.length} items`,
  submenu: (_val, done, submenuCtx) => {
    let latest = [...tags];
    return new ArrayEditor({
      label: "Tags",
      items: [...tags],
      theme: ctx.theme,
      // Forward the host's flag: the panel renders the single controls
      // line, so the editor hides its own footer and exposes shortcuts
      // through getShortcuts().
      hideHint: submenuCtx.hideHint,
      onSave: (items) => {
        latest = items;
        const updated = structuredClone(tabConfig ?? {}) as MyConfig;
        setNestedValue(updated, "tags", items);
        setDraft(updated);
      },
      onDone: () => done(`${latest.length} items`),
    });
  },
}
```

对于同步装入数据的子菜单,呼叫 `ctx.requestRender()` 一旦真正的编辑准备好了 渲染钩被自动接通 `registerSettingsCommand`; 独立 `SectionedSettings` 用户可以通过 `requestRender` 内 `SectionedSettingsOptions`。 。 。 .

```typescript
import type { Component } from "@earendil-works/pi-tui";
import { Key, matchesKey } from "@earendil-works/pi-tui";
import { FuzzySelector } from "@aliou/pi-utils-settings";

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function loadPresets(): Promise<string[]> {
  // Simulate a network or subprocess call.
  await sleep(2000);
  return ["dark", "light", "solarized-dark"];
}

{
  id: "remote.presets",
  label: "Remote presets",
  currentValue: "loading",
  submenu: (_val, done, { requestRender, hideHint }) => {
    class AsyncPresetPicker implements Component {
      private editor: FuzzySelector | null = null;

      constructor() {
        void loadPresets().then((presets) => {
          this.editor = new FuzzySelector({
            label: "Preset",
            items: presets,
            theme: ctx.theme,
            hideHint,
            onSelect: (selected) => {
              const updated = structuredClone(tabConfig ?? {}) as MyConfig;
              setNestedValue(updated, "appearance.theme", selected);
              setDraft(updated);
              done(selected);
            },
            onDone: () => done(undefined),
          });
          requestRender();
        });
      }

      render(width: number): string[] {
        return this.editor?.render(width) ?? [ctx.theme.hint("  (loading presets...)")];
      }

      // Forward shortcuts so the panel's controls line stays
      // accurate once the editor is ready.
      getShortcuts(): string | undefined {
        return this.editor?.getShortcuts();
      }

      handleInput(data: string): void {
        if (this.editor === null && matchesKey(data, Key.escape)) {
          done(undefined);
          return;
        }
        this.editor?.handleInput?.(data);
      }

      invalidate(): void {
        this.editor?.invalidate?.();
      }
    }

    return new AsyncPresetPicker();
  },
}
```

#### 带链的子菜单 `navigateTo`

`SectionedSettings` 和pi-tui的相匹配 `SettingsList` 子菜单合同。 这个 `done` 调用可选 `SubmenuDoneOptions` 对象:调用 `done(value, { navigateTo: "other.itemId" })` 关闭子菜单, 将光标移动到项目上, 并自动激活它 —— 打开子菜单项目的子菜单, 循环 a `values` 项目( `onChange`),或者只是选择一个普通项目。 导航到未知的 id 后退到当前选中的项目重新激活, 如 pi- tui .

```typescript
import type { Component } from "@earendil-works/pi-tui";
import type { SubmenuDoneOptions } from "@aliou/pi-utils-settings";

{
  id: "network.proxy",
  label: "Proxy",
  currentValue: "off",
  submenu: (_val, done) => {
    const confirm = (proxyUrl?: string, options?: SubmenuDoneOptions) =>
      done(proxyUrl, options);

    const editor: Component = {
      render: () => ["Proxy editor \u2014 Enter: save, then continue with Port"],
      handleInput: (data) => {
        if (data === "\r") {
          // Commit and jump to the "network.port" row, auto-opening its submenu.
          confirm("http://localhost:8080", { navigateTo: "network.port" });
        }
      },
    };
    return editor;
  },
}
```

`SectionedSettings` 还揭露 `selectItem(id)`,将光标移动到项目上,并使用该 id 。 用于程序导航,例如: `updateSections()`。 。 。 .

### 分区设置 vs 设置 细节编辑器

使用 **分区 设置** 单当每行可以一步地被编辑(toggle,enum cycle,或简单的子菜单)时.

使用 **分区 设置 + 设置 详细编辑器** 当选定的行需要一个有多个可编辑字段的焦点二级面板时.

`SettingsDetailEditor` 是数据驱动的。 您通过带有获取器/ 发送器和可选嵌入子菜单调用符的字段描述符 。 该组件仅拥有键盘导航和渲染.

```typescript
import {
  ArrayEditor,
  SettingsDetailEditor,
  type SettingsDetailField,
} from "@aliou/pi-utils-settings";
import { getSettingsListTheme } from "@earendil-works/pi-coding-agent";

const fields: SettingsDetailField[] = [
  {
    id: "autoSave",
    type: "boolean",
    label: "Auto save",
    getValue: () => editor.autoSave,
    setValue: (next) => {
      editor.autoSave = next;
    },
  },
  {
    id: "tabSize",
    type: "enum",
    label: "Tab size",
    getValue: () => String(editor.tabSize),
    setValue: (next) => {
      editor.tabSize = Number.parseInt(next, 10);
    },
    options: ["2", "4", "8"],
  },
  {
    id: "favorites",
    type: "submenu",
    label: "Favorites",
    getValue: () => `${favorites.length} items`,
    submenu: (done) =>
      new ArrayEditor({
        label: "Favorites",
        items: [...favorites],
        theme: getSettingsListTheme(),
        onSave: (items) => {
          favorites = items;
        },
        onDone: () => done(`${favorites.length} items`),
      }),
  },
  {
    id: "clear",
    type: "action",
    label: "Clear favorites",
    getValue: () => "destructive",
    onConfirm: () => {
      favorites = [];
    },
    confirmMessage: "Clear all favorites? This cannot be undone.",
  },
];

const detail = new SettingsDetailEditor({
  title: "Editor details",
  fields,
  theme: getSettingsListTheme(),
  onDone: (summary) => done(summary),
  getDoneSummary: () => `${favorites.length} items`,
  // When hosted via registerSettingsCommand, forward the submenu context's
  // hideHint so the editor's own footer is hidden and the panel shows the
  // editor's shortcuts as its single controls line.
  hideHint: submenuCtx.hideHint,
});
```

### 统一快捷线

设置面板每次制作一个完全的快捷键行,总是在分隔符下方. 当子菜单打开并执行时 `getShortcuts(): string | undefined` (见 `SettingsSubmenuComponent`),面板控制行显示子菜单当前快捷键(例如. `↑/↓ or j/k navigate · Enter edit/open · Esc back`,或 `Enter: confirm · Esc: cancel` 当字段编辑器打开时)而不是默认 `Enter/Space change · Ctrl+S save · Esc close`子菜单没有 `getShortcuts()` 返回默认控制行.

所有内置子菜单组件—— `SettingsDetailEditor`, (中文(简体) ), `ArrayEditor`, (中文(简体) ), `PathArrayEditor`, (中文(简体) ), `FuzzySelector`,以及 `FuzzyMultiSelector` 执行 `getShortcuts()` 每个内部模式并变形(身体上方的平面标题线,没有边框),所以它们干净地坐在面板自己的边界内. 每个接受一个 `hideHint` 选项,该选项会压制自己的提示页脚 `FuzzyMultiSelector`, (中文(简体) ), `hideHint` 优先于现有的 `showHints` 选项(默认) `true`) (中文(简体) ). `SectionedSettings` 转发 `hideHint` 选项,通过子菜单工厂上下文,所以由 `registerSettingsCommand` 只需要一个 `hideHint: ctx.hideHint` (同上)要保持一条捷径. Ctrl+S仍然能从任何深度中省出,尽管子菜单的行可能没有提及它,而埃斯克语义则保持准确:用子菜单打开后,埃斯克背出子菜单而不是关闭面板.

独立的组件用户应离开 `hideHint` 未设置, 因此组件会继续提供自己的提示页脚 .

### 配置接口

`createConfigStore(loader, { scopes? })` 调整一个 `ConfigLoader` 页:1 `ConfigStore` 界面,可选仅向设置 UI 显示一个子集:

```typescript
import { createConfigStore } from "@aliou/pi-utils-settings";

registerSettingsCommand(pi, {
  // ...
  configStore: createConfigStore(configLoader, { scopes: ["global", "local"] }),
});
```

安装自定义配置加载器的扩展 `ConfigStore` 直接代替使用 `ConfigLoader`数字 :

```typescript
interface ConfigStore<TConfig, TResolved> {
  getConfig(): TResolved;
  getRawConfig(scope: Scope): TConfig | null;
  hasScope(scope: Scope): boolean;
  hasConfig(scope: Scope): boolean;
  getEnabledScopes(): Scope[];
  save(scope: Scope, config: TConfig): Promise<void>;
}
```

### 构成部分

-   **分区 设置**: 分组设置列表,带有搜索过滤,在更新时保留光标,并使用pi-tui-parity子菜单导航(`done(value, { navigateTo })`, (中文(简体) ), `selectItem(id)`) (中文(简体) ).
-   **设置详细编辑器**:一个选定项目(文本、enum、布尔语、嵌入子菜单、破坏性行动)的二级重点编辑器.
-   **矩阵编辑器**: 有添加/再移动/重排的字符串阵列编辑器.
-   **路径对话框编辑器**: 路径聚焦阵列编辑器,在添加/编辑模式下Tab完成.
-   **模糊选择器**:模糊-可搜索单选列表.
-   **模糊多选项选择器**: 有锁定/推荐项和子选项的模糊-可搜索多选择清单.
-   **向导**:多步骤设置组件,并有标签导航,进度指标,并有相邻框架.

### 帮助者

-   `setNestedValue(obj, "a.b.c", value)`:通过点与点分隔路径来设置深嵌值.
-   `getNestedValue(obj, "a.b.c")`:通过点-相隔的路径获得深层嵌入值.
-   `getSettingsTheme(theme)`: 构建一个合并设置主题 (`SettingsTheme`既可用于设置列表的组件,也可用于诸如 `Wizard`。 。 。 .
-   `buildSchemaUrl(packageName, version, options?)`: 为 JSON Schema 文件构建一个 URL `$schema` 注入( 默认为 unpkg, 支持自定义) `baseUrl` 或者说 `template`) (中文(简体) ).
-   `pi-settings-schema` CLI: 从 TS 类型生成一个配置 JSON schema, 注射 `$schema`编号 :`version` (单位:千美元)`finalizeSchema`编号 :`generateSettingsSchema` 页:1.

## 出口

```typescript
export {
  ArrayEditor,
  type ArrayEditorOptions,
} from "./src/components/array-editor";
export {
  FuzzyMultiSelector,
  type FuzzyMultiSelectorItem,
  type FuzzyMultiSelectorOptions,
  type FuzzyMultiSelectorSubOption,
} from "./src/components/fuzzy-multi-selector";
export {
  FuzzySelector,
  type FuzzySelectorOptions,
} from "./src/components/fuzzy-selector";
export {
  PathArrayEditor,
  type PathArrayEditorOptions,
} from "./src/components/path-array-editor";
export {
  SectionedSettings,
  type SectionedSettingsOptions,
  type SettingsSection,
} from "./src/components/sectioned-settings";
export {
  type SettingsDetailActionField,
  type SettingsDetailBooleanField,
  SettingsDetailEditor,
  type SettingsDetailEditorOptions,
  type SettingsDetailEnumField,
  type SettingsDetailField,
  type SettingsDetailSubmenuField,
  type SettingsDetailTextField,
} from "./src/components/settings-detail-editor";
export {
  Wizard,
  type WizardOptions,
  type WizardStep,
  type WizardStepContext,
} from "./src/components/wizard";
export {
  ConfigLoader,
  type ConfigStore,
  createConfigStore,
  type Migration,
  type MigrationContext,
  type Scope,
} from "./src/config-loader";
export { getNestedValue, setNestedValue } from "./src/helpers";
export { type BuildSchemaUrlOptions, buildSchemaUrl } from "./src/schema";
export {
  finalizeSchema,
  generateSettingsSchema,
} from "./src/schema-gen.mjs";
export {
  type ExtraSettingsTab,
  type ExtraSettingsTabChangeContext,
  type ExtraSettingsTabContext,
  registerSettingsCommand,
  type SettingsCommandOptions,
} from "./src/settings-command";
export { getSettingsTheme, type SettingsTheme } from "./src/theme";
```

## 常见问题

### @aliou/pi-utils-settings 是什么？

Pi 扩展的共享设置 UI 和配置加载器

### 如何安装 @aliou/pi-utils-settings？

在项目目录运行 npm install @aliou/pi-utils-settings，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 pi-settings-schema，可以用 npx pi-settings-schema 直接运行。

### @aliou/pi-utils-settings 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/aliou\_\_pi-utils-settings 是否存在。

### @aliou/pi-utils-settings 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @aliou/pi-utils-settings 可以商用吗？

@aliou/pi-utils-settings 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @aliou/pi-utils-settings 的下载量有多少？

根据 npm 官方下载统计，@aliou/pi-utils-settings 在 2026/10/06 – 2026/11/04 这 30 天内被下载 8,165 次，日均约 272 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @aliou/pi-utils-settings 还在维护吗？

最新版本 0\.24\.1 发布于 2026/11/04（2 天前）；至今共发布 39 个版本，其中过去 12 个月发布了 39 个；首次发布于 2026/02/04。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

