@x-otto/setting 0.0.1-alpha.4 → 0.1.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Configuration loading, merging, validation, migration, and monitoring. Single source of truth for the config shape via zod schema.
4
4
 
5
- `@x-otto/setting` manages the entire configuration lifecycle: loading from file/env/memory sources, deep merging with precedence layering, version migration, validation with lenient error handling, and remote sync. The config shape is defined by a canonical zod schema (`schema.ts`) from which the `Setting` type and `SETTING_KEYS` are derived. Supports 2 built-in Reviewer Agent presets (spec-reviewer, quality-reviewer).
5
+ `@x-otto/setting` manages the entire configuration lifecycle: loading from file/env/memory sources, deep merging with precedence layering, version migration, validation with lenient error handling, and remote sync. The config shape is defined by a canonical zod schema (`schema.ts`) from which the `Setting` type and `SETTING_KEYS` are derived. `permissions` field merges by `policy.name` key (RFC-404 D4: same-name policies across layers are merged by override, not array union). `installed_plugins` persist is always routed to the global config layer (RFC-404 D3).
6
6
 
7
7
  ## Installation
8
8
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { PERMISSION_MODES, PermissionMode, PermissionPolicySetting, PermissionRuleConfig } from "@x-otto/hook-contracts";
2
2
  import { z } from "zod";
3
3
  import { TypedEventEmitter } from "@x-otto/shared";
4
+ import { ResilienceConfigOverride } from "@x-otto/env";
4
5
  import { AgentProfile } from "@x-otto/prompt";
5
6
 
6
7
  //#region src/store.d.ts
@@ -50,6 +51,9 @@ declare const categoryConfigSchema: z.ZodObject<{
50
51
  preferred_models: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
51
52
  default_model: z.ZodCatch<z.ZodOptional<z.ZodString>>;
52
53
  }, z.core.$strip>;
54
+ declare const providerOverridesSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
55
+ baseUrl: z.ZodString;
56
+ }, z.core.$strict>>;
53
57
  /** 会话结束后自动抽取跨会话经验(operational-learning)。默认关,灰度后再放开。 */
54
58
  declare const notificationConfigSchema: z.ZodObject<{
55
59
  enabled: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
@@ -107,6 +111,7 @@ declare const sandboxConfigSchema: z.ZodObject<{
107
111
  writablePaths: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
108
112
  protectCredentials: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
109
113
  autoAllowBashIfSandboxed: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
114
+ semanticReview: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
110
115
  }, z.core.$strip>;
111
116
  declare const proxyConfigSchema: z.ZodObject<{
112
117
  url: z.ZodCatch<z.ZodOptional<z.ZodString>>;
@@ -127,6 +132,24 @@ declare const mcpServerSettingSchema: z.ZodObject<{
127
132
  autoReconnect: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
128
133
  disabled: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
129
134
  }, z.core.$strip>;
135
+ /**
136
+ * RFC-412 M3:resilience override 的**唯一校验真源**(此前 env 手写递归校验器与本 zod schema
137
+ * 双实现,已收敛至此)。把任意 `unknown`(通常来自 `JSON.parse` 或 settings/programmatic 注入)
138
+ * 经 `resilienceConfigSchema` 校验,剔除非法字段/子对象,返回可安全传给
139
+ * `@x-otto/env` `mergeResilienceConfig` 的干净覆盖对象。
140
+ *
141
+ * 剪除 undefined 的必要性:`lenient = optional().catch(undefined)` 对非法字段产出 `key: undefined`,
142
+ * 而 `mergeResilienceConfig` 用 `Object.assign` 深合并——若保留 `key: undefined` 会把默认值覆盖成
143
+ * undefined。故 parse 后递归剪除 undefined 字段与空子对象,复刻 env 原"非法字段整体剔除、
144
+ * 兄弟字段不受影响"语义。非对象输入返回 undefined。
145
+ */
146
+ declare function validateResilienceOverride(input: unknown): ResilienceConfigOverride | undefined;
147
+ /**
148
+ * RFC-412 M3:解析 `OTTO_RESILIENCE_CONFIG` 环境变量(JSON 字符串)为已校验的覆盖对象。
149
+ * 整体 JSON 解析失败时经 `warn` 上报并返回 undefined(重要诊断,不静默吞);解析成功后走
150
+ * `validateResilienceOverride` 做字段级校验。
151
+ */
152
+ declare function parseResilienceEnvOverride(raw: string | undefined, warn?: (message: string) => void): ResilienceConfigOverride | undefined;
130
153
  /**
131
154
  * RFC-036 @ 面板「最近使用」条目快照(MRU,最多 5 条)——`/model` `recent_models` 同款
132
155
  * 持久化模式的推广:不止模型,@ 面板选中的任意 sigil 条目(文件/agent/skill/mcp/…)
@@ -160,8 +183,8 @@ declare const recentMentionEntrySchema: z.ZodObject<{
160
183
  label: z.ZodString;
161
184
  value: z.ZodString;
162
185
  kind: z.ZodEnum<{
163
- model: "model";
164
186
  file: "file";
187
+ model: "model";
165
188
  hashtag: "hashtag";
166
189
  person: "person";
167
190
  agent: "agent";
@@ -951,8 +974,8 @@ declare const SettingSchema: z.ZodObject<{
951
974
  label: z.ZodString;
952
975
  value: z.ZodString;
953
976
  kind: z.ZodEnum<{
954
- model: "model";
955
977
  file: "file";
978
+ model: "model";
956
979
  hashtag: "hashtag";
957
980
  person: "person";
958
981
  agent: "agent";
@@ -970,6 +993,13 @@ declare const SettingSchema: z.ZodObject<{
970
993
  text: z.ZodString;
971
994
  }, z.core.$strip>>>>;
972
995
  feedback_repo: z.ZodCatch<z.ZodOptional<z.ZodString>>;
996
+ feedback_platform: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
997
+ auto: "auto";
998
+ github: "github";
999
+ coding: "coding";
1000
+ }>>>;
1001
+ feedback_coding_base_url: z.ZodCatch<z.ZodOptional<z.ZodString>>;
1002
+ feedback_coding_repo: z.ZodCatch<z.ZodOptional<z.ZodString>>;
973
1003
  keybinding_overrides: z.ZodCatch<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
974
1004
  ctrl: z.ZodOptional<z.ZodBoolean>;
975
1005
  shift: z.ZodOptional<z.ZodBoolean>;
@@ -1456,6 +1486,8 @@ declare const SettingSchema: z.ZodObject<{
1456
1486
  retry: z.ZodCatch<z.ZodOptional<z.ZodObject<{
1457
1487
  enabled: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
1458
1488
  maxAttempts: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1489
+ backoffMs: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1490
+ backoffMultiplier: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1459
1491
  }, z.core.$strip>>>;
1460
1492
  circuitBreaker: z.ZodCatch<z.ZodOptional<z.ZodObject<{
1461
1493
  enabled: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
@@ -1465,6 +1497,12 @@ declare const SettingSchema: z.ZodObject<{
1465
1497
  routing: z.ZodCatch<z.ZodOptional<z.ZodObject<{
1466
1498
  enabled: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
1467
1499
  }, z.core.$strip>>>;
1500
+ orchestration: z.ZodCatch<z.ZodOptional<z.ZodObject<{
1501
+ maxActiveTasks: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1502
+ maxStoredTasks: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1503
+ maxDelegationDepth: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1504
+ maxFanOutPerParent: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
1505
+ }, z.core.$strip>>>;
1468
1506
  }, z.core.$strip>>>;
1469
1507
  model_slots: z.ZodCatch<z.ZodOptional<z.ZodObject<{
1470
1508
  slots: z.ZodCatch<z.ZodOptional<z.ZodRecord<z.ZodEnum<{
@@ -1483,6 +1521,9 @@ declare const SettingSchema: z.ZodObject<{
1483
1521
  vision: "vision";
1484
1522
  }>>>;
1485
1523
  }, z.core.$strip>>>;
1524
+ provider_overrides: z.ZodCatch<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
1525
+ baseUrl: z.ZodString;
1526
+ }, z.core.$strict>>>>;
1486
1527
  mcp_servers: z.ZodCatch<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
1487
1528
  command: z.ZodCatch<z.ZodOptional<z.ZodString>>;
1488
1529
  args: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
@@ -1534,6 +1575,7 @@ declare const SettingSchema: z.ZodObject<{
1534
1575
  writablePaths: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1535
1576
  protectCredentials: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
1536
1577
  autoAllowBashIfSandboxed: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
1578
+ semanticReview: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
1537
1579
  }, z.core.$strip>>>;
1538
1580
  residency: z.ZodCatch<z.ZodOptional<z.ZodObject<{
1539
1581
  total_bytes: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
@@ -1606,6 +1648,7 @@ declare const SettingSchema: z.ZodObject<{
1606
1648
  }>;
1607
1649
  tools: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1608
1650
  paths: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1651
+ commands: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1609
1652
  deny_reason: z.ZodCatch<z.ZodOptional<z.ZodString>>;
1610
1653
  ask_prompt: z.ZodCatch<z.ZodOptional<z.ZodString>>;
1611
1654
  }, z.core.$strip>>;
@@ -1625,7 +1668,6 @@ declare const SettingSchema: z.ZodObject<{
1625
1668
  _migrations: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1626
1669
  }, z.core.$strip>;
1627
1670
  type Setting = z.infer<typeof SettingSchema>;
1628
- type SettingFromSchema = Setting;
1629
1671
  type ThemeColorRole = z.infer<typeof themeColorRoleSchema>;
1630
1672
  type MarkdownThemeOverridesSetting = z.infer<typeof markdownThemeOverridesSchema>;
1631
1673
  type ThemeOverridesSetting = z.infer<typeof themeOverridesSchema>;
@@ -1636,6 +1678,7 @@ type RecentMentionEntry = z.infer<typeof recentMentionEntrySchema>;
1636
1678
  type InstalledPluginEntry = z.infer<typeof installedPluginEntrySchema>;
1637
1679
  type AgentOptions = z.infer<typeof agentOptionsSchema>;
1638
1680
  type CategoryConfig = z.infer<typeof categoryConfigSchema>;
1681
+ type ProviderOverrides = z.infer<typeof providerOverridesSchema>;
1639
1682
  type NotificationConfig = z.infer<typeof notificationConfigSchema>;
1640
1683
  type ExternalHistoryConfig = z.infer<typeof externalHistoryConfigSchema>;
1641
1684
  type HistoryConfig = z.infer<typeof historyConfigSchema>;
@@ -1643,7 +1686,7 @@ type SandboxConfig = z.infer<typeof sandboxConfigSchema>;
1643
1686
  type ProxyConfig = z.infer<typeof proxyConfigSchema>;
1644
1687
  type McpServerSetting = z.infer<typeof mcpServerSettingSchema>;
1645
1688
  type McpServersConfig = z.infer<typeof SettingSchema>['mcp_servers'];
1646
- declare const SETTING_KEYS: ("model" | "categories" | "prompt_output_token_budget" | "prompt_wall_clock_budget_ms" | "session_cost_budget_usd" | "stall_detection" | "config_version" | "version" | "log_level" | "model_fallback" | "recent_models" | "recent_mentions" | "shortcuts" | "feedback_repo" | "keybinding_overrides" | "language" | "theme" | "theme_overrides" | "theme_preset" | "nickname" | "has_completed_onboarding" | "has_completed_wizard" | "wizard_dont_show_again" | "first_prompt_submitted_at" | "thinking_level" | "agents" | "tool_preset" | "memory_auto_extract" | "skill_loop" | "skill_internalization" | "notification" | "pulse_survey" | "history" | "workflow" | "model_slots" | "mcp_servers" | "resilience" | "sandbox" | "residency" | "disabled_agents" | "disabled_hooks" | "disabled_tools" | "disabled_skills" | "disabled_plugins" | "installed_plugins" | "auto_update_check" | "last_update_check" | "todo_continue_max" | "permission_mode" | "permissions" | "permission_always_allow" | "plugin_lifecycle" | "proxy" | "web_fetch_allowed_hosts" | "_migrations")[];
1689
+ declare const SETTING_KEYS: ("model" | "categories" | "prompt_output_token_budget" | "prompt_wall_clock_budget_ms" | "session_cost_budget_usd" | "stall_detection" | "config_version" | "version" | "log_level" | "model_fallback" | "recent_models" | "recent_mentions" | "shortcuts" | "feedback_repo" | "feedback_platform" | "feedback_coding_base_url" | "feedback_coding_repo" | "keybinding_overrides" | "language" | "theme" | "theme_overrides" | "theme_preset" | "nickname" | "has_completed_onboarding" | "has_completed_wizard" | "wizard_dont_show_again" | "first_prompt_submitted_at" | "thinking_level" | "agents" | "tool_preset" | "memory_auto_extract" | "skill_loop" | "skill_internalization" | "notification" | "pulse_survey" | "history" | "workflow" | "model_slots" | "provider_overrides" | "mcp_servers" | "resilience" | "sandbox" | "residency" | "disabled_agents" | "disabled_hooks" | "disabled_tools" | "disabled_skills" | "disabled_plugins" | "installed_plugins" | "auto_update_check" | "last_update_check" | "todo_continue_max" | "permission_mode" | "permissions" | "permission_always_allow" | "plugin_lifecycle" | "proxy" | "web_fetch_allowed_hosts" | "_migrations")[];
1647
1690
  type SettingKey = keyof Setting;
1648
1691
  //#endregion
1649
1692
  //#region src/types.d.ts
@@ -1651,8 +1694,6 @@ declare const BUILTIN_REVIEWER_AGENTS: Record<string, AgentOptions>;
1651
1694
  interface SettingWarning {
1652
1695
  key: string;
1653
1696
  message: string;
1654
- line?: number;
1655
- column?: number;
1656
1697
  }
1657
1698
  interface LoadSettingOptions {
1658
1699
  store?: SettingStore;
@@ -1678,34 +1719,10 @@ declare function migrate(config: Record<string, unknown>, migrations?: Migration
1678
1719
  applied: string[];
1679
1720
  };
1680
1721
  //#endregion
1681
- //#region src/config-origins.d.ts
1682
- /**
1683
- * config-origins.ts —— RFC review D11:配置来源溯源(codex config/fingerprint.rs
1684
- * record_origins 移植)。
1685
- *
1686
- * 与 `setting.ts` 的 merge 链并行构建一棵「来源树」:每个配置字段记录其最终值的来源层。
1687
- * 用途:`otto doctor` / 诊断面回答「这个值来自哪层」(多层配置合并时最常见的排障问题)。
1688
- *
1689
- * 层序(低→高,与 setting.ts merge 调用序一致):
1690
- * 'default' < 'extra:N' < 'global' < 'project' < 'env'
1691
- *
1692
- * 纯函数、无 IO(与 merge 同构);数组/对象深合并语义与 merge 逐字对齐。
1693
- */
1694
- /** 配置层名:'default' | 'global' | 'project' | 'env' | 'extra:N'(N = extraLayers 下标)。 */
1695
- type ConfigLayerName = 'default' | 'global' | 'project' | 'env' | `extra:${number}`;
1696
- /** 来源树:与配置树同构;叶子 = 该字段最终值的来源层名。 */
1697
- interface ConfigOrigins {
1698
- [key: string]: ConfigLayerName | ConfigOrigins;
1699
- }
1700
- //#endregion
1701
1722
  //#region src/setting.d.ts
1702
1723
  declare class SettingLoader {
1703
1724
  private store?;
1704
- /** RFC review D11:上次 load 的来源树(惰性快照,供诊断面查询「值来自哪层」)。 */
1705
- private lastOrigins?;
1706
1725
  constructor(store?: SettingStore);
1707
- /** RFC review D11:上次 load 的配置来源树(未 load 过返回 undefined)。 */
1708
- getOrigins(): ConfigOrigins | undefined;
1709
1726
  load(options?: LoadSettingOptions): Promise<Setting>;
1710
1727
  }
1711
1728
  declare function loadSetting(options?: LoadSettingOptions): Promise<Setting>;
@@ -1791,19 +1808,49 @@ declare class RemoteSettingStore implements SettingStore {
1791
1808
  exists(_path: string): Promise<boolean>;
1792
1809
  }
1793
1810
  //#endregion
1794
- //#region src/remote-sync-keys.d.ts
1811
+ //#region src/field-meta.d.ts
1812
+ /** 字段合并策略类别(与 config-merge-strategy 的 MergeCategory 对齐)。 */
1813
+ type FieldMergeCategory = 'scalar-override' | 'array-merge' | 'array-merge-by-name' | 'record-merge';
1814
+ /** 是否参与导出/导入。 */
1815
+ type FieldExportPolicy = 'include' | 'exclude';
1816
+ /** 是否可跨设备远端同步。 */
1817
+ type FieldSyncPolicy = 'syncable' | 'never-synced' | 'local-only';
1818
+ /** 单字段元数据。 */
1819
+ interface FieldMeta {
1820
+ /** 跨层合并 / 导入合并策略。 */
1821
+ merge: FieldMergeCategory;
1822
+ /** 是否恒定路由 user 级配置存储(RFC-219 重要事项规则 5)。 */
1823
+ deviceBound: boolean;
1824
+ /** 导出/导入策略:exclude = 不导出不导入(元数据/内部记账字段)。 */
1825
+ export: FieldExportPolicy;
1826
+ /** 远端同步策略:syncable = 可跨设备同步;never-synced = 绝不同步(安全面/凭据/本地路径);local-only = 当前不支持同步但未来可能加入。 */
1827
+ sync: FieldSyncPolicy;
1828
+ }
1795
1829
  /**
1796
- * RFC-052 D2:可跨机器同步的用户偏好字段(syncable keys 白名单)。
1797
- *
1798
- * 与 SettingSchema 同包维护,字段增删时编译期提醒同步检查(R2)。
1830
+ * RFC-405 D1:字段元数据单表。每个 SettingKey 必须显式声明——satisfies 编译期穷举门
1831
+ * 钉死覆盖(新增 schema 字段后 tsc 报错逼停,不允许"先加字段后补元数据")。
1799
1832
  */
1800
- declare const SYNCABLE_KEYS: Set<"model" | "categories" | "prompt_output_token_budget" | "prompt_wall_clock_budget_ms" | "session_cost_budget_usd" | "stall_detection" | "config_version" | "version" | "log_level" | "model_fallback" | "recent_models" | "recent_mentions" | "shortcuts" | "feedback_repo" | "keybinding_overrides" | "language" | "theme" | "theme_overrides" | "theme_preset" | "nickname" | "has_completed_onboarding" | "has_completed_wizard" | "wizard_dont_show_again" | "first_prompt_submitted_at" | "thinking_level" | "agents" | "tool_preset" | "memory_auto_extract" | "skill_loop" | "skill_internalization" | "notification" | "pulse_survey" | "history" | "workflow" | "model_slots" | "mcp_servers" | "resilience" | "sandbox" | "residency" | "disabled_agents" | "disabled_hooks" | "disabled_tools" | "disabled_skills" | "disabled_plugins" | "installed_plugins" | "auto_update_check" | "last_update_check" | "todo_continue_max" | "permission_mode" | "permissions" | "permission_always_allow" | "plugin_lifecycle" | "proxy" | "web_fetch_allowed_hosts" | "_migrations">;
1833
+ declare const FIELD_META: Readonly<Record<SettingKey, FieldMeta>>;
1834
+ /** 不导出/不导入的字段集合(取代 EXCLUDED_KEYS)。 */
1835
+ declare const EXCLUDED_KEYS: ReadonlySet<SettingKey>;
1836
+ /** 可跨设备同步的字段集合(取代 SYNCABLE_KEYS)。 */
1837
+ declare const SYNCABLE_KEYS: ReadonlySet<SettingKey>;
1838
+ /** 绝不可远端同步的字段集合(取代 NEVER_SYNCED_KEYS)。 */
1839
+ declare const NEVER_SYNCED_KEYS: ReadonlySet<string>;
1840
+ /** 字段静态分类表(取代 FIELD_CLASSIFICATION)。 */
1841
+ declare const FIELD_CLASSIFICATION: ReadonlyMap<SettingKey, FieldClassification>;
1842
+ /** 单字段的静态分类(与具体 diff 值无关)。 */
1843
+ interface FieldClassification {
1844
+ category: FieldMergeCategory;
1845
+ deviceBound: boolean;
1846
+ }
1801
1847
  /**
1802
- * RFC-052 D2:绝不可远程同步的字段(安全面/本地路径/凭据)。
1803
- *
1804
- * 此列表保持与 SYNCABLE_KEYS 互斥;不在任一集合的字段为"当前不支持同步,未来可能加入"。
1848
+ * 断言字段元数据表覆盖全部 `SETTING_KEYS`。satisfies 已在编译期保证全覆盖,
1849
+ * 此函数保留供运行时测试调用(向后兼容现有测试)。
1805
1850
  */
1806
- declare const NEVER_SYNCED_KEYS: ReadonlySet<string>;
1851
+ declare function assertFieldClassificationCoversAllKeys(): void;
1852
+ //#endregion
1853
+ //#region src/remote-sync-keys.d.ts
1807
1854
  /**
1808
1855
  * 从 Partial<Setting> 中过滤出仅 syncable 字段(R2)。
1809
1856
  * NEVER_SYNCED 字段即使传入也被移除。
@@ -1950,12 +1997,12 @@ declare function loadClaudeSettingsLayer(workspaceDir?: string): Partial<Setting
1950
1997
  * - `mcp_servers` —— stdio server 启动即 spawn `command`+`args` 任意二进制。
1951
1998
  * - `disabled_hooks` —— 可关掉 permission-guard / sandbox-guard 等安全 hook。
1952
1999
  * - `sandbox` —— 可弱化/关闭沙箱(逃逸)。
2000
+ * - `provider_overrides` —— 可把模型请求与认证凭据转发到任意服务端。
1953
2001
  *
1954
- * 刻意不含的键:`model`/`model_slots`(otto provider 在代码注册、非 config 定义 base_url,
1955
- * 重定向风险低于业界 CLI 实现的 `model_providers`)、`disabled_tools`(减能力非提权)、`agents`
2002
+ * 刻意不含的键:`model`/`model_slots`(只选择已注册模型)、`disabled_tools`(减能力非提权)、`agents`
1956
2003
  * (prompt+工具限制、加载不执行,与业界终端 Agent 实现视 agent 为非可执行面一致)。这些如需收紧另议。
1957
2004
  */
1958
- declare const HIGH_RISK_PROJECT_KEYS: readonly ["permission_mode", "permissions", "permission_always_allow", "mcp_servers", "disabled_hooks", "sandbox"];
2005
+ declare const HIGH_RISK_PROJECT_KEYS: readonly ["permission_mode", "permissions", "permission_always_allow", "mcp_servers", "disabled_hooks", "sandbox", "provider_overrides"];
1959
2006
  interface SanitizeResult {
1960
2007
  /** 剔除高危键后的层(浅拷贝,不改入参)。 */
1961
2008
  value: Partial<Setting>;
@@ -1968,6 +2015,62 @@ interface SanitizeResult {
1968
2015
  */
1969
2016
  declare function sanitizeUntrustedProjectLayer(layer: Partial<Setting>): SanitizeResult;
1970
2017
  //#endregion
2018
+ //#region src/project-trust-gate.d.ts
2019
+ /**
2020
+ * 信任白名单落盘路径(用户级)。`OTTO_CLAUDE_TRUST_PATH` 可覆盖(测试/隔离用,
2021
+ * 避免污染真实 `~/.otto`——参照 auth-store 真路径教训)。调用时求值。
2022
+ */
2023
+ declare function claudeTrustStorePath(): string;
2024
+ /** 该项目根是否已被用户显式信任。 */
2025
+ declare function isProjectTrusted(workspaceDir: string, storePath?: string): boolean;
2026
+ /** 显式信任某项目根(幂等,持久化)。 */
2027
+ declare function trustProject(workspaceDir: string, storePath?: string): void;
2028
+ /** 撤销对某项目根的信任(持久化)。 */
2029
+ declare function untrustProject(workspaceDir: string, storePath?: string): void;
2030
+ /**
2031
+ * 严格项目配置门控是否开启(env-only,项目 config 不可影响,杜绝恶意仓库自关门)。
2032
+ * **默认开**(安全默认):克隆仓库的 `.otto/config.json` 高危键默认不生效,须 `/trust trust`。
2033
+ * `OTTO_STRICT_PROJECT_CONFIG=0` 是逃生口(关门控、恢复旧的全信任行为)。
2034
+ * 注:仅交互态实际剔除(headless fail-open,见 resolveProjectConfigTrusted),故 CI/脚本/测试不受影响。
2035
+ */
2036
+ declare function isStrictProjectConfigEnabled(): boolean;
2037
+ interface ProjectConfigTrustContext {
2038
+ /** 是否交互(TUI)态。缺省 false=headless → fail-open 放行。 */
2039
+ interactive?: boolean;
2040
+ }
2041
+ /**
2042
+ * 该 workspace 的项目配置是否受信任。
2043
+ * 严格模式关 → 恒 `true`;headless → 恒 `true`(fail-open);交互+严格 → 取信任白名单判定。
2044
+ */
2045
+ declare function resolveProjectConfigTrusted(workspaceDir: string, ctx?: ProjectConfigTrustContext): boolean;
2046
+ interface ProjectConfigGating {
2047
+ /** 项目 `.otto/config.json` 实际含有的高危键(空 = 无可门控内容)。 */
2048
+ highRiskKeys: string[];
2049
+ /** 这些高危键当前是否被剔除(严格开 + 交互 + 未信任)。 */
2050
+ gated: boolean;
2051
+ }
2052
+ /**
2053
+ * 探测项目 `.otto/config.json` 的高危键门控状态(供 `/compat status` 呈现)。
2054
+ * 严格模式关 → 返空(特性未启用,无需呈现噪声)。读文件失败/无文件 → 返空。
2055
+ */
2056
+ declare function detectProjectConfigGating(workspaceDir: string, ctx?: ProjectConfigTrustContext): ProjectConfigGating;
2057
+ /** 用户对工作区信任弹窗的选择。 */
2058
+ type WorkspaceTrustAction = 'trust' | 'readonly' | 'exit';
2059
+ interface WorkspaceTrustPromptDecision {
2060
+ /** 是否应弹"信任此文件夹吗"。 */
2061
+ shouldPrompt: boolean;
2062
+ /** 解析到的工作区根(信任按它记录)。 */
2063
+ root: string;
2064
+ /** 不弹的原因(诊断/测试)。 */
2065
+ reason: 'trusted' | 'not-interactive' | 'strict-off' | 'not-a-project' | 'untrusted';
2066
+ }
2067
+ /**
2068
+ * 工作区信任弹窗的纯决策:启动时是否要弹"信任此文件夹吗"。
2069
+ * 弹 ⟺ 交互 且 严格开 且 根未信任 且 是真项目。其余一律不弹。
2070
+ * 纯函数:只读 FS + env,不做 IO 副作用、不渲染。
2071
+ */
2072
+ declare function evaluateWorkspaceTrustPrompt(workspaceDir: string, ctx?: ProjectConfigTrustContext): WorkspaceTrustPromptDecision;
2073
+ //#endregion
1971
2074
  //#region src/presets.d.ts
1972
2075
  /**
1973
2076
  * 预制 agent persona 已移除(2026-06-13,agent-profiles-removal 方案)。
@@ -1979,34 +2082,11 @@ declare function sanitizeUntrustedProjectLayer(layer: Partial<Setting>): Sanitiz
1979
2082
  declare const BUILTIN_AGENT_PROFILES: AgentProfile[];
1980
2083
  //#endregion
1981
2084
  //#region src/config-merge-strategy.d.ts
1982
- /** 合并策略类别(RFC-219 milestone M2 §设计闸门要点订正后的接口)。 */
1983
- type MergeCategory = 'scalar-override' | 'array-merge' | 'record-merge';
1984
- /** 单个字段的静态分类(与具体 diff 值无关)。 */
1985
- interface FieldClassification {
1986
- category: MergeCategory;
1987
- /**
1988
- * 恒定路由 user 级配置存储,不受目标 scope 参数影响(RFC-219 重要事项规则 5)。
1989
- * 仅供 M3/M4 的导入落盘目标判定使用,本模块自身不做任何写入。
1990
- */
1991
- deviceBound: boolean;
1992
- }
1993
2085
  /**
1994
- * 排除字段——不导出、不导入,`diffConfig` 返回结果中永不出现(RFC-219 字段策略表)。
1995
- * `config_version`/`version` 是元数据字段(导入侧沿用当前 otto 版本自身值,不采用导入
1996
- * 文件里的值);`last_update_check`/`_migrations` 是内部记账字段。
2086
+ * RFC-405 D1:MergeCategory 从 field-meta 的 FieldMergeCategory 派生(单源)。
2087
+ * 保留原类型名向后兼容(消费方 import MergeCategory)。
1997
2088
  */
1998
- declare const EXCLUDED_KEYS: ReadonlySet<SettingKey>;
1999
- /**
2000
- * 字段静态分类表(RFC-219 §设计·字段策略表,M2 实现期订正版:合并策略与设备绑定分离为
2001
- * 两个独立字段)。`EXCLUDED_KEYS` 里的字段不在此表出现(完整性校验单独处理,见
2002
- * `assertFieldClassificationCoversAllKeys`)。
2003
- */
2004
- declare const FIELD_CLASSIFICATION: ReadonlyMap<SettingKey, FieldClassification>;
2005
- /**
2006
- * 断言字段分类表覆盖全部 `SETTING_KEYS`(含 excluded 字段)。新增 schema 字段忘记归类
2007
- * 时抛错——供单测调用,防止静默漏判(RFC-219 §风险与验证策略)。
2008
- */
2009
- declare function assertFieldClassificationCoversAllKeys(): void;
2089
+ type MergeCategory = FieldMergeCategory;
2010
2090
  /** 单字段差异。`risk` 是按本次具体 from/to 值计算的实例级结果,非字段静态属性。 */
2011
2091
  interface FieldDiff {
2012
2092
  key: SettingKey;
@@ -2120,5 +2200,5 @@ declare class ExportFileParseError extends Error {
2120
2200
  */
2121
2201
  declare function parseExportFile(raw: string): ConfigExportFile;
2122
2202
  //#endregion
2123
- export { type AgentOptions, BUILTIN_AGENT_PROFILES, BUILTIN_REVIEWER_AGENTS, CURRENT_EXPORT_VERSION, type CategoryConfig, type ConfigExportFile, type ConfigLayerName, type ConfigOrigins, DEFAULT_CONFIG, EXCLUDED_KEYS, ExportFileParseError, ExportFileVersionError, type ExternalHistoryConfig, FIELD_CLASSIFICATION, type FieldClassification, type FieldDiff, HIGH_RISK_PROJECT_KEYS, type HistoryConfig, type InstalledPluginEntry, LOG_LEVELS, type LoadSettingOptions, type LogLevel, type MarkdownThemeOverridesSetting, type McpServerSetting, type McpServersConfig, type MergeCategory, type Migration, NEVER_SYNCED_KEYS, type NotificationConfig, PERMISSION_MODES, type PermissionMode, type PermissionPolicySetting, type PermissionRuleConfig, type PluginDiff, type ProxyConfig, RawFileSettingStore, type RecentMentionEntry, RemoteSettingStore, SETTING_KEYS, SYNCABLE_KEYS, type SandboxConfig, type SanitizeResult, type Setting, type SettingFromSchema, type SettingKey, SettingLoader, type SettingStore, type SettingWarning, SettingsManager, type SettingsOptions, type StorageType, THEME_COLOR_ROLES, TOOL_PRESETS, type ThemeColorRole, type ThemeOverridesSetting, type ThemePresetSelectionSetting, type ToolPreset, applyMergeStrategy, assertFieldClassificationCoversAllKeys, buildExportPayload, classifyPluginChanges, diffConfig, filterSyncable, globToRegexSource, hasSecuritySensitiveChanges, loadClaudeSettingsLayer, loadSetting, migrate, parseExportFile, parseToolSpecifier, sanitizeUntrustedProjectLayer, translateClaudeSettings };
2203
+ export { type AgentOptions, BUILTIN_AGENT_PROFILES, BUILTIN_REVIEWER_AGENTS, CURRENT_EXPORT_VERSION, type CategoryConfig, type ConfigExportFile, DEFAULT_CONFIG, EXCLUDED_KEYS, ExportFileParseError, ExportFileVersionError, type ExternalHistoryConfig, FIELD_CLASSIFICATION, FIELD_META, type FieldClassification, type FieldDiff, type FieldExportPolicy, type FieldMergeCategory, type FieldMeta, type FieldSyncPolicy, HIGH_RISK_PROJECT_KEYS, type HistoryConfig, type InstalledPluginEntry, LOG_LEVELS, type LoadSettingOptions, type LogLevel, type MarkdownThemeOverridesSetting, type McpServerSetting, type McpServersConfig, type MergeCategory, type Migration, NEVER_SYNCED_KEYS, type NotificationConfig, PERMISSION_MODES, type PermissionMode, type PermissionPolicySetting, type PermissionRuleConfig, type PluginDiff, type ProjectConfigGating, type ProjectConfigTrustContext, type ProviderOverrides, type ProxyConfig, RawFileSettingStore, type RecentMentionEntry, RemoteSettingStore, SETTING_KEYS, SYNCABLE_KEYS, type SandboxConfig, type SanitizeResult, type Setting, type SettingKey, SettingLoader, type SettingStore, type SettingWarning, SettingsManager, type SettingsOptions, type StorageType, THEME_COLOR_ROLES, TOOL_PRESETS, type ThemeColorRole, type ThemeOverridesSetting, type ThemePresetSelectionSetting, type ToolPreset, type WorkspaceTrustAction, type WorkspaceTrustPromptDecision, applyMergeStrategy, assertFieldClassificationCoversAllKeys, buildExportPayload, classifyPluginChanges, claudeTrustStorePath, detectProjectConfigGating, diffConfig, evaluateWorkspaceTrustPrompt, filterSyncable, globToRegexSource, hasSecuritySensitiveChanges, isProjectTrusted, isStrictProjectConfigEnabled, loadClaudeSettingsLayer, loadSetting, migrate, parseExportFile, parseResilienceEnvOverride, parseToolSpecifier, resolveProjectConfigTrusted, sanitizeUntrustedProjectLayer, translateClaudeSettings, trustProject, untrustProject, validateResilienceOverride };
2124
2204
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/store.ts","../src/constants.ts","../src/schema.ts","../src/types.ts","../src/migrator.ts","../src/config-origins.ts","../src/setting.ts","../src/raw-file-store.ts","../src/remote-setting-store.ts","../src/remote-sync-keys.ts","../src/settings-manager.ts","../src/claude-settings-adapter.ts","../src/project-trust.ts","../src/presets.ts","../src/config-merge-strategy.ts","../src/config-export-format.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/store.ts","../src/constants.ts","../src/schema.ts","../src/types.ts","../src/migrator.ts","../src/setting.ts","../src/raw-file-store.ts","../src/remote-setting-store.ts","../src/field-meta.ts","../src/remote-sync-keys.ts","../src/settings-manager.ts","../src/claude-settings-adapter.ts","../src/project-trust.ts","../src/project-trust-gate.ts","../src/presets.ts","../src/config-merge-strategy.ts","../src/config-export-format.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{PERMISSION_MODES as e}from"@x-otto/hook-contracts";import{z as t}from"zod";import{MODEL_SLOTS as n}from"@x-otto/orchestration-contracts";import{compare as r}from"semver";import{TypedEventEmitter as i,createLogger as a,mapClaudeToolName as o,parseJsonc as s,safeStringify as c}from"@x-otto/shared";import{atomicWriteFile as l}from"@x-otto/persistence";import{CLAUDE_HOME as u,OTTO_CONFIG_FILENAME as d,OTTO_HOME as f,OTTO_PROJECT_CONFIG_RELPATH as ee,isClaudeSettingsCompatEnabled as te,isShadowModeEnabled as ne}from"@x-otto/env";import{isAbsolute as re,join as p,resolve as m}from"node:path";import{homedir as ie}from"node:os";import{existsSync as ae,readFileSync as oe}from"node:fs";import{HIGH_RISK_CAPABILITIES as se}from"@x-otto/plugin";const h=[`minimal`,`standard`,`full`],g=[`trace`,`debug`,`info`,`warn`,`error`,`fatal`],_=e=>e.optional().catch(void 0),v=t.enum(n),ce=t.object({model:_(t.string()),description:_(t.string()),system_prompt:_(t.string()),tools:_(t.array(t.string())),capabilities:_(t.array(t.string())),categories:_(t.array(t.string())),default_workflow_slot:_(v),max_tool_turns:_(t.number()),max_tool_turn_extensions:_(t.number()),prompt_output_token_budget:_(t.number()),prompt_wall_clock_budget_ms:_(t.number()),session_cost_budget_usd:_(t.number()),stall_detection:_(t.union([t.literal(!1),t.object({window_turns:_(t.number()),repeat_threshold:_(t.number())})])),temperature:_(t.number()),max_tokens:_(t.number()),disabled:_(t.boolean())}),le=t.object({preferred_models:_(t.array(t.string())),default_model:_(t.string())}),ue=t.object({enabled:_(t.boolean()),every_n_turns:_(t.number()),max_lessons:_(t.number()),similarity_threshold:_(t.number()),min_relevant_hits:_(t.number())}),de=t.object({enabled:_(t.boolean()),min_messages:_(t.number()),dismiss_cooldown_days:_(t.number())}),fe=t.object({enabled:_(t.boolean()),min_executions:_(t.number()),min_success_rate:_(t.number()),max_internalized:_(t.number())}),pe=t.object({slots:_(t.partialRecord(v,t.union([t.string(),t.array(t.string())]))),default:_(t.string()),subagent_default_slot:_(v)}),me=t.object({enabled:_(t.boolean()),sound:_(t.boolean()),on_completion:_(t.boolean()),on_error:_(t.boolean()),on_idle:_(t.boolean()),channel:_(t.enum([`auto`,`terminal_bell`,`iterm2`,`iterm2_with_bell`,`kitty`,`ghostty`,`disabled`])),condition:_(t.enum([`unfocused`,`always`])),idle_threshold_ms:_(t.number()),command:_(t.array(t.string()))}),he=t.object({enabled:_(t.boolean()),probability:_(t.number()),min_turn_gap:_(t.number()),sink:_(t.string())}),ge=t.object({id:_(t.string()),path:_(t.string()),enabled:_(t.boolean())}),_e=t.object({enabled:_(t.boolean()),maxEntries:_(t.number()),sources:_(t.array(ge))}),ve=t.object({external:_(_e)}),ye=t.object({enabled:t.boolean(),network:_(t.enum([`allow`,`deny`])),writablePaths:_(t.array(t.string())),protectCredentials:_(t.boolean()),autoAllowBashIfSandboxed:_(t.boolean())}),be=t.object({total_bytes:_(t.number()),min_per_session_bytes:_(t.number()),max_per_session_bytes:_(t.number()),max_history_messages:_(t.number()),resume_window_messages:_(t.number()),max_content_bytes:_(t.number()),warn_threshold_pct:_(t.number()),hard_threshold_pct:_(t.number()),compaction_timeout_ms:_(t.number()),coverage_warn_threshold:_(t.number()),coverage_error_threshold:_(t.number()),coverage_floor_threshold:_(t.number())});t.object({tool_preset:_(t.enum(h)),disabled_tools:_(t.array(t.string()))});const xe=t.object({enabled:_(t.boolean())}),Se=t.object({enabled:_(t.boolean()),maxAttempts:_(t.number())}),Ce=t.object({enabled:_(t.boolean()),failureThreshold:_(t.number()),timeoutMs:_(t.number())}),we=t.object({enabled:_(t.boolean())}),Te=t.object({enabled:_(t.boolean()),review:_(xe),retry:_(Se),circuitBreaker:_(Ce),routing:_(we)}),Ee=t.object({name:t.string(),effect:t.enum([`allow`,`deny`,`ask`]),tools:_(t.array(t.string())),paths:_(t.array(t.string())),deny_reason:_(t.string()),ask_prompt:_(t.string())}),De=t.object({name:t.string(),priority:_(t.number()),enabled:_(t.boolean()),scope:_(t.object({agents:_(t.array(t.string())),sessions:_(t.array(t.string()))})),rules:t.array(Ee)}),Oe=t.object({url:_(t.string()),enabled:_(t.boolean())}),ke=t.object({command:_(t.string()),args:_(t.array(t.string())),env:_(t.record(t.string(),t.string())),url:_(t.string()),type:_(t.enum([`stdio`,`sse`,`http`])),headers:_(t.record(t.string(),t.string())),requestTimeoutMs:_(t.number()),autoReconnect:_(t.boolean()),disabled:_(t.boolean())}),Ae=t.object({maxRetries:_(t.number().int().positive()),initialDelayMs:_(t.number().positive()),backoffFactor:_(t.number().positive()),maxDelayMs:_(t.number().positive())}),je=t.object({maxRetries:_(t.number().int().positive()),intervalMs:_(t.number().positive())}),Me=t.object({maxReconnectAttempts:_(t.number().int().nonnegative()),reconnectDelayMs:_(t.number().positive()),requestTimeoutMs:_(t.number().positive())}),Ne=t.object({retryBackoffMs:_(t.number().nonnegative())}),Pe=t.object({maxAttempts:_(t.number().int().positive()),intervalMs:_(t.number().positive())}),Fe=t.object({refreshLockTimeoutMs:_(t.number().min(1e3))}),Ie=t.object({stream:_(Ae),networkDisconnect:_(je),mcp:_(Me),schedule:_(Ne),errorRetry:_(Pe),oauth:_(Fe)}),Le=t.object({id:t.string(),source:t.enum([`npm`,`dir`,`url`,`git`]),sourceSpec:_(t.string()),installedAt:t.number(),version:_(t.string()),scope:t.enum([`global`,`project`,`repository`]),capabilities:_(t.array(t.string()))}),Re=t.object({label:t.string(),value:t.string(),kind:t.enum([`hashtag`,`file`,`person`,`agent`,`skill`,`mcp`,`plugin`,`model`,`resource`,`shortcut`,`effort`]),description:_(t.string())}),ze=t.object({name:t.string().min(1).max(64),text:t.string().min(1).max(4e3)}),y=`brand.brandShimmer.accent.accentDim.accentBright.text.inactive.secondary.subtle.replyPrefix.success.error.warning.special.suggestion.permission.codeText.diffAdd.diffRemove.diffAddBg.diffRemoveBg.panelBorder.overlayBg.tagBg.toolText.focusBorder.selection`.split(`.`),b=t.enum(y),Be=t.strictObject({heading1:_(b),heading2:_(b),headingWeak:_(b),listMarker:_(b),listMarkerMuted:_(b),quoteBar:_(b),quoteText:_(b),link:_(b),inlineCode:_(b),codeFence:_(b),tableHeader:_(b),tableDivider:_(b),listIndent:_(t.union([t.literal(2),t.literal(3)])),listMarkers:_(t.tuple([t.string().min(1),t.string().min(1),t.string().min(1),t.string().min(1)])),codeBlockDivider:_(t.enum([`hr`,`none`]))}),Ve=t.strictObject({markdown:_(Be)}),He=t.strictObject({dark:_(t.string().min(1).max(128)),light:_(t.string().min(1).max(128))}),x=t.object({config_version:_(t.string()),version:_(t.string()),log_level:_(t.enum(g)),model:_(t.string()),model_fallback:_(t.array(t.string())),recent_models:_(t.array(t.string())),recent_mentions:_(t.array(Re)),shortcuts:_(t.array(ze)),feedback_repo:_(t.string()),keybinding_overrides:_(t.record(t.string(),t.object({ctrl:t.boolean().optional(),shift:t.boolean().optional(),meta:t.boolean().optional(),input:t.string().optional(),key:t.enum([`tab`,`escape`,`return`]).optional()}))),language:_(t.string()),theme:_(t.enum([`dark`,`light`,`system`])),theme_overrides:_(Ve),theme_preset:_(He),nickname:_(t.string().max(64)),has_completed_onboarding:_(t.boolean()),has_completed_wizard:_(t.boolean()),wizard_dont_show_again:_(t.boolean()),first_prompt_submitted_at:_(t.number()),thinking_level:_(t.string()),agents:_(t.record(t.string(),ce)),categories:_(t.record(t.string(),le)),tool_preset:_(t.enum(h)),memory_auto_extract:_(ue),skill_loop:_(de),skill_internalization:_(fe),notification:_(me),pulse_survey:_(he),history:_(ve),workflow:_(Te),model_slots:_(pe),mcp_servers:_(t.record(t.string(),ke)),resilience:_(Ie),sandbox:_(ye),residency:_(be),disabled_agents:_(t.array(t.string())),disabled_hooks:_(t.array(t.string())),disabled_tools:_(t.array(t.string())),disabled_skills:_(t.array(t.string())),disabled_plugins:_(t.array(t.string())),installed_plugins:_(t.array(Le)),auto_update_check:_(t.boolean()),last_update_check:_(t.number()),prompt_output_token_budget:_(t.number()),prompt_wall_clock_budget_ms:_(t.number()),session_cost_budget_usd:_(t.number()),stall_detection:_(t.union([t.literal(!1),t.object({window_turns:_(t.number()),repeat_threshold:_(t.number())})])),todo_continue_max:_(t.number()),permission_mode:_(t.enum(e)),permissions:_(t.array(De)),permission_always_allow:_(t.array(t.string())),plugin_lifecycle:_(t.object({setupDone:_(t.array(t.object({id:t.string(),version:_(t.string())})))})),proxy:_(Oe),web_fetch_allowed_hosts:_(t.array(t.string())),_migrations:_(t.array(t.string()))}),Ue=y,S=x.keyof().options,C={"spec-reviewer":{description:`Reviews implementation against specification requirements`,categories:[`review`],default_workflow_slot:`critique`},"quality-reviewer":{description:`Reviews code quality, patterns, and best practices`,categories:[`review`],default_workflow_slot:`critique`}},w={config_version:`1.0.0`,log_level:`info`,model:void 0,recent_models:[],recent_mentions:[],shortcuts:[],language:`auto`,theme:void 0,nickname:void 0,has_completed_onboarding:void 0,has_completed_wizard:void 0,wizard_dont_show_again:void 0,first_prompt_submitted_at:void 0,thinking_level:void 0,tool_preset:`full`,agents:{...C},categories:{},workflow:{},disabled_agents:[],disabled_hooks:[],disabled_tools:[],disabled_skills:[],disabled_plugins:[],installed_plugins:[],auto_update_check:!0,last_update_check:void 0,permission_mode:`auto`,permissions:[],permission_always_allow:[],web_fetch_allowed_hosts:[],notification:{enabled:!0,sound:!1,on_completion:!0,on_error:!0,channel:`auto`,condition:`unfocused`,idle_threshold_ms:6e4}},We=a(`@x-otto/setting:migrator`);function T(e,t=[]){let n=typeof e.config_version==`string`?e.config_version:`0.0.0`,i=[],a={...e};for(let e of t)r(e.version,n)>0&&(a=e.migrate(a),a.config_version=e.version,i.push(`${n} → ${e.version}`),We.info({from:n,to:e.version},`Applying migration: ${e.description}`));if(i.length>0){let e=Array.isArray(a._migrations)?a._migrations:[];a._migrations=[...e,...i]}return{config:a,applied:i}}const E=[`permission_mode`,`permissions`,`permission_always_allow`,`mcp_servers`,`disabled_hooks`,`sandbox`];function D(e){let t={...e},n=[];for(let e of E)e in t&&(delete t[e],n.push(e));return{value:t,stripped:n}}function O(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function k(e,t,n,r){let i={...e},a={...n};for(let[e,o]of Object.entries(t))if(o!==void 0)if(O(o)&&O(i[e])){let t=k(i[e],o,n[e]??{},r);i[e]=t.value,a[e]=t.origins}else i[e]=o,a[e]=r;return{value:i,origins:a}}function Ge(e){let t={},n={};for(let{layer:r,name:i}of e)for(let[e,a]of Object.entries(r))if(a!==void 0){if(Array.isArray(t[e])&&Array.isArray(a)){let r=t[e],o=a;t[e]=[...new Set([...r,...o])],n[e]=i;continue}if(O(a)&&O(t[e])){let r=k(t[e],a,n[e]??{},i);t[e]=r.value,n[e]=r.origins}else if(O(a)){let r=k({},a,{},i);t[e]=r.value,n[e]=r.origins}else t[e]=a,n[e]=i}return{value:t,origins:n}}const A=a(`@x-otto/setting`),Ke=new Set(g),qe=[`mcp`,`skills`,`disabled_mcps`,`disabled_skills`],Je=[`theme_file`,`theme_spacing`,`theme_border`,`theme_figures`],Ye=new Set([`accent`,`accentDim`,`accentBright`,`colors`,`spacing`,`border`,`figures`,`text`,`inactive`,`secondary`,`success`,`error`,`warning`,`special`]);function j(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function M(e,t,n,r){for(let[i,a]of Object.entries(e)){if(a===void 0)continue;let e=t[i],o=[...n,i].join(`.`);if(e===void 0){r.push({key:o,message:`Invalid value for "${o}" ignored`});continue}j(a)&&j(e)&&M(a,e,[...n,i],r)}}function N(e,t){let n={...e};for(let[e,r]of Object.entries(t))r!==void 0&&(j(r)&&j(n[e])?n[e]=N(n[e],r):n[e]=r);return n}function P(...e){let[t,n,...r]=e,i={...t};if(n){for(let[e,t]of Object.entries(n))if(t!==void 0)if(Array.isArray(i[e])&&Array.isArray(t)){let n=i[e],r=t;i[e]=[...new Set([...n,...r])]}else j(t)&&j(i[e])?i[e]=N(i[e],t):i[e]=t}return r.length>0?P(i,...r):i}function Xe(){let e={},t=process.env.OTTO_MODEL;t&&(e.model=t);let n=process.env.OTTO_LOG_LEVEL;return n&&Ke.has(n)&&(e.log_level=n),e}function Ze(e){let t=[],n={...e};for(let e of qe)n[e]!==void 0&&(t.push({key:e,message:`Removed legacy config key is ignored`}),delete n[e]);for(let e of Je)n[e]!==void 0&&(t.push({key:e,message:`RFC-205 legacy theme override key is ignored`}),delete n[e]);if(j(n.theme_overrides)){let e=Object.keys(n.theme_overrides).filter(e=>Ye.has(e));e.length>0&&t.push({key:`theme_overrides`,message:`RFC-205 legacy theme_overrides shape (keys: ${e.join(`, `)}) is ignored — use theme_overrides.markdown instead`})}let r=x.loose().safeParse(n),i=r.success?r.data:n,a={};for(let[e,t]of Object.entries(i))t!==void 0&&(a[e]=t);for(let e of S){let r=n[e],i=a[e];if(r!==void 0&&i===void 0){t.push({key:e,message:`Invalid value for "${e}" ignored`});continue}j(r)&&j(i)&&M(r,i,[e],t)}return{value:a,warnings:t}}async function Qe(e,t,n){let r=[],i=[];for(let a of t)try{let t=await e.read(a);if(t!==void 0){let e=s(t);if(n!==void 0&&a===n){let t=D(e);e=t.value,i.push(...t.stripped)}r.push(e),A.debug({path:a},`Config loaded from store`)}}catch(e){A.warn({path:a,err:e},`Failed to parse config file, skipping`)}return{layers:r,stripped:i}}var F=class{store;lastOrigins;constructor(e){this.store=e}getOrigins(){return this.lastOrigins}async load(e={}){let{store:t=this.store,paths:n=[],extraLayers:r=[],untrustedProjectPath:i}=e,{layers:a,stripped:o}=t&&n.length>0?await Qe(t,n,i):{layers:[],stripped:[]};for(let e of o)A.warn({key:e,path:i},`未受信任项目配置剔除高危键(permission_mode/mcp_servers 等需先信任该目录)`);let s=Xe(),c=P(w,...r,...a,s);this.lastOrigins=Ge([{layer:w,name:`default`},...r.map((e,t)=>({layer:e,name:`extra:${t}`})),...a.map((e,t)=>({layer:e,name:t===a.length-1?`project`:`global`})),{layer:s,name:`env`}]).origins;let{config:l,applied:u}=T(c);u.length>0&&A.info({applied:u},`Config migrations applied`);let{value:d,warnings:f}=Ze(l);for(let e of f)A.warn({key:e.key,message:e.message},`Config validation issue`);return{...w,...d}}};async function I(e={}){return new F(e.store).load(e)}var L=class{type=`file`;async read(e){let{readFile:t}=await import(`node:fs/promises`);try{return await t(await R(e),`utf-8`)}catch{return}}async write(e,t){let{mkdir:n}=await import(`node:fs/promises`),{dirname:r}=await import(`node:path`),i=await R(e);await n(r(i),{recursive:!0}),await l(i,c(t,2))}async exists(e){let{access:t}=await import(`node:fs/promises`);try{return await t(await R(e)),!0}catch{return!1}}};async function R(e){if(!e.startsWith(`~/`))return e;let{homedir:t}=await import(`node:os`);return`${t()}${e.slice(1)}`}const z=new Set([`model`,`model_fallback`,`recent_models`,`language`,`nickname`,`has_completed_onboarding`,`has_completed_wizard`,`wizard_dont_show_again`,`first_prompt_submitted_at`,`log_level`,`notification`,`auto_update_check`,`model_slots`,`disabled_agents`,`disabled_hooks`,`disabled_tools`,`disabled_skills`]),B=new Set([`recent_mentions`,`shortcuts`,`mcp_servers`,`sandbox`,`permission_mode`,`permissions`,`permission_always_allow`,`web_fetch_allowed_hosts`,`session`,`tool_preset`,`config_version`,`version`,`_migrations`,`last_update_check`,`memory_auto_extract`,`skill_loop`,`skill_internalization`,`workflow`,`categories`,`agents`,`disabled_plugins`,`installed_plugins`]);function V(e){let t={};for(let n of Object.keys(e))z.has(n)&&!B.has(n)&&(t[n]=e[n]);return t}var $e=class{type=`file`;baseUrl;userId;getAuth;fetchImpl;timeoutMs;constructor(e){this.baseUrl=e.baseUrl.replace(/\/+$/,``),this.userId=e.userId,this.getAuth=e.getAuth,this.fetchImpl=e.fetch,this.timeoutMs=e.timeoutMs}async read(e){let t={Authorization:`Bearer ${(await this.getAuth()).token}`,Accept:`application/json`,"X-Otto-User-Id":this.userId},n=new AbortController,r=setTimeout(()=>n.abort(),this.timeoutMs),i;try{i=await this.fetchImpl(`${this.baseUrl}/config/user`,{method:`GET`,headers:t,signal:n.signal})}finally{clearTimeout(r)}if(i.status===404)return;if(!i.ok)throw Error(`remote settings read failed: HTTP ${i.status}`);let a=await i.json();return JSON.stringify(a)}async write(e,t){let n=V(t);if(Object.keys(n).length===0)return;let r={Authorization:`Bearer ${(await this.getAuth()).token}`,"Content-Type":`application/json`,"X-Otto-User-Id":this.userId},i=new AbortController,a=setTimeout(()=>i.abort(),this.timeoutMs),o;try{o=await this.fetchImpl(`${this.baseUrl}/config/user`,{method:`PUT`,headers:r,body:JSON.stringify(n),signal:i.signal})}finally{clearTimeout(a)}if(!o.ok)throw Error(`remote settings write failed: HTTP ${o.status}`)}async exists(e){return!1}};const H=a(`@x-otto/setting:claude-adapter`),et=new Set([`Read`,`Write`,`Edit`,`MultiEdit`,`Glob`,`Grep`]),U={default:`confirm`,acceptEdits:`auto`,bypassPermissions:`bypass`,plan:`readonly`};function W(e){let t=/^([A-Za-z][A-Za-z0-9_]*)(?:\((.*)\))?$/.exec(e.trim());return t?{tool:t[1],specifier:t[2]}:{tool:e.trim()}}function G(e){let t=e.startsWith(`~/`)?p(ie(),e.slice(2)):e,n=``;for(let e=0;e<t.length;e++){let r=t[e];r===`*`?t[e+1]===`*`?(n+=`.*`,e++):n+=`[^/]*`:r===`?`?n+=`.`:n+=r.replace(/[.+^${}()|[\]\\]/g,`\\$&`)}return`^${n}$`}function tt(e,t,n,r){let{tool:i,specifier:a}=W(e),s=o(i);if(!s){n.warnings.push(`未知工具 "${i}"(${e})→ fail-closed 丢弃`);return}if(i===`WebFetch`&&a?.startsWith(`domain:`)){let e=a.slice(7).trim();if(t===`allow`&&e){n.webFetchHosts.push(e);return}let i=t===`deny`?`deny`:`ask`;n.rules.push({name:`claude-${r}`,effect:i,tools:[s]}),n.warnings.push(`WebFetch(${a}) 的 ${t} 不可按域表达 → ${i===`deny`?`降工具级 deny(fail-closed)`:`降 ask`}`);return}if(a===void 0||a===``){n.rules.push({name:`claude-${r}`,effect:t,tools:[s]});return}if(et.has(i)){n.rules.push({name:`claude-${r}`,effect:t,tools:[s],paths:[G(a)]});return}n.rules.push({name:`claude-${r}`,effect:`ask`,tools:[s],ask_prompt:`Claude 规则 "${e}" 含命令参数限定,otto 无法精确表达,已降为询问。`}),n.warnings.push(`"${e}" 含参数 specifier 不可表达 → fail-closed 降 ask`)}function K(e){let t={rules:[],webFetchHosts:[],warnings:[]},n=e?.permissions,r=0;for(let e of[`allow`,`deny`,`ask`]){let i=n?.[e];if(Array.isArray(i))for(let n of i)typeof n==`string`&&tt(n,e,t,r++)}let i={};t.rules.length>0&&(i.permissions=[{name:`claude-compat`,rules:t.rules}]),t.webFetchHosts.length>0&&(i.web_fetch_allowed_hosts=[...new Set(t.webFetchHosts)]);let a=typeof n?.defaultMode==`string`?n.defaultMode:void 0;return a&&U[a]&&(i.permission_mode=U[a],a===`plan`&&t.warnings.push(`defaultMode=plan otto 无对应 → 降 readonly`)),{setting:i,warnings:t.warnings}}function q(e){if(!te())return{};let t=[p(u,`settings.json`),...e?[p(m(e),`.claude`,`settings.json`),p(m(e),`.claude`,`settings.local.json`)]:[]],n=[],r=[],i,a=[];for(let e of t){if(!ae(e))continue;let t;try{t=s(oe(e,`utf-8`))}catch(t){H.warn({file:e,err:t},`Failed to parse .claude settings, skipped`);continue}let{setting:o,warnings:c}=K(t);a.push(...c);let l=o.permissions?.[0]?.rules;l&&n.push(...l),o.web_fetch_allowed_hosts&&r.push(...o.web_fetch_allowed_hosts),o.permission_mode&&(i=o.permission_mode)}let o={};n.length>0&&(o.permissions=[{name:`claude-compat`,rules:n}]),r.length>0&&(o.web_fetch_allowed_hosts=[...new Set(r)]),i&&(o.permission_mode=i);let c=n.length;if(c>0||a.length>0){H.info({ruleCount:c,hosts:o.web_fetch_allowed_hosts?.length??0,mode:o.permission_mode},`Imported .claude/settings.json (RFC-032 D4)`);for(let e of a)H.warn({rule:e},`.claude settings 翻译降级`)}return o}var nt=class extends i{paths;workspaceDir;projectConfigTrusted;overrides;store;remoteStore;setting={};writeChain=Promise.resolve();constructor(e={}){super(),this.paths=rt(e),this.workspaceDir=e.workspaceDir,this.projectConfigTrusted=e.projectConfigTrusted??!0,this.overrides={...e.overrides},this.store=e.store??new L,this.remoteStore=e.remoteStore}get(e){return this.setting[e]}get config(){return this.setting}get model(){return this.setting.model}async load(){return this.reload(this.overrides)}async reload(e){let t;if(this.remoteStore)try{let e=await this.remoteStore.read(`/config/user`);e!==void 0&&(t=s(e))}catch(e){this.emit(`remote-sync-failed`,{op:`read`,error:e})}return this.setting={...await I({store:this.store,paths:this.paths,untrustedProjectPath:this.resolveUntrustedProjectPath(),extraLayers:[q(this.workspaceDir),...t?[t]:[]]}),...e},this.emit(`change`,this.setting),this.setting}async update(e){return this.overrides={...this.overrides,...e},this.reload(this.overrides)}async persist(e,t){if(ne())return this.update(e);let n=t===`global`?this.paths[0]:this.paths[this.paths.length-1],r=this.store;return r&&n?this.enqueueWrite(async()=>{let t=await r.read(n),i={};if(t)try{i=s(t)}catch{i={}}return await r.write(n,{...i,...e}),this.remoteStore&&this.remoteStore.write(`/config/user`,{...i,...e}).catch(e=>{this.emit(`remote-sync-failed`,{op:`write`,error:e})}),this.reload(this.overrides)}):this.update(e)}enqueueWrite(e){let t=this.writeChain.then(e,e);return this.writeChain=t.then(()=>void 0,()=>void 0),t}resolveUntrustedProjectPath(){if(this.paths.length!==0)return(typeof this.projectConfigTrusted==`function`?this.projectConfigTrusted():this.projectConfigTrusted)?void 0:this.paths[this.paths.length-1]}dispose(){this.removeAllListeners()}};function rt(e){let t;if(e.projectConfigPath?t=e.projectConfigPath:e.workspaceDir&&(t=m(e.workspaceDir,ee)),!t)return[];let n=m(f,d);return m(t)===n?[t]:[n,t]}const it=[],J=new Set([`config_version`,`version`,`last_update_check`,`_migrations`]),Y=new Map([[`model`,{category:`scalar-override`,deviceBound:!1}],[`language`,{category:`scalar-override`,deviceBound:!1}],[`nickname`,{category:`scalar-override`,deviceBound:!1}],[`has_completed_onboarding`,{category:`scalar-override`,deviceBound:!1}],[`has_completed_wizard`,{category:`scalar-override`,deviceBound:!1}],[`wizard_dont_show_again`,{category:`scalar-override`,deviceBound:!1}],[`first_prompt_submitted_at`,{category:`scalar-override`,deviceBound:!1}],[`thinking_level`,{category:`scalar-override`,deviceBound:!1}],[`tool_preset`,{category:`scalar-override`,deviceBound:!1}],[`log_level`,{category:`scalar-override`,deviceBound:!1}],[`feedback_repo`,{category:`scalar-override`,deviceBound:!1}],[`permission_mode`,{category:`scalar-override`,deviceBound:!1}],[`prompt_output_token_budget`,{category:`scalar-override`,deviceBound:!1}],[`prompt_wall_clock_budget_ms`,{category:`scalar-override`,deviceBound:!1}],[`session_cost_budget_usd`,{category:`scalar-override`,deviceBound:!1}],[`memory_auto_extract`,{category:`scalar-override`,deviceBound:!1}],[`skill_internalization`,{category:`scalar-override`,deviceBound:!1}],[`residency`,{category:`scalar-override`,deviceBound:!1}],[`skill_loop`,{category:`scalar-override`,deviceBound:!1}],[`history`,{category:`scalar-override`,deviceBound:!1}],[`workflow`,{category:`scalar-override`,deviceBound:!1}],[`todo_continue_max`,{category:`scalar-override`,deviceBound:!1}],[`stall_detection`,{category:`scalar-override`,deviceBound:!1}],[`sandbox`,{category:`scalar-override`,deviceBound:!1}],[`resilience`,{category:`scalar-override`,deviceBound:!1}],[`disabled_plugins`,{category:`array-merge`,deviceBound:!1}],[`model_fallback`,{category:`array-merge`,deviceBound:!1}],[`web_fetch_allowed_hosts`,{category:`array-merge`,deviceBound:!1}],[`recent_mentions`,{category:`array-merge`,deviceBound:!1}],[`shortcuts`,{category:`array-merge`,deviceBound:!1}],[`disabled_agents`,{category:`array-merge`,deviceBound:!1}],[`disabled_tools`,{category:`array-merge`,deviceBound:!1}],[`disabled_skills`,{category:`array-merge`,deviceBound:!1}],[`disabled_hooks`,{category:`array-merge`,deviceBound:!1}],[`permissions`,{category:`array-merge`,deviceBound:!1}],[`permission_always_allow`,{category:`array-merge`,deviceBound:!1}],[`agents`,{category:`record-merge`,deviceBound:!1}],[`categories`,{category:`record-merge`,deviceBound:!1}],[`model_slots`,{category:`record-merge`,deviceBound:!1}],[`mcp_servers`,{category:`record-merge`,deviceBound:!1}],[`recent_models`,{category:`array-merge`,deviceBound:!0}],[`keybinding_overrides`,{category:`record-merge`,deviceBound:!0}],[`installed_plugins`,{category:`array-merge`,deviceBound:!0}],[`plugin_lifecycle`,{category:`scalar-override`,deviceBound:!0}],[`auto_update_check`,{category:`scalar-override`,deviceBound:!0}],[`theme`,{category:`scalar-override`,deviceBound:!0}],[`theme_overrides`,{category:`scalar-override`,deviceBound:!0}],[`theme_preset`,{category:`scalar-override`,deviceBound:!0}],[`proxy`,{category:`scalar-override`,deviceBound:!0}],[`notification`,{category:`scalar-override`,deviceBound:!0}],[`pulse_survey`,{category:`scalar-override`,deviceBound:!0}]]);function at(){let e=S.filter(e=>!J.has(e)&&!Y.has(e));if(e.length>0)throw Error(`ConfigMergeStrategy 字段分类表遗漏以下 SettingKey(需在 FIELD_CLASSIFICATION 或 EXCLUDED_KEYS 中归类): ${e.join(`, `)}`)}const ot=new Set(E);function X(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Z(e,t){return e===t?!0:Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((e,n)=>JSON.stringify(e)===JSON.stringify(t[n])):JSON.stringify(e)===JSON.stringify(t)}const st={bypass:0,auto:1,confirm:2,strict:3,readonly:4};function ct(e,t){if(typeof t!=`string`||e===t)return!1;let n=typeof e==`string`?st[e]:void 0,r=st[t];return n===void 0||r===void 0?!0:r<n}function lt(e,t){let n=X(e)?e.enabled:void 0,r=X(t)?t.enabled:void 0;return n===!0&&r===!1}function ut(e,t){let n=Array.isArray(e)?e:[],r=Array.isArray(t)?t:[],i=new Set(n.map(e=>JSON.stringify(e)));return r.filter(e=>!i.has(JSON.stringify(e)))}function dt(e,t,n){if(!ot.has(e))return`safe`;if(e===`permission_mode`)return ct(t,n)?`sensitive`:`safe`;if(e===`sandbox`)return lt(t,n)?`sensitive`:`safe`;if(e===`mcp_servers`){let e=X(t)?t:{},r=X(n)?n:{};for(let[t,n]of Object.entries(r))if(!(t in e)||!Z(e[t],n))return`sensitive`;return`safe`}if(e===`disabled_hooks`)return Z(t,n)?`safe`:`sensitive`;if(e===`permissions`||e===`permission_always_allow`)return ut(t,n).length>0?`sensitive`:`safe`;throw Error(`classifyRisk: 字段 "${e}" 在 HIGH_RISK_PROJECT_KEYS 中但未被显式处理——新增高危字段必须同步补充判定分支,不允许 fail-open`)}function ft(e,t){let n=[];for(let r of S){if(J.has(r)||r===`installed_plugins`||!(r in t))continue;let i=e[r],a=t[r];if(Z(i,a))continue;let o=Y.get(r);o&&n.push({key:r,from:i,to:a,category:o.category,deviceBound:o.deviceBound,risk:dt(r,i,a)})}return n}function pt(e,t){let n=new Map(e.map(e=>[e.id,e])),r=new Map(t.map(e=>[e.id,e])),i=[],a=[];for(let e of t){let t=n.get(e.id);if(!t){i.push(e);continue}e.version!==void 0&&t.version!==void 0&&e.version!==t.version&&a.push({id:e.id,local:t.version,incoming:e.version})}return{toInstall:i,localOnly:e.filter(e=>!r.has(e.id)),versionMismatch:a}}function mt(e,t){return e.some(e=>e.risk===`sensitive`)?!0:t.toInstall.some(e=>(e.capabilities??[]).some(e=>se.includes(e)))}function ht(e,t){let n={};for(let r of e)if(!(t===`safe-only`&&r.risk===`sensitive`))if(r.category===`array-merge`){let e=Array.isArray(r.from)?r.from:[],t=Array.isArray(r.to)?r.to:[],i=new Set(e.map(e=>JSON.stringify(e))),a=[...e];for(let e of t){let t=JSON.stringify(e);i.has(t)||(i.add(t),a.push(e))}n[r.key]=a}else if(r.category===`record-merge`){let e=X(r.from)?r.from:{},t=X(r.to)?r.to:{};n[r.key]={...e,...t}}else n[r.key]=r.to;return n}const gt=new Set([`env`,`headers`]);function _t(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function vt(e){let t=[],n=(e,r)=>{if(!_t(e))return e;let i={};for(let[a,o]of Object.entries(e)){let e=[...r,a];if(r.length===2&&r[0]===`mcp_servers`&&gt.has(a)){t.push({path:e,set:o!==void 0});continue}i[a]=n(o,e)}return i};return{value:n(e,[]),secrets:t}}const yt=1;function bt(e,t,n,r=()=>new Date().toISOString()){let i={};for(let[t,n]of Object.entries(e))if(!J.has(t)&&n!==void 0){if(t===`installed_plugins`){i[t]=n.map(e=>e.sourceSpec&&re(e.sourceSpec)?{...e,sourceSpec:``}:e);continue}i[t]=n}let a=vt(i),o=a.value;return{otto_config_version:1,exported_at:r(),exported_from:n,scope:t,fields:o,...a.secrets.length>0?{redacted_secrets:a.secrets}:{redacted_secrets:[]}}}var xt=class extends Error{constructor(e,t){super(`导入文件 otto_config_version=${e},当前 otto 支持=${t}。请升级 otto 到最新版本后再试。`),this.fileVersion=e,this.supportedVersion=t,this.name=`ExportFileVersionError`}},Q=class extends Error{constructor(e){super(`导入文件格式非法:${e}`),this.name=`ExportFileParseError`}};function $(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function St(e){let t;try{t=JSON.parse(e)}catch(e){throw new Q(e instanceof Error?e.message:String(e))}if(!$(t))throw new Q(`顶层结构必须是 JSON 对象`);let{otto_config_version:n,exported_at:r,exported_from:i,scope:a,fields:o}=t;if(typeof n!=`number`)throw new Q(`缺少或非法的 otto_config_version 字段`);if(n!==1)throw new xt(n,1);if(typeof r!=`string`||typeof i!=`string`)throw new Q(`缺少或非法的 exported_at/exported_from 字段`);if(a!==`global`&&a!==`project`)throw new Q(`scope 字段必须是 "global" 或 "project"`);if(!$(o))throw new Q(`fields 字段必须是 JSON 对象`);return{otto_config_version:n,exported_at:r,exported_from:i,scope:a,fields:o,...Array.isArray(t.redacted_secrets)?{redacted_secrets:t.redacted_secrets}:{}}}export{it as BUILTIN_AGENT_PROFILES,C as BUILTIN_REVIEWER_AGENTS,yt as CURRENT_EXPORT_VERSION,w as DEFAULT_CONFIG,J as EXCLUDED_KEYS,Q as ExportFileParseError,xt as ExportFileVersionError,Y as FIELD_CLASSIFICATION,E as HIGH_RISK_PROJECT_KEYS,g as LOG_LEVELS,B as NEVER_SYNCED_KEYS,e as PERMISSION_MODES,L as RawFileSettingStore,$e as RemoteSettingStore,S as SETTING_KEYS,z as SYNCABLE_KEYS,F as SettingLoader,nt as SettingsManager,Ue as THEME_COLOR_ROLES,h as TOOL_PRESETS,ht as applyMergeStrategy,at as assertFieldClassificationCoversAllKeys,bt as buildExportPayload,pt as classifyPluginChanges,ft as diffConfig,V as filterSyncable,G as globToRegexSource,mt as hasSecuritySensitiveChanges,q as loadClaudeSettingsLayer,I as loadSetting,T as migrate,St as parseExportFile,W as parseToolSpecifier,D as sanitizeUntrustedProjectLayer,K as translateClaudeSettings};
1
+ import{PERMISSION_MODES as e}from"@x-otto/hook-contracts";import{z as t}from"zod";import{MODEL_SLOTS as n}from"@x-otto/orchestration-contracts";import{compare as r}from"semver";import{TypedEventEmitter as i,createLogger as a,mapClaudeToolName as o,parseJsonc as s,safeStringify as c}from"@x-otto/shared";import{atomicWriteFile as l}from"@x-otto/persistence";import{CLAUDE_HOME as u,OTTO_CONFIG_FILENAME as d,OTTO_HOME as f,OTTO_PROJECT_CONFIG_RELPATH as p,isClaudeSettingsCompatEnabled as ee,isShadowModeEnabled as te}from"@x-otto/env";import{isAbsolute as ne,join as m,resolve as h}from"node:path";import{homedir as g}from"node:os";import{existsSync as _,readFileSync as v}from"node:fs";import{HIGH_RISK_CAPABILITIES as re,isPathTrusted as ie,trustPath as ae,untrustPath as oe}from"@x-otto/plugin";const y=[`minimal`,`standard`,`full`],b=[`trace`,`debug`,`info`,`warn`,`error`,`fatal`],x=e=>e.optional().catch(void 0),S=t.enum(n),se=t.object({model:x(t.string()),description:x(t.string()),system_prompt:x(t.string()),tools:x(t.array(t.string())),capabilities:x(t.array(t.string())),categories:x(t.array(t.string())),default_workflow_slot:x(S),max_tool_turns:x(t.number()),max_tool_turn_extensions:x(t.number()),prompt_output_token_budget:x(t.number()),prompt_wall_clock_budget_ms:x(t.number()),session_cost_budget_usd:x(t.number()),stall_detection:x(t.union([t.literal(!1),t.object({window_turns:x(t.number()),repeat_threshold:x(t.number())})])),temperature:x(t.number()),max_tokens:x(t.number()),disabled:x(t.boolean())}),ce=t.object({preferred_models:x(t.array(t.string())),default_model:x(t.string())}),le=t.strictObject({baseUrl:t.string().min(1)}),ue=t.record(t.string().min(1),le),de=t.object({enabled:x(t.boolean()),every_n_turns:x(t.number()),max_lessons:x(t.number()),similarity_threshold:x(t.number()),min_relevant_hits:x(t.number())}),fe=t.object({enabled:x(t.boolean()),min_messages:x(t.number()),dismiss_cooldown_days:x(t.number())}),pe=t.object({enabled:x(t.boolean()),min_executions:x(t.number()),min_success_rate:x(t.number()),max_internalized:x(t.number())}),me=t.object({slots:x(t.partialRecord(S,t.union([t.string(),t.array(t.string())]))),default:x(t.string()),subagent_default_slot:x(S)}),he=t.object({enabled:x(t.boolean()),sound:x(t.boolean()),on_completion:x(t.boolean()),on_error:x(t.boolean()),on_idle:x(t.boolean()),channel:x(t.enum([`auto`,`terminal_bell`,`iterm2`,`iterm2_with_bell`,`kitty`,`ghostty`,`disabled`])),condition:x(t.enum([`unfocused`,`always`])),idle_threshold_ms:x(t.number()),command:x(t.array(t.string()))}),ge=t.object({enabled:x(t.boolean()),probability:x(t.number()),min_turn_gap:x(t.number()),sink:x(t.string())}),_e=t.object({id:x(t.string()),path:x(t.string()),enabled:x(t.boolean())}),ve=t.object({enabled:x(t.boolean()),maxEntries:x(t.number()),sources:x(t.array(_e))}),ye=t.object({external:x(ve)}),be=t.object({enabled:t.boolean(),network:x(t.enum([`allow`,`deny`])),writablePaths:x(t.array(t.string())),protectCredentials:x(t.boolean()),autoAllowBashIfSandboxed:x(t.boolean()),semanticReview:x(t.boolean())}),xe=t.object({total_bytes:x(t.number()),min_per_session_bytes:x(t.number()),max_per_session_bytes:x(t.number()),max_history_messages:x(t.number()),resume_window_messages:x(t.number()),max_content_bytes:x(t.number()),warn_threshold_pct:x(t.number()),hard_threshold_pct:x(t.number()),compaction_timeout_ms:x(t.number()),coverage_warn_threshold:x(t.number()),coverage_error_threshold:x(t.number()),coverage_floor_threshold:x(t.number())});t.object({tool_preset:x(t.enum(y)),disabled_tools:x(t.array(t.string()))});const Se=t.object({enabled:x(t.boolean())}),Ce=t.object({enabled:x(t.boolean()),maxAttempts:x(t.number().int().min(1)),backoffMs:x(t.number().min(0)),backoffMultiplier:x(t.number().min(0))}),we=t.object({enabled:x(t.boolean()),failureThreshold:x(t.number().int().min(1)),timeoutMs:x(t.number().min(0))}),Te=t.object({enabled:x(t.boolean())}),Ee=t.object({maxActiveTasks:x(t.number().int().min(1)),maxStoredTasks:x(t.number().int().min(1)),maxDelegationDepth:x(t.number().int().min(0)),maxFanOutPerParent:x(t.number().int().min(1))}),De=t.object({enabled:x(t.boolean()),review:x(Se),retry:x(Ce),circuitBreaker:x(we),routing:x(Te),orchestration:x(Ee)}),Oe=t.object({name:t.string(),effect:t.enum([`allow`,`deny`,`ask`]),tools:x(t.array(t.string())),paths:x(t.array(t.string())),commands:x(t.array(t.string())),deny_reason:x(t.string()),ask_prompt:x(t.string())}),ke=t.object({name:t.string(),priority:x(t.number()),enabled:x(t.boolean()),scope:x(t.object({agents:x(t.array(t.string())),sessions:x(t.array(t.string()))})),rules:t.array(Oe)}),Ae=t.object({url:x(t.string()),enabled:x(t.boolean())}),je=t.object({command:x(t.string()),args:x(t.array(t.string())),env:x(t.record(t.string(),t.string())),url:x(t.string()),type:x(t.enum([`stdio`,`sse`,`http`])),headers:x(t.record(t.string(),t.string())),requestTimeoutMs:x(t.number()),autoReconnect:x(t.boolean()),disabled:x(t.boolean())}),Me=t.object({maxRetries:x(t.number().int().positive()),initialDelayMs:x(t.number().positive()),backoffFactor:x(t.number().positive()),maxDelayMs:x(t.number().positive())}),Ne=t.object({maxRetries:x(t.number().int().positive()),intervalMs:x(t.number().positive())}),Pe=t.object({maxReconnectAttempts:x(t.number().int().nonnegative()),reconnectDelayMs:x(t.number().positive()),requestTimeoutMs:x(t.number().positive())}),Fe=t.object({retryBackoffMs:x(t.number().nonnegative())}),Ie=t.object({maxAttempts:x(t.number().int().positive()),intervalMs:x(t.number().positive())}),Le=t.object({refreshLockTimeoutMs:x(t.number().min(1e3))}),C=t.object({stream:x(Me),networkDisconnect:x(Ne),mcp:x(Pe),schedule:x(Fe),errorRetry:x(Ie),oauth:x(Le)});function w(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=C.parse(e),n={};for(let[e,r]of Object.entries(t)){if(!r||typeof r!=`object`)continue;let t={};for(let[e,n]of Object.entries(r))typeof n==`number`&&(t[e]=n);Object.keys(t).length>0&&(n[e]=t)}return n}function Re(e,t=e=>console.warn(`[resilience-config] ${e}`)){if(!e)return;let n;try{n=JSON.parse(e)}catch(e){t(`OTTO_RESILIENCE_CONFIG is not valid JSON, ignoring entirely: ${e instanceof Error?e.message:String(e)}`);return}return w(n)}const ze=t.object({id:t.string(),source:t.enum([`npm`,`dir`,`url`,`git`]),sourceSpec:x(t.string()),installedAt:t.number(),version:x(t.string()),scope:t.enum([`global`,`project`,`repository`]),capabilities:x(t.array(t.string()))}),Be=t.object({label:t.string(),value:t.string(),kind:t.enum([`hashtag`,`file`,`person`,`agent`,`skill`,`mcp`,`plugin`,`model`,`resource`,`shortcut`,`effort`]),description:x(t.string())}),Ve=t.object({name:t.string().min(1).max(64),text:t.string().min(1).max(4e3)}),T=`brand.brandShimmer.accent.accentDim.accentBright.text.inactive.secondary.subtle.replyPrefix.success.error.warning.special.suggestion.permission.codeText.diffAdd.diffRemove.diffAddBg.diffRemoveBg.panelBorder.overlayBg.tagBg.toolText.focusBorder.selection`.split(`.`),E=t.enum(T),He=t.strictObject({heading1:x(E),heading2:x(E),headingWeak:x(E),listMarker:x(E),listMarkerMuted:x(E),quoteBar:x(E),quoteText:x(E),link:x(E),inlineCode:x(E),codeFence:x(E),tableHeader:x(E),tableDivider:x(E),listIndent:x(t.union([t.literal(2),t.literal(3)])),listMarkers:x(t.tuple([t.string().min(1),t.string().min(1),t.string().min(1),t.string().min(1)])),codeBlockDivider:x(t.enum([`hr`,`none`]))}),Ue=t.strictObject({markdown:x(He)}),We=t.strictObject({dark:x(t.string().min(1).max(128)),light:x(t.string().min(1).max(128))}),D=t.object({config_version:x(t.string()),version:x(t.string()),log_level:x(t.enum(b)),model:x(t.string()),model_fallback:x(t.array(t.string())),recent_models:x(t.array(t.string())),recent_mentions:x(t.array(Be)),shortcuts:x(t.array(Ve)),feedback_repo:x(t.string()),feedback_platform:x(t.enum([`auto`,`github`,`coding`])),feedback_coding_base_url:x(t.string()),feedback_coding_repo:x(t.string()),keybinding_overrides:x(t.record(t.string(),t.object({ctrl:t.boolean().optional(),shift:t.boolean().optional(),meta:t.boolean().optional(),input:t.string().optional(),key:t.enum([`tab`,`escape`,`return`]).optional()}))),language:x(t.string()),theme:x(t.enum([`dark`,`light`,`system`])),theme_overrides:x(Ue),theme_preset:x(We),nickname:x(t.string().max(64)),has_completed_onboarding:x(t.boolean()),has_completed_wizard:x(t.boolean()),wizard_dont_show_again:x(t.boolean()),first_prompt_submitted_at:x(t.number()),thinking_level:x(t.string()),agents:x(t.record(t.string(),se)),categories:x(t.record(t.string(),ce)),tool_preset:x(t.enum(y)),memory_auto_extract:x(de),skill_loop:x(fe),skill_internalization:x(pe),notification:x(he),pulse_survey:x(ge),history:x(ye),workflow:x(De),model_slots:x(me),provider_overrides:x(ue),mcp_servers:x(t.record(t.string(),je)),resilience:x(C),sandbox:x(be),residency:x(xe),disabled_agents:x(t.array(t.string())),disabled_hooks:x(t.array(t.string())),disabled_tools:x(t.array(t.string())),disabled_skills:x(t.array(t.string())),disabled_plugins:x(t.array(t.string())),installed_plugins:x(t.array(ze)),auto_update_check:x(t.boolean()),last_update_check:x(t.number()),prompt_output_token_budget:x(t.number()),prompt_wall_clock_budget_ms:x(t.number()),session_cost_budget_usd:x(t.number()),stall_detection:x(t.union([t.literal(!1),t.object({window_turns:x(t.number()),repeat_threshold:x(t.number())})])),todo_continue_max:x(t.number()),permission_mode:x(t.enum(e)),permissions:x(t.array(ke)),permission_always_allow:x(t.array(t.string())),plugin_lifecycle:x(t.object({setupDone:x(t.array(t.object({id:t.string(),version:x(t.string())})))})),proxy:x(Ae),web_fetch_allowed_hosts:x(t.array(t.string())),_migrations:x(t.array(t.string()))}),Ge=T,O=D.keyof().options,k={"spec-reviewer":{description:`Reviews implementation against specification requirements`,categories:[`review`],default_workflow_slot:`critique`},"quality-reviewer":{description:`Reviews code quality, patterns, and best practices`,categories:[`review`],default_workflow_slot:`critique`}},A={config_version:`1.0.0`,log_level:`info`,model:void 0,recent_models:[],recent_mentions:[],shortcuts:[],language:`auto`,theme:void 0,nickname:void 0,has_completed_onboarding:void 0,has_completed_wizard:void 0,wizard_dont_show_again:void 0,first_prompt_submitted_at:void 0,thinking_level:void 0,tool_preset:`full`,agents:{...k},categories:{},workflow:{},disabled_agents:[],disabled_hooks:[],disabled_tools:[],disabled_skills:[],disabled_plugins:[],installed_plugins:[],auto_update_check:!0,last_update_check:void 0,permission_mode:`auto`,permissions:[],permission_always_allow:[],web_fetch_allowed_hosts:[],notification:{enabled:!0,sound:!1,on_completion:!0,on_error:!0,channel:`auto`,condition:`unfocused`,idle_threshold_ms:6e4},version:void 0,model_fallback:[],feedback_repo:void 0,feedback_platform:`auto`,feedback_coding_base_url:void 0,feedback_coding_repo:void 0,keybinding_overrides:{},theme_overrides:void 0,theme_preset:{dark:void 0,light:void 0},memory_auto_extract:{enabled:!1},skill_loop:{enabled:!1},skill_internalization:{enabled:!1},pulse_survey:{enabled:!0,probability:.05,min_turn_gap:20,sink:`local`},history:{external:{enabled:!1,maxEntries:1e3,sources:[]}},model_slots:{slots:void 0,default:void 0,subagent_default_slot:void 0},provider_overrides:{},mcp_servers:{},resilience:{},sandbox:{enabled:!0},residency:{},prompt_output_token_budget:void 0,prompt_wall_clock_budget_ms:void 0,session_cost_budget_usd:void 0,stall_detection:void 0,todo_continue_max:void 0,plugin_lifecycle:{setupDone:[]},proxy:{url:void 0,enabled:void 0},_migrations:[]},Ke=a(`@x-otto/setting:migrator`);function j(e,t=[]){let n=typeof e.config_version==`string`?e.config_version:`0.0.0`,i=[],a={...e};for(let e of t)r(e.version,n)>0&&(a=e.migrate(a),a.config_version=e.version,i.push(`${n} → ${e.version}`),Ke.info({from:n,to:e.version},`Applying migration: ${e.description}`));if(i.length>0){let e=Array.isArray(a._migrations)?a._migrations:[];a._migrations=[...e,...i]}return{config:a,applied:i}}const M=[`permission_mode`,`permissions`,`permission_always_allow`,`mcp_servers`,`disabled_hooks`,`sandbox`,`provider_overrides`];function N(e){let t={...e},n=[];for(let e of M)e in t&&(delete t[e],n.push(e));return{value:t,stripped:n}}const P=a(`@x-otto/setting`),qe=new Set(b),Je=[{key:`mcp`,message:`Removed legacy config key is ignored`},{key:`skills`,message:`Removed legacy config key is ignored`},{key:`disabled_mcps`,message:`Removed legacy config key is ignored`},{key:`disabled_skills`,message:`Removed legacy config key is ignored`},{key:`theme_file`,message:`RFC-205 legacy theme override key is ignored`},{key:`theme_spacing`,message:`RFC-205 legacy theme override key is ignored`},{key:`theme_border`,message:`RFC-205 legacy theme override key is ignored`},{key:`theme_figures`,message:`RFC-205 legacy theme override key is ignored`}],Ye=new Set([`accent`,`accentDim`,`accentBright`,`colors`,`spacing`,`border`,`figures`,`text`,`inactive`,`secondary`,`success`,`error`,`warning`,`special`]);function F(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function I(e,t,n,r){for(let[i,a]of Object.entries(e)){if(a===void 0)continue;let e=t[i],o=[...n,i].join(`.`);if(e===void 0){r.push({key:o,message:`Invalid value for "${o}" ignored`});continue}F(a)&&F(e)&&I(a,e,[...n,i],r)}}function L(e,t){let n={...e};for(let[e,r]of Object.entries(t))r!==void 0&&(F(r)&&F(n[e])?n[e]=L(n[e],r):n[e]=r);return n}function Xe(e,t,n){let r=new Map;for(let i of[...e,...t])F(i)&&typeof i[n]==`string`&&r.set(i[n],i);return[...r.values()]}function R(...e){let[t,n,...r]=e,i={...t};if(n){for(let[e,t]of Object.entries(n))if(t!==void 0)if(e===`permissions`&&Array.isArray(i[e])&&Array.isArray(t))i[e]=Xe(i[e],t,`name`);else if(Array.isArray(i[e])&&Array.isArray(t)){let n=i[e],r=t;i[e]=[...new Set([...n,...r])]}else F(t)&&F(i[e])?i[e]=L(i[e],t):i[e]=t}return r.length>0?R(i,...r):i}function Ze(){let e={},t=process.env.OTTO_MODEL;t&&(e.model=t);let n=process.env.OTTO_LOG_LEVEL;return n&&qe.has(n)&&(e.log_level=n),e}function Qe(e){let t={...e},n=[];for(let{key:e,message:r}of Je)t[e]!==void 0&&(n.push({key:e,message:r}),delete t[e]);if(F(t.theme_overrides)){let e=Object.keys(t.theme_overrides).filter(e=>Ye.has(e));e.length>0&&n.push({key:`theme_overrides`,message:`RFC-205 legacy theme_overrides shape (keys: ${e.join(`, `)}) is ignored — use theme_overrides.markdown instead`})}return{cleaned:t,warnings:n}}function $e(e){let t=D.loose().safeParse(e),n=t.success?t.data:e,r={};for(let[e,t]of Object.entries(n))t!==void 0&&(r[e]=t);return r}function et(e,t){let n=[];for(let r of O){let i=e[r],a=t[r];if(i!==void 0&&a===void 0){n.push({key:r,message:`Invalid value for "${r}" ignored`});continue}F(i)&&F(a)&&I(i,a,[r],n)}return n}function tt(e){let{cleaned:t,warnings:n}=Qe(e),r=$e(t),i=et(t,r);return{value:r,warnings:[...n,...i]}}async function nt(e,t,n){let r=[],i=[];for(let a of t)try{let t=await e.read(a);if(t!==void 0){let e=s(t);if(n!==void 0&&a===n){let t=N(e);e=t.value,i.push(...t.stripped)}r.push(e),P.debug({path:a},`Config loaded from store`)}}catch(e){P.warn({path:a,err:e},`Failed to parse config file, skipping`)}return{layers:r,stripped:i}}var z=class{store;constructor(e){this.store=e}async load(e={}){let{store:t=this.store,paths:n=[],extraLayers:r=[],untrustedProjectPath:i}=e,{layers:a,stripped:o}=t&&n.length>0?await nt(t,n,i):{layers:[],stripped:[]};for(let e of o)P.warn({key:e,path:i},`未受信任项目配置剔除高危键(permission_mode/mcp_servers 等需先信任该目录)`);let s=Ze(),{config:c,applied:l}=j(R(A,...r,...a,s));l.length>0&&P.info({applied:l},`Config migrations applied`);let{value:u,warnings:d}=tt(c);for(let e of d)P.warn({key:e.key,message:e.message},`Config validation issue`);return{...A,...u}}};async function B(e={}){return new z(e.store).load(e)}var V=class{type=`file`;async read(e){let{readFile:t}=await import(`node:fs/promises`);try{return await t(await H(e),`utf-8`)}catch{return}}async write(e,t){let{mkdir:n}=await import(`node:fs/promises`),{dirname:r}=await import(`node:path`),i=await H(e);await n(r(i),{recursive:!0}),await l(i,c(t,2))}async exists(e){let{access:t}=await import(`node:fs/promises`);try{return await t(await H(e)),!0}catch{return!1}}};async function H(e){if(!e.startsWith(`~/`))return e;let{homedir:t}=await import(`node:os`);return`${t()}${e.slice(1)}`}const U=(e={})=>({merge:`scalar-override`,deviceBound:!1,export:`include`,sync:`local-only`,...e}),W={config_version:U({export:`exclude`,sync:`never-synced`}),version:U({export:`exclude`,sync:`never-synced`}),last_update_check:U({export:`exclude`,sync:`never-synced`}),_migrations:U({export:`exclude`,sync:`never-synced`}),model:U({sync:`syncable`}),model_fallback:U({merge:`array-merge`,sync:`syncable`}),recent_models:U({merge:`array-merge`,deviceBound:!0,sync:`never-synced`}),recent_mentions:U({merge:`array-merge`,sync:`never-synced`}),shortcuts:U({merge:`array-merge`,sync:`never-synced`}),feedback_repo:U({sync:`local-only`}),feedback_platform:U({sync:`local-only`}),feedback_coding_base_url:U({sync:`local-only`}),feedback_coding_repo:U({sync:`local-only`}),keybinding_overrides:U({merge:`record-merge`,deviceBound:!0,sync:`never-synced`}),language:U({sync:`syncable`}),theme:U({deviceBound:!0,sync:`never-synced`}),theme_overrides:U({deviceBound:!0,sync:`never-synced`}),theme_preset:U({deviceBound:!0,sync:`never-synced`}),nickname:U({sync:`syncable`}),has_completed_onboarding:U({sync:`syncable`}),has_completed_wizard:U({sync:`syncable`}),wizard_dont_show_again:U({sync:`syncable`}),first_prompt_submitted_at:U({sync:`syncable`}),thinking_level:U({sync:`local-only`}),log_level:U({sync:`syncable`}),tool_preset:U({sync:`local-only`}),agents:U({merge:`record-merge`,sync:`never-synced`}),categories:U({merge:`record-merge`,sync:`never-synced`}),model_slots:U({merge:`record-merge`,sync:`syncable`}),provider_overrides:U({merge:`record-merge`,sync:`never-synced`}),memory_auto_extract:U({sync:`never-synced`}),skill_loop:U({sync:`never-synced`}),skill_internalization:U({sync:`never-synced`}),notification:U({deviceBound:!0,sync:`syncable`}),pulse_survey:U({deviceBound:!0,sync:`never-synced`}),history:U({sync:`never-synced`}),workflow:U({sync:`never-synced`}),residency:U({sync:`never-synced`}),resilience:U({sync:`never-synced`}),sandbox:U({sync:`never-synced`}),permission_mode:U({sync:`local-only`}),permissions:U({merge:`array-merge-by-name`,sync:`never-synced`}),permission_always_allow:U({merge:`array-merge`,sync:`never-synced`}),mcp_servers:U({merge:`record-merge`,sync:`never-synced`}),proxy:U({deviceBound:!0,sync:`never-synced`}),web_fetch_allowed_hosts:U({merge:`array-merge`,sync:`never-synced`}),prompt_output_token_budget:U({sync:`local-only`}),prompt_wall_clock_budget_ms:U({sync:`local-only`}),session_cost_budget_usd:U({sync:`local-only`}),stall_detection:U({sync:`never-synced`}),todo_continue_max:U({sync:`local-only`}),disabled_agents:U({merge:`array-merge`,sync:`syncable`}),disabled_hooks:U({merge:`array-merge`,sync:`syncable`}),disabled_tools:U({merge:`array-merge`,sync:`syncable`}),disabled_skills:U({merge:`array-merge`,sync:`syncable`}),disabled_plugins:U({merge:`array-merge`,sync:`never-synced`}),installed_plugins:U({merge:`array-merge`,deviceBound:!0,sync:`never-synced`}),plugin_lifecycle:U({deviceBound:!0,sync:`never-synced`}),auto_update_check:U({deviceBound:!0,sync:`syncable`})},G=new Set(Object.entries(W).filter(([,e])=>e.export===`exclude`).map(([e])=>e)),rt=new Set(Object.entries(W).filter(([,e])=>e.sync===`syncable`).map(([e])=>e)),it=new Set(Object.entries(W).filter(([,e])=>e.sync===`never-synced`).map(([e])=>e)),at=new Map(Object.entries(W).filter(([,e])=>e.export!==`exclude`).map(([e,t])=>[e,{category:t.merge,deviceBound:t.deviceBound}]));function ot(){let e=O.filter(e=>!W[e]);if(e.length>0)throw Error(`FIELD_META 遗漏以下 SettingKey(satisfies 门禁应已拦截): ${e.join(`, `)}`)}function st(e){let t={};for(let n of Object.keys(e))rt.has(n)&&!it.has(n)&&(t[n]=e[n]);return t}var ct=class{type=`file`;baseUrl;userId;getAuth;fetchImpl;timeoutMs;constructor(e){this.baseUrl=e.baseUrl.replace(/\/+$/,``),this.userId=e.userId,this.getAuth=e.getAuth,this.fetchImpl=e.fetch,this.timeoutMs=e.timeoutMs}async read(e){let t={Authorization:`Bearer ${(await this.getAuth()).token}`,Accept:`application/json`,"X-Otto-User-Id":this.userId},n=new AbortController,r=setTimeout(()=>n.abort(),this.timeoutMs),i;try{i=await this.fetchImpl(`${this.baseUrl}/config/user`,{method:`GET`,headers:t,signal:n.signal})}finally{clearTimeout(r)}if(i.status===404)return;if(!i.ok)throw Error(`remote settings read failed: HTTP ${i.status}`);let a=await i.json();return JSON.stringify(a)}async write(e,t){let n=st(t);if(Object.keys(n).length===0)return;let r={Authorization:`Bearer ${(await this.getAuth()).token}`,"Content-Type":`application/json`,"X-Otto-User-Id":this.userId},i=new AbortController,a=setTimeout(()=>i.abort(),this.timeoutMs),o;try{o=await this.fetchImpl(`${this.baseUrl}/config/user`,{method:`PUT`,headers:r,body:JSON.stringify(n),signal:i.signal})}finally{clearTimeout(a)}if(!o.ok)throw Error(`remote settings write failed: HTTP ${o.status}`)}async exists(e){return!1}};const K=a(`@x-otto/setting:claude-adapter`),lt=new Set([`Read`,`Write`,`Edit`,`MultiEdit`,`Glob`,`Grep`]),ut={default:`confirm`,acceptEdits:`auto`,bypassPermissions:`bypass`,plan:`readonly`};function dt(e){let t=/^([A-Za-z][A-Za-z0-9_]*)(?:\((.*)\))?$/.exec(e.trim());return t?{tool:t[1],specifier:t[2]}:{tool:e.trim()}}function ft(e){let t=e.startsWith(`~/`)?m(g(),e.slice(2)):e,n=``;for(let e=0;e<t.length;e++){let r=t[e];r===`*`?t[e+1]===`*`?(n+=`.*`,e++):n+=`[^/]*`:r===`?`?n+=`.`:n+=r.replace(/[.+^${}()|[\]\\]/g,`\\$&`)}return`^${n}$`}function pt(e,t,n,r){let{tool:i,specifier:a}=dt(e),s=o(i);if(!s){n.warnings.push(`未知工具 "${i}"(${e})→ fail-closed 丢弃`);return}if(i===`WebFetch`&&a?.startsWith(`domain:`)){let e=a.slice(7).trim();if(t===`allow`&&e){n.webFetchHosts.push(e);return}let i=t===`deny`?`deny`:`ask`;n.rules.push({name:`claude-${r}`,effect:i,tools:[s]}),n.warnings.push(`WebFetch(${a}) 的 ${t} 不可按域表达 → ${i===`deny`?`降工具级 deny(fail-closed)`:`降 ask`}`);return}if(a===void 0||a===``){n.rules.push({name:`claude-${r}`,effect:t,tools:[s]});return}if(lt.has(i)){n.rules.push({name:`claude-${r}`,effect:t,tools:[s],paths:[ft(a)]});return}n.rules.push({name:`claude-${r}`,effect:`ask`,tools:[s],ask_prompt:`Claude 规则 "${e}" 含命令参数限定,otto 无法精确表达,已降为询问。`}),n.warnings.push(`"${e}" 含参数 specifier 不可表达 → fail-closed 降 ask`)}function mt(e){let t={rules:[],webFetchHosts:[],warnings:[]},n=e?.permissions,r=0;for(let e of[`allow`,`deny`,`ask`]){let i=n?.[e];if(Array.isArray(i))for(let n of i)typeof n==`string`&&pt(n,e,t,r++)}let i={};t.rules.length>0&&(i.permissions=[{name:`claude-compat`,rules:t.rules}]),t.webFetchHosts.length>0&&(i.web_fetch_allowed_hosts=[...new Set(t.webFetchHosts)]);let a=typeof n?.defaultMode==`string`?n.defaultMode:void 0;return a&&ut[a]&&(i.permission_mode=ut[a],a===`plan`&&t.warnings.push(`defaultMode=plan otto 无对应 → 降 readonly`)),{setting:i,warnings:t.warnings}}function ht(e){if(!ee())return{};let t=[m(u,`settings.json`),...e?[m(h(e),`.claude`,`settings.json`),m(h(e),`.claude`,`settings.local.json`)]:[]],n=[],r=[],i,a=[];for(let e of t){if(!_(e))continue;let t;try{t=s(v(e,`utf-8`))}catch(t){K.warn({file:e,err:t},`Failed to parse .claude settings, skipped`);continue}let{setting:o,warnings:c}=mt(t);a.push(...c);let l=o.permissions?.[0]?.rules;l&&n.push(...l),o.web_fetch_allowed_hosts&&r.push(...o.web_fetch_allowed_hosts),o.permission_mode&&(i=o.permission_mode)}let o={};n.length>0&&(o.permissions=[{name:`claude-compat`,rules:n}]),r.length>0&&(o.web_fetch_allowed_hosts=[...new Set(r)]),i&&(o.permission_mode=i);let c=n.length;if(c>0||a.length>0){K.info({ruleCount:c,hosts:o.web_fetch_allowed_hosts?.length??0,mode:o.permission_mode},`Imported .claude/settings.json (RFC-032 D4)`);for(let e of a)K.warn({rule:e},`.claude settings 翻译降级`)}return o}var gt=class extends i{paths;workspaceDir;projectConfigTrusted;overrides;store;remoteStore;setting={};writeChain=Promise.resolve();constructor(e={}){super(),this.paths=_t(e),this.workspaceDir=e.workspaceDir,this.projectConfigTrusted=e.projectConfigTrusted??!0,this.overrides={...e.overrides},this.store=e.store??new V,this.remoteStore=e.remoteStore}get(e){return this.setting[e]}get config(){return this.setting}get model(){return this.setting.model}async load(){return this.reload(this.overrides)}async reload(e){let t;if(this.remoteStore)try{let e=await this.remoteStore.read(`/config/user`);e!==void 0&&(t=s(e))}catch(e){this.emit(`remote-sync-failed`,{op:`read`,error:e})}return this.setting={...await B({store:this.store,paths:this.paths,untrustedProjectPath:this.resolveUntrustedProjectPath(),extraLayers:[ht(this.workspaceDir),...t?[t]:[]]}),...e},this.emit(`change`,this.setting),this.setting}async update(e){return this.overrides={...this.overrides,...e},this.reload(this.overrides)}async persist(e,t){if(te())return this.update(e);let n=t===`global`?this.paths[0]:this.paths[this.paths.length-1],r=this.store;return r&&n?this.enqueueWrite(async()=>{let t=await r.read(n),i={};if(t)try{i=s(t)}catch{i={}}return await r.write(n,{...i,...e}),this.remoteStore&&this.remoteStore.write(`/config/user`,{...i,...e}).catch(e=>{this.emit(`remote-sync-failed`,{op:`write`,error:e})}),this.reload(this.overrides)}):this.update(e)}enqueueWrite(e){let t=this.writeChain.then(e,e);return this.writeChain=t.then(()=>void 0,()=>void 0),t}resolveUntrustedProjectPath(){if(this.paths.length!==0)return(typeof this.projectConfigTrusted==`function`?this.projectConfigTrusted():this.projectConfigTrusted)?void 0:this.paths[this.paths.length-1]}dispose(){this.removeAllListeners()}};function _t(e){let t;if(e.projectConfigPath?t=e.projectConfigPath:e.workspaceDir&&(t=h(e.workspaceDir,p)),!t)return[];let n=h(f,d);return h(t)===n?[t]:[n,t]}const vt=a(`@x-otto/setting:project-trust-gate`);function q(){return process.env.OTTO_CLAUDE_TRUST_PATH||m(f,`claude-trust.json`)}function J(e,t=q()){return ie(t,e)}function yt(e,t=q()){ae(t,e,`project-trust`)&&vt.info({root:h(e)},`Project trusted`)}function bt(e,t=q()){oe(t,e,`project-trust`)&&vt.info({root:h(e)},`Project trust revoked`)}function Y(){return process.env.OTTO_STRICT_PROJECT_CONFIG!==`0`}function xt(e,t={}){return!Y()||!t.interactive?!0:J(e)}function St(e,t={}){if(!Y())return{highRiskKeys:[],gated:!1};let n;try{n=s(v(m(e,p),`utf-8`))}catch{return{highRiskKeys:[],gated:!1}}let r=N(n).stripped;return{highRiskKeys:r,gated:r.length>0&&!xt(e,t)}}function Ct(e){return e===h(g())||e===h(`/`)?!1:[`.git`,`.claude`,`.mcp.json`].some(t=>_(m(e,t)))}function wt(e,t={}){let n=h(e);return t.interactive?Y()?J(e)?{shouldPrompt:!1,root:n,reason:`trusted`}:Ct(n)?{shouldPrompt:!0,root:n,reason:`untrusted`}:{shouldPrompt:!1,root:n,reason:`not-a-project`}:{shouldPrompt:!1,root:n,reason:`strict-off`}:{shouldPrompt:!1,root:n,reason:`not-interactive`}}const Tt=[],Et=new Set(M);function X(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Z(e,t){return e===t?!0:Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((e,n)=>JSON.stringify(e)===JSON.stringify(t[n])):JSON.stringify(e)===JSON.stringify(t)}const Dt={bypass:0,auto:1,confirm:2,strict:3,readonly:4};function Ot(e,t){if(typeof t!=`string`||e===t)return!1;let n=typeof e==`string`?Dt[e]:void 0,r=Dt[t];return n===void 0||r===void 0?!0:r<n}function kt(e,t){let n=X(e)?e.enabled:void 0,r=X(t)?t.enabled:void 0;return n===!0&&r===!1}function At(e,t){let n=Array.isArray(e)?e:[],r=Array.isArray(t)?t:[],i=new Set(n.map(e=>JSON.stringify(e)));return r.filter(e=>!i.has(JSON.stringify(e)))}function jt(e,t,n){if(!Et.has(e))return`safe`;if(e===`permission_mode`)return Ot(t,n)?`sensitive`:`safe`;if(e===`sandbox`)return kt(t,n)?`sensitive`:`safe`;if(e===`mcp_servers`||e===`provider_overrides`){let e=X(t)?t:{},r=X(n)?n:{};for(let[t,n]of Object.entries(r))if(!(t in e)||!Z(e[t],n))return`sensitive`;return`safe`}if(e===`disabled_hooks`)return Z(t,n)?`safe`:`sensitive`;if(e===`permissions`||e===`permission_always_allow`)return At(t,n).length>0?`sensitive`:`safe`;throw Error(`classifyRisk: 字段 "${e}" 在 HIGH_RISK_PROJECT_KEYS 中但未被显式处理——新增高危字段必须同步补充判定分支,不允许 fail-open`)}function Mt(e,t){let n=[];for(let r of O){if(G.has(r)||r===`installed_plugins`||!(r in t))continue;let i=e[r],a=t[r];if(Z(i,a))continue;let o=at.get(r);o&&n.push({key:r,from:i,to:a,category:o.category,deviceBound:o.deviceBound,risk:jt(r,i,a)})}return n}function Nt(e,t){let n=new Map(e.map(e=>[e.id,e])),r=new Map(t.map(e=>[e.id,e])),i=[],a=[];for(let e of t){let t=n.get(e.id);if(!t){i.push(e);continue}e.version!==void 0&&t.version!==void 0&&e.version!==t.version&&a.push({id:e.id,local:t.version,incoming:e.version})}return{toInstall:i,localOnly:e.filter(e=>!r.has(e.id)),versionMismatch:a}}function Pt(e,t){return e.some(e=>e.risk===`sensitive`)?!0:t.toInstall.some(e=>(e.capabilities??[]).some(e=>re.includes(e)))}function Ft(e,t){let n={};for(let r of e)if(!(t===`safe-only`&&r.risk===`sensitive`))if(r.category===`array-merge`){let e=Array.isArray(r.from)?r.from:[],t=Array.isArray(r.to)?r.to:[],i=new Set(e.map(e=>JSON.stringify(e))),a=[...e];for(let e of t){let t=JSON.stringify(e);i.has(t)||(i.add(t),a.push(e))}n[r.key]=a}else if(r.category===`array-merge-by-name`){let e=Array.isArray(r.from)?r.from:[],t=Array.isArray(r.to)?r.to:[],i=new Map;for(let n of[...e,...t])X(n)&&typeof n.name==`string`&&i.set(n.name,n);n[r.key]=[...i.values()]}else if(r.category===`record-merge`){let e=X(r.from)?r.from:{},t=X(r.to)?r.to:{};n[r.key]={...e,...t}}else n[r.key]=r.to;return n}const It=new Set([`env`,`headers`]);function Lt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Rt(e){let t=[],n=(e,r)=>{if(!Lt(e))return e;let i={};for(let[a,o]of Object.entries(e)){let e=[...r,a];if(r.length===2&&r[0]===`mcp_servers`&&It.has(a)){t.push({path:e,set:o!==void 0});continue}i[a]=n(o,e)}return i};return{value:n(e,[]),secrets:t}}const zt=1;function Bt(e,t,n,r=()=>new Date().toISOString()){let i={};for(let[t,n]of Object.entries(e))if(!G.has(t)&&n!==void 0){if(t===`installed_plugins`){i[t]=n.map(e=>e.sourceSpec&&ne(e.sourceSpec)?{...e,sourceSpec:``}:e);continue}i[t]=n}let a=Rt(i),o=a.value;return{otto_config_version:1,exported_at:r(),exported_from:n,scope:t,fields:o,...a.secrets.length>0?{redacted_secrets:a.secrets}:{redacted_secrets:[]}}}var Vt=class extends Error{constructor(e,t){super(`导入文件 otto_config_version=${e},当前 otto 支持=${t}。请升级 otto 到最新版本后再试。`),this.fileVersion=e,this.supportedVersion=t,this.name=`ExportFileVersionError`}},Q=class extends Error{constructor(e){super(`导入文件格式非法:${e}`),this.name=`ExportFileParseError`}};function $(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ht(e){let t;try{t=JSON.parse(e)}catch(e){throw new Q(e instanceof Error?e.message:String(e))}if(!$(t))throw new Q(`顶层结构必须是 JSON 对象`);let{otto_config_version:n,exported_at:r,exported_from:i,scope:a,fields:o}=t;if(typeof n!=`number`)throw new Q(`缺少或非法的 otto_config_version 字段`);if(n!==1)throw new Vt(n,1);if(typeof r!=`string`||typeof i!=`string`)throw new Q(`缺少或非法的 exported_at/exported_from 字段`);if(a!==`global`&&a!==`project`)throw new Q(`scope 字段必须是 "global" 或 "project"`);if(!$(o))throw new Q(`fields 字段必须是 JSON 对象`);return{otto_config_version:n,exported_at:r,exported_from:i,scope:a,fields:o,...Array.isArray(t.redacted_secrets)?{redacted_secrets:t.redacted_secrets}:{}}}export{Tt as BUILTIN_AGENT_PROFILES,k as BUILTIN_REVIEWER_AGENTS,zt as CURRENT_EXPORT_VERSION,A as DEFAULT_CONFIG,G as EXCLUDED_KEYS,Q as ExportFileParseError,Vt as ExportFileVersionError,at as FIELD_CLASSIFICATION,W as FIELD_META,M as HIGH_RISK_PROJECT_KEYS,b as LOG_LEVELS,it as NEVER_SYNCED_KEYS,e as PERMISSION_MODES,V as RawFileSettingStore,ct as RemoteSettingStore,O as SETTING_KEYS,rt as SYNCABLE_KEYS,z as SettingLoader,gt as SettingsManager,Ge as THEME_COLOR_ROLES,y as TOOL_PRESETS,Ft as applyMergeStrategy,ot as assertFieldClassificationCoversAllKeys,Bt as buildExportPayload,Nt as classifyPluginChanges,q as claudeTrustStorePath,St as detectProjectConfigGating,Mt as diffConfig,wt as evaluateWorkspaceTrustPrompt,st as filterSyncable,ft as globToRegexSource,Pt as hasSecuritySensitiveChanges,J as isProjectTrusted,Y as isStrictProjectConfigEnabled,ht as loadClaudeSettingsLayer,B as loadSetting,j as migrate,Ht as parseExportFile,Re as parseResilienceEnvOverride,dt as parseToolSpecifier,xt as resolveProjectConfigTrusted,N as sanitizeUntrustedProjectLayer,mt as translateClaudeSettings,yt as trustProject,bt as untrustProject,w as validateResilienceOverride};
2
2
  //# sourceMappingURL=index.js.map